From 8b8fb6427e3cbc16b818ddcbd6a971f3d2370f94 Mon Sep 17 00:00:00 2001 From: Liming Liu Date: Mon, 29 Apr 2024 15:14:37 +0000 Subject: [PATCH 001/203] 8324776: runtime/os/TestTransparentHugePageUsage.java fails with The usage of THP is not enough Reviewed-by: stuefe --- test/hotspot/jtreg/ProblemList.txt | 1 - .../os/TestTransparentHugePageUsage.java | 105 ------------------ 2 files changed, 106 deletions(-) delete mode 100644 test/hotspot/jtreg/runtime/os/TestTransparentHugePageUsage.java diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 8e144b692f29b..4b787c1b1ee22 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -111,7 +111,6 @@ runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 -runtime/os/TestTransparentHugePageUsage.java 8324776 linux-all runtime/Thread/TestAlwaysPreTouchStacks.java 8324781 linux-all applications/jcstress/accessAtomic.java 8325984 generic-all diff --git a/test/hotspot/jtreg/runtime/os/TestTransparentHugePageUsage.java b/test/hotspot/jtreg/runtime/os/TestTransparentHugePageUsage.java deleted file mode 100644 index 2b054fd6f4b03..0000000000000 --- a/test/hotspot/jtreg/runtime/os/TestTransparentHugePageUsage.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) Ampere Computing 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 TestTransparentHugePageUsage - * @bug 8315923 - * @library /test/lib - * @requires vm.gc.Serial & os.family == "linux" & os.maxMemory > 2G - * @summary Check that a pretouched java heap appears to use THPs by checking - * AnonHugePages in smaps - * @comment Use SerialGC to increase the time window for pretouching - * @run driver runtime.os.TestTransparentHugePageUsage - */ - -package runtime.os; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.InputStreamReader; -import java.util.AbstractMap.SimpleEntry; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import jdk.test.lib.process.ProcessTools; - -public class TestTransparentHugePageUsage { - private static final String[] fixedCmdLine = { - "-XX:+UseTransparentHugePages", "-XX:+AlwaysPreTouch", - "-Xlog:startuptime,pagesize,gc+heap=debug", - "-XX:+UseSerialGC", "-Xms1G", "-Xmx1G", - }; - - public static void main(String[] args) throws Exception { - ArrayList cmdLine = new ArrayList<>(Arrays.asList(fixedCmdLine)); - cmdLine.add("runtime.os.TestTransparentHugePageUsage$CatSmaps"); - ProcessBuilder builder = ProcessTools.createTestJavaProcessBuilder(cmdLine); - checkUsage(new BufferedReader(new InputStreamReader(builder.start().getInputStream()))); - } - - private static void checkUsage(BufferedReader reader) throws Exception { - final Pattern useThp = Pattern.compile(".*\\[info\\]\\[pagesize\\].+UseTransparentHugePages=1.*"); - // Ensure THP is not disabled by OS. - if (reader.lines().filter(line -> useThp.matcher(line).matches()).findFirst().isPresent()) { - final Pattern heapAddr = Pattern.compile(".*\\sHeap:\\s.+base=0x0*(\\p{XDigit}+).*"); - final Optional addr = reader.lines() - .map(line -> new SimpleEntry(line, heapAddr.matcher(line))) - .filter(e -> e.getValue().matches()) - .findFirst() - .map(e -> Long.valueOf(e.getKey().substring(e.getValue().start(1), e.getValue().end(1)), 16)); - if (!addr.isPresent()) throw new RuntimeException("Heap base was not found in smaps."); - // Match the start of a mapping, for example: - // 200000000-800000000 rw-p 00000000 00:00 0 - final Pattern mapping = Pattern.compile("^(\\p{XDigit}+)-\\p{XDigit}+.*"); - reader.lines() - .filter(line -> { - Matcher matcher = mapping.matcher(line); - if (matcher.matches()) { - Long mappingAddr = Long.valueOf(line.substring(matcher.start(1), matcher.end(1)), 16); - if (mappingAddr.equals(addr.get())) return true; - } - return false; - }) - .findFirst(); - final Pattern thpUsage = Pattern.compile("^AnonHugePages:\\s+(\\d+)\\skB"); - final Optional usage = reader.lines() - .map(line -> new SimpleEntry(line, thpUsage.matcher(line))) - .filter(e -> e.getValue().matches()) - .findFirst() - .map(e -> Long.valueOf(e.getKey().substring(e.getValue().start(1), e.getValue().end(1)))); - if (!usage.isPresent()) throw new RuntimeException("The usage of THP was not found."); - // Even with MADV_POPULATE_WRITE, the usage of THP is still one page less than the whole heap. - if (usage.get() < 524288) throw new RuntimeException("The usage of THP is not enough."); - } - } - - public static class CatSmaps { - public static void main(String[] args) throws Exception { - new BufferedReader(new FileReader("/proc/self/smaps")) - .lines() - .forEach(line -> System.out.println(line)); - } - } -} From bdcc2400db63e604d76f9b5bd3c876271743f69f Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 29 Apr 2024 15:58:03 +0000 Subject: [PATCH 002/203] 8331087: Move immutable nmethod data from CodeCache Reviewed-by: thartmann, dlong, dnsimon --- src/hotspot/share/code/nmethod.cpp | 249 ++++++++++++------ src/hotspot/share/code/nmethod.hpp | 104 +++++--- src/hotspot/share/runtime/vmStructs.cpp | 9 +- .../classes/sun/jvm/hotspot/code/NMethod.java | 52 ++-- .../compiler/c1/TestLinearScanOrderMain.java | 3 +- 5 files changed, 269 insertions(+), 148 deletions(-) diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 7e4f6994ff1c6..26d393d06db45 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -110,6 +110,11 @@ #endif +// Cast from int value to narrow type +#define CHECKED_CAST(result, T, thing) \ + result = static_cast(thing); \ + assert(static_cast(result) == thing, "failed: %d != %d", static_cast(result), thing); + //--------------------------------------------------------------------------------- // NMethod statistics // They are printed under various flags, including: @@ -121,26 +126,28 @@ // and make it simpler to print from the debugger. struct java_nmethod_stats_struct { uint nmethod_count; - uint total_size; + uint total_nm_size; + uint total_immut_size; uint relocation_size; uint consts_size; uint insts_size; uint stub_size; - uint scopes_data_size; - uint scopes_pcs_size; + uint oops_size; + uint metadata_size; uint dependencies_size; - uint handler_table_size; uint nul_chk_table_size; + uint handler_table_size; + uint scopes_pcs_size; + uint scopes_data_size; #if INCLUDE_JVMCI uint speculations_size; uint jvmci_data_size; #endif - uint oops_size; - uint metadata_size; void note_nmethod(nmethod* nm) { nmethod_count += 1; - total_size += nm->size(); + total_nm_size += nm->size(); + total_immut_size += nm->immutable_data_size(); relocation_size += nm->relocation_size(); consts_size += nm->consts_size(); insts_size += nm->insts_size(); @@ -160,23 +167,60 @@ struct java_nmethod_stats_struct { void print_nmethod_stats(const char* name) { if (nmethod_count == 0) return; tty->print_cr("Statistics for %u bytecoded nmethods for %s:", nmethod_count, name); - if (total_size != 0) tty->print_cr(" total in heap = %u (100%%)", total_size); + uint total_size = total_nm_size + total_immut_size; + if (total_nm_size != 0) { + tty->print_cr(" total size = %u (100%%)", total_size); + tty->print_cr(" in CodeCache = %u (%f%%)", total_nm_size, (total_nm_size * 100.0f)/total_size); + } uint header_size = (uint)(nmethod_count * sizeof(nmethod)); - if (nmethod_count != 0) tty->print_cr(" header = %u (%f%%)", header_size, (header_size * 100.0f)/total_size); - if (relocation_size != 0) tty->print_cr(" relocation = %u (%f%%)", relocation_size, (relocation_size * 100.0f)/total_size); - if (consts_size != 0) tty->print_cr(" constants = %u (%f%%)", consts_size, (consts_size * 100.0f)/total_size); - if (insts_size != 0) tty->print_cr(" main code = %u (%f%%)", insts_size, (insts_size * 100.0f)/total_size); - if (stub_size != 0) tty->print_cr(" stub code = %u (%f%%)", stub_size, (stub_size * 100.0f)/total_size); - if (oops_size != 0) tty->print_cr(" oops = %u (%f%%)", oops_size, (oops_size * 100.0f)/total_size); - if (metadata_size != 0) tty->print_cr(" metadata = %u (%f%%)", metadata_size, (metadata_size * 100.0f)/total_size); - if (scopes_data_size != 0) tty->print_cr(" scopes data = %u (%f%%)", scopes_data_size, (scopes_data_size * 100.0f)/total_size); - if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %u (%f%%)", scopes_pcs_size, (scopes_pcs_size * 100.0f)/total_size); - if (dependencies_size != 0) tty->print_cr(" dependencies = %u (%f%%)", dependencies_size, (dependencies_size * 100.0f)/total_size); - if (handler_table_size != 0) tty->print_cr(" handler table = %u (%f%%)", handler_table_size, (handler_table_size * 100.0f)/total_size); - if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %u (%f%%)", nul_chk_table_size, (nul_chk_table_size * 100.0f)/total_size); + if (nmethod_count != 0) { + tty->print_cr(" header = %u (%f%%)", header_size, (header_size * 100.0f)/total_nm_size); + } + if (relocation_size != 0) { + tty->print_cr(" relocation = %u (%f%%)", relocation_size, (relocation_size * 100.0f)/total_nm_size); + } + if (consts_size != 0) { + tty->print_cr(" constants = %u (%f%%)", consts_size, (consts_size * 100.0f)/total_nm_size); + } + if (insts_size != 0) { + tty->print_cr(" main code = %u (%f%%)", insts_size, (insts_size * 100.0f)/total_nm_size); + } + if (stub_size != 0) { + tty->print_cr(" stub code = %u (%f%%)", stub_size, (stub_size * 100.0f)/total_nm_size); + } + if (oops_size != 0) { + tty->print_cr(" oops = %u (%f%%)", oops_size, (oops_size * 100.0f)/total_nm_size); + } + if (metadata_size != 0) { + tty->print_cr(" metadata = %u (%f%%)", metadata_size, (metadata_size * 100.0f)/total_nm_size); + } #if INCLUDE_JVMCI - if (speculations_size != 0) tty->print_cr(" speculations = %u (%f%%)", speculations_size, (speculations_size * 100.0f)/total_size); - if (jvmci_data_size != 0) tty->print_cr(" JVMCI data = %u (%f%%)", jvmci_data_size, (jvmci_data_size * 100.0f)/total_size); + if (jvmci_data_size != 0) { + tty->print_cr(" JVMCI data = %u (%f%%)", jvmci_data_size, (jvmci_data_size * 100.0f)/total_nm_size); + } +#endif + if (total_immut_size != 0) { + tty->print_cr(" immutable data = %u (%f%%)", total_immut_size, (total_immut_size * 100.0f)/total_size); + } + if (dependencies_size != 0) { + tty->print_cr(" dependencies = %u (%f%%)", dependencies_size, (dependencies_size * 100.0f)/total_immut_size); + } + if (nul_chk_table_size != 0) { + tty->print_cr(" nul chk table = %u (%f%%)", nul_chk_table_size, (nul_chk_table_size * 100.0f)/total_immut_size); + } + if (handler_table_size != 0) { + tty->print_cr(" handler table = %u (%f%%)", handler_table_size, (handler_table_size * 100.0f)/total_immut_size); + } + if (scopes_pcs_size != 0) { + tty->print_cr(" scopes pcs = %u (%f%%)", scopes_pcs_size, (scopes_pcs_size * 100.0f)/total_immut_size); + } + if (scopes_data_size != 0) { + tty->print_cr(" scopes data = %u (%f%%)", scopes_data_size, (scopes_data_size * 100.0f)/total_immut_size); + } +#if INCLUDE_JVMCI + if (speculations_size != 0) { + tty->print_cr(" speculations = %u (%f%%)", speculations_size, (speculations_size * 100.0f)/total_immut_size); + } #endif } }; @@ -1101,31 +1145,40 @@ nmethod* nmethod::new_nmethod(const methodHandle& method, code_buffer->finalize_oop_references(method); // create nmethod nmethod* nm = nullptr; + int nmethod_size = CodeBlob::allocation_size(code_buffer, sizeof(nmethod)); #if INCLUDE_JVMCI - int jvmci_data_size = compiler->is_jvmci() ? jvmci_data->size() : 0; + if (compiler->is_jvmci()) { + nmethod_size += align_up(jvmci_data->size(), oopSize); + } #endif - int nmethod_size = - CodeBlob::allocation_size(code_buffer, sizeof(nmethod)) - + adjust_pcs_size(debug_info->pcs_size()) + + int immutable_data_size = + adjust_pcs_size(debug_info->pcs_size()) + align_up((int)dependencies->size_in_bytes(), oopSize) + align_up(handler_table->size_in_bytes() , oopSize) + align_up(nul_chk_table->size_in_bytes() , oopSize) #if INCLUDE_JVMCI + align_up(speculations_len , oopSize) - + align_up(jvmci_data_size , oopSize) #endif + align_up(debug_info->data_size() , oopSize); + + // First, allocate space for immutable data in C heap. + address immutable_data = nullptr; + if (immutable_data_size > 0) { + immutable_data = (address)os::malloc(immutable_data_size, mtCode); + if (immutable_data == nullptr) { + vm_exit_out_of_memory(immutable_data_size, OOM_MALLOC_ERROR, "nmethod: no space for immutable data"); + return nullptr; + } + } { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); nm = new (nmethod_size, comp_level) - nmethod(method(), compiler->type(), nmethod_size, compile_id, entry_bci, offsets, - orig_pc_offset, debug_info, dependencies, code_buffer, frame_size, - oop_maps, - handler_table, - nul_chk_table, - compiler, - comp_level + nmethod(method(), compiler->type(), nmethod_size, immutable_data_size, + compile_id, entry_bci, immutable_data, offsets, orig_pc_offset, + debug_info, dependencies, code_buffer, frame_size, oop_maps, + handler_table, nul_chk_table, compiler, comp_level #if INCLUDE_JVMCI , speculations, speculations_len, @@ -1196,11 +1249,11 @@ void nmethod::init_defaults(CodeBuffer *code_buffer, CodeOffsets* offsets) { int consts_offset = code_buffer->total_offset_of(code_buffer->consts()); assert(consts_offset == 0, "const_offset: %d", consts_offset); - _entry_offset = checked_cast(offsets->value(CodeOffsets::Entry)); - _verified_entry_offset = checked_cast(offsets->value(CodeOffsets::Verified_Entry)); - _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); + _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); - _skipped_instructions_size = checked_cast(code_buffer->total_skipped_instructions_size()); + CHECKED_CAST(_entry_offset, uint16_t, (offsets->value(CodeOffsets::Entry))); + CHECKED_CAST(_verified_entry_offset, uint16_t, (offsets->value(CodeOffsets::Verified_Entry))); + CHECKED_CAST(_skipped_instructions_size, uint16_t, (code_buffer->total_skipped_instructions_size())); } // Post initialization @@ -1262,21 +1315,26 @@ nmethod::nmethod( _deopt_mh_handler_offset = 0; _unwind_handler_offset = 0; - _metadata_offset = checked_cast(align_up(code_buffer->total_oop_size(), oopSize)); - _dependencies_offset = checked_cast(_metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize)); - _scopes_pcs_offset = _dependencies_offset; - _scopes_data_offset = _scopes_pcs_offset; - _handler_table_offset = _scopes_data_offset; - _nul_chk_table_offset = _handler_table_offset; + CHECKED_CAST(_metadata_offset, uint16_t, (align_up(code_buffer->total_oop_size(), oopSize))); + int data_end_offset = _metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize); #if INCLUDE_JVMCI - _speculations_offset = _nul_chk_table_offset; - _jvmci_data_offset = _speculations_offset; - DEBUG_ONLY( int data_end_offset = _jvmci_data_offset; ) -#else - DEBUG_ONLY( int data_end_offset = _nul_chk_table_offset; ) + // jvmci_data_size is 0 in native wrapper but we need to set offset + // to correctly calculate metadata_end address + CHECKED_CAST(_jvmci_data_offset, uint16_t, data_end_offset); #endif assert((data_offset() + data_end_offset) <= nmethod_size, "wrong nmethod's size: %d < %d", nmethod_size, (data_offset() + data_end_offset)); + // native wrapper does not have read-only data but we need unique not null address + _immutable_data = data_end(); + _immutable_data_size = 0; + _nul_chk_table_offset = 0; + _handler_table_offset = 0; + _scopes_pcs_offset = 0; + _scopes_data_offset = 0; +#if INCLUDE_JVMCI + _speculations_offset = 0; +#endif + code_buffer->copy_code_and_locs_to(this); code_buffer->copy_values_to(this); @@ -1343,8 +1401,10 @@ nmethod::nmethod( Method* method, CompilerType type, int nmethod_size, + int immutable_data_size, int compile_id, int entry_bci, + address immutable_data, CodeOffsets* offsets, int orig_pc_offset, DebugInformationRecorder* debug_info, @@ -1421,25 +1481,48 @@ nmethod::nmethod( } } if (offsets->value(CodeOffsets::UnwindHandler) != -1) { - _unwind_handler_offset = code_offset() + offsets->value(CodeOffsets::UnwindHandler); + // C1 generates UnwindHandler at the end of instructions section. + // Calculate positive offset as distance between the start of stubs section + // (which is also the end of instructions section) and the start of the handler. + int unwind_handler_offset = code_offset() + offsets->value(CodeOffsets::UnwindHandler); + CHECKED_CAST(_unwind_handler_offset, int16_t, (_stub_offset - unwind_handler_offset)); } else { _unwind_handler_offset = -1; } - _metadata_offset = checked_cast(align_up(code_buffer->total_oop_size(), oopSize)); - _dependencies_offset = checked_cast(_metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize)); - _scopes_pcs_offset = checked_cast(_dependencies_offset + align_up((int)dependencies->size_in_bytes(), oopSize)); - _scopes_data_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size()); - _handler_table_offset = _scopes_data_offset + align_up(debug_info->data_size (), oopSize); - _nul_chk_table_offset = _handler_table_offset + align_up(handler_table->size_in_bytes(), oopSize); + CHECKED_CAST(_metadata_offset, uint16_t, (align_up(code_buffer->total_oop_size(), oopSize))); + int metadata_end_offset = _metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize); + #if INCLUDE_JVMCI - _speculations_offset = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize); - _jvmci_data_offset = _speculations_offset + align_up(speculations_len, oopSize); + CHECKED_CAST(_jvmci_data_offset, uint16_t, metadata_end_offset); int jvmci_data_size = compiler->is_jvmci() ? jvmci_data->size() : 0; - DEBUG_ONLY( int data_end_offset = _jvmci_data_offset + align_up(jvmci_data_size, oopSize); ) + DEBUG_ONLY( int data_end_offset = _jvmci_data_offset + align_up(jvmci_data_size, oopSize); ) #else - DEBUG_ONLY( int data_end_offset = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize); ) + DEBUG_ONLY( int data_end_offset = metadata_end_offset; ) #endif - assert((data_offset() + data_end_offset) <= nmethod_size, "wrong nmethod's size: %d < %d", nmethod_size, (data_offset() + data_end_offset)); + assert((data_offset() + data_end_offset) <= nmethod_size, "wrong nmethod's size: %d > %d", + (data_offset() + data_end_offset), nmethod_size); + + _immutable_data_size = immutable_data_size; + if (immutable_data_size > 0) { + assert(immutable_data != nullptr, "required"); + _immutable_data = immutable_data; + } else { + // We need unique not null address + _immutable_data = data_end(); + } + CHECKED_CAST(_nul_chk_table_offset, uint16_t, (align_up((int)dependencies->size_in_bytes(), oopSize))); + CHECKED_CAST(_handler_table_offset, uint16_t, (_nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize))); + _scopes_pcs_offset = _handler_table_offset + align_up(handler_table->size_in_bytes(), oopSize); + _scopes_data_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size()); + +#if INCLUDE_JVMCI + _speculations_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); + DEBUG_ONLY( int immutable_data_end_offset = _speculations_offset + align_up(speculations_len, oopSize); ) +#else + DEBUG_ONLY( int immutable_data_end_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); ) +#endif + assert(immutable_data_end_offset <= immutable_data_size, "wrong read-only data size: %d > %d", + immutable_data_end_offset, immutable_data_size); // Copy code and relocation info code_buffer->copy_code_and_locs_to(this); @@ -2047,6 +2130,10 @@ void nmethod::purge(bool unregister_nmethod) { } delete[] _compiled_ic_data; + if (_immutable_data != data_end()) { + os::free(_immutable_data); + _immutable_data = data_end(); // Valid not null address + } if (unregister_nmethod) { Universe::heap()->unregister_nmethod(this); } @@ -2679,7 +2766,7 @@ PcDesc* PcDescContainer::find_pc_desc_internal(address pc, bool approximate, add // Find the last pc_offset less than the given offset. // The successor must be the required match, if there is a match at all. // (Use a fixed radix to avoid expensive affine pointer arithmetic.) - PcDesc* lower = lower_incl; // this is initial sentiel + PcDesc* lower = lower_incl; // this is initial sentinel PcDesc* upper = upper_incl - 1; // exclude final sentinel if (lower >= upper) return nullptr; // no PcDescs at all @@ -3002,35 +3089,41 @@ void nmethod::print(outputStream* st) const { p2i(metadata_begin()), p2i(metadata_end()), metadata_size()); - if (scopes_data_size () > 0) st->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(scopes_data_begin()), - p2i(scopes_data_end()), - scopes_data_size()); - if (scopes_pcs_size () > 0) st->print_cr(" scopes pcs [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(scopes_pcs_begin()), - p2i(scopes_pcs_end()), - scopes_pcs_size()); +#if INCLUDE_JVMCI + if (jvmci_data_size () > 0) st->print_cr(" JVMCI data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(jvmci_data_begin()), + p2i(jvmci_data_end()), + jvmci_data_size()); +#endif + if (immutable_data_size() > 0) st->print_cr(" immutable data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(immutable_data_begin()), + p2i(immutable_data_end()), + immutable_data_size()); if (dependencies_size () > 0) st->print_cr(" dependencies [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(dependencies_begin()), p2i(dependencies_end()), dependencies_size()); - if (handler_table_size() > 0) st->print_cr(" handler table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(handler_table_begin()), - p2i(handler_table_end()), - handler_table_size()); if (nul_chk_table_size() > 0) st->print_cr(" nul chk table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(nul_chk_table_begin()), p2i(nul_chk_table_end()), nul_chk_table_size()); + if (handler_table_size() > 0) st->print_cr(" handler table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(handler_table_begin()), + p2i(handler_table_end()), + handler_table_size()); + if (scopes_pcs_size () > 0) st->print_cr(" scopes pcs [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(scopes_pcs_begin()), + p2i(scopes_pcs_end()), + scopes_pcs_size()); + if (scopes_data_size () > 0) st->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(scopes_data_begin()), + p2i(scopes_data_end()), + scopes_data_size()); #if INCLUDE_JVMCI if (speculations_size () > 0) st->print_cr(" speculations [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(speculations_begin()), p2i(speculations_end()), speculations_size()); - if (jvmci_data_size () > 0) st->print_cr(" JVMCI data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(jvmci_data_begin()), - p2i(jvmci_data_end()), - jvmci_data_size()); #endif } diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 8ffb75eda34d4..22e38afeebd67 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -195,6 +195,9 @@ class nmethod : public CodeBlob { }; }; + // nmethod's read-only data + address _immutable_data; + PcDescContainer* _pc_desc_container; ExceptionCache* volatile _exception_cache; @@ -211,6 +214,7 @@ class nmethod : public CodeBlob { uint16_t _entry_offset; // entry point with class check uint16_t _verified_entry_offset; // entry point without class check int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method + int _immutable_data_size; // _consts_offset == _content_offset because SECT_CONSTS is first in code buffer @@ -224,21 +228,27 @@ class nmethod : public CodeBlob { // All deoptee's at a MethodHandle call site will resume execution // at this location described by this offset. int _deopt_mh_handler_offset; - // Offset of the unwind handler if it exists - int _unwind_handler_offset; - + // Offset (from insts_end) of the unwind handler if it exists + int16_t _unwind_handler_offset; + // Number of arguments passed on the stack + uint16_t _num_stack_arg_slots; uint16_t _skipped_instructions_size; + // Offsets in mutable data section // _oops_offset == _data_offset, offset where embedded oop table begins (inside data) uint16_t _metadata_offset; // embedded meta data table - uint16_t _dependencies_offset; - uint16_t _scopes_pcs_offset; +#if INCLUDE_JVMCI + uint16_t _jvmci_data_offset; +#endif + + // Offset in immutable data section + // _dependencies_offset == 0 + uint16_t _nul_chk_table_offset; + uint16_t _handler_table_offset; // This table could be big in C1 code + int _scopes_pcs_offset; int _scopes_data_offset; - int _handler_table_offset; - int _nul_chk_table_offset; #if INCLUDE_JVMCI int _speculations_offset; - int _jvmci_data_offset; #endif // location in frame (offset for sp) that deopt can store the original @@ -249,8 +259,6 @@ class nmethod : public CodeBlob { CompLevel _comp_level; // compilation level (s1) CompilerType _compiler_type; // which compiler made this nmethod (u1) - uint16_t _num_stack_arg_slots; // Number of arguments passed on the stack - #if INCLUDE_RTM_OPT // RTM state at compile time. Used during deoptimization to decide // whether to restart collecting RTM locking abort statistic again. @@ -307,8 +315,10 @@ class nmethod : public CodeBlob { nmethod(Method* method, CompilerType type, int nmethod_size, + int immutable_data_size, int compile_id, int entry_bci, + address immutable_data, CodeOffsets* offsets, int orig_pc_offset, DebugInformationRecorder *recorder, @@ -524,48 +534,56 @@ class nmethod : public CodeBlob { address exception_begin () const { return header_begin() + _exception_offset ; } address deopt_handler_begin () const { return header_begin() + _deopt_handler_offset ; } address deopt_mh_handler_begin() const { return header_begin() + _deopt_mh_handler_offset ; } - address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (header_begin() + _unwind_handler_offset) : nullptr; } - - oop* oops_begin () const { return (oop*) data_begin(); } - oop* oops_end () const { return (oop*) (data_begin() + _metadata_offset) ; } + address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (insts_end() - _unwind_handler_offset) : nullptr; } + // mutable data + oop* oops_begin () const { return (oop*) data_begin(); } + oop* oops_end () const { return (oop*) (data_begin() + _metadata_offset) ; } Metadata** metadata_begin () const { return (Metadata**) (data_begin() + _metadata_offset) ; } - Metadata** metadata_end () const { return (Metadata**) (data_begin() + _dependencies_offset) ; } - - address dependencies_begin () const { return data_begin() + _dependencies_offset ; } - address dependencies_end () const { return data_begin() + _scopes_pcs_offset ; } - PcDesc* scopes_pcs_begin () const { return (PcDesc*)(data_begin() + _scopes_pcs_offset) ; } - PcDesc* scopes_pcs_end () const { return (PcDesc*)(data_begin() + _scopes_data_offset) ; } - address scopes_data_begin () const { return data_begin() + _scopes_data_offset ; } - address scopes_data_end () const { return data_begin() + _handler_table_offset ; } - address handler_table_begin () const { return data_begin() + _handler_table_offset ; } - address handler_table_end () const { return data_begin() + _nul_chk_table_offset ; } - address nul_chk_table_begin () const { return data_begin() + _nul_chk_table_offset ; } +#if INCLUDE_JVMCI + Metadata** metadata_end () const { return (Metadata**) (data_begin() + _jvmci_data_offset) ; } + address jvmci_data_begin () const { return data_begin() + _jvmci_data_offset ; } + address jvmci_data_end () const { return data_end(); } +#else + Metadata** metadata_end () const { return (Metadata**) data_end(); } +#endif + + // immutable data + address immutable_data_begin () const { return _immutable_data; } + address immutable_data_end () const { return _immutable_data + _immutable_data_size ; } + address dependencies_begin () const { return _immutable_data; } + address dependencies_end () const { return _immutable_data + _nul_chk_table_offset; } + address nul_chk_table_begin () const { return _immutable_data + _nul_chk_table_offset; } + address nul_chk_table_end () const { return _immutable_data + _handler_table_offset; } + address handler_table_begin () const { return _immutable_data + _handler_table_offset; } + address handler_table_end () const { return _immutable_data + _scopes_pcs_offset ; } + PcDesc* scopes_pcs_begin () const { return (PcDesc*)(_immutable_data + _scopes_pcs_offset) ; } + PcDesc* scopes_pcs_end () const { return (PcDesc*)(_immutable_data + _scopes_data_offset) ; } + address scopes_data_begin () const { return _immutable_data + _scopes_data_offset ; } #if INCLUDE_JVMCI - address nul_chk_table_end () const { return data_begin() + _speculations_offset ; } - address speculations_begin () const { return data_begin() + _speculations_offset ; } - address speculations_end () const { return data_begin() + _jvmci_data_offset ; } - address jvmci_data_begin () const { return data_begin() + _jvmci_data_offset ; } - address jvmci_data_end () const { return data_end(); } + address scopes_data_end () const { return _immutable_data + _speculations_offset ; } + address speculations_begin () const { return _immutable_data + _speculations_offset ; } + address speculations_end () const { return immutable_data_end(); } #else - address nul_chk_table_end () const { return data_end(); } + address scopes_data_end () const { return immutable_data_end(); } #endif // Sizes - int consts_size () const { return int( consts_end () - consts_begin ()); } - int insts_size () const { return int( insts_end () - insts_begin ()); } - int stub_size () const { return int( stub_end () - stub_begin ()); } - int oops_size () const { return int((address) oops_end () - (address) oops_begin ()); } - int metadata_size () const { return int((address) metadata_end () - (address) metadata_begin ()); } - int scopes_data_size () const { return int( scopes_data_end () - scopes_data_begin ()); } - int scopes_pcs_size () const { return int((intptr_t)scopes_pcs_end () - (intptr_t)scopes_pcs_begin ()); } - int dependencies_size () const { return int( dependencies_end () - dependencies_begin ()); } - int handler_table_size() const { return int( handler_table_end() - handler_table_begin()); } - int nul_chk_table_size() const { return int( nul_chk_table_end() - nul_chk_table_begin()); } + int immutable_data_size() const { return _immutable_data_size; } + int consts_size () const { return int( consts_end () - consts_begin ()); } + int insts_size () const { return int( insts_end () - insts_begin ()); } + int stub_size () const { return int( stub_end () - stub_begin ()); } + int oops_size () const { return int((address) oops_end () - (address) oops_begin ()); } + int metadata_size () const { return int((address) metadata_end () - (address) metadata_begin ()); } + int scopes_data_size () const { return int( scopes_data_end () - scopes_data_begin ()); } + int scopes_pcs_size () const { return int((intptr_t)scopes_pcs_end () - (intptr_t)scopes_pcs_begin ()); } + int dependencies_size () const { return int( dependencies_end () - dependencies_begin ()); } + int handler_table_size () const { return int( handler_table_end() - handler_table_begin()); } + int nul_chk_table_size () const { return int( nul_chk_table_end() - nul_chk_table_begin()); } #if INCLUDE_JVMCI - int speculations_size () const { return int( speculations_end () - speculations_begin ()); } - int jvmci_data_size () const { return int( jvmci_data_end () - jvmci_data_begin ()); } + int speculations_size () const { return int( speculations_end () - speculations_begin ()); } + int jvmci_data_size () const { return int( jvmci_data_end () - jvmci_data_begin ()); } #endif int oops_count() const { assert(oops_size() % oopSize == 0, ""); return (oops_size() / oopSize) + 1; } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 8d86fb6ceb4bf..cc1351e2742ee 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -576,14 +576,15 @@ nonstatic_field(nmethod, _orig_pc_offset, int) \ nonstatic_field(nmethod, _stub_offset, int) \ nonstatic_field(nmethod, _metadata_offset, u2) \ - nonstatic_field(nmethod, _scopes_pcs_offset, u2) \ + nonstatic_field(nmethod, _scopes_pcs_offset, int) \ nonstatic_field(nmethod, _scopes_data_offset, int) \ - nonstatic_field(nmethod, _dependencies_offset, u2) \ - nonstatic_field(nmethod, _handler_table_offset, int) \ - nonstatic_field(nmethod, _nul_chk_table_offset, int) \ + nonstatic_field(nmethod, _handler_table_offset, u2) \ + nonstatic_field(nmethod, _nul_chk_table_offset, u2) \ nonstatic_field(nmethod, _entry_offset, u2) \ nonstatic_field(nmethod, _verified_entry_offset, u2) \ nonstatic_field(nmethod, _osr_entry_point, address) \ + nonstatic_field(nmethod, _immutable_data, address) \ + nonstatic_field(nmethod, _immutable_data_size, int) \ nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _comp_level, CompLevel) \ volatile_nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java index edcf85ce0c78f..ec329aa131a9b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -42,6 +42,8 @@ public class NMethod extends CodeBlob { private static CIntegerField entryBCIField; /** To support simple linked-list chaining of nmethods */ private static AddressField osrLinkField; + private static AddressField immutableDataField; + private static CIntegerField immutableDataSizeField; /** Offsets for different nmethod parts */ private static CIntegerField exceptionOffsetField; @@ -50,11 +52,10 @@ public class NMethod extends CodeBlob { private static CIntegerField origPCOffsetField; private static CIntegerField stubOffsetField; private static CIntField metadataOffsetField; - private static CIntField dependenciesOffsetField; - private static CIntField scopesPCsOffsetField; + private static CIntField handlerTableOffsetField; + private static CIntField nulChkTableOffsetField; + private static CIntegerField scopesPCsOffsetField; private static CIntegerField scopesDataOffsetField; - private static CIntegerField handlerTableOffsetField; - private static CIntegerField nulChkTableOffsetField; /** Offsets for entry points */ /** Entry point with class check */ @@ -82,6 +83,8 @@ private static void initialize(TypeDataBase db) { methodField = type.getAddressField("_method"); entryBCIField = type.getCIntegerField("_entry_bci"); osrLinkField = type.getAddressField("_osr_link"); + immutableDataField = type.getAddressField("_immutable_data"); + immutableDataSizeField = type.getCIntegerField("_immutable_data_size"); exceptionOffsetField = type.getCIntegerField("_exception_offset"); deoptHandlerOffsetField = type.getCIntegerField("_deopt_handler_offset"); @@ -89,11 +92,10 @@ private static void initialize(TypeDataBase db) { origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); stubOffsetField = type.getCIntegerField("_stub_offset"); metadataOffsetField = new CIntField(type.getCIntegerField("_metadata_offset"), 0); - dependenciesOffsetField = new CIntField(type.getCIntegerField("_dependencies_offset"), 0); - scopesPCsOffsetField = new CIntField(type.getCIntegerField("_scopes_pcs_offset"), 0); + scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset"); scopesDataOffsetField = type.getCIntegerField("_scopes_data_offset"); - handlerTableOffsetField = type.getCIntegerField("_handler_table_offset"); - nulChkTableOffsetField = type.getCIntegerField("_nul_chk_table_offset"); + handlerTableOffsetField = new CIntField(type.getCIntegerField("_handler_table_offset"), 0); + nulChkTableOffsetField = new CIntField(type.getCIntegerField("_nul_chk_table_offset"), 0); entryOffsetField = new CIntField(type.getCIntegerField("_entry_offset"), 0); verifiedEntryOffsetField = new CIntField(type.getCIntegerField("_verified_entry_offset"), 0); osrEntryPointField = type.getAddressField("_osr_entry_point"); @@ -133,18 +135,22 @@ public Method getMethod() { public Address oopsBegin() { return dataBegin(); } public Address oopsEnd() { return dataBegin().addOffsetTo(getMetadataOffset()); } public Address metadataBegin() { return dataBegin().addOffsetTo(getMetadataOffset()); } - public Address metadataEnd() { return dataBegin().addOffsetTo(getDependenciesOffset()); } - public Address dependenciesBegin() { return dataBegin().addOffsetTo(getDependenciesOffset()); } - public Address dependenciesEnd() { return dataBegin().addOffsetTo(getScopesDataOffset()); } - public Address scopesDataBegin() { return dataBegin().addOffsetTo(getScopesDataOffset()); } - public Address scopesDataEnd() { return dataBegin().addOffsetTo(getScopesPCsOffset()); } - public Address scopesPCsBegin() { return dataBegin().addOffsetTo(getScopesPCsOffset()); } - public Address scopesPCsEnd() { return dataBegin().addOffsetTo(getHandlerTableOffset()); } - public Address handlerTableBegin() { return dataBegin().addOffsetTo(getHandlerTableOffset()); } - public Address handlerTableEnd() { return dataBegin().addOffsetTo(getNulChkTableOffset()); } - public Address nulChkTableBegin() { return dataBegin().addOffsetTo(getNulChkTableOffset()); } - public Address nulChkTableEnd() { return dataEnd(); } - + public Address metadataEnd() { return dataEnd(); } + + public Address immutableDataBegin() { return immutableDataField.getValue(addr); } + public Address immutableDataEnd() { return immutableDataBegin().addOffsetTo(getImmutableDataSize()); } + public Address dependenciesBegin() { return immutableDataBegin(); } + public Address dependenciesEnd() { return immutableDataBegin().addOffsetTo(getHandlerTableOffset()); } + public Address handlerTableBegin() { return immutableDataBegin().addOffsetTo(getHandlerTableOffset()); } + public Address handlerTableEnd() { return immutableDataBegin().addOffsetTo(getNulChkTableOffset()); } + public Address nulChkTableBegin() { return immutableDataBegin().addOffsetTo(getNulChkTableOffset()); } + public Address nulChkTableEnd() { return immutableDataBegin().addOffsetTo(getScopesDataOffset()); } + public Address scopesDataBegin() { return immutableDataBegin().addOffsetTo(getScopesDataOffset()); } + public Address scopesDataEnd() { return immutableDataBegin().addOffsetTo(getScopesPCsOffset()); } + public Address scopesPCsBegin() { return immutableDataBegin().addOffsetTo(getScopesPCsOffset()); } + public Address scopesPCsEnd() { return immutableDataEnd(); } + + public int getImmutableDataSize() { return (int) immutableDataSizeField.getValue(addr); } public int constantsSize() { return (int) constantsEnd() .minus(constantsBegin()); } public int instsSize() { return (int) instsEnd() .minus(instsBegin()); } public int stubSize() { return (int) stubEnd() .minus(stubBegin()); } @@ -161,7 +167,10 @@ public int totalSize() { return constantsSize() + instsSize() + - stubSize() + + stubSize(); + } + public int immutableDataSize() { + return scopesDataSize() + scopesPCsSize() + dependenciesSize() + @@ -516,7 +525,6 @@ public void dumpReplayData(PrintStream out) { private int getMetadataOffset() { return (int) metadataOffsetField .getValue(addr); } private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); } private int getScopesPCsOffset() { return (int) scopesPCsOffsetField .getValue(addr); } - private int getDependenciesOffset() { return (int) dependenciesOffsetField.getValue(addr); } private int getHandlerTableOffset() { return (int) handlerTableOffsetField.getValue(addr); } private int getNulChkTableOffset() { return (int) nulChkTableOffsetField .getValue(addr); } private int getCompLevel() { return (int) compLevelField .getValue(addr); } diff --git a/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java b/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java index 4165fa4d0e14e..a154427530a4b 100644 --- a/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java +++ b/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8207355 * @compile TestLinearScanOrder.jasm * @run main/othervm -Xcomp -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+IgnoreUnrecognizedVMOptions -XX:NMethodSizeLimit=655360 * -XX:CompileCommand=compileonly,compiler.c1.TestLinearScanOrder::test * compiler.c1.TestLinearScanOrderMain */ From 4e4229438ad2e8ac59ac675465e4d3d4e13bf156 Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Mon, 29 Apr 2024 16:27:54 +0000 Subject: [PATCH 003/203] 8329004: Update Libpng to 1.6.43 Reviewed-by: prr, dnguyen --- src/java.desktop/share/legal/libpng.md | 43 +-- .../native/libsplashscreen/libpng/CHANGES | 67 +++++ .../native/libsplashscreen/libpng/LICENSE | 4 +- .../native/libsplashscreen/libpng/README | 12 +- .../libsplashscreen/libpng/UPDATING.txt | 25 +- .../share/native/libsplashscreen/libpng/png.c | 110 +++----- .../share/native/libsplashscreen/libpng/png.h | 61 ++--- .../native/libsplashscreen/libpng/pngconf.h | 4 +- .../native/libsplashscreen/libpng/pngerror.c | 34 +-- .../native/libsplashscreen/libpng/pngget.c | 245 +++++++++--------- .../libsplashscreen/libpng/pnglibconf.h | 2 +- .../native/libsplashscreen/libpng/pngpread.c | 16 +- .../native/libsplashscreen/libpng/pngpriv.h | 118 +++++++-- .../native/libsplashscreen/libpng/pngread.c | 12 +- .../native/libsplashscreen/libpng/pngrtran.c | 34 ++- .../native/libsplashscreen/libpng/pngrutil.c | 19 +- .../native/libsplashscreen/libpng/pngset.c | 22 +- .../native/libsplashscreen/libpng/pngtrans.c | 14 +- 18 files changed, 490 insertions(+), 352 deletions(-) diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md index f420ccd94ed2e..cbffed8133209 100644 --- a/src/java.desktop/share/legal/libpng.md +++ b/src/java.desktop/share/legal/libpng.md @@ -1,4 +1,4 @@ -## libpng v1.6.40 +## libpng v1.6.43 ### libpng License
@@ -9,11 +9,11 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
 PNG Reference Library License version 2
 ---------------------------------------
 
-Copyright (c) 1995-2023 The PNG Reference Library Authors.
-Copyright (c) 2018-2023 Cosmin Truta
-Copyright (c) 1998-2018 Glenn Randers-Pehrson
-Copyright (c) 1996-1997 Andreas Dilger
-Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+Copyright (C) 1995-2024 The PNG Reference Library Authors.
+Copyright (C) 2018-2024 Cosmin Truta
+Copyright (C) 1998-2018 Glenn Randers-Pehrson
+Copyright (C) 1996-1997 Andreas Dilger
+Copyright (C) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
 
 The software is supplied "as is", without warranty of any kind,
 express or implied, including, without limitation, the warranties
@@ -157,7 +157,9 @@ PNG REFERENCE LIBRARY AUTHORS
 This is the list of PNG Reference Library ("libpng") Contributing
 Authors, for copyright and licensing purposes.
 
+ * Adam Richter
  * Andreas Dilger
+ * Chris Blume
  * Cosmin Truta
  * Dave Martindale
  * Eric S. Raymond
@@ -186,21 +188,28 @@ Authors, for copyright and licensing purposes.
  * Vadim Barkov
  * Willem van Schaik
  * Zhijie Liang
+ * Apple Inc.
+    - Zixu Wang (王子旭)
  * Arm Holdings
-   - Richard Townsend
+    - Richard Townsend
  * Google Inc.
-   - Dan Field
-   - Leon Scroggins III
-   - Matt Sarett
-   - Mike Klein
-   - Sami Boukortt
-   - Wan-Teh Chang
+    - Dan Field
+    - Leon Scroggins III
+    - Matt Sarett
+    - Mike Klein
+    - Sami Boukortt
+    - Wan-Teh Chang
+ * Loongson Technology Corporation Ltd.
+    - GuXiWei (顾希伟)
+    - JinBo (金波)
+    - ZhangLixia (张利霞)
 
 The build projects, the build scripts, the test scripts, and other
-files in the "ci", "projects", "scripts" and "tests" directories, have
+files in the "projects", "scripts" and "tests" directories, have
 other copyright owners, but are released under the libpng license.
 
-Some files in the "contrib" directory, and some tools-generated files
-that are distributed with libpng, have other copyright owners, and are
-released under other open source licenses.
+Some files in the "ci" and "contrib" directories, as well as some
+of the tools-generated files that are distributed with libpng, have
+other copyright owners, and are released under other open source
+licenses.
 ```
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
index 2d8c585c0e794..441b57ecf1ab2 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
@@ -6129,6 +6129,73 @@ Version 1.6.40 [June 21, 2023]
   Updated the configurations and the scripts for continuous integration.
   Cleaned up the code, the build scripts, and the documentation.
 
+Version 1.6.41 [January 24, 2024]
+  Added SIMD-optimized code for the LoongArch LSX hardware.
+    (Contributed by GuXiWei, JinBo and ZhangLixia)
+  Fixed the run-time discovery of MIPS MSA hardware.
+    (Contributed by Sui Jingfeng)
+  Fixed an off-by-one error in the function png_do_check_palette_indexes(),
+    which failed to recognize errors that might have existed in the first
+    column of a broken palette-encoded image. This was a benign regression
+    accidentally introduced in libpng-1.6.33. No pixel was harmed.
+    (Contributed by Adam Richter; reviewed by John Bowler)
+  Fixed, improved and modernized the contrib/pngminus programs, i.e.,
+    png2pnm.c and pnm2png.c
+  Removed old and peculiar portability hacks that were meant to silence
+    warnings issued by gcc version 7.1 alone.
+    (Contributed by John Bowler)
+  Fixed and modernized the CMake file, and raised the minimum required
+    CMake version from 3.1 to 3.6.
+    (Contributed by Clinton Ingram, Timothy Lyanguzov, Tyler Kropp, et al.)
+  Allowed the configure script to disable the building of auxiliary tools
+    and tests, thus catching up with the CMake file.
+    (Contributed by Carlo Bramini)
+  Fixed a build issue on Mac.
+    (Contributed by Zixu Wang)
+  Moved the Autoconf macro files to scripts/autoconf.
+  Moved the CMake files (except for the main CMakeLists.txt) to
+    scripts/cmake and moved the list of their contributing authors to
+    scripts/cmake/AUTHORS.md
+  Updated the CI configurations and scripts.
+  Relicensed the CI scripts to the MIT License.
+  Improved the test coverage.
+    (Contributed by John Bowler)
+
+Version 1.6.42 [January 29, 2024]
+  Fixed the implementation of the macro function png_check_sig().
+    This was an API regression, introduced in libpng-1.6.41.
+    (Reported by Matthieu Darbois)
+  Fixed and updated the libpng manual.
+
+Version 1.6.43 [February 23, 2024]
+  Fixed the row width check in png_check_IHDR().
+    This corrected a bug that was specific to the 16-bit platforms,
+    and removed a spurious compiler warning from the 64-bit builds.
+    (Reported by Jacek Caban; fixed by John Bowler)
+  Added eXIf chunk support to the push-mode reader in pngpread.c.
+    (Contributed by Chris Blume)
+  Added contrib/pngexif for the benefit of the users who would like
+    to inspect the content of eXIf chunks.
+  Added contrib/conftest/basic.dfa, a basic build-time configuration.
+    (Contributed by John Bowler)
+  Fixed a preprocessor condition in pngread.c that broke build-time
+    configurations like contrib/conftest/pngcp.dfa.
+    (Contributed by John Bowler)
+  Added CMake build support for LoongArch LSX.
+    (Contributed by GuXiWei)
+  Fixed a CMake build error that occurred under a peculiar state of the
+    dependency tree. This was a regression introduced in libpng-1.6.41.
+    (Contributed by Dan Rosser)
+  Marked the installed libpng headers as system headers in CMake.
+    (Contributed by Benjamin Buch)
+  Updated the build support for RISCOS.
+    (Contributed by Cameron Cawley)
+  Updated the makefiles to allow cross-platform builds to initialize
+    conventional make variables like AR and ARFLAGS.
+  Added various improvements to the CI scripts in areas like version
+    consistency verification and text linting.
+  Added version consistency verification to pngtest.c also.
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
 Subscription is required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
index 086d1c2fda63b..25f298f0fcfd8 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
@@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
 PNG Reference Library License version 2
 ---------------------------------------
 
- * Copyright (c) 1995-2023 The PNG Reference Library Authors.
- * Copyright (c) 2018-2023 Cosmin Truta.
+ * Copyright (c) 1995-2024 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2024 Cosmin Truta.
  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  * Copyright (c) 1996-1997 Andreas Dilger.
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/README b/src/java.desktop/share/native/libsplashscreen/libpng/README
index dedd2c1639e24..a6ca3ae9f9406 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/README
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.40
+README for libpng version 1.6.43
 ================================
 
 See the note about version numbers near the top of `png.h`.
@@ -142,10 +142,11 @@ Files included in this distribution
     pngwrite.c    =>  High-level write functions
     pngwtran.c    =>  Write data transformations
     pngwutil.c    =>  Write utility functions
-    arm/          =>  Optimized code for the ARM platform
-    intel/        =>  Optimized code for the INTEL-SSE2 platform
-    mips/         =>  Optimized code for the MIPS platform
-    powerpc/      =>  Optimized code for the PowerPC platform
+    arm/          =>  Optimized code for ARM Neon
+    intel/        =>  Optimized code for INTEL SSE2
+    loongarch/    =>  Optimized code for LoongArch LSX
+    mips/         =>  Optimized code for MIPS MSA and MIPS MMI
+    powerpc/      =>  Optimized code for PowerPC VSX
     ci/           =>  Scripts for continuous integration
     contrib/      =>  External contributions
         arm-neon/     =>  Optimized code for the ARM-NEON platform
@@ -158,6 +159,7 @@ Files included in this distribution
         libtests/     =>  Test programs
         oss-fuzz/     =>  Files used by the OSS-Fuzz project for fuzz-testing
                           libpng
+        pngexif/      =>  Program to inspect the EXIF information in PNG files
         pngminim/     =>  Minimal decoder, encoder, and progressive decoder
                           programs demonstrating the use of pngusr.dfa
         pngminus/     =>  Simple pnm2png and png2pnm programs
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt b/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt
index 93c8f5bb7039c..88200db5d732f 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt
@@ -37,18 +37,21 @@ and instead just tweak the existing one.
 
 First cd into the libpng folder and run the following script.
 
+    shopt -s nullglob
     for f in *.c *.h;
-    do
-      # replace tabs with spaces
-      expand ${f} > ${f}.tmp;
-      mv ${f}.tmp $f;
-
-      # fix line endings to LF
-      sed -i -e 's/\r$//g' ${f};
-
-      # remove trailing spaces
-      sed -i -e 's/[ ]* $//g' ${f};
-    done
+         do
+            # replace tabs with spaces
+            expand ${f} > ${f}.tmp
+            mv ${f}.tmp $f
+
+            # fix line endings to LF
+            sed -e 's/\r$//g' ${f} > ${f}.tmp
+            mv ${f}.tmp $f
+
+            # remove trailing spaces
+            sed -e 's/[ ]* $//g' ${f} > ${f}.tmp
+            mv ${f}.tmp $f
+         done
 
 6) As with all native code, run it through the official build systems, in case
 the updated code trigger any fatal warnings with the official compilers.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.c b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
index 91a92e5f71871..232dff876c793 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -42,27 +42,7 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_40 Your_png_h_is_not_version_1_6_40;
-
-#ifdef __GNUC__
-/* The version tests may need to be added to, but the problem warning has
- * consistently been fixed in GCC versions which obtain wide-spread release.
- * The problem is that many versions of GCC rearrange comparison expressions in
- * the optimizer in such a way that the results of the comparison will change
- * if signed integer overflow occurs.  Such comparisons are not permitted in
- * ANSI C90, however GCC isn't clever enough to work out that that do not occur
- * below in png_ascii_from_fp and png_muldiv, so it produces a warning with
- * -Wextra.  Unfortunately this is highly dependent on the optimizer and the
- * machine architecture so the warning comes and goes unpredictably and is
- * impossible to "fix", even were that a good idea.
- */
-#if __GNUC__ == 7 && __GNUC_MINOR__ == 1
-#define GCC_STRICT_OVERFLOW 1
-#endif /* GNU 7.1.x */
-#endif /* GNU */
-#ifndef GCC_STRICT_OVERFLOW
-#define GCC_STRICT_OVERFLOW 0
-#endif
+typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43;
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
@@ -101,21 +81,21 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
 int PNGAPI
 png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check)
 {
-   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+   static const png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
 
    if (num_to_check > 8)
       num_to_check = 8;
 
    else if (num_to_check < 1)
-      return (-1);
+      return -1;
 
    if (start > 7)
-      return (-1);
+      return -1;
 
    if (start + num_to_check > 8)
       num_to_check = 8 - start;
 
-   return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
+   return memcmp(&sig[start], &png_signature[start], num_to_check);
 }
 
 #endif /* READ */
@@ -475,7 +455,6 @@ png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size),
    memset(info_ptr, 0, (sizeof *info_ptr));
 }
 
-/* The following API is not called internally */
 void PNGAPI
 png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
     int freer, png_uint_32 mask)
@@ -714,9 +693,9 @@ png_voidp PNGAPI
 png_get_io_ptr(png_const_structrp png_ptr)
 {
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
-   return (png_ptr->io_ptr);
+   return png_ptr->io_ptr;
 }
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
@@ -780,7 +759,7 @@ png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
 
    {
       size_t pos = 0;
-      char number_buf[5]; /* enough for a four-digit year */
+      char number_buf[5] = {0, 0, 0, 0, 0}; /* enough for a four-digit year */
 
 #     define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
 #     define APPEND_NUMBER(format, value)\
@@ -843,8 +822,8 @@ png_get_copyright(png_const_structrp png_ptr)
    return PNG_STRING_COPYRIGHT
 #else
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.40" PNG_STRING_NEWLINE \
-      "Copyright (c) 2018-2023 Cosmin Truta" PNG_STRING_NEWLINE \
+      "libpng version 1.6.43" PNG_STRING_NEWLINE \
+      "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
       PNG_STRING_NEWLINE \
       "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@@ -1005,7 +984,7 @@ png_reset_zstream(png_structrp png_ptr)
       return Z_STREAM_ERROR;
 
    /* WARNING: this resets the window bits to the maximum! */
-   return (inflateReset(&png_ptr->zstream));
+   return inflateReset(&png_ptr->zstream);
 }
 #endif /* READ */
 
@@ -1014,7 +993,7 @@ png_uint_32 PNGAPI
 png_access_version_number(void)
 {
    /* Version of *.c files used when building libpng */
-   return((png_uint_32)PNG_LIBPNG_VER);
+   return (png_uint_32)PNG_LIBPNG_VER;
 }
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
@@ -1870,14 +1849,14 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
    }
 #  ifdef PNG_WARNINGS_SUPPORTED
    else
-      {
-         char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
+   {
+      char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
 
-         pos = png_safecat(message, (sizeof message), pos,
-             png_format_number(number, number+(sizeof number),
-             PNG_NUMBER_FORMAT_x, value));
-         pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
-      }
+      pos = png_safecat(message, (sizeof message), pos,
+          png_format_number(number, number+(sizeof number),
+          PNG_NUMBER_FORMAT_x, value));
+      pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
+   }
 #  endif
    /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
    pos = png_safecat(message, (sizeof message), pos, reason);
@@ -2560,17 +2539,6 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
 
 #endif /* COLORSPACE */
 
-#ifdef __GNUC__
-/* This exists solely to work round a warning from GNU C. */
-static int /* PRIVATE */
-png_gt(size_t a, size_t b)
-{
-   return a > b;
-}
-#else
-#   define png_gt(a,b) ((a) > (b))
-#endif
-
 void /* PRIVATE */
 png_check_IHDR(png_const_structrp png_ptr,
     png_uint_32 width, png_uint_32 height, int bit_depth,
@@ -2592,8 +2560,16 @@ png_check_IHDR(png_const_structrp png_ptr,
       error = 1;
    }
 
-   if (png_gt(((width + 7) & (~7U)),
-       ((PNG_SIZE_MAX
+   /* The bit mask on the first line below must be at least as big as a
+    * png_uint_32.  "~7U" is not adequate on 16-bit systems because it will
+    * be an unsigned 16-bit value.  Casting to (png_alloc_size_t) makes the
+    * type of the result at least as bit (in bits) as the RHS of the > operator
+    * which also avoids a common warning on 64-bit systems that the comparison
+    * of (png_uint_32) against the constant value on the RHS will always be
+    * false.
+    */
+   if (((width + 7) & ~(png_alloc_size_t)7) >
+       (((PNG_SIZE_MAX
            - 48        /* big_row_buf hack */
            - 1)        /* filter byte */
            / 8)        /* 8-byte RGBA pixels */
@@ -2919,14 +2895,6 @@ png_pow10(int power)
 /* Function to format a floating point value in ASCII with a given
  * precision.
  */
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic push
-/* The problem arises below with exp_b10, which can never overflow because it
- * comes, originally, from frexp and is therefore limited to a range which is
- * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)).
- */
-#pragma GCC diagnostic warning "-Wstrict-overflow=2"
-#endif /* GCC_STRICT_OVERFLOW */
 void /* PRIVATE */
 png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
     double fp, unsigned int precision)
@@ -3248,10 +3216,6 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
    /* Here on buffer too small. */
    png_error(png_ptr, "ASCII conversion buffer too small");
 }
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic pop
-#endif /* GCC_STRICT_OVERFLOW */
-
 #  endif /* FLOATING_POINT */
 
 #  ifdef PNG_FIXED_POINT_SUPPORTED
@@ -3279,7 +3243,7 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
       if (num <= 0x80000000) /* else overflowed */
       {
          unsigned int ndigits = 0, first = 16 /* flag value */;
-         char digits[10];
+         char digits[10] = {0};
 
          while (num)
          {
@@ -3364,15 +3328,6 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
  * the nearest .00001).  Overflow and divide by zero are signalled in
  * the result, a boolean - true on success, false on overflow.
  */
-#if GCC_STRICT_OVERFLOW /* from above */
-/* It is not obvious which comparison below gets optimized in such a way that
- * signed overflow would change the result; looking through the code does not
- * reveal any tests which have the form GCC complains about, so presumably the
- * optimizer is moving an add or subtract into the 'if' somewhere.
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wstrict-overflow=2"
-#endif /* GCC_STRICT_OVERFLOW */
 int
 png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
     png_int_32 divisor)
@@ -3487,9 +3442,6 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
 
    return 0;
 }
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic pop
-#endif /* GCC_STRICT_OVERFLOW */
 #endif /* READ_GAMMA || INCH_CONVERSIONS */
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.h b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
index 578841c958049..9f61a773c1ddb 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
@@ -29,9 +29,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.40
+ * libpng version 1.6.43
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -43,7 +43,7 @@
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
  *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
  *     Glenn Randers-Pehrson
- *   libpng versions 1.6.36, December 2018, through 1.6.40, June 2023:
+ *   libpng versions 1.6.36, December 2018, through 1.6.43, February 2024:
  *     Cosmin Truta
  *   See also "Contributing Authors", below.
  */
@@ -55,8 +55,8 @@
  * PNG Reference Library License version 2
  * ---------------------------------------
  *
- *  * Copyright (c) 1995-2023 The PNG Reference Library Authors.
- *  * Copyright (c) 2018-2023 Cosmin Truta.
+ *  * Copyright (c) 1995-2024 The PNG Reference Library Authors.
+ *  * Copyright (c) 2018-2024 Cosmin Truta.
  *  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  *  * Copyright (c) 1996-1997 Andreas Dilger.
  *  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -267,7 +267,7 @@
  *    ...
  *    1.5.30                  15    10530  15.so.15.30[.0]
  *    ...
- *    1.6.40                  16    10640  16.so.16.40[.0]
+ *    1.6.43                  16    10643  16.so.16.43[.0]
  *
  *    Henceforth the source version will match the shared-library major and
  *    minor numbers; the shared-library major version number will be used for
@@ -283,9 +283,6 @@
  *    to the info_ptr or png_ptr members through png.h, and the compiled
  *    application is loaded with a different version of the library.
  *
- *    DLLNUM will change each time there are forward or backward changes
- *    in binary compatibility (e.g., when a new feature is added).
- *
  * See libpng.txt or libpng.3 for more information.  The PNG specification
  * is available as a W3C Recommendation and as an ISO/IEC Standard; see
  * 
@@ -306,19 +303,21 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.40"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.40 - June 21, 2023\n"
+#define PNG_LIBPNG_VER_STRING "1.6.43"
+#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
 
-#define PNG_LIBPNG_VER_SONUM   16
-#define PNG_LIBPNG_VER_DLLNUM  16
+/* The versions of shared library builds should stay in sync, going forward */
+#define PNG_LIBPNG_VER_SHAREDLIB 16
+#define PNG_LIBPNG_VER_SONUM     PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */
+#define PNG_LIBPNG_VER_DLLNUM    PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */
 
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 40
+#define PNG_LIBPNG_VER_RELEASE 43
 
 /* This should be zero for a public release, or non-zero for a
- * development version.  [Deprecated]
+ * development version.
  */
 #define PNG_LIBPNG_VER_BUILD  0
 
@@ -346,7 +345,7 @@
  * From version 1.0.1 it is:
  * XXYYZZ, where XX=major, YY=minor, ZZ=release
  */
-#define PNG_LIBPNG_VER 10640 /* 1.6.40 */
+#define PNG_LIBPNG_VER 10643 /* 1.6.43 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -456,7 +455,7 @@ extern "C" {
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char* png_libpng_version_1_6_40;
+typedef char* png_libpng_version_1_6_43;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -877,7 +876,7 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
 #define PNG_TRANSFORM_GRAY_TO_RGB   0x2000      /* read only */
 /* Added to libpng-1.5.4 */
 #define PNG_TRANSFORM_EXPAND_16     0x4000      /* read only */
-#if INT_MAX >= 0x8000 /* else this might break */
+#if ~0U > 0xffffU /* or else this might break on a 16-bit machine */
 #define PNG_TRANSFORM_SCALE_16      0x8000      /* read only */
 #endif
 
@@ -936,15 +935,15 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
 /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
  * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
  * signature, and non-zero otherwise.  Having num_to_check == 0 or
- * start > 7 will always fail (ie return non-zero).
+ * start > 7 will always fail (i.e. return non-zero).
  */
 PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start,
     size_t num_to_check));
 
 /* Simple signature checking function.  This is the same as calling
- * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
+ * png_check_sig(sig, n) := (png_sig_cmp(sig, 0, n) == 0).
  */
-#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n))
+#define png_check_sig(sig, n) (png_sig_cmp((sig), 0, (n)) == 0) /* DEPRECATED */
 
 /* Allocate and initialize png_ptr struct for reading, and any other memory. */
 PNG_EXPORTA(4, png_structp, png_create_read_struct,
@@ -1758,12 +1757,9 @@ PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr));
 PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr,
     png_inforp info_ptr, png_uint_32 free_me, int num));
 
-/* Reassign responsibility for freeing existing data, whether allocated
+/* Reassign the responsibility for freeing existing data, whether allocated
  * by libpng or by the application; this works on the png_info structure passed
- * in, it does not change the state for other png_info structures.
- *
- * It is unlikely that this function works correctly as of 1.6.0 and using it
- * may result either in memory leaks or double free of allocated data.
+ * in, without changing the state for other png_info structures.
  */
 PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
     png_inforp info_ptr, int freer, png_uint_32 mask));
@@ -3235,11 +3231,18 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
 #ifdef PNG_MIPS_MSA_API_SUPPORTED
 #  define PNG_MIPS_MSA   6 /* HARDWARE: MIPS Msa SIMD instructions supported */
 #endif
-#define PNG_IGNORE_ADLER32 8
+#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
+#  define PNG_IGNORE_ADLER32 8 /* SOFTWARE: disable Adler32 check on IDAT */
+#endif
 #ifdef PNG_POWERPC_VSX_API_SUPPORTED
-#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions supported */
+#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions
+                                * supported */
 #endif
-#define PNG_OPTION_NEXT  12 /* Next option - numbers must be even */
+#ifdef PNG_MIPS_MMI_API_SUPPORTED
+#  define PNG_MIPS_MMI   12 /* HARDWARE: MIPS MMI SIMD instructions supported */
+#endif
+
+#define PNG_OPTION_NEXT  14 /* Next option - numbers must be even */
 
 /* Return values: NOTE: there are four values and 'off' is *not* zero */
 #define PNG_OPTION_UNSET   0 /* Unset - defaults to off */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
index 41cbc91d39861..b3b441b1122c2 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
@@ -29,9 +29,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.40
+ * libpng version 1.6.43
  *
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
index 623735f06f12b..ea8dd1721972c 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -283,7 +283,7 @@ void
 png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
     png_alloc_size_t value)
 {
-   char buffer[PNG_NUMBER_BUFFER_SIZE];
+   char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
    png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
 }
 
@@ -293,7 +293,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format,
 {
    png_alloc_size_t u;
    png_charp str;
-   char buffer[PNG_NUMBER_BUFFER_SIZE];
+   char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
 
    /* Avoid overflow by doing the negate in a png_alloc_size_t: */
    u = (png_alloc_size_t)value;
@@ -886,7 +886,7 @@ png_get_error_ptr(png_const_structrp png_ptr)
    if (png_ptr == NULL)
       return NULL;
 
-   return ((png_voidp)png_ptr->error_ptr);
+   return (png_voidp)png_ptr->error_ptr;
 }
 
 
@@ -961,31 +961,25 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
 #endif
 
 int /* PRIVATE */
-png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
+png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
 {
-   volatile png_imagep image = image_in;
-   volatile int result;
-   volatile png_voidp saved_error_buf;
+   png_voidp saved_error_buf = image->opaque->error_buf;
    jmp_buf safe_jmpbuf;
+   int result;
 
-   /* Safely execute function(arg) with png_error returning to this function. */
-   saved_error_buf = image->opaque->error_buf;
-   result = setjmp(safe_jmpbuf) == 0;
-
-   if (result != 0)
+   /* Safely execute function(arg), with png_error returning back here. */
+   if (setjmp(safe_jmpbuf) == 0)
    {
-
       image->opaque->error_buf = safe_jmpbuf;
       result = function(arg);
+      image->opaque->error_buf = saved_error_buf;
+      return result;
    }
 
+   /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */
    image->opaque->error_buf = saved_error_buf;
-
-   /* And do the cleanup prior to any failure return. */
-   if (result == 0)
-      png_image_free(image);
-
-   return result;
+   png_image_free(image);
+   return 0;
 }
 #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
 #endif /* READ || WRITE */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
index 6e510b2732751..41e0a5abc3a8d 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -56,22 +56,22 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
        * valid tRNS chunk in this case.
        */
       if (flag == PNG_INFO_tRNS && png_ptr->num_trans == 0)
-         return(0);
+         return 0;
 #endif
 
-      return(info_ptr->valid & flag);
+      return info_ptr->valid & flag;
    }
 
-   return(0);
+   return 0;
 }
 
 size_t PNGAPI
 png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->rowbytes);
+      return info_ptr->rowbytes;
 
-   return(0);
+   return 0;
 }
 
 #ifdef PNG_INFO_IMAGE_SUPPORTED
@@ -79,9 +79,9 @@ png_bytepp PNGAPI
 png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->row_pointers);
+      return info_ptr->row_pointers;
 
-   return(0);
+   return 0;
 }
 #endif
 
@@ -93,7 +93,7 @@ png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->width;
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -102,7 +102,7 @@ png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->height;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -111,7 +111,7 @@ png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->bit_depth;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -120,7 +120,7 @@ png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->color_type;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -129,7 +129,7 @@ png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->filter_type;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -138,7 +138,7 @@ png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->interlace_type;
 
-   return (0);
+   return 0;
 }
 
 png_byte PNGAPI
@@ -147,7 +147,7 @@ png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return info_ptr->compression_type;
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -155,21 +155,20 @@ png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
    info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
+   png_debug(1, "in png_get_x_pixels_per_meter");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
-      {
-         png_debug1(1, "in %s retrieval function",
-             "png_get_x_pixels_per_meter");
-
-         if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
-            return (info_ptr->x_pixels_per_unit);
-      }
+   {
+      if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
+         return info_ptr->x_pixels_per_unit;
+   }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -177,42 +176,41 @@ png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
     info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
+   png_debug(1, "in png_get_y_pixels_per_meter");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function",
-          "png_get_y_pixels_per_meter");
-
       if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
-         return (info_ptr->y_pixels_per_unit);
+         return info_ptr->y_pixels_per_unit;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
 png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_pHYs_SUPPORTED
+   png_debug(1, "in png_get_pixels_per_meter");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
-
       if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER &&
           info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
-         return (info_ptr->x_pixels_per_unit);
+         return info_ptr->x_pixels_per_unit;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
@@ -221,21 +219,21 @@ png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
    info_ptr)
 {
 #ifdef PNG_READ_pHYs_SUPPORTED
+   png_debug(1, "in png_get_pixel_aspect_ratio");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
-
       if (info_ptr->x_pixels_per_unit != 0)
-         return ((float)((float)info_ptr->y_pixels_per_unit
-             /(float)info_ptr->x_pixels_per_unit));
+         return (float)info_ptr->y_pixels_per_unit
+              / (float)info_ptr->x_pixels_per_unit;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return ((float)0.0);
+   return (float)0.0;
 }
 #endif
 
@@ -245,6 +243,8 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
     png_const_inforp info_ptr)
 {
 #ifdef PNG_READ_pHYs_SUPPORTED
+   png_debug(1, "in png_get_pixel_aspect_ratio_fixed");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
        info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
@@ -253,8 +253,6 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
    {
       png_fixed_point res;
 
-      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed");
-
       /* The following casts work because a PNG 4 byte integer only has a valid
        * range of 0..2^31-1; otherwise the cast might overflow.
        */
@@ -275,80 +273,80 @@ png_int_32 PNGAPI
 png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_x_offset_microns");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-         return (info_ptr->x_offset);
+         return info_ptr->x_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_int_32 PNGAPI
 png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_y_offset_microns");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-         return (info_ptr->y_offset);
+         return info_ptr->y_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_int_32 PNGAPI
 png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_x_offset_pixels");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-         return (info_ptr->x_offset);
+         return info_ptr->x_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 png_int_32 PNGAPI
 png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
 #ifdef PNG_oFFs_SUPPORTED
+   png_debug(1, "in png_get_y_offset_pixels");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_oFFs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
-
       if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-         return (info_ptr->y_offset);
+         return info_ptr->y_offset;
    }
 #else
    PNG_UNUSED(png_ptr)
    PNG_UNUSED(info_ptr)
 #endif
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_INCH_CONVERSIONS_SUPPORTED
@@ -462,11 +460,11 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
 {
    png_uint_32 retval = 0;
 
+   png_debug1(1, "in %s retrieval function", "pHYs");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_pHYs) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "pHYs");
-
       if (res_x != NULL)
       {
          *res_x = info_ptr->x_pixels_per_unit;
@@ -492,7 +490,7 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
       }
    }
 
-   return (retval);
+   return retval;
 }
 #endif /* pHYs */
 #endif /* INCH_CONVERSIONS */
@@ -506,9 +504,9 @@ png_byte PNGAPI
 png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->channels);
+      return info_ptr->channels;
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_READ_SUPPORTED
@@ -516,9 +514,9 @@ png_const_bytep PNGAPI
 png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->signature);
+      return info_ptr->signature;
 
-   return (NULL);
+   return NULL;
 }
 #endif
 
@@ -527,17 +525,17 @@ png_uint_32 PNGAPI
 png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
     png_color_16p *background)
 {
+   png_debug1(1, "in %s retrieval function", "bKGD");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
        background != NULL)
    {
-      png_debug1(1, "in %s retrieval function", "bKGD");
-
       *background = &(info_ptr->background);
-      return (PNG_INFO_bKGD);
+      return PNG_INFO_bKGD;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -552,6 +550,8 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
     double *white_x, double *white_y, double *red_x, double *red_y,
     double *green_x, double *green_y, double *blue_x, double *blue_y)
 {
+   png_debug1(1, "in %s retrieval function", "cHRM");
+
    /* Quiet API change: this code used to only return the end points if a cHRM
     * chunk was present, but the end points can also come from iCCP or sRGB
     * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
@@ -561,8 +561,6 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
    if (png_ptr != NULL && info_ptr != NULL &&
       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "cHRM");
-
       if (white_x != NULL)
          *white_x = png_float(png_ptr,
              info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
@@ -587,10 +585,10 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
       if (blue_y != NULL)
          *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
              "cHRM blue Y");
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -599,11 +597,11 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
     double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
     double *blue_Z)
 {
+   png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
-
       if (red_X != NULL)
          *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
              "cHRM red X");
@@ -631,10 +629,10 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
       if (blue_Z != NULL)
          *blue_Z = png_float(png_ptr,
              info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 
@@ -647,11 +645,11 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
     png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
     png_fixed_point *int_blue_Z)
 {
+   png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
+
    if (png_ptr != NULL && info_ptr != NULL &&
       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
-
       if (int_red_X != NULL)
          *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
       if (int_red_Y != NULL)
@@ -670,10 +668,10 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
          *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
       if (int_blue_Z != NULL)
          *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 
 png_uint_32 PNGAPI
@@ -703,10 +701,10 @@ png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
          *blue_x = info_ptr->colorspace.end_points_xy.bluex;
       if (blue_y != NULL)
          *blue_y = info_ptr->colorspace.end_points_xy.bluey;
-      return (PNG_INFO_cHRM);
+      return PNG_INFO_cHRM;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 #endif
@@ -724,10 +722,10 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
        file_gamma != NULL)
    {
       *file_gamma = info_ptr->colorspace.gamma;
-      return (PNG_INFO_gAMA);
+      return PNG_INFO_gAMA;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 
@@ -744,10 +742,10 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
    {
       *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
           "png_get_gAMA");
-      return (PNG_INFO_gAMA);
+      return PNG_INFO_gAMA;
    }
 
-   return (0);
+   return 0;
 }
 #  endif
 #endif
@@ -763,10 +761,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
       (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
    {
       *file_srgb_intent = info_ptr->colorspace.rendering_intent;
-      return (PNG_INFO_sRGB);
+      return PNG_INFO_sRGB;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -790,10 +788,10 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
        */
       if (compression_type != NULL)
          *compression_type = PNG_COMPRESSION_TYPE_BASE;
-      return (PNG_INFO_iCCP);
+      return PNG_INFO_iCCP;
    }
 
-   return (0);
+   return 0;
 
 }
 #endif
@@ -803,13 +801,15 @@ int PNGAPI
 png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
     png_sPLT_tpp spalettes)
 {
+   png_debug1(1, "in %s retrieval function", "sPLT");
+
    if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
    {
       *spalettes = info_ptr->splt_palettes;
       return info_ptr->splt_palettes_num;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -835,10 +835,10 @@ png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr,
    {
       *num_exif = info_ptr->num_exif;
       *exif = info_ptr->exif;
-      return (PNG_INFO_eXIf);
+      return PNG_INFO_eXIf;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -853,10 +853,10 @@ png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
        (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
    {
       *hist = info_ptr->hist;
-      return (PNG_INFO_hIST);
+      return PNG_INFO_hIST;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -869,7 +869,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
    png_debug1(1, "in %s retrieval function", "IHDR");
 
    if (png_ptr == NULL || info_ptr == NULL)
-      return (0);
+      return 0;
 
    if (width != NULL)
        *width = info_ptr->width;
@@ -901,7 +901,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
        info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
        info_ptr->compression_type, info_ptr->filter_type);
 
-   return (1);
+   return 1;
 }
 
 #ifdef PNG_oFFs_SUPPORTED
@@ -918,10 +918,10 @@ png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr,
       *offset_x = info_ptr->x_offset;
       *offset_y = info_ptr->y_offset;
       *unit_type = (int)info_ptr->offset_unit_type;
-      return (PNG_INFO_oFFs);
+      return PNG_INFO_oFFs;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -945,10 +945,10 @@ png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
       *nparams = (int)info_ptr->pcal_nparams;
       *units = info_ptr->pcal_units;
       *params = info_ptr->pcal_params;
-      return (PNG_INFO_pCAL);
+      return PNG_INFO_pCAL;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -960,6 +960,8 @@ png_uint_32 PNGAPI
 png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
     int *unit, png_fixed_point *width, png_fixed_point *height)
 {
+   png_debug1(1, "in %s retrieval function", "sCAL");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_sCAL) != 0)
    {
@@ -971,10 +973,10 @@ png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
       *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
       *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
           "sCAL height");
-      return (PNG_INFO_sCAL);
+      return PNG_INFO_sCAL;
    }
 
-   return(0);
+   return 0;
 }
 #    endif /* FLOATING_ARITHMETIC */
 #  endif /* FIXED_POINT */
@@ -983,32 +985,36 @@ png_uint_32 PNGAPI
 png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr,
     int *unit, double *width, double *height)
 {
+   png_debug1(1, "in %s retrieval function", "sCAL(float)");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_sCAL) != 0)
    {
       *unit = info_ptr->scal_unit;
       *width = atof(info_ptr->scal_s_width);
       *height = atof(info_ptr->scal_s_height);
-      return (PNG_INFO_sCAL);
+      return PNG_INFO_sCAL;
    }
 
-   return(0);
+   return 0;
 }
 #  endif /* FLOATING POINT */
 png_uint_32 PNGAPI
 png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr,
     int *unit, png_charpp width, png_charpp height)
 {
+   png_debug1(1, "in %s retrieval function", "sCAL(str)");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_sCAL) != 0)
    {
       *unit = info_ptr->scal_unit;
       *width = info_ptr->scal_s_width;
       *height = info_ptr->scal_s_height;
-      return (PNG_INFO_sCAL);
+      return PNG_INFO_sCAL;
    }
 
-   return(0);
+   return 0;
 }
 #endif /* sCAL */
 
@@ -1043,7 +1049,7 @@ png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr,
       }
    }
 
-   return (retval);
+   return retval;
 }
 #endif /* pHYs */
 
@@ -1059,10 +1065,10 @@ png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr,
       *palette = info_ptr->palette;
       *num_palette = info_ptr->num_palette;
       png_debug1(3, "num_palette = %d", *num_palette);
-      return (PNG_INFO_PLTE);
+      return PNG_INFO_PLTE;
    }
 
-   return (0);
+   return 0;
 }
 
 #ifdef PNG_sBIT_SUPPORTED
@@ -1076,10 +1082,10 @@ png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
        (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
    {
       *sig_bit = &(info_ptr->sig_bit);
-      return (PNG_INFO_sBIT);
+      return PNG_INFO_sBIT;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -1090,7 +1096,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
 {
    if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
    {
-      png_debug1(1, "in 0x%lx retrieval function",
+      png_debug1(1, "in text retrieval function, chunk typeid = 0x%lx",
          (unsigned long)png_ptr->chunk_name);
 
       if (text_ptr != NULL)
@@ -1105,7 +1111,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
    if (num_text != NULL)
       *num_text = 0;
 
-   return(0);
+   return 0;
 }
 #endif
 
@@ -1120,10 +1126,10 @@ png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
        (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
    {
       *mod_time = &(info_ptr->mod_time);
-      return (PNG_INFO_tIME);
+      return PNG_INFO_tIME;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -1133,11 +1139,12 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
     png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
 {
    png_uint_32 retval = 0;
+
+   png_debug1(1, "in %s retrieval function", "tRNS");
+
    if (png_ptr != NULL && info_ptr != NULL &&
        (info_ptr->valid & PNG_INFO_tRNS) != 0)
    {
-      png_debug1(1, "in %s retrieval function", "tRNS");
-
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       {
          if (trans_alpha != NULL)
@@ -1169,7 +1176,7 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
       }
    }
 
-   return (retval);
+   return retval;
 }
 #endif
 
@@ -1184,7 +1191,7 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
       return info_ptr->unknown_chunks_num;
    }
 
-   return (0);
+   return 0;
 }
 #endif
 
@@ -1280,7 +1287,7 @@ png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
    if (png_ptr != NULL && info_ptr != NULL)
       return png_ptr->num_palette_max;
 
-   return (-1);
+   return -1;
 }
 #  endif
 #endif
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
index e98d49cf0ccd9..e238ccdb9a4d9 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
@@ -31,7 +31,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  */
-/* libpng version 1.6.40 */
+/* libpng version 1.6.43 */
 
 /* Copyright (c) 2018-2023 Cosmin Truta */
 /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
index a98b201325612..816631cae189b 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -173,10 +173,10 @@ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
        num_to_check);
    png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
 
-   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
    {
       if (num_checked < 4 &&
-          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
          png_error(png_ptr, "Not a PNG file");
 
       else
@@ -322,6 +322,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
       png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
    }
 
+#endif
+#ifdef PNG_READ_eXIf_SUPPORTED
+   else if (png_ptr->chunk_name == png_eXIf)
+   {
+      PNG_PUSH_SAVE_BUFFER_IF_FULL
+      png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
+   }
+
 #endif
 #ifdef PNG_READ_sRGB_SUPPORTED
    else if (chunk_name == png_sRGB)
@@ -1117,7 +1125,7 @@ png_voidp PNGAPI
 png_get_progressive_ptr(png_const_structrp png_ptr)
 {
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
    return png_ptr->io_ptr;
 }
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
index 914d0b97b1da9..18424542b00bf 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -64,7 +64,7 @@
  * still required (as of 2011-05-02.)
  */
 #ifndef _POSIX_SOURCE
-# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
+#  define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
 #endif
 
 #ifndef PNG_VERSION_INFO_ONLY
@@ -218,13 +218,27 @@
 #endif /* PNG_ARM_NEON_OPT > 0 */
 
 #ifndef PNG_MIPS_MSA_OPT
-#  if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
+#  if defined(__mips_msa) && (__mips_isa_rev >= 5) && \
+   defined(PNG_ALIGNED_MEMORY_SUPPORTED)
 #     define PNG_MIPS_MSA_OPT 2
 #  else
 #     define PNG_MIPS_MSA_OPT 0
 #  endif
 #endif
 
+#ifndef PNG_MIPS_MMI_OPT
+#  ifdef PNG_MIPS_MMI
+#    if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64) && \
+     defined(PNG_ALIGNED_MEMORY_SUPPORTED)
+#       define PNG_MIPS_MMI_OPT 1
+#    else
+#       define PNG_MIPS_MMI_OPT 0
+#    endif
+#  else
+#    define PNG_MIPS_MMI_OPT 0
+#  endif
+#endif
+
 #ifndef PNG_POWERPC_VSX_OPT
 #  if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
 #     define PNG_POWERPC_VSX_OPT 2
@@ -233,13 +247,21 @@
 #  endif
 #endif
 
+#ifndef PNG_LOONGARCH_LSX_OPT
+#  if defined(__loongarch_sx)
+#     define PNG_LOONGARCH_LSX_OPT 1
+#  else
+#     define PNG_LOONGARCH_LSX_OPT 0
+#  endif
+#endif
+
 #ifndef PNG_INTEL_SSE_OPT
 #   ifdef PNG_INTEL_SSE
       /* Only check for SSE if the build configuration has been modified to
        * enable SSE optimizations.  This means that these optimizations will
        * be off by default.  See contrib/intel for more details.
        */
-#     if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
+#      if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
        defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
        (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
 #         define PNG_INTEL_SSE_OPT 1
@@ -276,7 +298,6 @@
 #endif
 
 #if PNG_MIPS_MSA_OPT > 0
-#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa
 #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
 #     if defined(__mips_msa)
 #        if defined(__clang__)
@@ -292,11 +313,28 @@
 
 #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
 #     define PNG_MIPS_MSA_IMPLEMENTATION 1
+#     define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips
 #  endif
 #else
 #  define PNG_MIPS_MSA_IMPLEMENTATION 0
 #endif /* PNG_MIPS_MSA_OPT > 0 */
 
+#if PNG_MIPS_MMI_OPT > 0
+#  ifndef PNG_MIPS_MMI_IMPLEMENTATION
+#     if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64)
+#        define PNG_MIPS_MMI_IMPLEMENTATION 2
+#     else /* !defined __mips_loongson_mmi  || _MIPS_SIM != _ABI64 */
+#        define PNG_MIPS_MMI_IMPLEMENTATION 0
+#     endif /* __mips_loongson_mmi  && _MIPS_SIM == _ABI64 */
+#  endif /* !PNG_MIPS_MMI_IMPLEMENTATION */
+
+#   if PNG_MIPS_MMI_IMPLEMENTATION > 0
+#      define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips
+#   endif
+#else
+#   define PNG_MIPS_MMI_IMPLEMENTATION 0
+#endif /* PNG_MIPS_MMI_OPT > 0 */
+
 #if PNG_POWERPC_VSX_OPT > 0
 #  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
 #  define PNG_POWERPC_VSX_IMPLEMENTATION 1
@@ -304,6 +342,12 @@
 #  define PNG_POWERPC_VSX_IMPLEMENTATION 0
 #endif
 
+#if PNG_LOONGARCH_LSX_OPT > 0
+#   define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_lsx
+#   define PNG_LOONGARCH_LSX_IMPLEMENTATION 1
+#else
+#   define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
+#endif
 
 /* Is this a build of a DLL where compilation of the object modules requires
  * different preprocessor settings to those required for a simple library?  If
@@ -542,18 +586,8 @@
     */
 #  include 
 
-#  if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
-    defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
-   /* We need to check that  hasn't already been included earlier
-    * as it seems it doesn't agree with , yet we should really use
-    *  if possible.
-    */
-#    if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
-#      include 
-#    endif
-#  else
-#    include 
-#  endif
+#  include 
+
 #  if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
    /* Amiga SAS/C: We must include builtin FPU functions when compiling using
     * MATH=68881
@@ -1334,7 +1368,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 #endif
 
-#if PNG_MIPS_MSA_OPT > 0
+#if PNG_MIPS_MSA_IMPLEMENTATION == 1
 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info,
     png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop
@@ -1351,6 +1385,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 #endif
 
+#if PNG_MIPS_MMI_IMPLEMENTATION > 0
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_mmi,(png_row_infop row_info,
+    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_mmi,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+#endif
+
 #if PNG_POWERPC_VSX_OPT > 0
 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info,
     png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
@@ -1383,6 +1434,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 #endif
 
+#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+#endif
+
 /* Choose the best filter to use and filter the row data */
 PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
     png_row_infop row_info),PNG_EMPTY);
@@ -2122,17 +2190,27 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #endif
 
-#if PNG_MIPS_MSA_OPT > 0
-PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa,
+#if PNG_MIPS_MSA_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #endif
 
+#  if PNG_MIPS_MMI_IMPLEMENTATION > 0
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
+   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+#  endif
+
 #  if PNG_INTEL_SSE_IMPLEMENTATION > 0
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #  endif
 #endif
 
+#if PNG_LOONGARCH_LSX_OPT > 0
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx,
+    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+#endif
+
 PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
    png_const_charp key, png_bytep new_key), PNG_EMPTY);
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
index 3631e60f36ba2..e9e9447754523 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -596,7 +596,11 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
 #endif
 
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
-   if (png_ptr->transformations)
+   if (png_ptr->transformations
+#     ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+         || png_ptr->num_palette_max >= 0
+#     endif
+      )
       png_do_read_transformations(png_ptr, &row_info);
 #endif
 
@@ -813,7 +817,7 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
 #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
    /* Report invalid palette index; added at libng-1.5.10 */
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-       png_ptr->num_palette_max > png_ptr->num_palette)
+       png_ptr->num_palette_max >= png_ptr->num_palette)
       png_benign_error(png_ptr, "Read palette index exceeding num_palette");
 #endif
 
@@ -1077,6 +1081,8 @@ void PNGAPI
 png_read_png(png_structrp png_ptr, png_inforp info_ptr,
     int transforms, voidp params)
 {
+   png_debug(1, "in png_read_png");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
index 843eb5fff2adb..a393de4b79d07 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -318,21 +318,20 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
    int compose = 0;
    png_fixed_point file_gamma;
 
-   png_debug(1, "in png_set_alpha_mode");
+   png_debug(1, "in png_set_alpha_mode_fixed");
 
    if (png_rtran_ok(png_ptr, 0) == 0)
       return;
 
    output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
 
-   /* Validate the value to ensure it is in a reasonable range. The value
+   /* Validate the value to ensure it is in a reasonable range.  The value
     * is expected to be 1 or greater, but this range test allows for some
-    * viewing correction values.  The intent is to weed out users of this API
-    * who use the inverse of the gamma value accidentally!  Since some of these
-    * values are reasonable this may have to be changed:
+    * viewing correction values.  The intent is to weed out the API users
+    * who might use the inverse of the gamma value accidentally!
     *
-    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit
-    * gamma of 36, and its reciprocal.)
+    * In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate
+    * the optimal 16-bit gamma of 36 and its reciprocal.
     */
    if (output_gamma < 1000 || output_gamma > 10000000)
       png_error(png_ptr, "output gamma out of expected range");
@@ -469,7 +468,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
       int i;
 
       png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
-          (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
+          (png_alloc_size_t)num_palette);
       for (i = 0; i < num_palette; i++)
          png_ptr->quantize_index[i] = (png_byte)i;
    }
@@ -486,7 +485,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
 
          /* Initialize an array to sort colors */
          png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
+             (png_alloc_size_t)num_palette);
 
          /* Initialize the quantize_sort array */
          for (i = 0; i < num_palette; i++)
@@ -620,11 +619,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
 
          /* Initialize palette index arrays */
          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette *
-             (sizeof (png_byte))));
+             (png_alloc_size_t)num_palette);
          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette *
-             (sizeof (png_byte))));
+             (png_alloc_size_t)num_palette);
 
          /* Initialize the sort array */
          for (i = 0; i < num_palette; i++)
@@ -789,12 +786,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
       size_t num_entries = ((size_t)1 << total_bits);
 
       png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
-          (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
+          (png_alloc_size_t)(num_entries));
 
-      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
-          (sizeof (png_byte))));
+      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)num_entries);
 
-      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
+      memset(distance, 0xff, num_entries);
 
       for (i = 0; i < num_palette; i++)
       {
@@ -998,7 +994,7 @@ void PNGFAPI
 png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
     png_fixed_point red, png_fixed_point green)
 {
-   png_debug(1, "in png_set_rgb_to_gray");
+   png_debug(1, "in png_set_rgb_to_gray_fixed");
 
    /* Need the IHDR here because of the check on color_type below. */
    /* TODO: fix this */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
index 524297c5a10b7..5280140d12bcb 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2022 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -54,7 +54,7 @@ png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
    if (uval > PNG_UINT_31_MAX)
       png_error(png_ptr, "PNG unsigned integer out of range");
 
-   return (uval);
+   return uval;
 }
 
 #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
@@ -168,7 +168,7 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
    {
       if (num_checked < 4 &&
-          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
          png_error(png_ptr, "Not a PNG file");
       else
          png_error(png_ptr, "PNG file corrupted by ASCII conversion");
@@ -199,7 +199,7 @@ png_read_chunk_header(png_structrp png_ptr)
    /* Put the chunk name into png_ptr->chunk_name. */
    png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
 
-   png_debug2(0, "Reading %lx chunk, length = %lu",
+   png_debug2(0, "Reading chunk typeid = 0x%lx, length = %lu",
        (unsigned long)png_ptr->chunk_name, (unsigned long)length);
 
    /* Reset the crc and run it over the chunk name. */
@@ -266,10 +266,10 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
       else
          png_chunk_error(png_ptr, "CRC error");
 
-      return (1);
+      return 1;
    }
 
-   return (0);
+   return 0;
 }
 
 /* Compare the CRC stored in the PNG file with that calculated by libpng from
@@ -305,11 +305,11 @@ png_crc_error(png_structrp png_ptr)
    if (need_crc != 0)
    {
       crc = png_get_uint_32(crc_bytes);
-      return ((int)(crc != png_ptr->crc));
+      return crc != png_ptr->crc;
    }
 
    else
-      return (0);
+      return 0;
 }
 
 #if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
@@ -449,8 +449,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
             png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
       }
 
-#if ZLIB_VERNUM >= 0x1290 && \
-   defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32)
+#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
       if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON)
          /* Turn off validation of the ADLER32 checksum in IDAT chunks */
          ret = inflateValidate(&png_ptr->zstream, 0);
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
index 62612a0227893..f53ab6fa1d18f 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2023 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -791,11 +791,11 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
 {
    int i;
 
-   png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
-      (unsigned long)png_ptr->chunk_name);
+   png_debug1(1, "in text storage function, chunk typeid = 0x%lx",
+      png_ptr == NULL ? 0xabadca11UL : (unsigned long)png_ptr->chunk_name);
 
    if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
-      return(0);
+      return 0;
 
    /* Make sure we have enough space in the "text" array in info_struct
     * to hold all of the incoming text_ptr objects.  This compare can't overflow
@@ -975,7 +975,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
       png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
    }
 
-   return(0);
+   return 0;
 }
 #endif
 
@@ -1091,6 +1091,8 @@ png_set_sPLT(png_const_structrp png_ptr,
 {
    png_sPLT_tp np;
 
+   png_debug1(1, "in %s storage function", "sPLT");
+
    if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
       return;
 
@@ -1565,7 +1567,7 @@ void PNGAPI
 png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
     png_bytepp row_pointers)
 {
-   png_debug1(1, "in %s storage function", "rows");
+   png_debug(1, "in png_set_rows");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
@@ -1584,6 +1586,8 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
 void PNGAPI
 png_set_compression_buffer_size(png_structrp png_ptr, size_t size)
 {
+   png_debug(1, "in png_set_compression_buffer_size");
+
    if (png_ptr == NULL)
       return;
 
@@ -1655,6 +1659,8 @@ void PNGAPI
 png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
     png_uint_32 user_height_max)
 {
+   png_debug(1, "in png_set_user_limits");
+
    /* Images with dimensions larger than these limits will be
     * rejected by png_set_IHDR().  To accept any PNG datastream
     * regardless of dimensions, set both limits to 0x7fffffff.
@@ -1670,6 +1676,8 @@ png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
 void PNGAPI
 png_set_chunk_cache_max(png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
 {
+   png_debug(1, "in png_set_chunk_cache_max");
+
    if (png_ptr != NULL)
       png_ptr->user_chunk_cache_max = user_chunk_cache_max;
 }
@@ -1679,6 +1687,8 @@ void PNGAPI
 png_set_chunk_malloc_max(png_structrp png_ptr,
     png_alloc_size_t user_chunk_malloc_max)
 {
+   png_debug(1, "in png_set_chunk_malloc_max");
+
    if (png_ptr != NULL)
       png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
 }
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
index 89a62191b6f18..2350057e70e54 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2024 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -131,10 +131,10 @@ png_set_interlace_handling(png_structrp png_ptr)
    if (png_ptr != 0 && png_ptr->interlaced != 0)
    {
       png_ptr->transformations |= PNG_INTERLACE;
-      return (7);
+      return 7;
    }
 
-   return (1);
+   return 1;
 }
 #endif
 
@@ -526,6 +526,8 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
    png_bytep dp = row; /* destination pointer */
    png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
 
+   png_debug(1, "in png_do_strip_channel");
+
    /* At the start sp will point to the first byte to copy and dp to where
     * it is copied to.  ep always points just beyond the end of the row, so
     * the loop simply copies (channels-1) channels until sp reaches ep.
@@ -726,6 +728,8 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
 void /* PRIVATE */
 png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
 {
+   png_debug(1, "in png_do_check_palette_indexes");
+
    if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
       png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
    {
@@ -736,7 +740,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
        * forms produced on either GCC or MSVC.
        */
       int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
-      png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
+      png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
 
       switch (row_info->bit_depth)
       {
@@ -861,7 +865,7 @@ png_voidp PNGAPI
 png_get_user_transform_ptr(png_const_structrp png_ptr)
 {
    if (png_ptr == NULL)
-      return (NULL);
+      return NULL;
 
    return png_ptr->user_transform_ptr;
 }

From 9b423a8509d6bf8a76297d74aaaea40613f5f2ae Mon Sep 17 00:00:00 2001
From: Axel Boldt-Christmas 
Date: Mon, 29 Apr 2024 17:14:09 +0000
Subject: [PATCH 004/203] 8330253: Remove verify_consistent_lock_order

Co-authored-by: Patricio Chilano Mateo 
Reviewed-by: dcubed, pchilanomate, dnsimon
---
 src/hotspot/share/runtime/deoptimization.cpp | 13 -----
 src/hotspot/share/runtime/lockStack.cpp      | 54 --------------------
 src/hotspot/share/runtime/lockStack.hpp      |  3 --
 3 files changed, 70 deletions(-)

diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp
index cf2f7e9c216d1..7a4a59a855315 100644
--- a/src/hotspot/share/runtime/deoptimization.cpp
+++ b/src/hotspot/share/runtime/deoptimization.cpp
@@ -391,7 +391,6 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArray lock_order{0};)
   // Start locking from outermost/oldest frame
   for (int i = (chunk->length() - 1); i >= 0; i--) {
     compiledVFrame* cvf = chunk->at(i);
@@ -401,13 +400,6 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArrayowner());
-        }
-      }
-#endif // ASSERT
 #ifndef PRODUCT
       if (PrintDeoptimizationDetails) {
         ResourceMark rm;
@@ -439,11 +431,6 @@ static void restore_eliminated_locks(JavaThread* thread, GrowableArraylock_stack().verify_consistent_lock_order(lock_order, exec_mode != Deoptimization::Unpack_none);
-  }
-#endif // ASSERT
 }
 
 // Deoptimize objects, that is reallocate and relock them, just before they escape through JVMTI.
diff --git a/src/hotspot/share/runtime/lockStack.cpp b/src/hotspot/share/runtime/lockStack.cpp
index c7889da1a76a2..2f783c97c998c 100644
--- a/src/hotspot/share/runtime/lockStack.cpp
+++ b/src/hotspot/share/runtime/lockStack.cpp
@@ -103,60 +103,6 @@ void LockStack::verify(const char* msg) const {
 }
 #endif
 
-#ifdef ASSERT
-void LockStack::verify_consistent_lock_order(GrowableArray& lock_order, bool leaf_frame) const {
-  int top_index = to_index(_top);
-  int lock_index = lock_order.length();
-
-  if (!leaf_frame) {
-    // If the lock_order is not from the leaf frame we must search
-    // for the top_index which fits with the most recent fast_locked
-    // objects in the lock stack.
-    while (lock_index-- > 0) {
-      const oop obj = lock_order.at(lock_index);
-      if (contains(obj)) {
-        for (int index = 0; index < top_index; index++) {
-          if (_base[index] == obj) {
-            // Found top index
-            top_index = index + 1;
-            break;
-          }
-        }
-
-        if (VM_Version::supports_recursive_lightweight_locking()) {
-          // With recursive looks there may be more of the same object
-          while (lock_index-- > 0 && lock_order.at(lock_index) == obj) {
-            top_index++;
-          }
-          assert(top_index <= to_index(_top), "too many obj in lock_order");
-        }
-
-        break;
-      }
-    }
-
-    lock_index = lock_order.length();
-  }
-
-  while (lock_index-- > 0) {
-    const oop obj = lock_order.at(lock_index);
-    const markWord mark = obj->mark_acquire();
-    assert(obj->is_locked(), "must be locked");
-    if (top_index > 0 && obj == _base[top_index - 1]) {
-      assert(mark.is_fast_locked() || mark.monitor()->is_owner_anonymous(),
-             "must be fast_locked or inflated by other thread");
-      top_index--;
-    } else {
-      assert(!mark.is_fast_locked(), "must be inflated");
-      assert(mark.monitor()->owner_raw() == get_thread() ||
-             (!leaf_frame && get_thread()->current_waiting_monitor() == mark.monitor()),
-             "must be owned by (or waited on by) thread");
-      assert(!contains(obj), "must not be on lock_stack");
-    }
-  }
-}
-#endif
-
 void LockStack::print_on(outputStream* st) {
   for (int i = to_index(_top); (--i) >= 0;) {
     st->print("LockStack[%d]: ", i);
diff --git a/src/hotspot/share/runtime/lockStack.hpp b/src/hotspot/share/runtime/lockStack.hpp
index 2cf02f00a8d47..064f70a37fbba 100644
--- a/src/hotspot/share/runtime/lockStack.hpp
+++ b/src/hotspot/share/runtime/lockStack.hpp
@@ -121,9 +121,6 @@ class LockStack {
 
   // Printing
   void print_on(outputStream* st);
-
-  // Verify Lock Stack consistent with lock order
-  void verify_consistent_lock_order(GrowableArray& lock_order, bool leaf_frame) const NOT_DEBUG_RETURN;
 };
 
 #endif // SHARE_RUNTIME_LOCKSTACK_HPP

From eb88343fb763ee89010b7a9879638152decc6892 Mon Sep 17 00:00:00 2001
From: SendaoYan 
Date: Mon, 29 Apr 2024 17:50:39 +0000
Subject: [PATCH 005/203] 8331164: createJMHBundle.sh download jars fail when
 url needed to be redirected

Reviewed-by: erikj, shade
---
 make/devkit/createJMHBundle.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/make/devkit/createJMHBundle.sh b/make/devkit/createJMHBundle.sh
index b2b10769d1533..889b7f914a41b 100644
--- a/make/devkit/createJMHBundle.sh
+++ b/make/devkit/createJMHBundle.sh
@@ -44,7 +44,7 @@ rm -f *
 fetchJar() {
   url="${MAVEN_MIRROR}/$1/$2/$3/$2-$3.jar"
   if command -v curl > /dev/null; then
-      curl -O --fail $url
+      curl -OL --fail $url
   elif command -v wget > /dev/null; then
       wget $url
   else

From 819f3d6fc70ff6fe54ac5f9033c17c3dd4326aa5 Mon Sep 17 00:00:00 2001
From: Brian Burkhalter 
Date: Mon, 29 Apr 2024 17:54:13 +0000
Subject: [PATCH 006/203] 8330748: ByteArrayOutputStream.writeTo(OutputStream)
 pins carrier

Reviewed-by: alanb
---
 .../java/io/ByteArrayOutputStream.java        |  14 +-
 .../WriteToReleasesCarrier.java               | 131 ++++++++++++++++++
 2 files changed, 142 insertions(+), 3 deletions(-)
 create mode 100644 test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java

diff --git a/src/java.base/share/classes/java/io/ByteArrayOutputStream.java b/src/java.base/share/classes/java/io/ByteArrayOutputStream.java
index 109acce3853d0..8f5ff41957e70 100644
--- a/src/java.base/share/classes/java/io/ByteArrayOutputStream.java
+++ b/src/java.base/share/classes/java/io/ByteArrayOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -159,8 +159,16 @@ public void writeBytes(byte[] b) {
      * @throws  NullPointerException if {@code out} is {@code null}.
      * @throws  IOException if an I/O error occurs.
      */
-    public synchronized void writeTo(OutputStream out) throws IOException {
-        out.write(buf, 0, count);
+    public void writeTo(OutputStream out) throws IOException {
+        if (Thread.currentThread().isVirtual()) {
+            byte[] bytes;
+            synchronized (this) {
+                bytes = Arrays.copyOf(buf, count);
+            }
+            out.write(bytes);
+        } else synchronized (this) {
+            out.write(buf, 0, count);
+        }
     }
 
     /**
diff --git a/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java b/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java
new file mode 100644
index 0000000000000..c0607fd94946e
--- /dev/null
+++ b/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8330748
+ * @summary Test ByteArrayOutputStream.writeTo releases carrier thread
+ * @requires vm.continuations
+ * @modules java.base/java.lang:+open
+ * @run main WriteToReleasesCarrier
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.LockSupport;
+
+public class WriteToReleasesCarrier {
+    public static void main(String[] args) throws Exception {
+        byte[] bytes = "Hello".getBytes(StandardCharsets.UTF_8);
+
+        var baos = new ByteArrayOutputStream();
+        baos.write(bytes);
+
+        var target = new ParkingOutputStream();
+
+        try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) {
+            Thread.Builder builder = virtualThreadBuilder(scheduler);
+            var started = new CountDownLatch(1);
+            var vthread1 = builder.start(() -> {
+                started.countDown();
+                try {
+                    baos.writeTo(target);
+                } catch (IOException ioe) { }
+            });
+            try {
+                started.await();
+                await(vthread1, Thread.State.WAITING);
+
+                // carrier should be released, use it for another thread
+                var executed = new AtomicBoolean();
+                var vthread2 = builder.start(() -> {
+                    executed.set(true);
+                });
+                vthread2.join();
+                if (!executed.get()) {
+                    throw new RuntimeException("Second virtual thread did not run");
+                }
+            } finally {
+                LockSupport.unpark(vthread1);
+                vthread1.join();
+            }
+        }
+
+        if (!Arrays.equals(target.toByteArray(), bytes)) {
+            throw new RuntimeException("Expected bytes not written");
+        }
+    }
+
+    /**
+     * Waits for a thread to get to the expected state.
+     */
+    private static void await(Thread thread, Thread.State expectedState) throws Exception {
+        Thread.State state = thread.getState();
+        while (state != expectedState) {
+            Thread.sleep(10);
+            state = thread.getState();
+        }
+    }
+
+    /**
+     * An OutputStream that parks when writing.
+     */
+    static class ParkingOutputStream extends OutputStream {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        @Override
+        public void write(int i) {
+            LockSupport.park();
+            baos.write(i);
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) {
+            LockSupport.park();
+            baos.write(b, off, len);
+        }
+
+        byte[] toByteArray() {
+            return baos.toByteArray();
+        }
+    }
+
+    /**
+     * Returns a builder to create virtual threads that use the given scheduler.
+     */
+    static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) throws Exception {
+        Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
+        Constructor ctor = clazz.getDeclaredConstructor(Executor.class);
+        ctor.setAccessible(true);
+        return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler);
+    }
+}

From b128bd7b5a1dcf3e7a55d3e3b0c4a9998bde963e Mon Sep 17 00:00:00 2001
From: David Holmes 
Date: Tue, 30 Apr 2024 06:53:16 +0000
Subject: [PATCH 007/203] 8331021: Deprecate and then obsolete the
 DontYieldALot flag

Reviewed-by: coleenp, stuefe, shade
---
 src/hotspot/share/runtime/arguments.cpp                      | 1 +
 src/hotspot/share/runtime/globals.hpp                        | 5 +----
 .../jtreg/runtime/CommandLine/VMDeprecatedOptions.java       | 1 +
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
index 802ddee756f2b..f2b370037311c 100644
--- a/src/hotspot/share/runtime/arguments.cpp
+++ b/src/hotspot/share/runtime/arguments.cpp
@@ -501,6 +501,7 @@ static SpecialFlag const special_jvm_flags[] = {
   { "RequireSharedSpaces",          JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() },
   { "UseSharedSpaces",              JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() },
   { "RegisterFinalizersAtInit",     JDK_Version::jdk(22), JDK_Version::jdk(23), JDK_Version::jdk(24) },
+  { "DontYieldALot",                JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) },
   { "PreserveAllAnnotations",       JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) },
   { "UseNotificationThread",        JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) },
   { "UseEmptySlotsInSupers",        JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) },
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
index 1d23e4164c43d..3995a87147464 100644
--- a/src/hotspot/share/runtime/globals.hpp
+++ b/src/hotspot/share/runtime/globals.hpp
@@ -698,7 +698,7 @@ const int ObjectAlignmentInBytes = 8;
           "registering as parallel capable")                                \
                                                                             \
   product_pd(bool, DontYieldALot,                                           \
-          "Throw away obvious excess yield calls")                          \
+             "(Deprecated) Throw away obvious excess yield calls")          \
                                                                             \
   product(bool, DisablePrimordialThreadGuardPages, false, EXPERIMENTAL,     \
                "Disable the use of stack guard pages if the JVM is loaded " \
@@ -1313,9 +1313,6 @@ const int ObjectAlignmentInBytes = 8;
   develop(intx, MethodHistogramCutoff, 100,                                 \
           "The cutoff value for method invocation histogram (+CountCalls)") \
                                                                             \
-  develop(intx, DontYieldALotInterval,    10,                               \
-          "Interval between which yields will be dropped (milliseconds)")   \
-                                                                            \
   develop(intx, DeoptimizeALotInterval,     5,                              \
           "Number of exits until DeoptimizeALot kicks in")                  \
                                                                             \
diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java
index 50751a62bdf3d..fa4ff56b691c2 100644
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java
@@ -56,6 +56,7 @@ public class VMDeprecatedOptions {
         ArrayList deprecated = new ArrayList(
           Arrays.asList(new String[][] {
             // deprecated non-alias flags:
+            {"DontYieldALot", "false"},
             {"UseNotificationThread", "true"},
             {"PreserveAllAnnotations", "true"},
             {"AllowRedefinitionToAddDeleteMethods", "true"},

From 60b61e588c1252b4b1fbc64d0f818a85670f7146 Mon Sep 17 00:00:00 2001
From: Matthias Baesken 
Date: Tue, 30 Apr 2024 07:31:29 +0000
Subject: [PATCH 008/203] 8331298: avoid alignment checks in UBSAN enabled
 build

Reviewed-by: erikj, mdoerr
---
 make/autoconf/jdk-options.m4 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
index 1e9a5637ae5ad..8c91a2ccd33eb 100644
--- a/make/autoconf/jdk-options.m4
+++ b/make/autoconf/jdk-options.m4
@@ -491,7 +491,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER],
 [
   # GCC reports lots of likely false positives for stringop-truncation and format-overflow.
   # Silence them for now.
-  UBSAN_CHECKS="-fsanitize=undefined -fsanitize=float-divide-by-zero -fno-sanitize=shift-base"
+  UBSAN_CHECKS="-fsanitize=undefined -fsanitize=float-divide-by-zero -fno-sanitize=shift-base -fno-sanitize=alignment"
   UBSAN_CFLAGS="$UBSAN_CHECKS -Wno-stringop-truncation -Wno-format-overflow -fno-omit-frame-pointer -DUNDEFINED_BEHAVIOR_SANITIZER"
   UBSAN_LDFLAGS="$UBSAN_CHECKS"
   UTIL_ARG_ENABLE(NAME: ubsan, DEFAULT: false, RESULT: UBSAN_ENABLED,

From 0630bb02eb760081ddd612ccb1b12d57d43aab5e Mon Sep 17 00:00:00 2001
From: Claes Redestad 
Date: Tue, 30 Apr 2024 08:27:38 +0000
Subject: [PATCH 009/203] 8331264: Reduce java.lang.constant initialization
 overhead

Reviewed-by: liach, mchung
---
 .../classes/java/lang/constant/ClassDesc.java |  4 +-
 .../java/lang/constant/ConstantDescs.java     | 86 +++++++++----------
 .../java/lang/constant/ConstantUtils.java     |  1 -
 .../constant/DirectMethodHandleDescImpl.java  |  4 +-
 .../lang/constant/DynamicConstantDesc.java    |  7 +-
 .../lang/constant/MethodTypeDescImpl.java     | 27 +++---
 .../lang/constant/ReferenceClassDescImpl.java |  7 +-
 7 files changed, 69 insertions(+), 67 deletions(-)

diff --git a/src/java.base/share/classes/java/lang/constant/ClassDesc.java b/src/java.base/share/classes/java/lang/constant/ClassDesc.java
index 767fa953e9777..89be851dbf5bf 100644
--- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java
+++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java
@@ -270,7 +270,7 @@ default ClassDesc nested(String firstNestedName, String... moreNestedNames) {
      * @return whether this {@linkplain ClassDesc} describes an array type
      */
     default boolean isArray() {
-        return descriptorString().startsWith("[");
+        return descriptorString().charAt(0) == '[';
     }
 
     /**
@@ -288,7 +288,7 @@ default boolean isPrimitive() {
      * @return whether this {@linkplain ClassDesc} describes a class or interface type
      */
     default boolean isClassOrInterface() {
-        return descriptorString().startsWith("L");
+        return descriptorString().charAt(0) == 'L';
     }
 
     /**
diff --git a/src/java.base/share/classes/java/lang/constant/ConstantDescs.java b/src/java.base/share/classes/java/lang/constant/ConstantDescs.java
index de895fc7af5d9..a67a16643c306 100644
--- a/src/java.base/share/classes/java/lang/constant/ConstantDescs.java
+++ b/src/java.base/share/classes/java/lang/constant/ConstantDescs.java
@@ -64,125 +64,125 @@ private ConstantDescs() { }
     // Don't change the order of these declarations!
 
     /** {@link ClassDesc} representing {@link Object} */
-    public static final ClassDesc CD_Object = ClassDesc.of("java.lang.Object");
+    public static final ClassDesc CD_Object = new ReferenceClassDescImpl("Ljava/lang/Object;");
 
     /** {@link ClassDesc} representing {@link String} */
-    public static final ClassDesc CD_String = ClassDesc.of("java.lang.String");
+    public static final ClassDesc CD_String = new ReferenceClassDescImpl("Ljava/lang/String;");
 
     /** {@link ClassDesc} representing {@link Class} */
-    public static final ClassDesc CD_Class = ClassDesc.of("java.lang.Class");
+    public static final ClassDesc CD_Class = new ReferenceClassDescImpl("Ljava/lang/Class;");
 
     /** {@link ClassDesc} representing {@link Number} */
-    public static final ClassDesc CD_Number = ClassDesc.of("java.lang.Number");
+    public static final ClassDesc CD_Number = new ReferenceClassDescImpl("Ljava/lang/Number;");
 
     /** {@link ClassDesc} representing {@link Integer} */
-    public static final ClassDesc CD_Integer = ClassDesc.of("java.lang.Integer");
+    public static final ClassDesc CD_Integer = new ReferenceClassDescImpl("Ljava/lang/Integer;");
 
     /** {@link ClassDesc} representing {@link Long} */
-    public static final ClassDesc CD_Long = ClassDesc.of("java.lang.Long");
+    public static final ClassDesc CD_Long = new ReferenceClassDescImpl("Ljava/lang/Long;");
 
     /** {@link ClassDesc} representing {@link Float} */
-    public static final ClassDesc CD_Float = ClassDesc.of("java.lang.Float");
+    public static final ClassDesc CD_Float = new ReferenceClassDescImpl("Ljava/lang/Float;");
 
     /** {@link ClassDesc} representing {@link Double} */
-    public static final ClassDesc CD_Double = ClassDesc.of("java.lang.Double");
+    public static final ClassDesc CD_Double = new ReferenceClassDescImpl("Ljava/lang/Double;");
 
     /** {@link ClassDesc} representing {@link Short} */
-    public static final ClassDesc CD_Short = ClassDesc.of("java.lang.Short");
+    public static final ClassDesc CD_Short = new ReferenceClassDescImpl("Ljava/lang/Short;");
 
     /** {@link ClassDesc} representing {@link Byte} */
-    public static final ClassDesc CD_Byte = ClassDesc.of("java.lang.Byte");
+    public static final ClassDesc CD_Byte = new ReferenceClassDescImpl("Ljava/lang/Byte;");
 
     /** {@link ClassDesc} representing {@link Character} */
-    public static final ClassDesc CD_Character = ClassDesc.of("java.lang.Character");
+    public static final ClassDesc CD_Character = new ReferenceClassDescImpl("Ljava/lang/Character;");
 
     /** {@link ClassDesc} representing {@link Boolean} */
-    public static final ClassDesc CD_Boolean = ClassDesc.of("java.lang.Boolean");
+    public static final ClassDesc CD_Boolean = new ReferenceClassDescImpl("Ljava/lang/Boolean;");
 
     /** {@link ClassDesc} representing {@link Void} */
-    public static final ClassDesc CD_Void = ClassDesc.of("java.lang.Void");
+    public static final ClassDesc CD_Void = new ReferenceClassDescImpl("Ljava/lang/Void;");
 
     /** {@link ClassDesc} representing {@link Throwable} */
-    public static final ClassDesc CD_Throwable = ClassDesc.of("java.lang.Throwable");
+    public static final ClassDesc CD_Throwable = new ReferenceClassDescImpl("Ljava/lang/Throwable;");
 
     /** {@link ClassDesc} representing {@link Exception} */
-    public static final ClassDesc CD_Exception = ClassDesc.of("java.lang.Exception");
+    public static final ClassDesc CD_Exception = new ReferenceClassDescImpl("Ljava/lang/Exception;");
 
     /** {@link ClassDesc} representing {@link Enum} */
-    public static final ClassDesc CD_Enum = ClassDesc.of("java.lang.Enum");
+    public static final ClassDesc CD_Enum = new ReferenceClassDescImpl("Ljava/lang/Enum;");
 
     /** {@link ClassDesc} representing {@link VarHandle} */
-    public static final ClassDesc CD_VarHandle = ClassDesc.of("java.lang.invoke.VarHandle");
+    public static final ClassDesc CD_VarHandle = new ReferenceClassDescImpl("Ljava/lang/invoke/VarHandle;");
 
     /** {@link ClassDesc} representing {@link MethodHandles} */
-    public static final ClassDesc CD_MethodHandles = ClassDesc.of("java.lang.invoke.MethodHandles");
+    public static final ClassDesc CD_MethodHandles = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodHandles;");
 
     /** {@link ClassDesc} representing {@link MethodHandles.Lookup} */
-    public static final ClassDesc CD_MethodHandles_Lookup = CD_MethodHandles.nested("Lookup");
+    public static final ClassDesc CD_MethodHandles_Lookup = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodHandles$Lookup;");
 
     /** {@link ClassDesc} representing {@link MethodHandle} */
-    public static final ClassDesc CD_MethodHandle = ClassDesc.of("java.lang.invoke.MethodHandle");
+    public static final ClassDesc CD_MethodHandle = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodHandle;");
 
     /** {@link ClassDesc} representing {@link MethodType} */
-    public static final ClassDesc CD_MethodType = ClassDesc.of("java.lang.invoke.MethodType");
+    public static final ClassDesc CD_MethodType = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodType;");
 
     /** {@link ClassDesc} representing {@link CallSite} */
-    public static final ClassDesc CD_CallSite = ClassDesc.of("java.lang.invoke.CallSite");
+    public static final ClassDesc CD_CallSite = new ReferenceClassDescImpl("Ljava/lang/invoke/CallSite;");
 
     /** {@link ClassDesc} representing {@link Collection} */
-    public static final ClassDesc CD_Collection = ClassDesc.of("java.util.Collection");
+    public static final ClassDesc CD_Collection = new ReferenceClassDescImpl("Ljava/util/Collection;");
 
     /** {@link ClassDesc} representing {@link List} */
-    public static final ClassDesc CD_List = ClassDesc.of("java.util.List");
+    public static final ClassDesc CD_List = new ReferenceClassDescImpl("Ljava/util/List;");
 
     /** {@link ClassDesc} representing {@link Set} */
-    public static final ClassDesc CD_Set = ClassDesc.of("java.util.Set");
+    public static final ClassDesc CD_Set = new ReferenceClassDescImpl("Ljava/util/Set;");
 
     /** {@link ClassDesc} representing {@link Map} */
-    public static final ClassDesc CD_Map = ClassDesc.of("java.util.Map");
+    public static final ClassDesc CD_Map = new ReferenceClassDescImpl("Ljava/util/Map;");
 
     /** {@link ClassDesc} representing {@link ConstantDesc} */
-    public static final ClassDesc CD_ConstantDesc = ClassDesc.of("java.lang.constant.ConstantDesc");
+    public static final ClassDesc CD_ConstantDesc = new ReferenceClassDescImpl("Ljava/lang/constant/ConstantDesc;");
 
     /** {@link ClassDesc} representing {@link ClassDesc} */
-    public static final ClassDesc CD_ClassDesc = ClassDesc.of("java.lang.constant.ClassDesc");
+    public static final ClassDesc CD_ClassDesc = new ReferenceClassDescImpl("Ljava/lang/constant/ClassDesc;");
 
     /** {@link ClassDesc} representing {@link EnumDesc} */
-    public static final ClassDesc CD_EnumDesc = CD_Enum.nested("EnumDesc");
+    public static final ClassDesc CD_EnumDesc = new ReferenceClassDescImpl("Ljava/lang/Enum$EnumDesc;");
 
     /** {@link ClassDesc} representing {@link MethodTypeDesc} */
-    public static final ClassDesc CD_MethodTypeDesc = ClassDesc.of("java.lang.constant.MethodTypeDesc");
+    public static final ClassDesc CD_MethodTypeDesc = new ReferenceClassDescImpl("Ljava/lang/constant/MethodTypeDesc;");
 
     /** {@link ClassDesc} representing {@link MethodHandleDesc} */
-    public static final ClassDesc CD_MethodHandleDesc = ClassDesc.of("java.lang.constant.MethodHandleDesc");
+    public static final ClassDesc CD_MethodHandleDesc = new ReferenceClassDescImpl("Ljava/lang/constant/MethodHandleDesc;");
 
     /** {@link ClassDesc} representing {@link DirectMethodHandleDesc} */
-    public static final ClassDesc CD_DirectMethodHandleDesc = ClassDesc.of("java.lang.constant.DirectMethodHandleDesc");
+    public static final ClassDesc CD_DirectMethodHandleDesc = new ReferenceClassDescImpl("Ljava/lang/constant/DirectMethodHandleDesc;");
 
     /** {@link ClassDesc} representing {@link VarHandleDesc} */
-    public static final ClassDesc CD_VarHandleDesc = CD_VarHandle.nested("VarHandleDesc");
+    public static final ClassDesc CD_VarHandleDesc = new ReferenceClassDescImpl("Ljava/lang/invoke/VarHandle$VarHandleDesc;");
 
     /** {@link ClassDesc} representing {@link DirectMethodHandleDesc.Kind} */
-    public static final ClassDesc CD_MethodHandleDesc_Kind = CD_DirectMethodHandleDesc.nested("Kind");
+    public static final ClassDesc CD_MethodHandleDesc_Kind = new ReferenceClassDescImpl("Ljava/lang/constant/DirectMethodHandleDesc$Kind;");
 
     /** {@link ClassDesc} representing {@link DynamicConstantDesc} */
-    public static final ClassDesc CD_DynamicConstantDesc = ClassDesc.of("java.lang.constant.DynamicConstantDesc");
+    public static final ClassDesc CD_DynamicConstantDesc = new ReferenceClassDescImpl("Ljava/lang/constant/DynamicConstantDesc;");
 
     /** {@link ClassDesc} representing {@link DynamicCallSiteDesc} */
-    public static final ClassDesc CD_DynamicCallSiteDesc = ClassDesc.of("java.lang.constant.DynamicCallSiteDesc");
+    public static final ClassDesc CD_DynamicCallSiteDesc = new ReferenceClassDescImpl("Ljava/lang/constant/DynamicCallSiteDesc;");
 
     /** {@link ClassDesc} representing {@link ConstantBootstraps} */
-    public static final ClassDesc CD_ConstantBootstraps = ClassDesc.of("java.lang.invoke.ConstantBootstraps");
+    public static final ClassDesc CD_ConstantBootstraps = new ReferenceClassDescImpl("Ljava/lang/invoke/ConstantBootstraps;");
 
     private static final ClassDesc[] INDY_BOOTSTRAP_ARGS = {
-            ConstantDescs.CD_MethodHandles_Lookup,
-            ConstantDescs.CD_String,
-            ConstantDescs.CD_MethodType};
+            CD_MethodHandles_Lookup,
+            CD_String,
+            CD_MethodType};
 
     private static final ClassDesc[] CONDY_BOOTSTRAP_ARGS = {
-            ConstantDescs.CD_MethodHandles_Lookup,
-            ConstantDescs.CD_String,
-            ConstantDescs.CD_Class};
+            CD_MethodHandles_Lookup,
+            CD_String,
+            CD_Class};
 
     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#primitiveClass(Lookup, String, Class) ConstantBootstraps.primitiveClass} */
     public static final DirectMethodHandleDesc BSM_PRIMITIVE_CLASS
diff --git a/src/java.base/share/classes/java/lang/constant/ConstantUtils.java b/src/java.base/share/classes/java/lang/constant/ConstantUtils.java
index d975eaa1d0cfa..d8a1ccd543b0f 100644
--- a/src/java.base/share/classes/java/lang/constant/ConstantUtils.java
+++ b/src/java.base/share/classes/java/lang/constant/ConstantUtils.java
@@ -146,7 +146,6 @@ public static String validateModuleName(String name) {
      * @throws IllegalArgumentException if the member name is invalid
      */
     public static String validateMemberName(String name, boolean method) {
-        requireNonNull(name);
         if (name.length() == 0)
             throw new IllegalArgumentException("zero-length member name");
         for (int i=0; i 0) {
+            System.arraycopy(argTypes, 0, newArgs, 0, start);
+        }
+        if (end < argTypes.length) {
+            System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
+        }
         return ofTrusted(returnType, newArgs);
     }
 
@@ -154,10 +158,13 @@ public MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes) {
             throw new IndexOutOfBoundsException(pos);
 
         ClassDesc[] newArgs = new ClassDesc[argTypes.length + paramTypes.length];
-        System.arraycopy(argTypes, 0, newArgs, 0, pos);
+        if (pos > 0) {
+            System.arraycopy(argTypes, 0, newArgs, 0, pos);
+        }
         System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
-        System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, argTypes.length - pos);
-
+        if (pos < argTypes.length) {
+            System.arraycopy(argTypes, pos, newArgs, pos + paramTypes.length, argTypes.length - pos);
+        }
         return ofTrusted(returnType, newArgs);
     }
 
diff --git a/src/java.base/share/classes/java/lang/constant/ReferenceClassDescImpl.java b/src/java.base/share/classes/java/lang/constant/ReferenceClassDescImpl.java
index 4cc77b1851deb..5e2aaa98442e0 100644
--- a/src/java.base/share/classes/java/lang/constant/ReferenceClassDescImpl.java
+++ b/src/java.base/share/classes/java/lang/constant/ReferenceClassDescImpl.java
@@ -47,10 +47,9 @@ final class ReferenceClassDescImpl implements ClassDesc {
      * @jvms 4.3.2 Field Descriptors
      */
     ReferenceClassDescImpl(String descriptor) {
-        requireNonNull(descriptor);
-        int len = ConstantUtils.skipOverFieldSignature(descriptor, 0, descriptor.length(), false);
-        if (len == 0 || len == 1
-            || len != descriptor.length())
+        int dLen = descriptor.length();
+        int len = ConstantUtils.skipOverFieldSignature(descriptor, 0, dLen, false);
+        if (len <= 1 || len != dLen)
             throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
         this.descriptor = descriptor;
     }

From cff841f1de41c911ec1b642b998c074e13e75554 Mon Sep 17 00:00:00 2001
From: Aleksey Shipilev 
Date: Tue, 30 Apr 2024 09:13:12 +0000
Subject: [PATCH 010/203] 8328934: Assert that ABS input and output are legal

Reviewed-by: aph, dlong
---
 .../share/utilities/globalDefinitions.hpp     |  14 ++-
 test/hotspot/gtest/utilities/test_abs.cpp     | 115 ++++++++++++++++++
 2 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 test/hotspot/gtest/utilities/test_abs.cpp

diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp
index 87af33d97e705..34f0a40a826d3 100644
--- a/src/hotspot/share/utilities/globalDefinitions.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp
@@ -37,6 +37,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 class oopDesc;
@@ -1110,7 +1111,18 @@ template constexpr T MIN3(T a, T b, T c)      { return MIN2(MIN2(a, b),
 template constexpr T MAX4(T a, T b, T c, T d) { return MAX2(MAX3(a, b, c), d); }
 template constexpr T MIN4(T a, T b, T c, T d) { return MIN2(MIN3(a, b, c), d); }
 
-template inline T ABS(T x)                 { return (x > 0) ? x : -x; }
+#define ABS(x) asserted_abs(x, __FILE__, __LINE__)
+
+template inline T asserted_abs(T x, const char* file, int line) {
+  bool valid_arg = !(std::is_integral::value && x == std::numeric_limits::min());
+#ifdef ASSERT
+  if (!valid_arg) {
+    report_vm_error(file, line, "ABS: argument should not allow overflow");
+  }
+#endif
+  // Prevent exposure to UB by checking valid_arg here as well.
+  return (x < 0 && valid_arg) ? -x : x;
+}
 
 // Return the given value clamped to the range [min ... max]
 template
diff --git a/test/hotspot/gtest/utilities/test_abs.cpp b/test/hotspot/gtest/utilities/test_abs.cpp
new file mode 100644
index 0000000000000..74e4fdb02e942
--- /dev/null
+++ b/test/hotspot/gtest/utilities/test_abs.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "unittest.hpp"
+#include "memory/allocation.hpp"
+#include "memory/resourceArea.inline.hpp"
+#include "runtime/thread.hpp"
+
+TEST(absTest, sanity) {
+  // Simple integer cases
+  EXPECT_EQ(0, ABS(0));
+  EXPECT_EQ(1, ABS(1));
+  EXPECT_EQ(1, ABS(-1));
+
+  // Simple floating point cases, should be exactly representable
+  EXPECT_EQ(0.0f, ABS(0.0f));
+  EXPECT_EQ(1.0f, ABS(1.0f));
+  EXPECT_EQ(1.0f, ABS(-1.0f));
+
+  EXPECT_EQ(0.0, ABS(0.0));
+  EXPECT_EQ(1.0, ABS(1.0));
+  EXPECT_EQ(1.0, ABS(-1.0));
+
+  // Upper bounds for unsigned integers
+  EXPECT_EQ(max_jubyte,  ABS(max_jubyte));
+  EXPECT_EQ(max_jushort, ABS(max_jushort));
+  EXPECT_EQ(max_juint,   ABS(max_juint));
+  EXPECT_EQ(max_julong,  ABS(max_julong));
+
+  // Upper bounds for signed integers
+  EXPECT_EQ(max_jbyte,  ABS(max_jbyte));
+  EXPECT_EQ(max_jshort, ABS(max_jshort));
+  EXPECT_EQ(max_jint,   ABS(max_jint));
+  EXPECT_EQ(max_jlong,  ABS(max_jlong));
+
+  // Lower valid bounds for signed integers
+  EXPECT_EQ(max_jbyte,  ABS(min_jbyte + 1));
+  EXPECT_EQ(max_jshort, ABS(min_jshort + 1));
+  EXPECT_EQ(max_jint,   ABS(min_jint + 1));
+  EXPECT_EQ(max_jlong,  ABS(min_jlong + 1));
+
+  // Lower bounds for signed integers after explicit FP cast
+  EXPECT_TRUE(ABS((float)min_jbyte)  > 0);
+  EXPECT_TRUE(ABS((float)min_jshort) > 0);
+  EXPECT_TRUE(ABS((float)min_jint)   > 0);
+  EXPECT_TRUE(ABS((float)min_jlong)  > 0);
+}
+
+// Now check what happens when we feed invalid arguments.
+
+#ifndef ASSERT
+
+// In release builds, ABS would return incorrect values.
+
+TEST(absTest, release_sanity) {
+  EXPECT_EQ(min_jbyte,  ABS(min_jbyte));
+  EXPECT_EQ(min_jshort, ABS(min_jshort));
+  EXPECT_EQ(min_jint,   ABS(min_jint));
+  EXPECT_EQ(min_jlong,  ABS(min_jlong));
+}
+
+#else
+
+// In debug builds, ABS would assert.
+
+TEST_VM_ASSERT_MSG(absTest, debug_sanity_min_jbyte,
+  "Error: ABS: argument should not allow overflow") {
+
+  jbyte r = ABS(min_jbyte); // should fail
+  EXPECT_TRUE(r > 0); // should not be normally reachable
+}
+
+TEST_VM_ASSERT_MSG(absTest, debug_sanity_min_jshort,
+  "Error: ABS: argument should not allow overflow") {
+
+  jshort r = ABS(min_jshort); // should fail
+  EXPECT_TRUE(r > 0); // should not be normally reachable
+}
+
+TEST_VM_ASSERT_MSG(absTest, debug_sanity_min_jint,
+  "Error: ABS: argument should not allow overflow") {
+
+  jint r = ABS(min_jint); // should fail
+  EXPECT_TRUE(r > 0); // should not be normally reachable
+}
+
+TEST_VM_ASSERT_MSG(absTest, debug_sanity_min_jlong,
+  "Error: ABS: argument should not allow overflow") {
+
+  jlong r = ABS(min_jlong); // should fail
+  EXPECT_TRUE(r > 0); // should not be normally reachable
+}
+
+#endif

From ef4ec2d3b061c0eeea1aba88135e8d0e272b3bea Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang 
Date: Tue, 30 Apr 2024 10:37:33 +0000
Subject: [PATCH 011/203] 8331284: Inline methods in softRefPolicy.cpp

Reviewed-by: gli, tschatzl
---
 src/hotspot/share/gc/shared/softRefPolicy.cpp | 35 -------------------
 src/hotspot/share/gc/shared/softRefPolicy.hpp |  8 +++--
 2 files changed, 6 insertions(+), 37 deletions(-)
 delete mode 100644 src/hotspot/share/gc/shared/softRefPolicy.cpp

diff --git a/src/hotspot/share/gc/shared/softRefPolicy.cpp b/src/hotspot/share/gc/shared/softRefPolicy.cpp
deleted file mode 100644
index b3467b523b85c..0000000000000
--- a/src/hotspot/share/gc/shared/softRefPolicy.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/shared/softRefPolicy.hpp"
-
-SoftRefPolicy::SoftRefPolicy() :
-    _should_clear_all_soft_refs(false),
-    _all_soft_refs_clear(false) {
-}
-
-void SoftRefPolicy::cleared_all_soft_refs() {
-  _all_soft_refs_clear = true;
-}
diff --git a/src/hotspot/share/gc/shared/softRefPolicy.hpp b/src/hotspot/share/gc/shared/softRefPolicy.hpp
index 1b31262eca5bc..d3240d7079fc6 100644
--- a/src/hotspot/share/gc/shared/softRefPolicy.hpp
+++ b/src/hotspot/share/gc/shared/softRefPolicy.hpp
@@ -41,7 +41,9 @@ class SoftRefPolicy {
   bool _all_soft_refs_clear;
 
  public:
-  SoftRefPolicy();
+  SoftRefPolicy() :
+    _should_clear_all_soft_refs(false),
+    _all_soft_refs_clear(false) {}
 
   bool should_clear_all_soft_refs() { return _should_clear_all_soft_refs; }
   void set_should_clear_all_soft_refs(bool v) { _should_clear_all_soft_refs = v; }
@@ -51,7 +53,9 @@ class SoftRefPolicy {
 
   // Called by the GC after Soft Refs have been cleared to indicate
   // that the request in _should_clear_all_soft_refs has been fulfilled.
-  virtual void cleared_all_soft_refs();
+  void cleared_all_soft_refs() {
+    _all_soft_refs_clear = true;
+  }
 };
 
 class ClearedAllSoftRefs : public StackObj {

From 22a1c617dbe771d8f5cea52af0e2a630af34b35b Mon Sep 17 00:00:00 2001
From: Patricio Chilano Mateo 
Date: Tue, 30 Apr 2024 13:08:35 +0000
Subject: [PATCH 012/203] 8330817: jdk/internal/vm/Continuation/OSRTest.java
 times out on libgraal

Reviewed-by: dnsimon, dlong
---
 test/jdk/jdk/internal/vm/Continuation/OSRTest.java | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/test/jdk/jdk/internal/vm/Continuation/OSRTest.java b/test/jdk/jdk/internal/vm/Continuation/OSRTest.java
index bf0bfeab6746a..a9eed4e93b6af 100644
--- a/test/jdk/jdk/internal/vm/Continuation/OSRTest.java
+++ b/test/jdk/jdk/internal/vm/Continuation/OSRTest.java
@@ -32,13 +32,13 @@
 * @build jdk.test.whitebox.WhiteBox
 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 *
-* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI OSRTest true true true
-* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=inline,*::yield0 OSRTest true true false
-* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::yield* OSRTest true true false
-* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,*::bar() OSRTest true false false
-* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI OSRTest false true true
-* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI OSRTest false true false
-* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,*::bar() OSRTest false false false
+* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::foo* OSRTest true true true
+* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::foo* -XX:CompileCommand=inline,*::yield0 OSRTest true true false
+* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::foo* -XX:CompileCommand=dontinline,*::yield* OSRTest true true false
+* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::foo* -XX:CompileCommand=exclude,*::bar() OSRTest true false false
+* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::foo* OSRTest false true true
+* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::foo* OSRTest false true false
+* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=dontinline,*::foo* -XX:CompileCommand=exclude,*::bar() OSRTest false false false
 *
 */
 

From 33e81229bd1b4b28cf2e35f0f8f0a42a04d59c3d Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang 
Date: Tue, 30 Apr 2024 13:52:08 +0000
Subject: [PATCH 013/203] 8331410: Remove unused
 MemAllocator::mem_allocate_inside_tlab

Reviewed-by: tschatzl, gli
---
 src/hotspot/share/gc/shared/memAllocator.cpp | 14 --------------
 src/hotspot/share/gc/shared/memAllocator.hpp |  1 -
 2 files changed, 15 deletions(-)

diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp
index 053f49dd6dd60..971feed6aaf7a 100644
--- a/src/hotspot/share/gc/shared/memAllocator.cpp
+++ b/src/hotspot/share/gc/shared/memAllocator.cpp
@@ -250,19 +250,6 @@ HeapWord* MemAllocator::mem_allocate_outside_tlab(Allocation& allocation) const
   return mem;
 }
 
-HeapWord* MemAllocator::mem_allocate_inside_tlab(Allocation& allocation) const {
-  assert(UseTLAB, "should use UseTLAB");
-
-  // Try allocating from an existing TLAB.
-  HeapWord* mem = mem_allocate_inside_tlab_fast();
-  if (mem != nullptr) {
-    return mem;
-  }
-
-  // Try refilling the TLAB and allocating the object in it.
-  return mem_allocate_inside_tlab_slow(allocation);
-}
-
 HeapWord* MemAllocator::mem_allocate_inside_tlab_fast() const {
   return _thread->tlab().allocate(_word_size);
 }
@@ -331,7 +318,6 @@ HeapWord* MemAllocator::mem_allocate_inside_tlab_slow(Allocation& allocation) co
   return mem;
 }
 
-
 HeapWord* MemAllocator::mem_allocate_slow(Allocation& allocation) const {
   // Allocation of an oop can always invoke a safepoint.
   debug_only(allocation._thread->check_for_valid_safepoint_state());
diff --git a/src/hotspot/share/gc/shared/memAllocator.hpp b/src/hotspot/share/gc/shared/memAllocator.hpp
index bd4ae04babfcd..dca1add31b6b0 100644
--- a/src/hotspot/share/gc/shared/memAllocator.hpp
+++ b/src/hotspot/share/gc/shared/memAllocator.hpp
@@ -47,7 +47,6 @@ class MemAllocator: StackObj {
 
 private:
   // Allocate in a TLAB. Could allocate a new TLAB, and therefore potentially safepoint.
-  HeapWord* mem_allocate_inside_tlab(Allocation& allocation) const;
   HeapWord* mem_allocate_inside_tlab_slow(Allocation& allocation) const;
 
   // Allocate outside a TLAB. Could safepoint.

From 2cc8eccb360848f3ddf3259f1d943552f86234b9 Mon Sep 17 00:00:00 2001
From: Viktor Klang 
Date: Tue, 30 Apr 2024 15:11:04 +0000
Subject: [PATCH 014/203] 8331346: Update PreviewFeature of STREAM_GATHERERS to
 JEP-473

Reviewed-by: pminborg, alanb
---
 .../share/classes/jdk/internal/javac/PreviewFeature.java        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
index c24a58f023017..cfccff7dd9302 100644
--- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
+++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
@@ -79,7 +79,7 @@ public enum Feature {
         STRUCTURED_CONCURRENCY,
         @JEP(number=466, title="ClassFile API", status="Second Preview")
         CLASSFILE_API,
-        @JEP(number=461, title="Stream Gatherers", status="Preview")
+        @JEP(number=473, title="Stream Gatherers", status="Second Preview")
         STREAM_GATHERERS,
         LANGUAGE_MODEL,
         /**

From f4caac8dea1c95234743712386cb28a1ecb11197 Mon Sep 17 00:00:00 2001
From: Tim Prinzing 
Date: Tue, 30 Apr 2024 15:39:23 +0000
Subject: [PATCH 015/203] 8329138: Convert JFR FileForceEvent to static mirror
 event

Reviewed-by: alanb, egahlin
---
 .../jdk/internal/event/FileForceEvent.java    | 110 ++++++++++++++++++
 .../classes/sun/nio/ch/FileChannelImpl.java   |  15 ++-
 .../ch/SimpleAsynchronousFileChannelImpl.java |  26 ++++-
 .../sun/nio/fs/UnixChannelFactory.java        |   2 +-
 .../WindowsAsynchronousFileChannelImpl.java   |  26 ++++-
 .../sun/nio/fs/WindowsChannelFactory.java     |   2 +-
 .../jdk/jfr/events/EventConfigurations.java   |   3 +-
 .../jdk/jfr/events/FileForceEvent.java        |   8 +-
 .../jdk/jfr/internal/MirrorEvents.java        |   4 +-
 .../FileChannelImplInstrumentor.java          |  21 +---
 .../jfr/internal/instrument/JDKEvents.java    |   2 +-
 .../io/TestAsynchronousFileChannelEvents.java |  75 ++++++++++++
 12 files changed, 252 insertions(+), 42 deletions(-)
 create mode 100644 src/java.base/share/classes/jdk/internal/event/FileForceEvent.java
 create mode 100644 test/jdk/jdk/jfr/event/io/TestAsynchronousFileChannelEvents.java

diff --git a/src/java.base/share/classes/jdk/internal/event/FileForceEvent.java b/src/java.base/share/classes/jdk/internal/event/FileForceEvent.java
new file mode 100644
index 0000000000000..f6dec6c8a5ead
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/event/FileForceEvent.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+package jdk.internal.event;
+
+/**
+ * A JFR event for forced updates written to files.  This event is mirrored in
+ * {@code jdk.jfr.events.FileForceEvent } where the event annotations are
+ * provided.  Some of the methods are replaced by generated
+ * methods when jfr is enabled.  Note that the order of the arguments of the
+ * {@link #commit(long, long, String, boolean)} method
+ * must be the same as the order of the fields.
+ */
+public class FileForceEvent extends Event {
+
+    // THE ORDER OF THE FOLLOWING FIELDS IS IMPORTANT!
+    // The order must match the argument order of the generated commit method.
+    public String path;
+    public boolean metaData;
+
+    /**
+     * Helper method to offer the data needed to potentially commit an event.
+     * The duration of the operation is computed using the current
+     * timestamp and the given start time.  If the duration is meets
+     * or exceeds the configured value (determined by calling the generated method
+     * {@link #shouldCommit(long)}), an event will be emitted by calling
+     * {@link #commit(long, long, String, boolean)}.
+     *
+     * @param start     timestamp of the start of the operation
+     * @param path      the full pathname of the file
+     * @param metaData  true if the file metadata is updated
+     */
+    public static void offer(long start, String path, boolean metaData) {
+        long duration = timestamp() - start;
+        if (shouldCommit(duration)) {
+            commit(start, duration, path, metaData);
+        }
+    }
+
+    /**
+     * Actually commit an event.  The implementation is generated automatically.
+     * The order of the fields must be the same as the parameters in this method.
+     *
+     * @param start     timestamp of the start of the operation
+     * @param duration  time in nanoseconds to complete the operation
+     * @param path      the full pathname of the file
+     * @param metaData  true if the file metadata is updated
+     */
+    public static void commit(long start, long duration, String path, boolean metaData) {
+        // Generated by JFR
+    }
+
+    /**
+     * Determine if an event should be emitted.  The duration of the operation
+     * must exceed some threshold in order to commit the event.  The implementation
+     * of this method is generated automatically if jfr is enabled.
+     *
+     * @param duration  time in nanoseconds to complete the operation
+     * @return  true if the event should be commited
+     */
+    public static boolean shouldCommit(long duration) {
+        // Generated by JFR
+        return false;
+    }
+
+    /**
+     * Determine if this kind of event is enabled.  The implementation
+     * of this method is generated automatically if jfr is enabled.
+     *
+     * @return true if this type of event is enabled, false otherwise
+     */
+    public static boolean enabled() {
+        // Generated by JFR
+        return false;
+    }
+
+    /**
+     * Fetch the current timestamp in nanoseconds.  This method is used
+     * to determine the start and end of an operation.  The implementation
+     * of this method is generated automatically if jfr is enabled.
+     *
+     * @return  the current timestamp value
+     */
+    public static long timestamp() {
+        // Generated by JFR
+        return 0L;
+    }
+}
diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
index ab386bb14a5a3..0b72ee6a7c2e2 100644
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
@@ -50,6 +50,7 @@
 
 import jdk.internal.access.JavaIOFileDescriptorAccess;
 import jdk.internal.access.SharedSecrets;
+import jdk.internal.event.FileForceEvent;
 import jdk.internal.foreign.MemorySessionImpl;
 import jdk.internal.foreign.SegmentFactories;
 import jdk.internal.misc.Blocker;
@@ -486,8 +487,7 @@ public FileChannel truncate(long newSize) throws IOException {
         }
     }
 
-    @Override
-    public void force(boolean metaData) throws IOException {
+    private void implForce(boolean metaData) throws IOException {
         ensureOpen();
         int rv = -1;
         int ti = -1;
@@ -511,6 +511,17 @@ public void force(boolean metaData) throws IOException {
         }
     }
 
+    @Override
+    public void force(boolean metaData) throws IOException {
+        if (!FileForceEvent.enabled()) {
+            implForce(metaData);
+            return;
+        }
+        long start = FileForceEvent.timestamp();
+        implForce(metaData);
+        FileForceEvent.offer(start, path, metaData);
+    }
+
     // Assume at first that the underlying kernel supports sendfile/equivalent;
     // set this to true if we find out later that it doesn't
     //
diff --git a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java
index b41430c8d9d69..5f3f91e7aff96 100644
--- a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java
+++ b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package sun.nio.ch;
 
+import jdk.internal.event.FileForceEvent;
+
 import java.nio.channels.*;
 import java.util.concurrent.*;
 import java.nio.ByteBuffer;
@@ -50,19 +52,25 @@ private static class DefaultExecutorHolder {
     // Used to make native read and write calls
     private static final FileDispatcher nd = new FileDispatcherImpl();
 
+    // file path
+    private final String path;
+
     // Thread-safe set of IDs of native threads, for signalling
     private final NativeThreadSet threads = new NativeThreadSet(2);
 
 
     SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
+                                      String path,
                                       boolean reading,
                                       boolean writing,
                                       ExecutorService executor)
     {
         super(fdObj, reading, writing, executor);
+        this.path = path;
     }
 
     public static AsynchronousFileChannel open(FileDescriptor fdo,
+                                               String path,
                                                boolean reading,
                                                boolean writing,
                                                ThreadPool pool)
@@ -70,7 +78,7 @@ public static AsynchronousFileChannel open(FileDescriptor fdo,
         // Executor is either default or based on pool parameters
         ExecutorService executor = (pool == null) ?
             DefaultExecutorHolder.defaultExecutor : pool.executor();
-        return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
+        return new SimpleAsynchronousFileChannelImpl(fdo, path, reading, writing, executor);
     }
 
     @Override
@@ -151,8 +159,7 @@ public AsynchronousFileChannel truncate(long size) throws IOException {
         }
     }
 
-    @Override
-    public void force(boolean metaData) throws IOException {
+    private void implForce(boolean metaData) throws IOException {
         int ti = threads.add();
         try {
             int n = 0;
@@ -169,6 +176,17 @@ public void force(boolean metaData) throws IOException {
         }
     }
 
+    @Override
+    public void force(boolean metaData) throws IOException {
+        if (!FileForceEvent.enabled()) {
+            implForce(metaData);
+            return;
+        }
+        long start = FileForceEvent.timestamp();
+        implForce(metaData);
+        FileForceEvent.offer(start, path, metaData);
+    }
+
     @Override
      Future implLock(final long position,
                                   final long size,
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java b/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java
index 475b61036a266..8e5bf38882c26 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java
@@ -168,7 +168,7 @@ static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path,
 
         // for now use simple implementation
         FileDescriptor fdObj = open(-1, path, null, flags, mode);
-        return SimpleAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);
+        return SimpleAsynchronousFileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, pool);
     }
 
     /**
diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java
index a1bacc1fae140..15ae425850ed6 100644
--- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java
+++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 import java.io.FileDescriptor;
 import jdk.internal.access.SharedSecrets;
 import jdk.internal.access.JavaIOFileDescriptorAccess;
+import jdk.internal.event.FileForceEvent;
 
 /**
  * Windows implementation of AsynchronousFileChannel using overlapped I/O.
@@ -63,6 +64,9 @@ private static Iocp defaultIocp() {
     // Used for force/truncate/size methods
     private static final FileDispatcher nd = new FileDispatcherImpl();
 
+    // file path
+    private final String path;
+
     // The handle is extracted for use in native methods invoked from this class.
     private final long handle;
 
@@ -79,6 +83,7 @@ private static Iocp defaultIocp() {
 
 
     private WindowsAsynchronousFileChannelImpl(FileDescriptor fdObj,
+                                               String path,
                                                boolean reading,
                                                boolean writing,
                                                Iocp iocp,
@@ -86,6 +91,7 @@ private WindowsAsynchronousFileChannelImpl(FileDescriptor fdObj,
         throws IOException
     {
         super(fdObj, reading, writing, iocp.executor());
+        this.path = path;
         this.handle = fdAccess.getHandle(fdObj);
         this.iocp = iocp;
         this.isDefaultIocp = isDefaultIocp;
@@ -94,6 +100,7 @@ private WindowsAsynchronousFileChannelImpl(FileDescriptor fdObj,
     }
 
     public static AsynchronousFileChannel open(FileDescriptor fdo,
+                                               String path,
                                                boolean reading,
                                                boolean writing,
                                                ThreadPool pool)
@@ -109,8 +116,7 @@ public static AsynchronousFileChannel open(FileDescriptor fdo,
             isDefaultIocp = false;
         }
         try {
-            return new
-                WindowsAsynchronousFileChannelImpl(fdo, reading, writing, iocp, isDefaultIocp);
+            return new WindowsAsynchronousFileChannelImpl(fdo, path, reading, writing, iocp, isDefaultIocp);
         } catch (IOException x) {
             // error binding to port so need to close it (if created for this channel)
             if (!isDefaultIocp)
@@ -196,8 +202,7 @@ public AsynchronousFileChannel truncate(long size) throws IOException {
         return this;
     }
 
-    @Override
-    public void force(boolean metaData) throws IOException {
+    private void implForce(boolean metaData) throws IOException {
         try {
             begin();
             nd.force(fdObj, metaData);
@@ -206,6 +211,17 @@ public void force(boolean metaData) throws IOException {
         }
     }
 
+    @Override
+    public void force(boolean metaData) throws IOException {
+        if (!FileForceEvent.enabled()) {
+            implForce(metaData);
+            return;
+        }
+        long start = FileForceEvent.timestamp();
+        implForce(metaData);
+        FileForceEvent.offer(start, path, metaData);
+    }
+
     // -- file locking --
 
     /**
diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java b/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java
index 3a14221d62ab9..59db82d3fab77 100644
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java
@@ -212,7 +212,7 @@ static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows,
 
         // create the AsynchronousFileChannel
         try {
-            return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool);
+            return WindowsAsynchronousFileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, pool);
         } catch (IOException x) {
             // IOException is thrown if the file handle cannot be associated
             // with the completion port. All we can do is close the file.
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java b/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
index d4dba462f4bd3..7d829f690767e 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,5 +30,4 @@
 public final class EventConfigurations {
     public static final EventConfiguration FILE_READ = JVMSupport.getConfiguration(FileReadEvent.class);
     public static final EventConfiguration FILE_WRITE = JVMSupport.getConfiguration(FileWriteEvent.class);
-    public static final EventConfiguration FILE_FORCE = JVMSupport.getConfiguration(FileForceEvent.class);
 }
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/FileForceEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/FileForceEvent.java
index d54d5e9b2a475..495112ffa9d64 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/FileForceEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/FileForceEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,13 +29,14 @@
 import jdk.jfr.Description;
 import jdk.jfr.Label;
 import jdk.jfr.Name;
+import jdk.jfr.internal.MirrorEvent;
 import jdk.jfr.internal.Type;
 
 @Name(Type.EVENT_NAME_PREFIX + "FileForce")
 @Label("File Force")
 @Category("Java Application")
 @Description("Force updates to be written to file")
-public final class FileForceEvent extends AbstractJDKEvent {
+public final class FileForceEvent extends MirrorEvent {
 
     // The order of these fields must be the same as the parameters in
     // commit(..., String, boolean)
@@ -48,7 +49,4 @@ public final class FileForceEvent extends AbstractJDKEvent {
     @Description("Whether the file metadata is updated")
     public boolean metaData;
 
-    public static void commit(long start, long duration, String path, boolean metaData) {
-        // Generated
-    }
 }
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java
index db148c105c4c7..8ae1f3b031fdc 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 import jdk.jfr.events.ErrorThrownEvent;
 import jdk.jfr.events.ExceptionStatisticsEvent;
 import jdk.jfr.events.ExceptionThrownEvent;
+import jdk.jfr.events.FileForceEvent;
 import jdk.jfr.events.ProcessStartEvent;
 import jdk.jfr.events.SecurityPropertyModificationEvent;
 import jdk.jfr.events.SecurityProviderServiceEvent;
@@ -55,6 +56,7 @@ final class MirrorEvents {
     // Add mirror event mapping here. See MirrorEvent class for details.
     static {
         register("jdk.internal.event.DeserializationEvent", DeserializationEvent.class);
+        register("jdk.internal.event.FileForceEvent", FileForceEvent.class);
         register("jdk.internal.event.ProcessStartEvent", ProcessStartEvent.class);
         register("jdk.internal.event.SecurityPropertyModificationEvent", SecurityPropertyModificationEvent.class);
         register("jdk.internal.event.SecurityProviderServiceEvent", SecurityProviderServiceEvent.class);
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java
index d0d8d9b4509e1..5a795395c72c0 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,25 +45,6 @@ private FileChannelImplInstrumentor() {
 
     private String path;
 
-    @JIInstrumentationMethod
-    public void force(boolean metaData) throws IOException {
-        EventConfiguration eventConfiguration = EventConfigurations.FILE_FORCE;
-        if (!eventConfiguration.isEnabled()) {
-            force(metaData);
-            return;
-        }
-        long start = 0;
-        try {
-            start = EventConfiguration.timestamp();
-            force(metaData);
-        } finally {
-            long duration = EventConfiguration.timestamp() - start;
-            if (eventConfiguration.shouldCommit(duration)) {
-                FileForceEvent.commit(start, duration, path, metaData);
-            }
-        }
-    }
-
     @JIInstrumentationMethod
     public int read(ByteBuffer dst) throws IOException {
         EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java
index a6c65641cd30c..fb981c42cae46 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java
@@ -57,7 +57,6 @@
 public final class JDKEvents {
 
     private static final Class[] eventClasses = {
-        FileForceEvent.class,
         FileReadEvent.class,
         FileWriteEvent.class,
         ActiveSettingEvent.class,
@@ -68,6 +67,7 @@ public final class JDKEvents {
         jdk.internal.event.ErrorThrownEvent.class,
         jdk.internal.event.ExceptionStatisticsEvent.class,
         jdk.internal.event.ExceptionThrownEvent.class,
+        jdk.internal.event.FileForceEvent.class,
         jdk.internal.event.ProcessStartEvent.class,
         jdk.internal.event.SecurityPropertyModificationEvent.class,
         jdk.internal.event.SecurityProviderServiceEvent.class,
diff --git a/test/jdk/jdk/jfr/event/io/TestAsynchronousFileChannelEvents.java b/test/jdk/jdk/jfr/event/io/TestAsynchronousFileChannelEvents.java
new file mode 100644
index 0000000000000..f1ddba369eb41
--- /dev/null
+++ b/test/jdk/jdk/jfr/event/io/TestAsynchronousFileChannelEvents.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.event.io;
+
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.test.lib.Utils;
+import jdk.test.lib.jfr.Events;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousFileChannel;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.nio.file.StandardOpenOption.READ;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+/**
+ * @test
+ * @key jfr
+ * @requires vm.hasJFR
+ * @library /test/lib /test/jdk
+ * @run main/othervm jdk.jfr.event.io.TestAsynchronousFileChannelEvents
+ */
+public class TestAsynchronousFileChannelEvents {
+
+    public static void main(String[] args) throws Throwable {
+        File tmp = Utils.createTempFile("TestAsynchronousFileChannelEvents", ".tmp").toFile();
+        String s = "unremarkable data";
+        ByteBuffer data = ByteBuffer.allocate(s.length());
+        data.put(s.getBytes());
+
+        try (Recording recording = new Recording();
+             AsynchronousFileChannel ch = AsynchronousFileChannel.open(tmp.toPath(), READ, WRITE)) {
+
+            List expectedEvents = new ArrayList<>();
+            recording.enable(IOEvent.EVENT_FILE_FORCE).withThreshold(Duration.ofMillis(0));
+            recording.start();
+
+            data.flip();
+            ch.write(data, 0).get();
+
+            // test force(boolean)
+            ch.force(true);
+            expectedEvents.add(IOEvent.createFileForceEvent(tmp));
+
+            recording.stop();
+            List events = Events.fromRecording(recording);
+            IOHelper.verifyEqualsInOrder(events, expectedEvents);
+        }
+    }
+}

From 130f71cadca5b46d9bf589708dcea03ad51e8de0 Mon Sep 17 00:00:00 2001
From: Evgeny Nikitin 
Date: Tue, 30 Apr 2024 15:48:09 +0000
Subject: [PATCH 016/203] 8326742: Change compiler tests without additional VM
 flags from @run driver to @run main

Reviewed-by: kvn, thartmann, chagedorn
---
 .../jtreg/compiler/ccp/TestShiftConvertAndNotification.java   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/hotspot/jtreg/compiler/ccp/TestShiftConvertAndNotification.java b/test/hotspot/jtreg/compiler/ccp/TestShiftConvertAndNotification.java
index 7ce4463367017..a076a1c255821 100644
--- a/test/hotspot/jtreg/compiler/ccp/TestShiftConvertAndNotification.java
+++ b/test/hotspot/jtreg/compiler/ccp/TestShiftConvertAndNotification.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
  * @bug 8313672
  * @summary Test CCP notification for value update of AndL through LShiftI and
  *          ConvI2L (no flags).
- * @run driver compiler.ccp.TestShiftConvertAndNotification
+ * @run main compiler.ccp.TestShiftConvertAndNotification
  *
  */
 

From 9ce21d1382a4f5ad601a7ee610bab64a9c575302 Mon Sep 17 00:00:00 2001
From: Matias Saavedra Silva 
Date: Tue, 30 Apr 2024 16:02:55 +0000
Subject: [PATCH 017/203] 8327647: Occasional SIGSEGV in
 markWord::displaced_mark_helper() for SPECjvm2008 sunflow

Reviewed-by: coleenp, fyang, dlong
---
 src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp   |  2 ++
 src/hotspot/cpu/aarch64/templateTable_aarch64.cpp | 15 +++++----------
 src/hotspot/cpu/riscv/interp_masm_riscv.cpp       |  2 ++
 src/hotspot/cpu/riscv/templateTable_riscv.cpp     | 15 +++++----------
 src/hotspot/cpu/x86/templateTable_x86.cpp         |  2 +-
 5 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
index da38f1d12e70f..5fea0b8d925b0 100644
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
@@ -1778,6 +1778,8 @@ void InterpreterMacroAssembler::load_field_entry(Register cache, Register index,
   ldr(cache, Address(rcpool, ConstantPoolCache::field_entries_offset()));
   add(cache, cache, Array::base_offset_in_bytes());
   lea(cache, Address(cache, index));
+  // Prevents stale data from being read after the bytecode is patched to the fast bytecode
+  membar(MacroAssembler::LoadLoad);
 }
 
 void InterpreterMacroAssembler::load_method_entry(Register cache, Register index, int bcp_offset) {
diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
index eaaefb55f3691..f32a4ee7372a7 100644
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
@@ -2355,7 +2355,9 @@ void TemplateTable::load_resolved_field_entry(Register obj,
   __ load_unsigned_byte(flags, Address(cache, in_bytes(ResolvedFieldEntry::flags_offset())));
 
   // TOS state
-  __ load_unsigned_byte(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset())));
+  if (tos_state != noreg) {
+    __ load_unsigned_byte(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset())));
+  }
 
   // Klass overwrite register
   if (is_static) {
@@ -3069,13 +3071,9 @@ void TemplateTable::fast_storefield(TosState state)
 
   // access constant pool cache
   __ load_field_entry(r2, r1);
-  __ push(r0);
-  // R1: field offset, R2: TOS, R3: flags
-  load_resolved_field_entry(r2, r2, r0, r1, r3);
-  __ pop(r0);
 
-  // Must prevent reordering of the following cp cache loads with bytecode load
-  __ membar(MacroAssembler::LoadLoad);
+  // R1: field offset, R2: field holder, R3: flags
+  load_resolved_field_entry(r2, r2, noreg, r1, r3);
 
   {
     Label notVolatile;
@@ -3163,9 +3161,6 @@ void TemplateTable::fast_accessfield(TosState state)
   // access constant pool cache
   __ load_field_entry(r2, r1);
 
-  // Must prevent reordering of the following cp cache loads with bytecode load
-  __ membar(MacroAssembler::LoadLoad);
-
   __ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/);
   __ load_unsigned_byte(r3, Address(r2, in_bytes(ResolvedFieldEntry::flags_offset())));
 
diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
index a770482b12189..c5f97b60c4239 100644
--- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
@@ -1881,6 +1881,8 @@ void InterpreterMacroAssembler::load_field_entry(Register cache, Register index,
   ld(cache, Address(xcpool, ConstantPoolCache::field_entries_offset()));
   add(cache, cache, Array::base_offset_in_bytes());
   add(cache, cache, index);
+  // Prevents stale data from being read after the bytecode is patched to the fast bytecode
+  membar(MacroAssembler::LoadLoad);
 }
 
 void InterpreterMacroAssembler::get_method_counters(Register method,
diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
index 6240e4b4b50e1..5c72ddc9f81de 100644
--- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp
+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
@@ -2272,7 +2272,9 @@ void TemplateTable::load_resolved_field_entry(Register obj,
   __ load_unsigned_byte(flags, Address(cache, in_bytes(ResolvedFieldEntry::flags_offset())));
 
   // TOS state
-  __ load_unsigned_byte(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset())));
+  if (tos_state != noreg) {
+    __ load_unsigned_byte(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset())));
+  }
 
   // Klass overwrite register
   if (is_static) {
@@ -3036,13 +3038,9 @@ void TemplateTable::fast_storefield(TosState state) {
 
   // access constant pool cache
   __ load_field_entry(x12, x11);
-  __ push_reg(x10);
-  // X11: field offset, X12: TOS, X13: flags
-  load_resolved_field_entry(x12, x12, x10, x11, x13);
-  __ pop_reg(x10);
 
-  // Must prevent reordering of the following cp cache loads with bytecode load
-  __ membar(MacroAssembler::LoadLoad);
+  // X11: field offset, X12: field holder, X13: flags
+  load_resolved_field_entry(x12, x12, noreg, x11, x13);
 
   {
     Label notVolatile;
@@ -3133,9 +3131,6 @@ void TemplateTable::fast_accessfield(TosState state) {
   // access constant pool cache
   __ load_field_entry(x12, x11);
 
-  // Must prevent reordering of the following cp cache loads with bytecode load
-  __ membar(MacroAssembler::LoadLoad);
-
   __ load_sized_value(x11, Address(x12, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/);
   __ load_unsigned_byte(x13, Address(x12, in_bytes(ResolvedFieldEntry::flags_offset())));
 
diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp
index 664cd86d486a1..248055337d824 100644
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp
@@ -3495,7 +3495,7 @@ void TemplateTable::fast_storefield(TosState state) {
   __ push(rax);
   __ load_field_entry(rcx, rax);
   load_resolved_field_entry(noreg, cache, rax, rbx, rdx);
-  // RBX: field offset, RCX: RAX: TOS, RDX: flags
+  // RBX: field offset, RAX: TOS, RDX: flags
   __ andl(rdx, (1 << ResolvedFieldEntry::is_volatile_shift));
   __ pop(rax);
 

From 3d11692bf369af951867209962e8bf5886d1655f Mon Sep 17 00:00:00 2001
From: Emanuel Peter 
Date: Tue, 30 Apr 2024 16:15:07 +0000
Subject: [PATCH 018/203] 8331252: C2: MergeStores: handle negative shift
 values

Reviewed-by: kvn, shade
---
 src/hotspot/share/opto/memnode.cpp            |  4 +--
 .../jtreg/compiler/c2/TestMergeStores.java    | 25 ++++++++++++++++++-
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp
index a13a53f9b1952..e0eed9e3f57a8 100644
--- a/src/hotspot/share/opto/memnode.cpp
+++ b/src/hotspot/share/opto/memnode.cpp
@@ -3108,8 +3108,8 @@ bool MergePrimitiveArrayStores::is_con_RShift(const Node* n, Node const*& base_o
       n->in(2)->is_ConI()) {
     base_out = n->in(1);
     shift_out = n->in(2)->get_int();
-    assert(shift_out >= 0, "must be positive");
-    return true;
+    // The shift must be positive:
+    return shift_out >= 0;
   }
   return false;
 }
diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java
index 2f662a1ed263c..555946502196b 100644
--- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java
+++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java
@@ -187,6 +187,10 @@ public TestMergeStores() {
         testGroups.put("test600", new HashMap());
         testGroups.get("test600").put("test600R", (_,i) -> { return test600R(aB.clone(), aI.clone(), i); });
         testGroups.get("test600").put("test600a", (_,i) -> { return test600a(aB.clone(), aI.clone(), i); });
+
+        testGroups.put("test700", new HashMap());
+        testGroups.get("test700").put("test700R", (_,i) -> { return test700R(aI.clone(), i); });
+        testGroups.get("test700").put("test700a", (_,i) -> { return test700a(aI.clone(), i); });
     }
 
     @Warmup(100)
@@ -220,7 +224,8 @@ public TestMergeStores() {
                  "test500a",
                  "test501a",
                  "test502a",
-                 "test600a"})
+                 "test600a",
+                 "test700a"})
     public void runTests(RunInfo info) {
         // Repeat many times, so that we also have multiple iterations for post-warmup to potentially recompile
         int iters = info.isWarmUp() ? 1_000 : 50_000;
@@ -1296,4 +1301,22 @@ static Object[] test600a(byte[] aB, int[] aI, int i) {
         return new Object[]{ aB, aI };
     }
 
+    @DontCompile
+    static Object[] test700R(int[] a, long v1) {
+        a[0] = (int)(v1 >> -1);
+        a[1] = (int)(v1 >> -2);
+        return new Object[]{ a };
+    }
+
+    @Test
+    @IR(counts = {IRNode.STORE_B_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+                  IRNode.STORE_C_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0",
+                  IRNode.STORE_I_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "2",
+                  IRNode.STORE_L_OF_CLASS, "int\\\\[int:>=0] \\\\(java/lang/Cloneable,java/io/Serializable\\\\)", "0"})
+    static Object[] test700a(int[] a, long v1) {
+        // Negative shift: cannot optimize
+        a[0] = (int)(v1 >> -1);
+        a[1] = (int)(v1 >> -2);
+        return new Object[]{ a };
+    }
 }

From aca1e8365bf0f64bf18caf798bbca1d25b3c4117 Mon Sep 17 00:00:00 2001
From: Zhengyu Gu 
Date: Tue, 30 Apr 2024 16:20:10 +0000
Subject: [PATCH 019/203] 8329223: Parallel: Parallel GC resizes heap even if
 -Xms = -Xmx

Reviewed-by: ayang, gli
---
 src/hotspot/share/gc/shared/genArguments.cpp | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/hotspot/share/gc/shared/genArguments.cpp b/src/hotspot/share/gc/shared/genArguments.cpp
index 8e8abc6fb960d..da9fc3f9a851e 100644
--- a/src/hotspot/share/gc/shared/genArguments.cpp
+++ b/src/hotspot/share/gc/shared/genArguments.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -276,6 +276,9 @@ void GenArguments::initialize_size_info() {
   // and maximum heap size since no explicit flags exist
   // for setting the old generation maximum.
   MaxOldSize = MAX2(MaxHeapSize - max_young_size, GenAlignment);
+  MinOldSize = MIN3(MaxOldSize,
+                    InitialHeapSize - initial_young_size,
+                    MinHeapSize - MinNewSize);
 
   size_t initial_old_size = OldSize;
 
@@ -287,9 +290,8 @@ void GenArguments::initialize_size_info() {
     // with the overall heap size).  In either case make
     // the minimum, maximum and initial sizes consistent
     // with the young sizes and the overall heap sizes.
-    MinOldSize = GenAlignment;
     initial_old_size = clamp(InitialHeapSize - initial_young_size, MinOldSize, MaxOldSize);
-    // MaxOldSize has already been made consistent above.
+    // MaxOldSize and MinOldSize have already been made consistent above.
   } else {
     // OldSize has been explicitly set on the command line. Use it
     // for the initial size but make sure the minimum allow a young
@@ -304,9 +306,10 @@ void GenArguments::initialize_size_info() {
                             ", -XX:OldSize flag is being ignored",
                             MaxHeapSize);
       initial_old_size = MaxOldSize;
+    } else if (initial_old_size < MinOldSize) {
+      log_warning(gc, ergo)("Inconsistency between initial old size and minimum old size");
+      MinOldSize = initial_old_size;
     }
-
-    MinOldSize = MIN2(initial_old_size, MinHeapSize - MinNewSize);
   }
 
   // The initial generation sizes should match the initial heap size,

From a863ef5d74e9001a143af4638422348ee946c939 Mon Sep 17 00:00:00 2001
From: Justin Lu 
Date: Tue, 30 Apr 2024 16:50:01 +0000
Subject: [PATCH 020/203] 8331207: Misleading example in DateFormat#parse docs

Reviewed-by: naoto
---
 src/java.base/share/classes/java/text/DateFormat.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/java.base/share/classes/java/text/DateFormat.java b/src/java.base/share/classes/java/text/DateFormat.java
index d7a4b5a39b72a..a67ba6768366d 100644
--- a/src/java.base/share/classes/java/text/DateFormat.java
+++ b/src/java.base/share/classes/java/text/DateFormat.java
@@ -407,7 +407,8 @@ public Date parse(String source) throws ParseException
 
     /**
      * Parse a date/time string according to the given parse position.  For
-     * example, a time text {@code "07/10/96 4:5 PM, PDT"} will be parsed into a {@code Date}
+     * example, if {@code this} has the pattern {@code "M/d/yy h:m a, z"},
+     * then a time text {@code "07/10/96 4:5 PM, PDT"} will be parsed into a {@code Date}
      * that is equivalent to {@code Date(837039900000L)}.
      *
      * 

By default, parsing is lenient: If the input is not in the form used From b96b38c2c9a310d5fe49b2eda3e113a71223c7d1 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 30 Apr 2024 17:33:23 +0000 Subject: [PATCH 021/203] 8318682: SA decoding of scalar replaced objects is broken Reviewed-by: cjplummer, cslucas --- .../sun/jvm/hotspot/asm/Disassembler.java | 5 +- .../jvm/hotspot/code/DebugInfoReadStream.java | 18 ++- .../sun/jvm/hotspot/code/MarkerValue.java | 38 ++++++ .../classes/sun/jvm/hotspot/code/NMethod.java | 17 ++- .../jvm/hotspot/code/ObjectMergeValue.java | 71 +++++++++++ .../sun/jvm/hotspot/code/ObjectValue.java | 8 +- .../sun/jvm/hotspot/code/ScopeValue.java | 23 +++- .../sun/jvm/hotspot/oops/ConstMethod.java | 8 +- .../jtreg/ProblemList-generational-zgc.txt | 1 + .../serviceability/sa/ClhsdbLauncher.java | 1 + .../sa/ClhsdbTestAllocationMerge.java | 64 ++++++++++ .../sa/LingeredAppWithAllocationMerge.java | 64 ++++++++++ .../sa/TestDebugInfoDecode.java | 119 ++++++++++++++++++ 13 files changed, 423 insertions(+), 14 deletions(-) create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/MarkerValue.java create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectMergeValue.java create mode 100644 test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java create mode 100644 test/hotspot/jtreg/serviceability/sa/LingeredAppWithAllocationMerge.java create mode 100644 test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/asm/Disassembler.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/asm/Disassembler.java index 6fc7f94af38d2..11a4c3962bc2e 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/asm/Disassembler.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/asm/Disassembler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,9 @@ private Disassembler(long startPc, byte[] code) { .get(); String arch = targetSysProps.getProperty("os.arch"); + if (arch.equals("x86_64")) { + arch = "amd64"; + } String libname = "hsdis-" + arch + ext; List libs = List.of( diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java index 0ab2bbdc60850..c687fa0bbf548 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,22 @@ ScopeValue readObjectValue() { return result; } + ScopeValue readObjectMergeValue() { + int id = readInt(); + if (Assert.ASSERTS_ENABLED) { + Assert.that(objectPool != null, "object pool does not exist"); + for (Iterator itr = objectPool.iterator(); itr.hasNext();) { + ObjectValue ov = (ObjectValue) itr.next(); + Assert.that(ov.id() != id, "should not be read twice"); + } + } + ObjectValue result = new ObjectMergeValue(id); + // Cache the object since an object field could reference it. + objectPool.add(result); + result.readObject(this); + return result; + } + ScopeValue getCachedObject() { int id = readInt(); Assert.that(objectPool != null, "object pool does not exist"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/MarkerValue.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/MarkerValue.java new file mode 100644 index 0000000000000..39d48c60f2e0a --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/MarkerValue.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.code; + +import java.io.PrintStream; + +/** A placeholder value that has no concrete meaning other than helping constructing + * other values. + */ +public class MarkerValue extends ScopeValue { + public boolean isMarker() { return true; } + + public void printOn(PrintStream tty) { + tty.print("marker"); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java index ec329aa131a9b..8eacd1a8a8643 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -199,7 +199,7 @@ public int immutableDataSize() { public OopHandle getOopAt(int index) { if (index == 0) return null; if (Assert.ASSERTS_ENABLED) { - Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index"); + Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index: " + index); } return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize()); } @@ -208,7 +208,7 @@ public OopHandle getOopAt(int index) { public Address getMetadataAt(int index) { if (index == 0) return null; if (Assert.ASSERTS_ENABLED) { - Assert.that(index > 0 && index <= getMetadataLength(), "must be a valid non-zero index"); + Assert.that(index > 0 && index <= getMetadataLength(), "must be a valid non-zero index: " + index); } return metadataBegin().getAddressAt((index - 1) * VM.getVM().getOopSize()); } @@ -298,6 +298,19 @@ public PCDesc getPCDescAt(Address pc) { return null; } + /** + * Attempt to decode all the debug info in this nmethod. This is intended purely for testing. + */ + public void decodeAllScopeDescs() { + for (Address p = scopesPCsBegin(); p.lessThan(scopesPCsEnd()); p = p.addOffsetTo(pcDescSize)) { + PCDesc pd = new PCDesc(p); + if (pd.getPCOffset() == -1) { + break; + } + ScopeDesc sd = new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute()); + } + } + /** ScopeDesc for an instruction */ public ScopeDesc getScopeDescAt(Address pc) { PCDesc pd = getPCDescAt(pc); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectMergeValue.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectMergeValue.java new file mode 100644 index 0000000000000..e91c70f75972d --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectMergeValue.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.code; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + +class ObjectMergeValue extends ObjectValue { + + private ScopeValue selector; + private ScopeValue mergePointer; + private List possibleObjects; + + public ObjectMergeValue(int id) { + super(id); + } + + public boolean isObjectMerge() { return true; } + + void readObject(DebugInfoReadStream stream) { + selector = ScopeValue.readFrom(stream); + mergePointer = ScopeValue.readFrom(stream); + possibleObjects = new ArrayList<>(); + int length = stream.readInt(); + for (int i = 0; i < length; i++) { + ScopeValue val = readFrom(stream); + possibleObjects.add(val); + } + } + + @Override + public void printOn(PrintStream tty) { + tty.print("merge_obj[" + id + "]"); + tty.print(" selector=\""); + selector.printOn(tty); + tty.print("\""); + + tty.print(" merge_pointer=\""); + mergePointer.printOn(tty); + tty.print("\""); + + tty.print(", candidate_objs=[" + ((ObjectValue) possibleObjects.get(0)).id); + for (int i = 1; i < possibleObjects.size(); i++) { + tty.print("," + ((ObjectValue) possibleObjects.get(i)).id); + } + tty.print("]"); + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectValue.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectValue.java index 56d0ce160f29f..1cbc1f71e020b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectValue.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ObjectValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,8 @@ /** An ObjectValue describes an object eliminated by escape analysis. */ public class ObjectValue extends ScopeValue { - private int id; + protected final int id; + private boolean isRoot; private ScopeValue klass; private List fieldsValue; @@ -61,8 +62,9 @@ public ObjectValue(int id) { /** Serialization of debugging information */ void readObject(DebugInfoReadStream stream) { + isRoot = stream.readBoolean(); klass = readFrom(stream); - Assert.that(klass.isConstantOop(), "should be constant klass oop"); + Assert.that(klass.isConstantOop(), "should be constant klass oop: " + klass); int length = stream.readInt(); for (int i = 0; i < length; i++) { ScopeValue val = readFrom(stream); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ScopeValue.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ScopeValue.java index 163b0d12294af..4bb2076e8e9d8 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ScopeValue.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/ScopeValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.jvm.hotspot.code; import java.io.*; +import java.nio.charset.StandardCharsets; import sun.jvm.hotspot.utilities.*; @@ -51,6 +52,9 @@ public abstract class ScopeValue { static final int CONSTANT_DOUBLE_CODE = 4; static final int CONSTANT_OBJECT_CODE = 5; static final int CONSTANT_OBJECT_ID_CODE = 6; + static final int AUTO_BOX_OBJECT_CODE = 7; + static final int MARKER_CODE = 8; + static final int OBJECT_MERGE_CODE = 9; public boolean isLocation() { return false; } public boolean isConstantInt() { return false; } @@ -58,6 +62,8 @@ public abstract class ScopeValue { public boolean isConstantLong() { return false; } public boolean isConstantOop() { return false; } public boolean isObject() { return false; } + public boolean isMarker() { return false; } + public boolean isObjectMerge() { return false; } public static ScopeValue readFrom(DebugInfoReadStream stream) { switch (stream.readInt()) { @@ -72,9 +78,17 @@ public static ScopeValue readFrom(DebugInfoReadStream stream) { case CONSTANT_DOUBLE_CODE: return new ConstantDoubleValue(stream); case CONSTANT_OBJECT_CODE: + case AUTO_BOX_OBJECT_CODE: + // The C++ code handles these 2 cases separately because the autobox case needs + // some extra state during deoptimization. That's not required to display the + // information so treat it like a normal object value. return stream.readObjectValue(); case CONSTANT_OBJECT_ID_CODE: return stream.getCachedObject(); + case MARKER_CODE: + return new MarkerValue(); + case OBJECT_MERGE_CODE: + return stream.readObjectMergeValue(); default: Assert.that(false, "should not reach here"); return null; @@ -82,4 +96,11 @@ public static ScopeValue readFrom(DebugInfoReadStream stream) { } public abstract void printOn(PrintStream tty); + + public String toString() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos, true, StandardCharsets.UTF_8); + printOn(ps); + return baos.toString(StandardCharsets.UTF_8); + } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstMethod.java index 4bd2c9d3cbd07..4e7456a774537 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstMethod.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -317,13 +317,9 @@ public int getLineNumberFromBCI(int bci) { return -1; } - if (Assert.ASSERTS_ENABLED) { - Assert.that(0 <= bci && bci < getCodeSize(), - "illegal bci(" + bci + ") codeSize(" + getCodeSize() + ")"); - } int bestBCI = 0; int bestLine = -1; - if (hasLineNumberTable()) { + if (0 <= bci && bci < getCodeSize() && hasLineNumberTable()) { // The line numbers are a short array of 2-tuples [start_pc, line_number]. // Not necessarily sorted and not necessarily one-to-one. CompressedLineNumberReadStream stream = diff --git a/test/hotspot/jtreg/ProblemList-generational-zgc.txt b/test/hotspot/jtreg/ProblemList-generational-zgc.txt index cbe76d68dff3a..a92751cc62106 100644 --- a/test/hotspot/jtreg/ProblemList-generational-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-generational-zgc.txt @@ -106,6 +106,7 @@ serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java 8307393 generic- serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java 8307393 generic-all serviceability/sa/sadebugd/ClhsdbAttachToDebugServer.java 8307393 generic-all serviceability/sa/sadebugd/ClhsdbTestConnectArgument.java 8307393 generic-all +serviceability/sa/ClhsdbTestAllocationMerge.java 8307393 generic-all serviceability/sa/sadebugd/DebugdConnectTest.java 8307393 generic-all serviceability/sa/sadebugd/DebugdUtils.java 8307393 generic-all serviceability/sa/sadebugd/DisableRegistryTest.java 8307393 generic-all diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java index 961311f5d5b09..849ec2eb109fe 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java @@ -149,6 +149,7 @@ private String runCmd(List commands, oa.shouldNotMatch("^WARNING in native method:.*$"); // This will detect most SA failures, including during the attach. oa.shouldNotMatch("^sun.jvm.hotspot.debugger.DebuggerException:.*$"); + oa.shouldNotMatch("sun.jvm.hotspot.utilities.AssertionFailure"); // This will detect unexpected exceptions, like NPEs and asserts, that are caught // by sun.jvm.hotspot.CommandProcessor. oa.shouldNotMatch("^Error: .*$"); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java new file mode 100644 index 0000000000000..2e17bc038de66 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.util.List; +import jdk.test.lib.apps.LingeredApp; +import jtreg.SkippedException; + +/** + * @test + * @bug 8318682 + * @summary Test clhsdb that decoding of AllocationMerge objects in debug info works correctly + * @requires vm.hasSA + * @library /test/lib + * @run main/othervm ClhsdbTestAllocationMerge + */ + +public class ClhsdbTestAllocationMerge { + + public static void main(String[] args) throws Exception { + System.out.println("Starting ClhsdbTestDebugInfodDecode test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + + theApp = new LingeredAppWithAllocationMerge(); + LingeredApp.startApp(theApp); + System.out.println("Started LingeredAppWithAllocationMerge with pid " + theApp.getPid()); + + List cmds = List.of("jstack -v"); + + // sun.jvm.hotspot.utilities.AssertionFailure is caught by the harness so it's not + // necessary to include extra filters here. + test.run(theApp.getPid(), cmds, null, null); + } catch (SkippedException se) { + throw se; + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithAllocationMerge.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithAllocationMerge.java new file mode 100644 index 0000000000000..a4743d763072d --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithAllocationMerge.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 jdk.test.lib.apps.LingeredApp; + +// Derived from test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndHeapDump.java +public class LingeredAppWithAllocationMerge extends LingeredApp { + // Helper class + static class Point { + public int x; + + public Point(int xx) { + this.x = xx; + } + } + + + public static Point p = new Point(0); + + public static void main(String[] args) { + for (int i = 0; i < 5000; i++) { + testIt(i, args); + } + } + + public static void testIt(int i, String[] args) { + Point p = (i % 2 == 0) ? new Point(i) : new Point(i); + + dummy(i, args); + + if (i < 5000) { + dummy(i, args); + } else { + dummy(p.x + i, args); + } + } + + public static void dummy(int x, String[] args) { + if (x > 4900) { + LingeredApp.main(args); + throw new InternalError("should never return"); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java b/test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java new file mode 100644 index 0000000000000..257f950b12f96 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 sun.jvm.hotspot.HotSpotAgent; +import sun.jvm.hotspot.code.CodeCacheVisitor; +import sun.jvm.hotspot.code.CodeBlob; +import sun.jvm.hotspot.code.NMethod; +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; + +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.SA.SATestUtils; + +/** + * @test + * @bug 8318682 + * @summary Test decoding debug info for all nmethods in the code cache + * @requires vm.hasSA + * @library /test/lib + * @modules jdk.hotspot.agent/sun.jvm.hotspot + * jdk.hotspot.agent/sun.jvm.hotspot.code + * jdk.hotspot.agent/sun.jvm.hotspot.debugger + * jdk.hotspot.agent/sun.jvm.hotspot.runtime + * @run main/othervm/timeout=2400 -Xmx1g -Xcomp TestDebugInfoDecode + */ + +public class TestDebugInfoDecode { + + private static LingeredApp theApp = null; + + private static void checkDecode(String pid) throws Exception { + HotSpotAgent agent = new HotSpotAgent(); + + try { + agent.attach(Integer.parseInt(pid)); + + CodeCacheVisitor v = new CodeCacheVisitor() { + Throwable throwable; + public void prologue(Address start, Address end) { + } + public void visit(CodeBlob blob) { + if (throwable != null) { + // Only report the first failure. + return; + } + if (blob instanceof NMethod) { + NMethod nm = (NMethod) blob; + try { + nm.decodeAllScopeDescs(); + } catch (Throwable t) { + System.err.println("Exception while decoding debug info for " + blob); + throwable = t; + throw t; + } + } + } + public void epilogue() { + } + }; + VM.getVM().getCodeCache().iterate(v); + } finally { + agent.detach(); + } + } + + private static void createAnotherToAttach(long lingeredAppPid) throws Exception { + // Start a new process to attach to the lingered app + ProcessBuilder processBuilder = ProcessTools.createLimitedTestJavaProcessBuilder( + "--add-modules=jdk.hotspot.agent", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.code=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED", + "TestDebugInfoDecode", + Long.toString(lingeredAppPid) + ); + SATestUtils.addPrivilegesIfNeeded(processBuilder); + OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder); + SAOutput.shouldHaveExitValue(0); + System.out.println(SAOutput.getOutput()); + } + + public static void main (String... args) throws Exception { + SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work. + if (args == null || args.length == 0) { + try { + theApp = new LingeredApp(); + LingeredApp.startApp(theApp); + createAnotherToAttach(theApp.getPid()); + } finally { + LingeredApp.stopApp(theApp); + } + } else { + checkDecode(args[0]); + } + } +} From f215899a088d1abe86adccf0e65a073189272ddd Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Wed, 1 May 2024 08:09:53 +0000 Subject: [PATCH 022/203] 8331393: AArch64: u32 _partial_subtype_ctr loaded/stored as 64 Reviewed-by: aph, fyang --- src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 6 +----- src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp | 5 +---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 8eb2000359ca6..b90b5862ee50e 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -1560,11 +1560,7 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, } #ifndef PRODUCT - mov(rscratch2, (address)&SharedRuntime::_partial_subtype_ctr); - Address pst_counter_addr(rscratch2); - ldr(rscratch1, pst_counter_addr); - add(rscratch1, rscratch1, 1); - str(rscratch1, pst_counter_addr); + incrementw(ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr)); #endif //PRODUCT // We will consult the secondary-super array. diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 29b95fdb2dd0c..8d207b3f66569 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -86,10 +86,7 @@ class StubGenerator: public StubCodeGenerator { #define inc_counter_np(counter) ((void)0) #else void inc_counter_np_(uint& counter) { - __ lea(rscratch2, ExternalAddress((address)&counter)); - __ ldrw(rscratch1, Address(rscratch2)); - __ addw(rscratch1, rscratch1, 1); - __ strw(rscratch1, Address(rscratch2)); + __ incrementw(ExternalAddress((address)&counter)); } #define inc_counter_np(counter) \ BLOCK_COMMENT("inc_counter " #counter); \ From 663acd2e173114fec7c2f50084af9ec56150d394 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 1 May 2024 08:40:48 +0000 Subject: [PATCH 023/203] 8330969: scalability issue with loaded JVMTI agent Reviewed-by: amenkov, cjplummer --- src/hotspot/share/prims/jvmtiEnvBase.cpp | 17 +++++------ src/hotspot/share/prims/jvmtiThreadState.cpp | 32 +++++++++++--------- src/hotspot/share/prims/jvmtiThreadState.hpp | 5 +-- src/hotspot/share/runtime/javaThread.cpp | 1 + src/hotspot/share/runtime/javaThread.hpp | 4 +++ 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 4ed01df0b3d80..1615e3c349cc9 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1633,19 +1633,16 @@ class VM_SetNotifyJvmtiEventsMode : public VM_Operation { } // This function is called only if _enable == true. - // Iterates over all JavaThread's, counts VTMS transitions and restores - // jt->jvmti_thread_state() and jt->jvmti_vthread() for VTMS transition protocol. - int count_transitions_and_correct_jvmti_thread_states() { - int count = 0; - + // Iterates over all JavaThread's, restores jt->jvmti_thread_state() and + // jt->jvmti_vthread() for VTMS transition protocol. + void correct_jvmti_thread_states() { for (JavaThread* jt : ThreadsListHandle()) { if (jt->is_in_VTMS_transition()) { - count++; + jt->set_VTMS_transition_mark(true); continue; // no need in JvmtiThreadState correction below if in transition } correct_jvmti_thread_state(jt); } - return count; } public: @@ -1655,9 +1652,9 @@ class VM_SetNotifyJvmtiEventsMode : public VM_Operation { } void doit() { - int count = _enable ? count_transitions_and_correct_jvmti_thread_states() : 0; - - JvmtiVTMSTransitionDisabler::set_VTMS_transition_count(count); + if (_enable) { + correct_jvmti_thread_states(); + } JvmtiVTMSTransitionDisabler::set_VTMS_notify_jvmti_events(_enable); } }; diff --git a/src/hotspot/share/prims/jvmtiThreadState.cpp b/src/hotspot/share/prims/jvmtiThreadState.cpp index 1e866236c985a..c95f56461936c 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.cpp +++ b/src/hotspot/share/prims/jvmtiThreadState.cpp @@ -214,9 +214,6 @@ JvmtiThreadState::periodic_clean_up() { // Virtual Threads Mount State transition (VTMS transition) mechanism // -// VTMS transitions cannot be disabled while this counter is positive. -volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_count = 0; - // VTMS transitions for one virtual thread are disabled while it is positive volatile int JvmtiVTMSTransitionDisabler::_VTMS_transition_disable_for_one_count = 0; @@ -238,11 +235,14 @@ volatile bool JvmtiVTMSTransitionDisabler::_sync_protocol_enabled_permanently = #ifdef ASSERT void JvmtiVTMSTransitionDisabler::print_info() { - log_error(jvmti)("_VTMS_transition_count: %d\n", _VTMS_transition_count); log_error(jvmti)("_VTMS_transition_disable_for_one_count: %d\n", _VTMS_transition_disable_for_one_count); log_error(jvmti)("_VTMS_transition_disable_for_all_count: %d\n\n", _VTMS_transition_disable_for_all_count); int attempts = 10000; for (JavaThreadIteratorWithHandle jtiwh; JavaThread *java_thread = jtiwh.next(); ) { + if (java_thread->VTMS_transition_mark()) { + log_error(jvmti)("jt: %p VTMS_transition_mark: %d\n", + (void*)java_thread, java_thread->VTMS_transition_mark()); + } ResourceMark rm; // Handshake with target. PrintStackTraceClosure pstc; @@ -358,11 +358,13 @@ JvmtiVTMSTransitionDisabler::VTMS_transition_disable_for_all() { // Block while some mount/unmount transitions are in progress. // Debug version fails and prints diagnostic information. - while (_VTMS_transition_count > 0) { - if (ml.wait(10)) { - attempts--; + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { + while (jt->VTMS_transition_mark()) { + if (ml.wait(10)) { + attempts--; + } + DEBUG_ONLY(if (attempts == 0) break;) } - DEBUG_ONLY(if (attempts == 0) break;) } assert(!thread->is_VTMS_transition_disabler(), "VTMS_transition sanity check"); #ifdef ASSERT @@ -427,8 +429,9 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun assert(!thread->is_in_VTMS_transition(), "VTMS_transition sanity check"); // Avoid using MonitorLocker on performance critical path, use - // two-level synchronization with lock-free operations on counters. - Atomic::inc(&_VTMS_transition_count); // Try to enter VTMS transition section optmistically. + // two-level synchronization with lock-free operations on state bits. + assert(!thread->VTMS_transition_mark(), "sanity check"); + thread->set_VTMS_transition_mark(true); // Try to enter VTMS transition section optmistically. java_lang_Thread::set_is_in_VTMS_transition(vt, true); if (!sync_protocol_enabled()) { @@ -448,9 +451,9 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun thread->is_suspended() || JvmtiVTSuspender::is_vthread_suspended(thread_id) ) { - // Slow path: undo unsuccessful optimistic counter incrementation. + // Slow path: undo unsuccessful optimistic set of the VTMS_transition_mark. // It can cause an extra waiting cycle for VTMS transition disablers. - Atomic::dec(&_VTMS_transition_count); + thread->set_VTMS_transition_mark(false); java_lang_Thread::set_is_in_VTMS_transition(vth(), false); while (true) { @@ -470,7 +473,7 @@ JvmtiVTMSTransitionDisabler::start_VTMS_transition(jthread vthread, bool is_moun DEBUG_ONLY(if (attempts == 0) break;) continue; // ~ThreadBlockInVM has handshake-based suspend point. } - Atomic::inc(&_VTMS_transition_count); + thread->set_VTMS_transition_mark(true); java_lang_Thread::set_is_in_VTMS_transition(vth(), true); break; } @@ -495,7 +498,8 @@ JvmtiVTMSTransitionDisabler::finish_VTMS_transition(jthread vthread, bool is_mou thread->set_is_in_VTMS_transition(false); oop vt = JNIHandles::resolve_external_guard(vthread); java_lang_Thread::set_is_in_VTMS_transition(vt, false); - Atomic::dec(&_VTMS_transition_count); + assert(thread->VTMS_transition_mark(), "sanity check"); + thread->set_VTMS_transition_mark(false); if (!sync_protocol_enabled()) { return; diff --git a/src/hotspot/share/prims/jvmtiThreadState.hpp b/src/hotspot/share/prims/jvmtiThreadState.hpp index 8d49f8af96c0c..ff7b6a1ebde57 100644 --- a/src/hotspot/share/prims/jvmtiThreadState.hpp +++ b/src/hotspot/share/prims/jvmtiThreadState.hpp @@ -82,9 +82,8 @@ class JvmtiVTMSTransitionDisabler { static volatile int _VTMS_transition_disable_for_one_count; // transitions for one virtual thread are disabled while it is positive static volatile int _VTMS_transition_disable_for_all_count; // transitions for all virtual threads are disabled while it is positive static volatile bool _SR_mode; // there is an active suspender or resumer - static volatile int _VTMS_transition_count; // current number of VTMS transitions static volatile int _sync_protocol_enabled_count; // current number of JvmtiVTMSTransitionDisablers enabled sync protocol - static volatile bool _sync_protocol_enabled_permanently; // seen a suspender: JvmtiVTMSTraansitionDisabler protocol is enabled permanently + static volatile bool _sync_protocol_enabled_permanently; // seen a suspender: JvmtiVTMSTransitionDisabler protocol is enabled permanently bool _is_SR; // is suspender or resumer jthread _thread; // virtual thread to disable transitions for, no-op if it is a platform thread @@ -100,8 +99,6 @@ class JvmtiVTMSTransitionDisabler { static bool VTMS_notify_jvmti_events() { return _VTMS_notify_jvmti_events; } static void set_VTMS_notify_jvmti_events(bool val) { _VTMS_notify_jvmti_events = val; } - static void set_VTMS_transition_count(bool val) { _VTMS_transition_count = val; } - static void inc_sync_protocol_enabled_count() { Atomic::inc(&_sync_protocol_enabled_count); } static void dec_sync_protocol_enabled_count() { Atomic::dec(&_sync_protocol_enabled_count); } static int sync_protocol_enabled_count() { return Atomic::load(&_sync_protocol_enabled_count); } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index cbb63fd60dfe7..2e40c99455c9d 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -450,6 +450,7 @@ JavaThread::JavaThread() : _is_in_VTMS_transition(false), _is_in_tmp_VTMS_transition(false), _is_disable_suspend(false), + _VTMS_transition_mark(false), #ifdef ASSERT _is_VTMS_transition_disabler(false), #endif diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index abba4c75de881..6b6c9139b78eb 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -317,6 +317,7 @@ class JavaThread: public Thread { bool _is_in_VTMS_transition; // thread is in virtual thread mount state transition bool _is_in_tmp_VTMS_transition; // thread is in temporary virtual thread mount state transition bool _is_disable_suspend; // JVMTI suspend is temporarily disabled; used on current thread only + bool _VTMS_transition_mark; // used for sync between VTMS transitions and disablers #ifdef ASSERT bool _is_VTMS_transition_disabler; // thread currently disabled VTMS transitions #endif @@ -664,6 +665,9 @@ class JavaThread: public Thread { bool is_disable_suspend() const { return _is_disable_suspend; } void toggle_is_disable_suspend() { _is_disable_suspend = !_is_disable_suspend; }; + bool VTMS_transition_mark() const { return Atomic::load(&_VTMS_transition_mark); } + void set_VTMS_transition_mark(bool val) { Atomic::store(&_VTMS_transition_mark, val); } + #ifdef ASSERT bool is_VTMS_transition_disabler() const { return _is_VTMS_transition_disabler; } void set_is_VTMS_transition_disabler(bool val); From b2fb5ea13ba5087411410519213fc953ecc44618 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Wed, 1 May 2024 11:53:28 +0000 Subject: [PATCH 024/203] 8331142: Add test for number of loader threads in BasicDirectoryModel Reviewed-by: serb, tr --- .../LoaderThreadCount.java | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java diff --git a/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java new file mode 100644 index 0000000000000..b471c51a260b9 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.LongStream; +import java.util.stream.Stream; + +import javax.swing.JFileChooser; + +/* + * @test + * @bug 8325179 + * @summary Verifies there's only one BasicDirectoryModel.FilesLoader thread + * at any given moment + * @run main/othervm -Djava.awt.headless=true LoaderThreadCount + */ +public final class LoaderThreadCount extends ThreadGroup { + /** Initial number of files. */ + private static final long NUMBER_OF_FILES = 500; + + /** + * Number of threads running {@code fileChooser.rescanCurrentDirectory()}. + */ + private static final int NUMBER_OF_THREADS = 5; + + /** Number of snapshots with live threads. */ + private static final int SNAPSHOTS = 20; + + /** The barrier to synchronise scanner threads and capturing live threads. */ + private static final CyclicBarrier start = new CyclicBarrier(NUMBER_OF_THREADS + 1); + + /** List of scanner threads. */ + private static final List threads = new ArrayList<>(NUMBER_OF_THREADS); + + /** + * Stores an exception caught by any of the threads. + * If more exceptions are caught, they're added as suppressed exceptions. + */ + private static final AtomicReference exception = + new AtomicReference<>(); + + /** + * Stores an {@code IOException} thrown while removing the files. + */ + private static final AtomicReference ioException = + new AtomicReference<>(); + + + public static void main(String[] args) throws Throwable { + try { + // Start the test in its own thread group to catch and handle + // all thrown exceptions, in particular in + // BasicDirectoryModel.FilesLoader which is created by Swing. + ThreadGroup threadGroup = new LoaderThreadCount(); + Thread runner = new Thread(threadGroup, + LoaderThreadCount::wrapper, + "Test Runner"); + runner.start(); + runner.join(); + } catch (Throwable throwable) { + handleException(throwable); + } + + if (ioException.get() != null) { + System.err.println("An error occurred while removing files:"); + ioException.get().printStackTrace(); + } + + if (exception.get() != null) { + throw exception.get(); + } + } + + private static void wrapper() { + final long timeStart = System.currentTimeMillis(); + try { + runTest(timeStart); + } catch (Throwable throwable) { + handleException(throwable); + } finally { + System.out.printf("Duration: %,d\n", + (System.currentTimeMillis() - timeStart)); + } + } + + private static void runTest(final long timeStart) throws Throwable { + final Path temp = Files.createDirectory(Paths.get("fileChooser-concurrency-" + timeStart)); + + try { + createFiles(temp); + + final JFileChooser fc = new JFileChooser(temp.toFile()); + + threads.addAll(Stream.generate(() -> new Thread(new Scanner(fc))) + .limit(NUMBER_OF_THREADS) + .toList()); + threads.forEach(Thread::start); + + // Create snapshots of live threads + List threadsCapture = + Stream.generate(LoaderThreadCount::getThreadSnapshot) + .limit(SNAPSHOTS) + .toList(); + + threads.forEach(Thread::interrupt); + + List loaderCount = + threadsCapture.stream() + .map(ta -> Arrays.stream(ta) + .filter(Objects::nonNull) + .map(Thread::getName) + .filter(tn -> tn.startsWith("Basic L&F File Loading Thread")) + .count()) + .filter(c -> c > 0) + .toList(); + + if (loaderCount.isEmpty()) { + throw new RuntimeException("Invalid results: no loader threads detected"); + } + + System.out.println("Number of snapshots: " + loaderCount.size()); + + long ones = loaderCount.stream() + .filter(n -> n == 1) + .count(); + long twos = loaderCount.stream() + .filter(n -> n == 2) + .count(); + long count = loaderCount.stream() + .filter(n -> n > 2) + .count(); + System.out.println("Number of snapshots where number of loader threads:"); + System.out.println(" = 1: " + ones); + System.out.println(" = 2: " + twos); + System.out.println(" > 2: " + count); + if (count > 0) { + throw new RuntimeException("Detected " + count + " snapshots " + + "with several loading threads"); + } + } catch (Throwable e) { + threads.forEach(Thread::interrupt); + throw e; + } finally { + deleteFiles(temp); + deleteFile(temp); + } + } + + private static Thread[] getThreadSnapshot() { + try { + start.await(); + // Allow for the scanner threads to initiate re-scanning + Thread.sleep(10); + + Thread[] array = new Thread[Thread.activeCount()]; + Thread.currentThread() + .getThreadGroup() + .enumerate(array, false); + + // Additional delay between captures + Thread.sleep(500); + + return array; + } catch (InterruptedException | BrokenBarrierException e) { + handleException(e); + throw new RuntimeException("getThreadSnapshot is interrupted"); + } + } + + + private LoaderThreadCount() { + super("bdmConcurrency"); + } + + @Override + public void uncaughtException(Thread t, Throwable e) { + handleException(t, e); + } + + private static void handleException(Throwable throwable) { + handleException(Thread.currentThread(), throwable); + } + + private static void handleException(final Thread thread, + final Throwable throwable) { + System.err.println("Exception in " + thread.getName() + ": " + + throwable.getClass() + + (throwable.getMessage() != null + ? ": " + throwable.getMessage() + : "")); + if (!exception.compareAndSet(null, throwable)) { + exception.get().addSuppressed(throwable); + } + threads.stream() + .filter(t -> t != thread) + .forEach(Thread::interrupt); + } + + + private record Scanner(JFileChooser fileChooser) + implements Runnable { + + @Override + public void run() { + try { + do { + start.await(); + fileChooser.rescanCurrentDirectory(); + } while (!Thread.interrupted()); + } catch (InterruptedException | BrokenBarrierException e) { + // Just exit the loop + } + } + } + + private static void createFiles(final Path parent) { + LongStream.range(0, LoaderThreadCount.NUMBER_OF_FILES) + .mapToObj(n -> parent.resolve(n + ".file")) + .forEach(LoaderThreadCount::createFile); + } + + private static void createFile(final Path file) { + try { + Files.createFile(file); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static void deleteFiles(final Path parent) throws IOException { + try (var stream = Files.walk(parent)) { + stream.filter(p -> p != parent) + .forEach(LoaderThreadCount::deleteFile); + } + } + + private static void deleteFile(final Path file) { + try { + Files.delete(file); + } catch (IOException e) { + if (!ioException.compareAndSet(null, e)) { + ioException.get().addSuppressed(e); + } + } + } +} From 44dc85001d8c17a12efebd1a69d52e0b7e4e95e4 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 1 May 2024 12:19:11 +0000 Subject: [PATCH 025/203] 8331212: Error recovery for broken switch expressions could be improved Reviewed-by: asotona --- .../com/sun/tools/javac/comp/Flow.java | 3 +- .../tools/javac/recovery/FlowRecovery.java | 92 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 test/langtools/tools/javac/recovery/FlowRecovery.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 eda2772fb7593..da008bc4b539f 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 @@ -470,7 +470,8 @@ public void visitPackageDef(JCPackageDecl tree) { protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) { if (swtch.hasTag(SWITCH_EXPRESSION)) { - JCYield brk = make.at(Position.NOPOS).Yield(null); + JCYield brk = make.at(Position.NOPOS).Yield(make.Erroneous() + .setType(swtch.type)); brk.target = swtch; scan(brk); } else { diff --git a/test/langtools/tools/javac/recovery/FlowRecovery.java b/test/langtools/tools/javac/recovery/FlowRecovery.java new file mode 100644 index 0000000000000..930f230222b37 --- /dev/null +++ b/test/langtools/tools/javac/recovery/FlowRecovery.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8331212 + * @summary Verify error recovery w.r.t. Flow + * @library /tools/lib + * @enablePreview + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * java.base/jdk.internal.classfile.impl + * @build toolbox.ToolBox toolbox.JavacTask + * @run main FlowRecovery + */ + +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; + +import toolbox.JavacTask; +import toolbox.Task.Expect; +import toolbox.Task.OutputKind; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class FlowRecovery extends TestRunner { + + ToolBox tb; + + public FlowRecovery() { + super(System.err); + tb = new ToolBox(); + } + + public static void main(String[] args) throws Exception { + FlowRecovery t = new FlowRecovery(); + t.runTests(); + } + + @Test //8331212 + public void testYieldErrors() throws Exception { + String code = """ + class Test { + public boolean test() { + return switch (0) { + case 0 -> true; + default -> {} + }; + } + } + """; + Path curPath = Path.of("."); + List actual = new JavacTask(tb) + .options("-XDrawDiagnostics", "-XDdev") + .sources(code) + .outdir(curPath) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + List expected = List.of( + "Test.java:5:25: compiler.err.rule.completes.normally", + "1 error" + ); + + if (!Objects.equals(actual, expected)) { + error("Expected: " + expected + ", but got: " + actual); + } + } + +} From 4f529f8c232b4082aa4aa39766bcf42b09885ee4 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Wed, 1 May 2024 12:23:13 +0000 Subject: [PATCH 026/203] 8331427: Rename confusingly named ArraysSupport.signedHashCode Reviewed-by: redestad --- .../share/classes/jdk/internal/util/ArraysSupport.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java index 61be28519fc24..8f8ea651d6508 100644 --- a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -200,7 +200,7 @@ public static int vectorizedMismatch(Object a, long aOffset, public static int vectorizedHashCode(Object array, int fromIndex, int length, int initialValue, int basicType) { return switch (basicType) { - case T_BOOLEAN -> signedHashCode(initialValue, (byte[]) array, fromIndex, length); + case T_BOOLEAN -> unsignedHashCode(initialValue, (byte[]) array, fromIndex, length); case T_CHAR -> array instanceof byte[] ? utf16hashCode(initialValue, (byte[]) array, fromIndex, length) : hashCode(initialValue, (char[]) array, fromIndex, length); @@ -211,7 +211,7 @@ public static int vectorizedHashCode(Object array, int fromIndex, int length, in }; } - private static int signedHashCode(int result, byte[] a, int fromIndex, int length) { + private static int unsignedHashCode(int result, byte[] a, int fromIndex, int length) { int end = fromIndex + length; for (int i = fromIndex; i < end; i++) { result = 31 * result + (a[i] & 0xff); From e833bfc8ac6104522d037e7eb300f5aa112688bb Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Wed, 1 May 2024 15:26:57 +0000 Subject: [PATCH 027/203] 8331222: Malformed text in the jpackage doc page Reviewed-by: almatvee --- src/jdk.jpackage/share/man/jpackage.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jdk.jpackage/share/man/jpackage.1 b/src/jdk.jpackage/share/man/jpackage.1 index 3f5e062ee6c34..f98482000592f 100644 --- a/src/jdk.jpackage/share/man/jpackage.1 +++ b/src/jdk.jpackage/share/man/jpackage.1 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. +.\" Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. .\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. .\" .\" This code is free software; you can redistribute it and/or modify it @@ -189,7 +189,7 @@ All files in the input directory will be packaged into the application image. .RE .TP -\[ga]--app-content \f[I]additional-content\f[R][,\f[I]additional-content\f[R]...] +\f[V]--app-content\f[R] \f[I]additional-content\f[R] [\f[V],\f[R]\f[I]additional-content\f[R]...] A comma separated list of paths to files and/or directories to add to the application payload. .RS @@ -443,7 +443,7 @@ Group value of the RPM /.spec file or Section value of DEB control file Creates a shortcut for the application. .SS macOS platform options (available only when running on macOS): .TP -\[aq]--mac-dmg-content \f[I]additional-content\f[R][,\f[I]additional-content\f[R]...] +\f[V]--mac-dmg-content\f[R] \f[I]additional-content\f[R] [\f[V],\f[R]\f[I]additional-content\f[R]...] Include all the referenced content in the dmg. .RS .PP From 2a95cd473aaefcacd976d1c17aa2badf330a6c32 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Wed, 1 May 2024 16:38:25 +0000 Subject: [PATCH 028/203] 8331495: Limit BasicDirectoryModel/LoaderThreadCount.java to Windows only Reviewed-by: prr --- .../swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java index b471c51a260b9..689aca5bbdb1e 100644 --- a/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java +++ b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java @@ -40,6 +40,7 @@ /* * @test * @bug 8325179 + * @requires os.family == "windows" * @summary Verifies there's only one BasicDirectoryModel.FilesLoader thread * at any given moment * @run main/othervm -Djava.awt.headless=true LoaderThreadCount From 62d5d1e99c118b6ed26e79a2f7247308f8c23310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Trukenm=C3=BCller?= Date: Wed, 1 May 2024 16:45:42 +0000 Subject: [PATCH 029/203] 8319598: SMFParser misinterprets interrupted running status Reviewed-by: prr, serb --- .../media/sound/StandardMidiFileReader.java | 13 +- .../File/SMFInterruptedRunningStatus.java | 144 ++++++++++++++++++ 2 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java diff --git a/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java b/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java index fb24eca661157..de2a8b6306b7b 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java @@ -313,10 +313,10 @@ void readTrack(Track track) throws IOException, InvalidMidiDataException { // reset current tick to 0 long tick = 0; - // reset current status byte to 0 (invalid value). + // reset current running status byte to 0 (invalid value). // this should cause us to throw an InvalidMidiDataException if we don't // get a valid status byte from the beginning of the track. - int status = 0; + int runningStatus = 0; boolean endOfTrackFound = false; while (!trackFinished() && !endOfTrackFound) { @@ -333,10 +333,17 @@ void readTrack(Track track) throws IOException, InvalidMidiDataException { // check for new status int byteValue = readUnsigned(); + int status; if (byteValue >= 0x80) { status = byteValue; + + // update running status (only for channel messages) + if ((status & 0xF0) != 0xF0) { + runningStatus = status; + } } else { - data1 = byteValue; + status = runningStatus; + data1 = byteValue; } switch (status & 0xF0) { diff --git a/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java b/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java new file mode 100644 index 0000000000000..8aac012b45552 --- /dev/null +++ b/test/jdk/javax/sound/midi/File/SMFInterruptedRunningStatus.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2023, 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. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; + +/** + * @test + * @bug 8319598 + * @summary SMFParser bug with running status, interrupted by Meta or SysEx messages + */ +public class SMFInterruptedRunningStatus { + + public static void main(String[] args) throws Exception { + + byte[][] files = new byte[][] {SMF_1, SMF_2, SMF_3}; + for (int i = 0; i < files.length; i++) { + Sequence seq = MidiSystem.getSequence( + new ByteArrayInputStream(files[i])); + testSequence(seq, i + 1); + } + + // no exception thrown, all files have been parsed correctly + System.out.println("Test passed"); + } + + private static void testSequence(Sequence seq, int fileNumber) { + + // check number of tracks and number of events + Track[] tracks = seq.getTracks(); + if (1 != tracks.length) { + throw new RuntimeException("file number " + + fileNumber + " fails (incorrect number of tracks: " + + tracks.length + ")"); + } + Track track = tracks[0]; + if (7 != track.size()) { + throw new RuntimeException("file number " + fileNumber + + " fails (incorrect number of events: " + + track.size() + ")"); + } + + // check status byte of each message + int[] expectedStatusBytes = new int[] { + 0x90, 0xFF, 0x90, 0x90, 0x90, 0xFF, 0xFF}; + for (int i = 0; i < expectedStatusBytes.length; i++) { + int expected = expectedStatusBytes[i]; + if (expected != track.get(i).getMessage().getStatus()) { + throw new RuntimeException("file number " + fileNumber + + " fails (wrong status byte in event " + i + ")"); + } + } + } + + // MIDI file without running status - should work equally before + // and after the bugfix + private static final byte[] SMF_1 = { + 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) + 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) + 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x24, // track header + 0x00, // delta time + (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) + 0x40, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x20, // delta time + (byte) 0x90, 0x3C, 0x00, // Note-OFF (C) + 0x20, // delta time + (byte) 0x90, 0x3E, 0x7F, // Note-ON (D) + 0x60, // delta time + (byte) 0x90, 0x3E, 0x00, // Note-OFF (D) + 0x20, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x00, // delta time + (byte) 0xFF, 0x2F, 0x00 // META (end of track) + }; + + // MIDI file with running status, interrupted by a META message + // - failed before the bugfix + private static final byte[] SMF_2 = { + 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) + 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) + 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x21, // track header + 0x00, // delta time + (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) + 0x40, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (interruptor) + 0x20, // delta time + 0x3C, 0x00, // Note-OFF (C) - running status + 0x20, // delta time + 0x3E, 0x7F, // Note-ON (D) - running status + 0x60, // delta time + 0x3E, 0x00, // Note-OFF (D) - running status + 0x20, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x00, // delta time + (byte) 0xFF, 0x2F, 0x00 // META (end of track) + }; + + // MIDI file with running status, interrupted by a META message + // - succeeded before the bugfix but with wrong interpretation of the data + private static final byte[] SMF_3 = { + 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) + 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) + 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x21, // track header + 0x00, // delta time + (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) + 0x40, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (interruptor) + 0x20, // delta time + 0x3C, 0x00, // Note-OFF (C) - running status + 0x0D, // delta time + 0x3E, 0x7F, // Note-ON (D) - running status + 0x60, // delta time + 0x3E, 0x00, // Note-OFF (D) - running status + 0x20, // delta time + (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) + 0x00, // delta time + (byte) 0xFF, 0x2F, 0x00 // META (end of track) + }; +} + From 0a24daecebd90eb46a813923bb2d5672514197ce Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Wed, 1 May 2024 18:02:47 +0000 Subject: [PATCH 030/203] 8322043: HeapDumper should use parallel dump by default Reviewed-by: yyang, sspitsyn, dholmes --- src/hotspot/share/services/attachListener.cpp | 2 +- src/hotspot/share/services/heapDumper.cpp | 12 ++++++++++++ src/hotspot/share/services/heapDumper.hpp | 6 +++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/services/attachListener.cpp b/src/hotspot/share/services/attachListener.cpp index 40b1a7440184a..d1531e1ec012e 100644 --- a/src/hotspot/share/services/attachListener.cpp +++ b/src/hotspot/share/services/attachListener.cpp @@ -254,7 +254,7 @@ static jint dump_heap(AttachOperation* op, outputStream* out) { // This helps reduces the amount of unreachable objects in the dump // and makes it easier to browse. HeapDumper dumper(live_objects_only /* request GC */); - dumper.dump(path, out, level, false, HeapDumper::default_num_of_dump_threads()); + dumper.dump(path, out, level); } return JNI_OK; } diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp index c28f10215404c..eb568304dc03f 100644 --- a/src/hotspot/share/services/heapDumper.cpp +++ b/src/hotspot/share/services/heapDumper.cpp @@ -2604,6 +2604,18 @@ int HeapDumper::dump(const char* path, outputStream* out, int compression, bool out->print_cr("Dumping heap to %s ...", path); timer()->start(); } + + if (_oome && num_dump_threads > 1) { + // Each additional parallel writer requires several MB of internal memory + // (DumpWriter buffer, DumperClassCacheTable, GZipCompressor buffers). + // For the OOM handling we may already be limited in memory. + // Lets ensure we have at least 20MB per thread. + julong max_threads = os::free_memory() / (20 * M); + if (num_dump_threads > max_threads) { + num_dump_threads = MAX2(1, (uint)max_threads); + } + } + // create JFR event EventHeapDump event; diff --git a/src/hotspot/share/services/heapDumper.hpp b/src/hotspot/share/services/heapDumper.hpp index bfc31b2f2312b..a69cf72aaf0d3 100644 --- a/src/hotspot/share/services/heapDumper.hpp +++ b/src/hotspot/share/services/heapDumper.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,8 +60,8 @@ class HeapDumper : public StackObj { // dumps the heap to the specified file, returns 0 if success. // additional info is written to out if not null. // compression >= 0 creates a gzipped file with the given compression level. - // parallel_thread_num >= 0 indicates thread numbers of parallel object dump - int dump(const char* path, outputStream* out = nullptr, int compression = -1, bool overwrite = false, uint parallel_thread_num = 1); + // parallel_thread_num >= 0 indicates thread numbers of parallel object dump. + int dump(const char* path, outputStream* out = nullptr, int compression = -1, bool overwrite = false, uint parallel_thread_num = default_num_of_dump_threads()); // returns error message (resource allocated), or null if no error char* error_as_C_string() const; From 19e46eed580339a61fd1309c2cc7040e8c83597d Mon Sep 17 00:00:00 2001 From: Sonia Zaldana Calles Date: Thu, 2 May 2024 01:41:09 +0000 Subject: [PATCH 031/203] 8331088: Incorrect TraceLoopPredicate output Reviewed-by: chagedorn, dlong --- src/hotspot/share/opto/loopPredicate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 29f4e6257fca7..278f636d9c712 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1247,7 +1247,7 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); _igvn.hash_delete(upper_bound_iff); upper_bound_iff->set_req(1, upper_bound_bol); - if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx); + if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", upper_bound_iff->_idx); // Fall through into rest of the cleanup code which will move any dependent nodes to the skeleton predicates of the // upper bound test. We always need to create skeleton predicates in order to properly remove dead loops when later From 5ab8713b3fcdf8a1e9d44fc71190845f32449fce Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 2 May 2024 06:29:46 +0000 Subject: [PATCH 032/203] 8331360: RISCV: u32 _partial_subtype_ctr loaded/stored as 64 Reviewed-by: fyang, mli, tonyp --- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 6 +----- src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 5 +---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 1cd7ac98b3490..234d85ed2469a 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -3344,11 +3344,7 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, mv(x10, super_klass); #ifndef PRODUCT - mv(t1, (address)&SharedRuntime::_partial_subtype_ctr); - Address pst_counter_addr(t1); - ld(t0, pst_counter_addr); - add(t0, t0, 1); - sd(t0, pst_counter_addr); + incrementw(ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr)); #endif // PRODUCT // We will consult the secondary-super array. diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 9712f8c326c02..582538a18b496 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -77,10 +77,7 @@ class StubGenerator: public StubCodeGenerator { #define inc_counter_np(counter) ((void)0) #else void inc_counter_np_(uint& counter) { - __ la(t1, ExternalAddress((address)&counter)); - __ lwu(t0, Address(t1, 0)); - __ addiw(t0, t0, 1); - __ sw(t0, Address(t1, 0)); + __ incrementw(ExternalAddress((address)&counter)); } #define inc_counter_np(counter) \ BLOCK_COMMENT("inc_counter " #counter); \ From 9108091f0ce21a52c3b8b22a52485ee5594eb185 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 2 May 2024 07:06:25 +0000 Subject: [PATCH 033/203] 8330989: unify os::create_binary_file across platforms Reviewed-by: dholmes, kbarrett --- src/hotspot/os/aix/os_aix.cpp | 7 ------- src/hotspot/os/bsd/os_bsd.cpp | 8 -------- src/hotspot/os/linux/os_linux.cpp | 8 -------- src/hotspot/os/windows/os_windows.cpp | 7 ------- src/hotspot/share/runtime/os.cpp | 7 +++++++ 5 files changed, 7 insertions(+), 30 deletions(-) diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 1925357e1b435..f0a984d3d1fe0 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -2442,13 +2442,6 @@ int os::open(const char *path, int oflag, int mode) { return fd; } -// create binary file, rewriting existing file if required -int os::create_binary_file(const char* path, bool rewrite_existing) { - int oflags = O_WRONLY | O_CREAT; - oflags |= rewrite_existing ? O_TRUNC : O_EXCL; - return ::open(path, oflags, S_IREAD | S_IWRITE); -} - // return current position of file pointer jlong os::current_file_offset(int fd) { return (jlong)::lseek(fd, (off_t)0, SEEK_CUR); diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 17b52bc1efab0..e5b6c74ce2f1b 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -2384,14 +2384,6 @@ int os::open(const char *path, int oflag, int mode) { return fd; } - -// create binary file, rewriting existing file if required -int os::create_binary_file(const char* path, bool rewrite_existing) { - int oflags = O_WRONLY | O_CREAT; - oflags |= rewrite_existing ? O_TRUNC : O_EXCL; - return ::open(path, oflags, S_IREAD | S_IWRITE); -} - // return current position of file pointer jlong os::current_file_offset(int fd) { return (jlong)::lseek(fd, (off_t)0, SEEK_CUR); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 3180dddfe50d7..20d3c99cd3eac 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -5121,14 +5121,6 @@ int os::open(const char *path, int oflag, int mode) { return fd; } - -// create binary file, rewriting existing file if required -int os::create_binary_file(const char* path, bool rewrite_existing) { - int oflags = O_WRONLY | O_CREAT; - oflags |= rewrite_existing ? O_TRUNC : O_EXCL; - return ::open(path, oflags, S_IREAD | S_IWRITE); -} - // return current position of file pointer jlong os::current_file_offset(int fd) { return (jlong)::lseek(fd, (off_t)0, SEEK_CUR); diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index ccd7a8f10ce4c..20422e83cb77c 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4889,13 +4889,6 @@ bool os::dir_is_empty(const char* path) { return is_empty; } -// create binary file, rewriting existing file if required -int os::create_binary_file(const char* path, bool rewrite_existing) { - int oflags = _O_CREAT | _O_WRONLY | _O_BINARY; - oflags |= rewrite_existing ? _O_TRUNC : _O_EXCL; - return ::open(path, oflags, _S_IREAD | _S_IWRITE); -} - // return current position of file pointer jlong os::current_file_offset(int fd) { return (jlong)::_lseeki64(fd, (__int64)0L, SEEK_CUR); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 4e3bce881810a..53c438cd20895 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1711,6 +1711,13 @@ const char* os::errno_name(int e) { return errno_to_string(e, true); } +// create binary file, rewriting existing file if required +int os::create_binary_file(const char* path, bool rewrite_existing) { + int oflags = O_WRONLY | O_CREAT WINDOWS_ONLY(| O_BINARY); + oflags |= rewrite_existing ? O_TRUNC : O_EXCL; + return ::open(path, oflags, S_IREAD | S_IWRITE); +} + #define trace_page_size_params(size) byte_size_in_exact_unit(size), exact_unit_for_byte_size(size) void os::trace_page_sizes(const char* str, From 4036d7d8246da0550adf8543848606c777da20a1 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Thu, 2 May 2024 07:19:56 +0000 Subject: [PATCH 034/203] 8330076: NMT: add/make a mandatory MEMFLAGS argument to family of os::reserve/commit/uncommit memory API Reviewed-by: stefank, jsjolen, stuefe --- .../cpu/aarch64/compressedKlass_aarch64.cpp | 4 +- src/hotspot/os/aix/os_aix.cpp | 10 +- .../bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp | 4 +- .../bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp | 4 +- src/hotspot/os/bsd/os_bsd.cpp | 16 +-- src/hotspot/os/linux/os_linux.cpp | 26 ++-- src/hotspot/os/posix/os_posix.cpp | 6 +- src/hotspot/os/posix/perfMemory_posix.cpp | 6 +- src/hotspot/os/windows/os_windows.cpp | 70 ++++++----- src/hotspot/os/windows/perfMemory_windows.cpp | 6 +- src/hotspot/share/cds/archiveBuilder.cpp | 2 +- src/hotspot/share/cds/filemap.cpp | 27 +++-- src/hotspot/share/cds/metaspaceShared.cpp | 15 +-- .../share/classfile/compactHashtable.cpp | 4 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 2 +- .../share/gc/g1/g1PageBasedVirtualSpace.cpp | 8 +- .../share/gc/g1/g1RegionToSpaceMapper.cpp | 6 +- .../share/gc/parallel/mutableNUMASpace.cpp | 4 +- .../share/gc/parallel/mutableSpace.cpp | 4 +- .../share/gc/parallel/objectStartArray.cpp | 3 +- .../share/gc/parallel/parMarkBitMap.cpp | 6 +- .../share/gc/parallel/psParallelCompact.cpp | 4 +- .../share/gc/parallel/psVirtualspace.cpp | 4 +- .../gc/serial/serialBlockOffsetTable.cpp | 4 +- src/hotspot/share/gc/shared/cardTable.cpp | 9 +- .../gc/shenandoah/shenandoahCollectionSet.cpp | 10 +- .../share/gc/shenandoah/shenandoahHeap.cpp | 40 +++--- .../gc/shenandoah/shenandoahHeapRegion.cpp | 4 +- .../share/gc/x/xMarkStackAllocator.cpp | 6 +- src/hotspot/share/gc/x/xPhysicalMemory.cpp | 6 +- src/hotspot/share/gc/x/xVirtualMemory.cpp | 5 +- .../share/gc/z/zMarkStackAllocator.cpp | 6 +- src/hotspot/share/gc/z/zNMT.cpp | 4 +- .../jfr/recorder/storage/jfrVirtualMemory.cpp | 6 +- .../share/memory/allocation.inline.hpp | 6 +- src/hotspot/share/memory/heap.cpp | 6 +- src/hotspot/share/memory/metaspace.cpp | 9 +- .../share/memory/metaspace/testHelpers.cpp | 4 +- .../memory/metaspace/virtualSpaceNode.cpp | 7 +- src/hotspot/share/memory/virtualspace.cpp | 114 +++++++++--------- src/hotspot/share/memory/virtualspace.hpp | 38 +++--- src/hotspot/share/nmt/memTracker.hpp | 16 +-- .../share/nmt/virtualMemoryTracker.cpp | 12 +- .../share/nmt/virtualMemoryTracker.hpp | 13 +- src/hotspot/share/oops/compressedKlass.cpp | 4 +- src/hotspot/share/prims/jni.cpp | 5 +- src/hotspot/share/prims/whitebox.cpp | 16 +-- src/hotspot/share/runtime/os.cpp | 46 +++---- src/hotspot/share/runtime/os.hpp | 47 ++++---- .../share/runtime/safepointMechanism.cpp | 7 +- src/hotspot/share/utilities/debug.cpp | 5 +- .../gtest/gc/g1/test_freeRegionList.cpp | 2 +- .../gtest/gc/g1/test_stressCommitUncommit.cpp | 4 +- test/hotspot/gtest/gc/z/test_zForwarding.cpp | 8 +- .../gtest/memory/test_virtualspace.cpp | 24 ++-- .../gtest/nmt/test_nmt_locationprinting.cpp | 2 +- .../runtime/test_committed_virtualmemory.cpp | 6 +- test/hotspot/gtest/runtime/test_os.cpp | 36 +++--- test/hotspot/gtest/runtime/test_os_linux.cpp | 16 +-- .../gtest/runtime/test_os_reserve_between.cpp | 8 +- .../hotspot/gtest/runtime/test_os_windows.cpp | 8 +- .../runtime/test_virtualMemoryTracker.cpp | 8 +- 62 files changed, 398 insertions(+), 420 deletions(-) diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp index 54af69ffaba6c..c918d9bdf0eb5 100644 --- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp @@ -69,7 +69,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) { const uint64_t immediate = ((uint64_t)immediates[index]) << 32; assert(immediate > 0 && Assembler::operand_valid_for_logical_immediate(/*is32*/false, immediate), "Invalid immediate %d " UINT64_FORMAT, index, immediate); - result = os::attempt_reserve_memory_at((char*)immediate, size, false); + result = os::attempt_reserve_memory_at((char*)immediate, size, !ExecMem, mtClass); if (result == nullptr) { log_trace(metaspace, map)("Failed to attach at " UINT64_FORMAT_X, immediate); } @@ -112,7 +112,7 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size if (result == nullptr) { constexpr size_t alignment = nth_bit(32); log_debug(metaspace, map)("Trying to reserve at a 32-bit-aligned address"); - result = os::reserve_memory_aligned(size, alignment, false); + result = os::reserve_memory_aligned(size, alignment, !ExecMem, mtClass); } return result; diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index f0a984d3d1fe0..862d8e8b0f4e2 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -1805,7 +1805,7 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) { void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { } size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) { @@ -1847,7 +1847,7 @@ bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, siz } // Reserves and attaches a shared memory segment. -char* os::pd_reserve_memory(size_t bytes, bool exec) { +char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { // Always round to os::vm_page_size(), which may be larger than 4K. bytes = align_up(bytes, os::vm_page_size()); @@ -1996,7 +1996,7 @@ void os::large_page_init() { return; // Nothing to do. See query_multipage_support and friends. } -char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) { +char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec, MEMFLAGS flag) { fatal("os::reserve_memory_special should not be called on AIX."); return nullptr; } @@ -2015,7 +2015,7 @@ bool os::can_commit_large_page_memory() { return false; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { assert(file_desc >= 0, "file_desc is not valid"); char* result = nullptr; @@ -2033,7 +2033,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) { +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec, MEMFLAGS flag) { char* addr = nullptr; // Always round to os::vm_page_size(), which may be larger than 4K. diff --git a/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp index 2c64c3788d34d..ea7a128cd13a0 100644 --- a/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp +++ b/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,7 +78,7 @@ XPhysicalMemoryBacking::XPhysicalMemoryBacking(size_t max_capacity) : _initialized(false) { // Reserve address space for backing memory - _base = (uintptr_t)os::reserve_memory(max_capacity); + _base = (uintptr_t)os::reserve_memory(max_capacity, !ExecMem, mtJavaHeap); if (_base == 0) { // Failed log_error_pd(gc)("Failed to reserve address space for backing memory"); diff --git a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp index bd1d7174c12d1..5bc901d0c0ba2 100644 --- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,7 +79,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) _initialized(false) { // Reserve address space for backing memory - _base = (uintptr_t)os::reserve_memory(max_capacity); + _base = (uintptr_t)os::reserve_memory(max_capacity, !ExecMem, mtJavaHeap); if (_base == 0) { // Failed log_error_pd(gc)("Failed to reserve address space for backing memory"); diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index e5b6c74ce2f1b..95f8016e2e990 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -1668,7 +1668,7 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size, void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { ::madvise(addr, bytes, MADV_DONTNEED); } @@ -1766,13 +1766,13 @@ bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) { } bool os::pd_create_stack_guard_pages(char* addr, size_t size) { - return os::commit_memory(addr, size, !ExecMem); + return os::commit_memory(addr, size, !ExecMem, mtThreadStack); } // If this is a growable mapping, remove the guard pages entirely by // munmap()ping them. If not, just call uncommit_memory(). bool os::remove_stack_guard_pages(char* addr, size_t size) { - return os::uncommit_memory(addr, size); + return os::uncommit_memory(addr, size, !ExecMem, mtThreadStack); } // 'requested_addr' is only treated as a hint, the return value may or @@ -1809,7 +1809,7 @@ static int anon_munmap(char * addr, size_t size) { } } -char* os::pd_reserve_memory(size_t bytes, bool exec) { +char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { return anon_mmap(nullptr /* addr */, bytes, exec); } @@ -1869,7 +1869,7 @@ void os::large_page_init() { } -char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) { +char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec, MEMFLAGS flag) { fatal("os::reserve_memory_special should not be called on BSD."); return nullptr; } @@ -1888,9 +1888,9 @@ bool os::can_commit_large_page_memory() { return false; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { assert(file_desc >= 0, "file_desc is not valid"); - char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem); + char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem, flag); if (result != nullptr) { if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == nullptr) { vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); @@ -1902,7 +1902,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) { +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec, MEMFLAGS flag) { // Assert only that the size is a multiple of the page size, since // that's all that mmap requires, and since that's all we really know // about at this low abstraction level. If we need higher alignment, diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 20d3c99cd3eac..3181ad82dab9f 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -3023,14 +3023,14 @@ void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { // This method works by doing an mmap over an existing mmaping and effectively discarding // the existing pages. However it won't work for SHM-based large pages that cannot be // uncommitted at all. We don't do anything in this case to avoid creating a segment with // small pages on top of the SHM segment. This method always works for small pages, so we // allow that in any case. if (alignment_hint <= os::vm_page_size() || can_commit_large_page_memory()) { - commit_memory(addr, bytes, alignment_hint, !ExecMem); + commit_memory(addr, bytes, alignment_hint, !ExecMem, flag); } } @@ -3637,7 +3637,7 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) { } } - return os::commit_memory(addr, size, !ExecMem); + return os::commit_memory(addr, size, !ExecMem, mtThreadStack); } // If this is a growable mapping, remove the guard pages entirely by @@ -3653,7 +3653,7 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) { return ::munmap(addr, size) == 0; } - return os::uncommit_memory(addr, size); + return os::uncommit_memory(addr, size, !ExecMem, mtThreadStack); } // 'requested_addr' is only treated as a hint, the return value may or @@ -3757,7 +3757,7 @@ static int anon_munmap(char * addr, size_t size) { return 1; } -char* os::pd_reserve_memory(size_t bytes, bool exec) { +char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { return anon_mmap(nullptr, bytes); } @@ -4214,7 +4214,7 @@ static char* reserve_memory_special_huge_tlbfs(size_t bytes, } char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, - char* req_addr, bool exec) { + char* req_addr, bool exec, MEMFLAGS flag) { assert(UseLargePages, "only for large pages"); char* const addr = reserve_memory_special_huge_tlbfs(bytes, alignment, page_size, req_addr, exec); @@ -4249,9 +4249,9 @@ bool os::can_commit_large_page_memory() { return UseTransparentHugePages; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { assert(file_desc >= 0, "file_desc is not valid"); - char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem); + char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem, flag); if (result != nullptr) { if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == nullptr) { vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); @@ -4263,7 +4263,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) { +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec, MEMFLAGS flag) { // Assert only that the size is a multiple of the page size, since // that's all that mmap requires, and since that's all we really know // about at this low abstraction level. If we need higher alignment, @@ -4655,7 +4655,7 @@ static void workaround_expand_exec_shield_cs_limit() { */ char* hint = (char*)(os::Linux::initial_thread_stack_bottom() - (StackOverflow::stack_guard_zone_size() + page_size)); - char* codebuf = os::attempt_reserve_memory_at(hint, page_size); + char* codebuf = os::attempt_reserve_memory_at(hint, page_size, !ExecMem, mtInternal); if (codebuf == nullptr) { // JDK-8197429: There may be a stack gap of one megabyte between @@ -4663,15 +4663,13 @@ static void workaround_expand_exec_shield_cs_limit() { // Linux kernel workaround for CVE-2017-1000364. If we failed to // map our codebuf, try again at an address one megabyte lower. hint -= 1 * M; - codebuf = os::attempt_reserve_memory_at(hint, page_size); + codebuf = os::attempt_reserve_memory_at(hint, page_size, !ExecMem, mtInternal); } - if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, true))) { + if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, ExecMem, mtInternal))) { return; // No matter, we tried, best effort. } - MemTracker::record_virtual_memory_type((address)codebuf, mtInternal); - log_info(os)("[CS limit NX emulation work-around, exec code at: %p]", codebuf); // Some code to exec: the 'ret' instruction diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index a18a633002c4b..db3aef14543f7 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -395,9 +395,9 @@ static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base, // Multiple threads can race in this code, and can remap over each other with MAP_FIXED, // so on posix, unmap the section at the start and at the end of the chunk that we mapped // rather than unmapping and remapping the whole chunk to get requested alignment. -char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) { +char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec, MEMFLAGS flag) { size_t extra_size = calculate_aligned_extra_size(size, alignment); - char* extra_base = os::reserve_memory(extra_size, exec); + char* extra_base = os::reserve_memory(extra_size, exec, flag); if (extra_base == nullptr) { return nullptr; } @@ -421,7 +421,7 @@ char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int file_des if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == nullptr) { vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); } - MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC); + MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC, flag); return aligned_base; } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 4339a21ae4e92..2ed33c3fb9c91 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -65,14 +65,14 @@ static char* backing_store_file_name = nullptr; // name of the backing store static char* create_standard_memory(size_t size) { // allocate an aligned chuck of memory - char* mapAddress = os::reserve_memory(size); + char* mapAddress = os::reserve_memory(size, !ExecMem, mtInternal); if (mapAddress == nullptr) { return nullptr; } // commit memory - if (!os::commit_memory(mapAddress, size, !ExecMem)) { + if (!os::commit_memory(mapAddress, size, !ExecMem, mtInternal)) { if (PrintMiscellaneous && Verbose) { warning("Could not commit PerfData memory\n"); } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 20422e83cb77c..a99e67d417c5b 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2755,7 +2755,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { addr = (address)((uintptr_t)addr & (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); os::commit_memory((char *)addr, thread->stack_base() - addr, - !ExecMem); + !ExecMem, mtThreadStack); return EXCEPTION_CONTINUE_EXECUTION; } #endif @@ -3117,8 +3117,9 @@ static bool numa_interleaving_init() { // Reasons for doing this: // * UseLargePagesIndividualAllocation was set (normally only needed on WS2003 but possible to be set otherwise) // * UseNUMAInterleaving requires a separate node for each piece -static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, +static char* allocate_pages_individually(size_t bytes, char* addr, DWORD alloc_type, DWORD prot, + MEMFLAGS flag, bool should_inject_error = false) { char * p_buf; // note: at setup time we guaranteed that NUMAInterleaveGranularity was aligned up to a page size @@ -3142,7 +3143,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, PAGE_READWRITE); // If reservation failed, return null if (p_buf == nullptr) return nullptr; - MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC, flag); os::release_memory(p_buf, bytes + chunk_size); // we still need to round up to a page boundary (in case we are using large pages) @@ -3184,13 +3185,13 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, if (!UseNUMAInterleaving) { p_new = (char *) virtualAlloc(next_alloc_addr, bytes_to_rq, - flags, + alloc_type, prot); } else { // get the next node to use from the used_node_list assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected"); DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count()); - p_new = (char *)virtualAllocExNuma(hProc, next_alloc_addr, bytes_to_rq, flags, prot, node); + p_new = (char *)virtualAllocExNuma(hProc, next_alloc_addr, bytes_to_rq, alloc_type, prot, node); } } @@ -3203,7 +3204,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, // need to create a dummy 'reserve' record to match // the release. MemTracker::record_virtual_memory_reserve((address)p_buf, - bytes_to_release, CALLER_PC); + bytes_to_release, CALLER_PC, flag); os::release_memory(p_buf, bytes_to_release); } #ifdef ASSERT @@ -3220,10 +3221,10 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, } // Although the memory is allocated individually, it is returned as one. // NMT records it as one block. - if ((flags & MEM_COMMIT) != 0) { - MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC); + if ((alloc_type & MEM_COMMIT) != 0) { + MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC, flag); } else { - MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC, flag); } // made it this far, success @@ -3351,7 +3352,7 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in // Multiple threads can race in this code but it's not possible to unmap small sections of // virtual space to get requested alignment, like posix-like os's. // Windows prevents multiple thread from remapping over each other so this loop is thread-safe. -static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MEMFLAGS flag = mtNone) { +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MEMFLAGS flag) { assert(is_aligned(alignment, os::vm_allocation_granularity()), "Alignment must be a multiple of allocation granularity (page size)"); assert(is_aligned(size, os::vm_allocation_granularity()), @@ -3365,7 +3366,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) { char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc, flag) : - os::reserve_memory(extra_size, false, flag); + os::reserve_memory(extra_size, !ExecMem, flag); if (extra_base == nullptr) { return nullptr; } @@ -3382,7 +3383,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi // Attempt to map, into the just vacated space, the slightly smaller aligned area. // Which may fail, hence the loop. aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, flag) : - os::attempt_reserve_memory_at(aligned_base, size, false, flag); + os::attempt_reserve_memory_at(aligned_base, size, !ExecMem, flag); } assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts?", max_attempts); @@ -3390,22 +3391,22 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi return aligned_base; } -char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) { +char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec, MEMFLAGS flag) { // exec can be ignored - return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */); + return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */, flag); } char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MEMFLAGS flag) { return map_or_reserve_memory_aligned(size, alignment, fd, flag); } -char* os::pd_reserve_memory(size_t bytes, bool exec) { - return pd_attempt_reserve_memory_at(nullptr /* addr */, bytes, exec); +char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { + return pd_attempt_reserve_memory_at(nullptr /* addr */, bytes, exec, flag); } // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec) { +char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec, MEMFLAGS flag) { assert((size_t)addr % os::vm_allocation_granularity() == 0, "reserve alignment"); assert(bytes % os::vm_page_size() == 0, "reserve page size"); @@ -3420,7 +3421,7 @@ char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec) { if (Verbose && PrintMiscellaneous) reserveTimer.start(); // in numa interleaving, we have to allocate pages individually // (well really chunks of NUMAInterleaveGranularity size) - res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE); + res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE, flag); if (res == nullptr) { warning("NUMA page allocation failed"); } @@ -3441,7 +3442,7 @@ size_t os::vm_min_address() { return _vm_min_address_default; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { assert(file_desc >= 0, "file_desc is not valid"); return map_memory_to_file(requested_addr, bytes, file_desc); } @@ -3457,13 +3458,13 @@ bool os::can_commit_large_page_memory() { return false; } -static char* reserve_large_pages_individually(size_t size, char* req_addr, bool exec) { +static char* reserve_large_pages_individually(size_t size, char* req_addr, bool exec, MEMFLAGS flag) { log_debug(pagesize)("Reserving large pages individually."); const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; + const DWORD alloc_type = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; - char * p_buf = allocate_pages_individually(size, req_addr, flags, prot, LargePagesIndividualAllocationInjectError); + char * p_buf = allocate_pages_individually(size, req_addr, alloc_type, prot, flag, LargePagesIndividualAllocationInjectError); if (p_buf == nullptr) { // give an appropriate warning message if (UseNUMAInterleaving) { @@ -3487,12 +3488,12 @@ static char* reserve_large_pages_single_range(size_t size, char* req_addr, bool return (char *) virtualAlloc(req_addr, size, flags, prot); } -static char* reserve_large_pages(size_t size, char* req_addr, bool exec) { +static char* reserve_large_pages(size_t size, char* req_addr, bool exec, MEMFLAGS flag) { // with large pages, there are two cases where we need to use Individual Allocation // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003) // 2) NUMA Interleaving is enabled, in which case we use a different node for each page if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) { - return reserve_large_pages_individually(size, req_addr, exec); + return reserve_large_pages_individually(size, req_addr, exec, flag); } return reserve_large_pages_single_range(size, req_addr, exec); } @@ -3509,7 +3510,7 @@ static char* find_aligned_address(size_t size, size_t alignment) { return aligned_addr; } -static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exec) { +static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exec, MEMFLAGS flag) { log_debug(pagesize)("Reserving large pages at an aligned address, alignment=" SIZE_FORMAT "%s", byte_size_in_exact_unit(alignment), exact_unit_for_byte_size(alignment)); @@ -3522,7 +3523,7 @@ static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exe char* aligned_address = find_aligned_address(size, alignment); // Try to do the large page reservation using the aligned address. - aligned_address = reserve_large_pages(size, aligned_address, exec); + aligned_address = reserve_large_pages(size, aligned_address, exec, flag); if (aligned_address != nullptr) { // Reservation at the aligned address succeeded. guarantee(is_aligned(aligned_address, alignment), "Must be aligned"); @@ -3535,7 +3536,7 @@ static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exe } char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* addr, - bool exec) { + bool exec, MEMFLAGS flag) { assert(UseLargePages, "only for large pages"); assert(page_size == os::large_page_size(), "Currently only support one large page size on Windows"); assert(is_aligned(addr, alignment), "Must be"); @@ -3551,11 +3552,11 @@ char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_ // ensure that the requested alignment is met. When there is a requested address // this solves it self, since it must be properly aligned already. if (addr == nullptr && alignment > page_size) { - return reserve_large_pages_aligned(bytes, alignment, exec); + return reserve_large_pages_aligned(bytes, alignment, exec, flag); } // No additional requirements, just reserve the large pages. - return reserve_large_pages(bytes, addr, exec); + return reserve_large_pages(bytes, addr, exec, flag); } bool os::pd_release_memory_special(char* base, size_t bytes) { @@ -3721,11 +3722,11 @@ bool os::pd_release_memory(char* addr, size_t bytes) { } bool os::pd_create_stack_guard_pages(char* addr, size_t size) { - return os::commit_memory(addr, size, !ExecMem); + return os::commit_memory(addr, size, !ExecMem, mtThreadStack); } bool os::remove_stack_guard_pages(char* addr, size_t size) { - return os::uncommit_memory(addr, size); + return os::uncommit_memory(addr, size, !ExecMem, mtThreadStack); } static bool protect_pages_individually(char* addr, size_t bytes, unsigned int p, DWORD *old_status) { @@ -3776,7 +3777,7 @@ bool os::protect_memory(char* addr, size_t bytes, ProtType prot, // memory, not a big deal anyway, as bytes less or equal than 64K if (!is_committed) { commit_memory_or_exit(addr, bytes, prot == MEM_PROT_RWX, - "cannot commit protection page"); + mtInternal, "cannot commit protection page"); } // One cannot use os::guard_memory() here, as on Win32 guard page // have different (one-shot) semantics, from MSDN on PAGE_GUARD: @@ -3816,7 +3817,7 @@ bool os::unguard_memory(char* addr, size_t bytes) { } void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { } +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { } size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) { return page_size; @@ -5104,9 +5105,6 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, return nullptr; } - // Record virtual memory allocation - MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC); - DWORD bytes_read; OVERLAPPED overlapped; overlapped.Offset = (DWORD)file_offset; diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index a71101731fb98..0e5b5fedbcd51 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,14 +55,14 @@ typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)( static char* create_standard_memory(size_t size) { // allocate an aligned chuck of memory - char* mapAddress = os::reserve_memory(size); + char* mapAddress = os::reserve_memory(size, !ExecMem, mtInternal); if (mapAddress == nullptr) { return nullptr; } // commit memory - if (!os::commit_memory(mapAddress, size, !ExecMem)) { + if (!os::commit_memory(mapAddress, size, !ExecMem, mtInternal)) { if (PrintMiscellaneous && Verbose) { warning("Could not commit PerfData memory\n"); } diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index 51399f03434f6..b8004f741ba63 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -326,7 +326,7 @@ size_t ArchiveBuilder::estimate_archive_size() { address ArchiveBuilder::reserve_buffer() { size_t buffer_size = estimate_archive_size(); - ReservedSpace rs(buffer_size, MetaspaceShared::core_region_alignment(), os::vm_page_size()); + ReservedSpace rs(buffer_size, MetaspaceShared::core_region_alignment(), os::vm_page_size(), mtClassShared); if (!rs.is_reserved()) { log_error(cds)("Failed to reserve " SIZE_FORMAT " bytes of output buffer.", buffer_size); MetaspaceShared::unrecoverable_writing_error(); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 2182865ebaacc..22895bd326162 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1710,9 +1710,9 @@ void FileMapInfo::close() { /* * Same as os::map_memory() but also pretouches if AlwaysPreTouch is enabled. */ -static char* map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only, - bool allow_exec, MEMFLAGS flags = mtNone) { +static char* map_and_pretouch_memory(int fd, const char* file_name, size_t file_offset, + char *addr, size_t bytes, bool read_only, + bool allow_exec, MEMFLAGS flags) { char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes, AlwaysPreTouch ? false : read_only, allow_exec, flags); @@ -1741,7 +1741,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() { // Replace old mapping with new one that is writable. char *base = os::map_memory(_fd, _full_path, r->file_offset(), addr, size, false /* !read_only */, - r->allow_exec()); + r->allow_exec(), mtClassShared); close(); // These have to be errors because the shared region is now unmapped. if (base == nullptr) { @@ -1800,7 +1800,7 @@ bool FileMapInfo::read_region(int i, char* base, size_t size, bool do_commit) { log_info(cds)("Commit %s region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)%s", is_static() ? "static " : "dynamic", i, p2i(base), p2i(base + size), shared_region_name[i], r->allow_exec() ? " exec" : ""); - if (!os::commit_memory(base, size, r->allow_exec())) { + if (!os::commit_memory(base, size, r->allow_exec(), mtClassShared)) { log_error(cds)("Failed to commit %s region #%d (%s)", is_static() ? "static " : "dynamic", i, shared_region_name[i]); return false; @@ -1860,9 +1860,9 @@ MapArchiveResult FileMapInfo::map_region(int i, intx addr_delta, char* mapped_ba // Note that this may either be a "fresh" mapping into unreserved address // space (Windows, first mapping attempt), or a mapping into pre-reserved // space (Posix). See also comment in MetaspaceShared::map_archives(). - char* base = map_memory(_fd, _full_path, r->file_offset(), - requested_addr, size, r->read_only(), - r->allow_exec(), mtClassShared); + char* base = map_and_pretouch_memory(_fd, _full_path, r->file_offset(), + requested_addr, size, r->read_only(), + r->allow_exec(), mtClassShared); if (base != requested_addr) { log_info(cds)("Unable to map %s shared space at " INTPTR_FORMAT, shared_region_name[i], p2i(requested_addr)); @@ -1889,8 +1889,8 @@ char* FileMapInfo::map_bitmap_region() { } bool read_only = true, allow_exec = false; char* requested_addr = nullptr; // allow OS to pick any location - char* bitmap_base = map_memory(_fd, _full_path, r->file_offset(), - requested_addr, r->used_aligned(), read_only, allow_exec, mtClassShared); + char* bitmap_base = map_and_pretouch_memory(_fd, _full_path, r->file_offset(), + requested_addr, r->used_aligned(), read_only, allow_exec, mtClassShared); if (bitmap_base == nullptr) { log_info(cds)("failed to map relocation bitmap"); return nullptr; @@ -2176,10 +2176,11 @@ bool FileMapInfo::map_heap_region_impl() { // Map the archived heap data. No need to call MemTracker::record_virtual_memory_type() // for mapped region as it is part of the reserved java heap, which is already recorded. + // So we pass the mtJavaHeap to tell MemTracker the type of the already tracked memory. char* addr = (char*)_mapped_heap_memregion.start(); - char* base = map_memory(_fd, _full_path, r->file_offset(), - addr, _mapped_heap_memregion.byte_size(), r->read_only(), - r->allow_exec()); + char* base = map_and_pretouch_memory(_fd, _full_path, r->file_offset(), + addr, _mapped_heap_memregion.byte_size(), r->read_only(), + r->allow_exec(), mtJavaHeap); if (base == nullptr || base != addr) { dealloc_heap_region(); log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. " diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index c7d14f83d036a..3f5560ca22ae0 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -269,7 +269,7 @@ void MetaspaceShared::initialize_for_static_dump() { SharedBaseAddress = (size_t)_requested_base_address; size_t symbol_rs_size = LP64_ONLY(3 * G) NOT_LP64(128 * M); - _symbol_rs = ReservedSpace(symbol_rs_size); + _symbol_rs = ReservedSpace(symbol_rs_size, mtClassShared); if (!_symbol_rs.is_reserved()) { log_error(cds)("Unable to reserve memory for symbols: " SIZE_FORMAT " bytes.", symbol_rs_size); MetaspaceShared::unrecoverable_writing_error(); @@ -1270,12 +1270,10 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma // Get the simple case out of the way first: // no compressed class space, simple allocation. archive_space_rs = ReservedSpace(archive_space_size, archive_space_alignment, - os::vm_page_size(), (char*)base_address); + os::vm_page_size(), mtClassShared, (char*)base_address); if (archive_space_rs.is_reserved()) { assert(base_address == nullptr || (address)archive_space_rs.base() == base_address, "Sanity"); - // Register archive space with NMT. - MemTracker::record_virtual_memory_type(archive_space_rs.base(), mtClassShared); return archive_space_rs.base(); } return nullptr; @@ -1319,21 +1317,18 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma // via sequential file IO. address ccs_base = base_address + archive_space_size + gap_size; archive_space_rs = ReservedSpace(archive_space_size, archive_space_alignment, - os::vm_page_size(), (char*)base_address); + os::vm_page_size(), mtClassShared, (char*)base_address); class_space_rs = ReservedSpace(class_space_size, class_space_alignment, - os::vm_page_size(), (char*)ccs_base); + os::vm_page_size(), mtClass, (char*)ccs_base); } if (!archive_space_rs.is_reserved() || !class_space_rs.is_reserved()) { release_reserved_spaces(total_space_rs, archive_space_rs, class_space_rs); return nullptr; } - // NMT: fix up the space tags - MemTracker::record_virtual_memory_type(archive_space_rs.base(), mtClassShared); - MemTracker::record_virtual_memory_type(class_space_rs.base(), mtClass); } else { if (use_archive_base_addr && base_address != nullptr) { total_space_rs = ReservedSpace(total_range_size, archive_space_alignment, - os::vm_page_size(), (char*) base_address); + os::vm_page_size(), mtClassShared, (char*) base_address); } else { // We did not manage to reserve at the preferred address, or were instructed to relocate. In that // case we reserve wherever possible, but the start address needs to be encodable as narrow Klass diff --git a/src/hotspot/share/classfile/compactHashtable.cpp b/src/hotspot/share/classfile/compactHashtable.cpp index d4657e35a84eb..890d0e035f862 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,7 +240,7 @@ HashtableTextDump::HashtableTextDump(const char* filename) : _fd(-1) { if (_fd < 0) { quit("Unable to open hashtable dump file", filename); } - _base = os::map_memory(_fd, filename, 0, nullptr, _size, true, false); + _base = os::map_memory(_fd, filename, 0, nullptr, _size, true, false, mtClassShared); if (_base == nullptr) { quit("Unable to map hashtable dump file", filename); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 1384c30d2be2f..2b890530c4bdf 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1213,7 +1213,7 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des size_t translation_factor) { size_t preferred_page_size = os::page_size_for_region_unaligned(size, 1); // Allocate a new reserved space, preferring to use large pages. - ReservedSpace rs(size, preferred_page_size); + ReservedSpace rs(size, preferred_page_size, mtGC); size_t page_size = rs.page_size(); G1RegionToSpaceMapper* result = G1RegionToSpaceMapper::create_mapper(rs, diff --git a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp index bdb732f6ebb39..c0cf66fb2fdc2 100644 --- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp +++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,14 +135,14 @@ void G1PageBasedVirtualSpace::commit_preferred_pages(size_t start, size_t num_pa char* start_addr = page_start(start); size_t size = num_pages * _page_size; - os::commit_memory_or_exit(start_addr, size, _page_size, false, "G1 virtual space"); + os::commit_memory_or_exit(start_addr, size, _page_size, !ExecMem, mtGC, "G1 virtual space"); } void G1PageBasedVirtualSpace::commit_tail() { vmassert(_tail_size > 0, "The size of the tail area must be > 0 when reaching here"); char* const aligned_end_address = align_down(_high_boundary, _page_size); - os::commit_memory_or_exit(aligned_end_address, _tail_size, os::vm_page_size(), false, "G1 virtual space"); + os::commit_memory_or_exit(aligned_end_address, _tail_size, os::vm_page_size(), !ExecMem, mtGC, "G1 virtual space"); } void G1PageBasedVirtualSpace::commit_internal(size_t start_page, size_t end_page) { @@ -201,7 +201,7 @@ void G1PageBasedVirtualSpace::uncommit_internal(size_t start_page, size_t end_pa "Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page); char* start_addr = page_start(start_page); - os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char))); + os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char)), !ExecMem, mtGC); } void G1PageBasedVirtualSpace::uncommit(size_t start_page, size_t size_in_pages) { diff --git a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp index 5f903960cce8c..104b126c01674 100644 --- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp +++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,12 +43,10 @@ G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs, MEMFLAGS type) : _listener(nullptr), _storage(rs, used_size, page_size), - _region_commit_map(rs.size() * commit_factor / region_granularity, mtGC), + _region_commit_map(rs.size() * commit_factor / region_granularity, type), _memory_type(type) { guarantee(is_power_of_2(page_size), "must be"); guarantee(is_power_of_2(region_granularity), "must be"); - - MemTracker::record_virtual_memory_type((address)rs.base(), type); } // Used to manually signal a mapper to handle a set of regions as committed. diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 2a39ce7b4700d..c94da37741000 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -227,7 +227,7 @@ void MutableNUMASpace::bias_region(MemRegion mr, uint lgrp_id) { // Then we uncommit the pages in the range. // The alignment_hint argument must be less than or equal to the small page // size if not using large pages or else this function does nothing. - os::free_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align); + os::free_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align, mtGC); // And make them local/first-touch biased. os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), checked_cast(lgrp_id)); } diff --git a/src/hotspot/share/gc/parallel/mutableSpace.cpp b/src/hotspot/share/gc/parallel/mutableSpace.cpp index 4641b4ce5c611..019d457f293df 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ void MutableSpace::numa_setup_pages(MemRegion mr, size_t page_size, bool clear_s size_t size = pointer_delta(end, start, sizeof(char)); if (clear_space) { // Prefer page reallocation to migration. - os::free_memory((char*)start, size, page_size); + os::free_memory((char*)start, size, page_size, mtJavaHeap); } os::numa_make_global((char*)start, size); } diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index b1fc956a54a21..2a0f12ec70e72 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -47,11 +47,10 @@ void ObjectStartArray::initialize(MemRegion reserved_region) { // Do not use large-pages for the backing store. The one large page region // will be used for the heap proper. - ReservedSpace backing_store(bytes_to_reserve); + ReservedSpace backing_store(bytes_to_reserve, mtGC); if (!backing_store.is_reserved()) { vm_exit_during_initialization("Could not reserve space for ObjectStartArray"); } - MemTracker::record_virtual_memory_type(backing_store.base(), mtGC); // We do not commit any memory initially _virtual_space.initialize(backing_store); diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp index deffcc019c95c..fefc915094576 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,13 +49,11 @@ ParMarkBitMap::initialize(MemRegion covered_region) const size_t rs_align = page_sz == os::vm_page_size() ? 0 : MAX2(page_sz, granularity); - ReservedSpace rs(_reserved_byte_size, rs_align, page_sz); + ReservedSpace rs(_reserved_byte_size, rs_align, page_sz, mtGC); const size_t used_page_sz = rs.page_size(); os::trace_page_sizes("Mark Bitmap", raw_bytes, raw_bytes, rs.base(), rs.size(), used_page_sz); - MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); - _virtual_space = new PSVirtualSpace(rs, page_sz); if (_virtual_space != nullptr && _virtual_space->expand_by(_reserved_byte_size)) { _region_start = covered_region.start(); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 8ac16e059b1ea..165f9d3c05c15 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -440,12 +440,10 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) const size_t rs_align = page_sz == os::vm_page_size() ? 0 : MAX2(page_sz, granularity); - ReservedSpace rs(_reserved_byte_size, rs_align, page_sz); + ReservedSpace rs(_reserved_byte_size, rs_align, page_sz, mtGC); os::trace_page_sizes("Parallel Compact Data", raw_bytes, raw_bytes, rs.base(), rs.size(), page_sz); - MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); - PSVirtualSpace* vspace = new PSVirtualSpace(rs, page_sz); if (vspace != 0) { if (vspace->expand_by(_reserved_byte_size)) { diff --git a/src/hotspot/share/gc/parallel/psVirtualspace.cpp b/src/hotspot/share/gc/parallel/psVirtualspace.cpp index a4d686d867042..8e441ec806137 100644 --- a/src/hotspot/share/gc/parallel/psVirtualspace.cpp +++ b/src/hotspot/share/gc/parallel/psVirtualspace.cpp @@ -78,7 +78,7 @@ bool PSVirtualSpace::expand_by(size_t bytes) { char* const base_addr = committed_high_addr(); bool result = special() || - os::commit_memory(base_addr, bytes, alignment(), !ExecMem); + os::commit_memory(base_addr, bytes, alignment(), !ExecMem, mtGC); if (result) { _committed_high_addr += bytes; } @@ -95,7 +95,7 @@ bool PSVirtualSpace::shrink_by(size_t bytes) { } char* const base_addr = committed_high_addr() - bytes; - bool result = special() || os::uncommit_memory(base_addr, bytes); + bool result = special() || os::uncommit_memory(base_addr, bytes, !ExecMem, mtGC); if (result) { _committed_high_addr -= bytes; } diff --git a/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp b/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp index 59b7f130df30b..7ac0fcc8b53c5 100644 --- a/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp +++ b/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp @@ -37,13 +37,11 @@ SerialBlockOffsetTable::SerialBlockOffsetTable(MemRegion reserved, size_t init_word_size): _reserved(reserved) { size_t size = compute_size(reserved.word_size()); - ReservedSpace rs(size); + ReservedSpace rs(size, mtGC); if (!rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for heap offset array"); } - MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); - if (!_vs.initialize(rs, 0)) { vm_exit_during_initialization("Could not reserve enough space for heap offset array"); } diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 95f7058f4e4ee..243f47eee239d 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -82,9 +82,7 @@ void CardTable::initialize(void* region0_start, void* region1_start) { const size_t rs_align = _page_size == os::vm_page_size() ? 0 : MAX2(_page_size, os::vm_allocation_granularity()); - ReservedSpace heap_rs(_byte_map_size, rs_align, _page_size); - - MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtGC); + ReservedSpace heap_rs(_byte_map_size, rs_align, _page_size, mtGC); os::trace_page_sizes("Card Table", num_bytes, num_bytes, heap_rs.base(), heap_rs.size(), _page_size); @@ -166,6 +164,7 @@ void CardTable::resize_covered_region(MemRegion new_region) { delta.byte_size(), _page_size, !ExecMem, + mtGCCardSet, "card table expansion"); memset(delta.start(), clean_card, delta.byte_size()); @@ -174,7 +173,9 @@ void CardTable::resize_covered_region(MemRegion new_region) { MemRegion delta = MemRegion(new_committed.end(), old_committed.word_size() - new_committed.word_size()); bool res = os::uncommit_memory((char*)delta.start(), - delta.byte_size()); + delta.byte_size(), + !ExecMem, + mtGCCardSet); assert(res, "uncommit should succeed"); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp index 25062c5317dcb..34a66d9f6d963 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp @@ -57,21 +57,19 @@ ShenandoahCollectionSet::ShenandoahCollectionSet(ShenandoahHeap* heap, ReservedS // subsystem for mapping not-yet-written-to pages to a single physical backing page, // but this is not guaranteed, and would confuse NMT and other memory accounting tools. - MemTracker::record_virtual_memory_type(_map_space.base(), mtGC); - size_t page_size = os::vm_page_size(); if (!_map_space.special()) { // Commit entire pages that cover the heap cset map. char* bot_addr = align_down(_cset_map, page_size); char* top_addr = align_up(_cset_map + _map_size, page_size); - os::commit_memory_or_exit(bot_addr, pointer_delta(top_addr, bot_addr, 1), false, - "Unable to commit collection set bitmap: heap"); + os::commit_memory_or_exit(bot_addr, pointer_delta(top_addr, bot_addr, 1), !ExecMem, + mtGC, "Unable to commit collection set bitmap: heap"); // Commit the zero page, if not yet covered by heap cset map. if (bot_addr != _biased_cset_map) { - os::commit_memory_or_exit(_biased_cset_map, page_size, false, - "Unable to commit collection set bitmap: zero page"); + os::commit_memory_or_exit(_biased_cset_map, page_size, !ExecMem, + mtGC, "Unable to commit collection set bitmap: zero page"); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index c9d3d1d93647f..09737d68352c5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -213,8 +213,8 @@ jint ShenandoahHeap::initialize() { ReservedSpace sh_rs = heap_rs.first_part(max_byte_size); if (!_heap_region_special) { - os::commit_memory_or_exit(sh_rs.base(), _initial_size, heap_alignment, false, - "Cannot commit heap memory"); + os::commit_memory_or_exit(sh_rs.base(), _initial_size, heap_alignment, !ExecMem, + mtGC, "Cannot commit heap memory"); } // @@ -247,12 +247,11 @@ jint ShenandoahHeap::initialize() { "Bitmap slices should be page-granular: bps = " SIZE_FORMAT ", page size = " SIZE_FORMAT, _bitmap_bytes_per_slice, bitmap_page_size); - ReservedSpace bitmap(_bitmap_size, bitmap_page_size); + ReservedSpace bitmap(_bitmap_size, bitmap_page_size, mtGC); os::trace_page_sizes_for_requested_size("Mark Bitmap", bitmap_size_orig, bitmap_page_size, bitmap.base(), bitmap.size(), bitmap.page_size()); - MemTracker::record_virtual_memory_type(bitmap.base(), mtGC); _bitmap_region = MemRegion((HeapWord*) bitmap.base(), bitmap.size() / HeapWordSize); _bitmap_region_special = bitmap.special(); @@ -260,23 +259,22 @@ jint ShenandoahHeap::initialize() { align_up(num_committed_regions, _bitmap_regions_per_slice) / _bitmap_regions_per_slice; bitmap_init_commit = MIN2(_bitmap_size, bitmap_init_commit); if (!_bitmap_region_special) { - os::commit_memory_or_exit((char *) _bitmap_region.start(), bitmap_init_commit, bitmap_page_size, false, - "Cannot commit bitmap memory"); + os::commit_memory_or_exit((char *) _bitmap_region.start(), bitmap_init_commit, bitmap_page_size, !ExecMem, + mtGC, "Cannot commit bitmap memory"); } _marking_context = new ShenandoahMarkingContext(_heap_region, _bitmap_region, _num_regions, _max_workers); if (ShenandoahVerify) { - ReservedSpace verify_bitmap(_bitmap_size, bitmap_page_size); + ReservedSpace verify_bitmap(_bitmap_size, bitmap_page_size, mtGC); os::trace_page_sizes_for_requested_size("Verify Bitmap", bitmap_size_orig, bitmap_page_size, verify_bitmap.base(), verify_bitmap.size(), verify_bitmap.page_size()); if (!verify_bitmap.special()) { - os::commit_memory_or_exit(verify_bitmap.base(), verify_bitmap.size(), bitmap_page_size, false, - "Cannot commit verification bitmap memory"); + os::commit_memory_or_exit(verify_bitmap.base(), verify_bitmap.size(), bitmap_page_size, !ExecMem, + mtGC, "Cannot commit verification bitmap memory"); } - MemTracker::record_virtual_memory_type(verify_bitmap.base(), mtGC); MemRegion verify_bitmap_region = MemRegion((HeapWord *) verify_bitmap.base(), verify_bitmap.size() / HeapWordSize); _verification_bit_map.initialize(_heap_region, verify_bitmap_region); _verifier = new ShenandoahVerifier(this, &_verification_bit_map); @@ -292,12 +290,11 @@ jint ShenandoahHeap::initialize() { aux_bitmap_page_size = os::vm_page_size(); } #endif - ReservedSpace aux_bitmap(_bitmap_size, aux_bitmap_page_size); + ReservedSpace aux_bitmap(_bitmap_size, aux_bitmap_page_size, mtGC); os::trace_page_sizes_for_requested_size("Aux Bitmap", bitmap_size_orig, aux_bitmap_page_size, aux_bitmap.base(), aux_bitmap.size(), aux_bitmap.page_size()); - MemTracker::record_virtual_memory_type(aux_bitmap.base(), mtGC); _aux_bitmap_region = MemRegion((HeapWord*) aux_bitmap.base(), aux_bitmap.size() / HeapWordSize); _aux_bitmap_region_special = aux_bitmap.special(); _aux_bit_map.initialize(_heap_region, _aux_bitmap_region); @@ -310,15 +307,14 @@ jint ShenandoahHeap::initialize() { size_t region_storage_size = align_up(region_storage_size_orig, MAX2(region_page_size, os::vm_allocation_granularity())); - ReservedSpace region_storage(region_storage_size, region_page_size); + ReservedSpace region_storage(region_storage_size, region_page_size, mtGC); os::trace_page_sizes_for_requested_size("Region Storage", region_storage_size_orig, region_page_size, region_storage.base(), region_storage.size(), region_storage.page_size()); - MemTracker::record_virtual_memory_type(region_storage.base(), mtGC); if (!region_storage.special()) { - os::commit_memory_or_exit(region_storage.base(), region_storage_size, region_page_size, false, - "Cannot commit region memory"); + os::commit_memory_or_exit(region_storage.base(), region_storage_size, region_page_size, !ExecMem, + mtGC, "Cannot commit region memory"); } // Try to fit the collection set bitmap at lower addresses. This optimizes code generation for cset checks. @@ -336,7 +332,7 @@ jint ShenandoahHeap::initialize() { for (uintptr_t addr = min; addr <= max; addr <<= 1u) { char* req_addr = (char*)addr; assert(is_aligned(req_addr, cset_align), "Should be aligned"); - cset_rs = ReservedSpace(cset_size, cset_align, cset_page_size, req_addr); + cset_rs = ReservedSpace(cset_size, cset_align, cset_page_size, mtGC, req_addr); if (cset_rs.is_reserved()) { assert(cset_rs.base() == req_addr, "Allocated where requested: " PTR_FORMAT ", " PTR_FORMAT, p2i(cset_rs.base()), addr); _collection_set = new ShenandoahCollectionSet(this, cset_rs, sh_rs.base()); @@ -345,7 +341,7 @@ jint ShenandoahHeap::initialize() { } if (_collection_set == nullptr) { - cset_rs = ReservedSpace(cset_size, cset_align, os::vm_page_size()); + cset_rs = ReservedSpace(cset_size, cset_align, os::vm_page_size(), mtGC); _collection_set = new ShenandoahCollectionSet(this, cset_rs, sh_rs.base()); } os::trace_page_sizes_for_requested_size("Collection Set", @@ -1414,7 +1410,7 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) { bool ShenandoahHeap::prepare_aux_bitmap_for_iteration() { assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints"); - if (!_aux_bitmap_region_special && !os::commit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), false)) { + if (!_aux_bitmap_region_special && !os::commit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), !ExecMem, mtGC)) { log_warning(gc)("Could not commit native memory for auxiliary marking bitmap for heap iteration"); return false; } @@ -1434,7 +1430,7 @@ void ShenandoahHeap::scan_roots_for_iteration(ShenandoahScanObjectStack* oop_sta } void ShenandoahHeap::reclaim_aux_bitmap_for_iteration() { - if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size())) { + if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), !ExecMem, mtGC)) { log_warning(gc)("Could not uncommit native memory for auxiliary marking bitmap for heap iteration"); } } @@ -2264,7 +2260,7 @@ bool ShenandoahHeap::commit_bitmap_slice(ShenandoahHeapRegion* r) { size_t len = _bitmap_bytes_per_slice; char* start = (char*) _bitmap_region.start() + off; - if (!os::commit_memory(start, len, false)) { + if (!os::commit_memory(start, len, !ExecMem, mtGC)) { return false; } @@ -2293,7 +2289,7 @@ bool ShenandoahHeap::uncommit_bitmap_slice(ShenandoahHeapRegion *r) { size_t slice = r->index() / _bitmap_regions_per_slice; size_t off = _bitmap_bytes_per_slice * slice; size_t len = _bitmap_bytes_per_slice; - if (!os::uncommit_memory((char*)_bitmap_region.start() + off, len)) { + if (!os::uncommit_memory((char*)_bitmap_region.start() + off, len, !ExecMem, mtGC)) { return false; } return true; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index 8a94b20670a9f..a8386a36c3f9a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -620,7 +620,7 @@ size_t ShenandoahHeapRegion::setup_sizes(size_t max_heap_size) { void ShenandoahHeapRegion::do_commit() { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->is_heap_region_special() && !os::commit_memory((char *) bottom(), RegionSizeBytes, false)) { + if (!heap->is_heap_region_special() && !os::commit_memory((char *) bottom(), RegionSizeBytes, !ExecMem, mtJavaHeap)) { report_java_out_of_memory("Unable to commit region"); } if (!heap->commit_bitmap_slice(this)) { @@ -634,7 +634,7 @@ void ShenandoahHeapRegion::do_commit() { void ShenandoahHeapRegion::do_uncommit() { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->is_heap_region_special() && !os::uncommit_memory((char *) bottom(), RegionSizeBytes)) { + if (!heap->is_heap_region_special() && !os::uncommit_memory((char *) bottom(), RegionSizeBytes, !ExecMem, mtJavaHeap)) { report_java_out_of_memory("Unable to uncommit region"); } if (!heap->uncommit_bitmap_slice(this)) { diff --git a/src/hotspot/share/gc/x/xMarkStackAllocator.cpp b/src/hotspot/share/gc/x/xMarkStackAllocator.cpp index b5cc3ad641aff..70892879d2b8f 100644 --- a/src/hotspot/share/gc/x/xMarkStackAllocator.cpp +++ b/src/hotspot/share/gc/x/xMarkStackAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ size_t XMarkStackSpace::expand_space() { old_size / M, new_size / M); // Expand - os::commit_memory_or_exit((char*)_end, expand_size, false /* executable */, "Mark stack space"); + os::commit_memory_or_exit((char*)_end, expand_size, !ExecMem, mtGC, "Mark stack space"); return expand_size; } @@ -105,7 +105,7 @@ size_t XMarkStackSpace::shrink_space() { old_size / M, new_size / M); const uintptr_t shrink_start = _end - shrink_size; - os::uncommit_memory((char*)shrink_start, shrink_size, false /* executable */); + os::uncommit_memory((char*)shrink_start, shrink_size, !ExecMem, mtGC); } return shrink_size; diff --git a/src/hotspot/share/gc/x/xPhysicalMemory.cpp b/src/hotspot/share/gc/x/xPhysicalMemory.cpp index 0269c64f0f1aa..619e41cab9c9e 100644 --- a/src/hotspot/share/gc/x/xPhysicalMemory.cpp +++ b/src/hotspot/share/gc/x/xPhysicalMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -279,13 +279,13 @@ void XPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max void XPhysicalMemoryManager::nmt_commit(uintptr_t offset, size_t size) const { // From an NMT point of view we treat the first heap view (marked0) as committed const uintptr_t addr = XAddress::marked0(offset); - MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC); + MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC, mtGC); } void XPhysicalMemoryManager::nmt_uncommit(uintptr_t offset, size_t size) const { const uintptr_t addr = XAddress::marked0(offset); ThreadCritical tc; - MemTracker::record_virtual_memory_uncommit((address)addr, size); + MemTracker::record_virtual_memory_uncommit((address)addr, size, mtGC); } void XPhysicalMemoryManager::alloc(XPhysicalMemory& pmem, size_t size) { diff --git a/src/hotspot/share/gc/x/xVirtualMemory.cpp b/src/hotspot/share/gc/x/xVirtualMemory.cpp index 1d66cdd069ef7..496dcdc2464e3 100644 --- a/src/hotspot/share/gc/x/xVirtualMemory.cpp +++ b/src/hotspot/share/gc/x/xVirtualMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,8 +181,7 @@ bool XVirtualMemoryManager::reserve(size_t max_capacity) { } void XVirtualMemoryManager::nmt_reserve(uintptr_t start, size_t size) { - MemTracker::record_virtual_memory_reserve((void*)start, size, CALLER_PC); - MemTracker::record_virtual_memory_type((void*)start, mtJavaHeap); + MemTracker::record_virtual_memory_reserve((void*)start, size, CALLER_PC, mtJavaHeap); } bool XVirtualMemoryManager::is_initialized() const { diff --git a/src/hotspot/share/gc/z/zMarkStackAllocator.cpp b/src/hotspot/share/gc/z/zMarkStackAllocator.cpp index a9e404a0f55c1..866121ce0d330 100644 --- a/src/hotspot/share/gc/z/zMarkStackAllocator.cpp +++ b/src/hotspot/share/gc/z/zMarkStackAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ size_t ZMarkStackSpace::expand_space() { old_size / M, new_size / M); // Expand - os::commit_memory_or_exit((char*)_end, expand_size, false /* executable */, "Mark stack space"); + os::commit_memory_or_exit((char*)_end, expand_size, !ExecMem, mtGC, "Mark stack space"); return expand_size; } @@ -104,7 +104,7 @@ size_t ZMarkStackSpace::shrink_space() { old_size / M, new_size / M); const uintptr_t shrink_start = _end - shrink_size; - os::uncommit_memory((char*)shrink_start, shrink_size, false /* executable */); + os::uncommit_memory((char*)shrink_start, shrink_size, !ExecMem, mtGC); } return shrink_size; diff --git a/src/hotspot/share/gc/z/zNMT.cpp b/src/hotspot/share/gc/z/zNMT.cpp index 9a54c0f596343..9778ac0c975d1 100644 --- a/src/hotspot/share/gc/z/zNMT.cpp +++ b/src/hotspot/share/gc/z/zNMT.cpp @@ -71,10 +71,10 @@ void ZNMT::process_fake_mapping(zoffset offset, size_t size, bool commit) { // commit / uncommit memory if (commit) { - MemTracker::record_virtual_memory_commit((void*)sub_range_addr, sub_range_size, CALLER_PC); + MemTracker::record_virtual_memory_commit((void*)sub_range_addr, sub_range_size, CALLER_PC, mtGC); } else { ThreadCritical tc; - MemTracker::record_virtual_memory_uncommit((address)sub_range_addr, sub_range_size); + MemTracker::record_virtual_memory_uncommit((address)sub_range_addr, sub_range_size, mtGC); } left_to_process -= sub_range_size; diff --git a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp index 78309f00913cc..31855ee1eb627 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,7 +104,8 @@ bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes) assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant"); _rs = ReservedSpace(reservation_size_request_bytes, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), + mtTracing); if (!_rs.is_reserved()) { return false; } @@ -117,7 +118,6 @@ bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes) _rs.base(), _rs.size(), os::vm_page_size()); - MemTracker::record_virtual_memory_type((address)_rs.base(), mtTracing); assert(is_aligned(_rs.base(), os::vm_page_size()), "invariant"); assert(is_aligned(_rs.size(), os::vm_page_size()), "invariant"); diff --git a/src/hotspot/share/memory/allocation.inline.hpp b/src/hotspot/share/memory/allocation.inline.hpp index 4a1b0b0c5971b..3b4f163a51d73 100644 --- a/src/hotspot/share/memory/allocation.inline.hpp +++ b/src/hotspot/share/memory/allocation.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ E* MmapArrayAllocator::allocate_or_null(size_t length, MEMFLAGS flags) { return nullptr; } - if (os::commit_memory(addr, size, !ExecMem)) { + if (os::commit_memory(addr, size, !ExecMem, flags)) { return (E*)addr; } else { os::release_memory(addr, size); @@ -80,7 +80,7 @@ E* MmapArrayAllocator::allocate(size_t length, MEMFLAGS flags) { vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)"); } - os::commit_memory_or_exit(addr, size, !ExecMem, "Allocator (commit)"); + os::commit_memory_or_exit(addr, size, !ExecMem, flags, "Allocator (commit)"); return (E*)addr; } diff --git a/src/hotspot/share/memory/heap.cpp b/src/hotspot/share/memory/heap.cpp index 98e59f5818432..92a376defa5a5 100644 --- a/src/hotspot/share/memory/heap.cpp +++ b/src/hotspot/share/memory/heap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -227,13 +227,11 @@ bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_s const size_t committed_segments_size = align_to_page_size(_number_of_committed_segments); // reserve space for _segmap - ReservedSpace seg_rs(reserved_segments_size); + ReservedSpace seg_rs(reserved_segments_size, mtCode); if (!_segmap.initialize(seg_rs, committed_segments_size)) { return false; } - MemTracker::record_virtual_memory_type((address)_segmap.low_boundary(), mtCode); - assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "could not commit enough space for segment map"); assert(_segmap.reserved_size() >= (size_t) _number_of_reserved_segments , "could not reserve enough space for segment map"); assert(_segmap.reserved_size() >= _segmap.committed_size() , "just checking"); diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 22ec4d942a6b1..65eeaefe74cd7 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -589,7 +589,7 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz if (result == nullptr) { // Fallback: reserve anywhere log_debug(metaspace, map)("Trying anywhere..."); - result = os::reserve_memory_aligned(size, Metaspace::reserve_alignment(), false); + result = os::reserve_memory_aligned(size, Metaspace::reserve_alignment(), !ExecMem, mtClass); } // Wrap resulting range in ReservedSpace @@ -598,7 +598,7 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz log_debug(metaspace, map)("Mapped at " PTR_FORMAT, p2i(result)); assert(is_aligned(result, Metaspace::reserve_alignment()), "Alignment too small for metaspace"); rs = ReservedSpace::space_for_range(result, size, Metaspace::reserve_alignment(), - os::vm_page_size(), false, false); + os::vm_page_size(), false, false, mtClass); } else { log_debug(metaspace, map)("Failed to map."); rs = ReservedSpace(); @@ -739,7 +739,7 @@ void Metaspace::global_initialize() { CompressedClassSpaceBaseAddress, Metaspace::reserve_alignment())); } rs = ReservedSpace(size, Metaspace::reserve_alignment(), - os::vm_page_size() /* large */, (char*)base); + os::vm_page_size() /* large */, mtClass, (char*)base); if (rs.is_reserved()) { log_info(metaspace)("Successfully forced class space address to " PTR_FORMAT, p2i(base)); } else { @@ -767,9 +767,6 @@ void Metaspace::global_initialize() { CompressedClassSpaceSize)); } - // Mark class space as such - MemTracker::record_virtual_memory_type((address)rs.base(), mtClass); - // Initialize space Metaspace::initialize_class_space(rs); diff --git a/src/hotspot/share/memory/metaspace/testHelpers.cpp b/src/hotspot/share/memory/metaspace/testHelpers.cpp index 2d1071d77dd6a..ecc8af2f7dc63 100644 --- a/src/hotspot/share/memory/metaspace/testHelpers.cpp +++ b/src/hotspot/share/memory/metaspace/testHelpers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -78,7 +78,7 @@ MetaspaceTestContext::MetaspaceTestContext(const char* name, size_t commit_limit reserve_limit, Metaspace::reserve_alignment_words()); if (reserve_limit > 0) { // have reserve limit -> non-expandable context - _rs = ReservedSpace(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size()); + _rs = ReservedSpace(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size(), mtMetaspace); _context = MetaspaceContext::create_nonexpandable_context(name, _rs, &_commit_limiter); } else { // no reserve limit -> expandable vslist diff --git a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp index a8afbc130c968..52553b889dfa5 100644 --- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp +++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp @@ -109,7 +109,7 @@ bool VirtualSpaceNode::commit_range(MetaWord* p, size_t word_size) { } // Commit... - if (os::commit_memory((char*)p, word_size * BytesPerWord, false) == false) { + if (os::commit_memory((char*)p, word_size * BytesPerWord, !ExecMem, _rs.nmt_flag()) == false) { vm_exit_out_of_memory(word_size * BytesPerWord, OOM_MMAP_ERROR, "Failed to commit metaspace."); } @@ -188,7 +188,7 @@ void VirtualSpaceNode::uncommit_range(MetaWord* p, size_t word_size) { } // Uncommit... - if (os::uncommit_memory((char*)p, word_size * BytesPerWord) == false) { + if (os::uncommit_memory((char*)p, word_size * BytesPerWord, !ExecMem, _rs.nmt_flag()) == false) { // Note: this can actually happen, since uncommit may increase the number of mappings. fatal("Failed to uncommit metaspace."); } @@ -255,11 +255,10 @@ VirtualSpaceNode* VirtualSpaceNode::create_node(size_t word_size, DEBUG_ONLY(assert_is_aligned(word_size, chunklevel::MAX_CHUNK_WORD_SIZE);) ReservedSpace rs(word_size * BytesPerWord, Settings::virtual_space_node_reserve_alignment_words() * BytesPerWord, - os::vm_page_size()); + os::vm_page_size(), mtMetaspace); if (!rs.is_reserved()) { vm_exit_out_of_memory(word_size * BytesPerWord, OOM_MMAP_ERROR, "Failed to reserve memory for metaspace"); } - MemTracker::record_virtual_memory_type(rs.base(), mtMetaspace); assert_is_aligned(rs.base(), chunklevel::MAX_CHUNK_BYTE_SIZE); InternalStats::inc_num_vsnodes_births(); return new VirtualSpaceNode(rs, true, limiter, reserve_words_counter, commit_words_counter); diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index a75d9f076ad22..ffa918f099809 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -42,19 +42,19 @@ // Dummy constructor ReservedSpace::ReservedSpace() : _base(nullptr), _size(0), _noaccess_prefix(0), - _alignment(0), _special(false), _fd_for_heap(-1), _executable(false) { + _alignment(0), _fd_for_heap(-1), _special(false), _executable(false), _flag(mtNone) { } -ReservedSpace::ReservedSpace(size_t size) : _fd_for_heap(-1) { +ReservedSpace::ReservedSpace(size_t size, MEMFLAGS flag) : _fd_for_heap(-1), _flag(flag) { // Want to use large pages where possible. If the size is // not large page aligned the mapping will be a mix of // large and normal pages. size_t page_size = os::page_size_for_region_unaligned(size, 1); size_t alignment = os::vm_allocation_granularity(); - initialize(size, alignment, page_size, nullptr, false); + initialize(size, alignment, page_size, nullptr, false, flag); } -ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) : _fd_for_heap(-1) { +ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size, MEMFLAGS flag) : _fd_for_heap(-1), _flag(flag) { // When a page size is given we don't want to mix large // and normal pages. If the size is not a multiple of the // page size it will be aligned up to achieve this. @@ -63,45 +63,46 @@ ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) : _fd_for_ alignment = MAX2(preferred_page_size, alignment); size = align_up(size, alignment); } - initialize(size, alignment, preferred_page_size, nullptr, false); + initialize(size, alignment, preferred_page_size, nullptr, false, flag); } ReservedSpace::ReservedSpace(size_t size, size_t alignment, size_t page_size, - char* requested_address) : _fd_for_heap(-1) { - initialize(size, alignment, page_size, requested_address, false); + MEMFLAGS flag, + char* requested_address) : _fd_for_heap(-1), _flag(flag) { + initialize(size, alignment, page_size, requested_address, false, flag); } ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment, size_t page_size, - bool special, bool executable) : _fd_for_heap(-1) { + bool special, bool executable, MEMFLAGS flag) : _fd_for_heap(-1), _flag(flag) { assert((size % os::vm_allocation_granularity()) == 0, "size not allocation aligned"); - initialize_members(base, size, alignment, page_size, special, executable); + initialize_members(base, size, alignment, page_size, special, executable, flag); } // Helper method -static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd, bool executable) { +static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd, bool executable, MEMFLAGS flag) { if (fd != -1) { - return os::attempt_map_memory_to_file_at(base, size, fd); + return os::attempt_map_memory_to_file_at(base, size, fd, flag); } - return os::attempt_reserve_memory_at(base, size, executable); + return os::attempt_reserve_memory_at(base, size, executable, flag); } // Helper method -static char* map_or_reserve_memory(size_t size, int fd, bool executable) { +static char* map_or_reserve_memory(size_t size, int fd, bool executable, MEMFLAGS flag) { if (fd != -1) { - return os::map_memory_to_file(size, fd); + return os::map_memory_to_file(size, fd, flag); } - return os::reserve_memory(size, executable); + return os::reserve_memory(size, executable, flag); } // Helper method -static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd, bool executable) { +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd, bool executable, MEMFLAGS flag) { if (fd != -1) { - return os::map_memory_to_file_aligned(size, alignment, fd); + return os::map_memory_to_file_aligned(size, alignment, fd, flag); } - return os::reserve_memory_aligned(size, alignment, executable); + return os::reserve_memory_aligned(size, alignment, executable, flag); } // Helper method @@ -154,7 +155,7 @@ static void log_on_large_pages_failure(char* req_addr, size_t bytes) { } static char* reserve_memory(char* requested_address, const size_t size, - const size_t alignment, int fd, bool exec) { + const size_t alignment, int fd, bool exec, MEMFLAGS flag) { char* base; // If the memory was requested at a particular address, use // os::attempt_reserve_memory_at() to avoid mapping over something @@ -163,19 +164,19 @@ static char* reserve_memory(char* requested_address, const size_t size, assert(is_aligned(requested_address, alignment), "Requested address " PTR_FORMAT " must be aligned to " SIZE_FORMAT, p2i(requested_address), alignment); - base = attempt_map_or_reserve_memory_at(requested_address, size, fd, exec); + base = attempt_map_or_reserve_memory_at(requested_address, size, fd, exec, flag); } else { // Optimistically assume that the OS returns an aligned base pointer. // When reserving a large address range, most OSes seem to align to at // least 64K. - base = map_or_reserve_memory(size, fd, exec); + base = map_or_reserve_memory(size, fd, exec, flag); // Check alignment constraints. This is only needed when there is // no requested address. if (!is_aligned(base, alignment)) { // Base not aligned, retry. unmap_or_release_memory(base, size, fd != -1 /*is_file_mapped*/); // Map using the requested alignment. - base = map_or_reserve_memory_aligned(size, alignment, fd, exec); + base = map_or_reserve_memory_aligned(size, alignment, fd, exec, flag); } } @@ -183,14 +184,14 @@ static char* reserve_memory(char* requested_address, const size_t size, } static char* reserve_memory_special(char* requested_address, const size_t size, - const size_t alignment, const size_t page_size, bool exec) { + const size_t alignment, const size_t page_size, bool exec, MEMFLAGS flag) { log_trace(pagesize)("Attempt special mapping: size: " SIZE_FORMAT "%s, " "alignment: " SIZE_FORMAT "%s", byte_size_in_exact_unit(size), exact_unit_for_byte_size(size), byte_size_in_exact_unit(alignment), exact_unit_for_byte_size(alignment)); - char* base = os::reserve_memory_special(size, alignment, page_size, requested_address, exec); + char* base = os::reserve_memory_special(size, alignment, page_size, requested_address, exec, flag); if (base != nullptr) { // Check alignment constraints. assert(is_aligned(base, alignment), @@ -202,18 +203,19 @@ static char* reserve_memory_special(char* requested_address, const size_t size, } void ReservedSpace::clear_members() { - initialize_members(nullptr, 0, 0, 0, false, false); + initialize_members(nullptr, 0, 0, 0, false, false, mtNone); } void ReservedSpace::initialize_members(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable) { + size_t page_size, bool special, bool executable, MEMFLAGS flag) { _base = base; _size = size; + _noaccess_prefix = 0; _alignment = alignment; _page_size = page_size; _special = special; _executable = executable; - _noaccess_prefix = 0; + _flag = flag; } void ReservedSpace::reserve(size_t size, @@ -235,9 +237,9 @@ void ReservedSpace::reserve(size_t size, // When there is a backing file directory for this space then whether // large pages are allocated is up to the filesystem of the backing file. // So UseLargePages is not taken into account for this reservation. - char* base = reserve_memory(requested_address, size, alignment, _fd_for_heap, executable); + char* base = reserve_memory(requested_address, size, alignment, _fd_for_heap, executable, _flag); if (base != nullptr) { - initialize_members(base, size, alignment, os::vm_page_size(), true, executable); + initialize_members(base, size, alignment, os::vm_page_size(), true, executable, _flag); } // Always return, not possible to fall back to reservation not using a file. return; @@ -250,10 +252,10 @@ void ReservedSpace::reserve(size_t size, // explicit large pages and these have to be committed up front to ensure // no reservations are lost. do { - char* base = reserve_memory_special(requested_address, size, alignment, page_size, executable); + char* base = reserve_memory_special(requested_address, size, alignment, page_size, executable, _flag); if (base != nullptr) { // Successful reservation using large pages. - initialize_members(base, size, alignment, page_size, true, executable); + initialize_members(base, size, alignment, page_size, true, executable, _flag); return; } page_size = os::page_sizes().next_smaller(page_size); @@ -266,10 +268,10 @@ void ReservedSpace::reserve(size_t size, } // == Case 3 == - char* base = reserve_memory(requested_address, size, alignment, -1, executable); + char* base = reserve_memory(requested_address, size, alignment, -1, executable, _flag); if (base != nullptr) { // Successful mapping. - initialize_members(base, size, alignment, page_size, false, executable); + initialize_members(base, size, alignment, page_size, false, executable, _flag); } } @@ -277,7 +279,8 @@ void ReservedSpace::initialize(size_t size, size_t alignment, size_t page_size, char* requested_address, - bool executable) { + bool executable, + MEMFLAGS flag) { const size_t granularity = os::vm_allocation_granularity(); assert((size & (granularity - 1)) == 0, "size not aligned to os::vm_allocation_granularity()"); @@ -290,6 +293,9 @@ void ReservedSpace::initialize(size_t size, clear_members(); + // _flag is cleared in clear_members in above call + _flag = flag; + if (size == 0) { return; } @@ -310,14 +316,14 @@ void ReservedSpace::initialize(size_t size, ReservedSpace ReservedSpace::first_part(size_t partition_size, size_t alignment) { assert(partition_size <= size(), "partition failed"); - ReservedSpace result(base(), partition_size, alignment, page_size(), special(), executable()); + ReservedSpace result(base(), partition_size, alignment, page_size(), special(), executable(), nmt_flag()); return result; } ReservedSpace ReservedSpace::last_part(size_t partition_size, size_t alignment) { assert(partition_size <= size(), "partition failed"); ReservedSpace result(base() + partition_size, size() - partition_size, - alignment, page_size(), special(), executable()); + alignment, page_size(), special(), executable(), nmt_flag()); return result; } @@ -360,12 +366,12 @@ void ReservedSpace::release() { // Put a ReservedSpace over an existing range ReservedSpace ReservedSpace::space_for_range(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable) { + size_t page_size, bool special, bool executable, MEMFLAGS flag) { assert(is_aligned(base, os::vm_allocation_granularity()), "Unaligned base"); assert(is_aligned(size, os::vm_page_size()), "Unaligned size"); assert(os::page_sizes().contains(page_size), "Invalid pagesize"); ReservedSpace space; - space.initialize_members(base, size, alignment, page_size, special, executable); + space.initialize_members(base, size, alignment, page_size, special, executable, flag); return space; } @@ -607,16 +613,17 @@ void ReservedHeapSpace::initialize_compressed_heap(const size_t size, size_t ali // Last, desperate try without any placement. if (_base == nullptr) { log_trace(gc, heap, coops)("Trying to allocate at address null heap of size " SIZE_FORMAT_X, size + noaccess_prefix); - initialize(size + noaccess_prefix, alignment, page_size, nullptr, false); + initialize(size + noaccess_prefix, alignment, page_size, nullptr, !ExecMem, nmt_flag()); } } } ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, size_t page_size, const char* heap_allocation_directory) : ReservedSpace() { - if (size == 0) { return; } + // _flag is used internally by initialize_compressed_heap + _flag = mtJavaHeap; if (heap_allocation_directory != nullptr) { _fd_for_heap = os::create_file_for_heap(heap_allocation_directory); @@ -644,7 +651,7 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, size_t page_ establish_noaccess_prefix(); } } else { - initialize(size, alignment, page_size, nullptr, false); + initialize(size, alignment, page_size, nullptr, false, nmt_flag()); } assert(markWord::encode_pointer_as_mark(_base).decode_pointer() == _base, @@ -652,9 +659,6 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, size_t page_ assert(markWord::encode_pointer_as_mark(&_base[size]).decode_pointer() == &_base[size], "area must be distinguishable from marks for mark-sweep"); - if (base() != nullptr) { - MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap); - } if (_fd_for_heap != -1) { ::close(_fd_for_heap); @@ -670,8 +674,7 @@ MemRegion ReservedHeapSpace::region() const { ReservedCodeSpace::ReservedCodeSpace(size_t r_size, size_t rs_align, size_t rs_page_size) : ReservedSpace() { - initialize(r_size, rs_align, rs_page_size, /*requested address*/ nullptr, /*executable*/ true); - MemTracker::record_virtual_memory_type((address)base(), mtCode); + initialize(r_size, rs_align, rs_page_size, /*requested address*/ nullptr, /*executable*/ true, mtCode); } // VirtualSpace @@ -692,6 +695,7 @@ VirtualSpace::VirtualSpace() { _upper_alignment = 0; _special = false; _executable = false; + _flag = mtNone; } @@ -713,6 +717,7 @@ bool VirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t committe _special = rs.special(); _executable = rs.executable(); + _flag = rs.nmt_flag(); // When a VirtualSpace begins life at a large size, make all future expansion // and shrinking occur aligned to a granularity of large pages. This avoids @@ -771,6 +776,7 @@ void VirtualSpace::release() { _upper_alignment = 0; _special = false; _executable = false; + _flag = mtNone; } @@ -836,8 +842,8 @@ static void pretouch_expanded_memory(void* start, void* end) { os::pretouch_memory(start, end); } -static bool commit_expanded(char* start, size_t size, size_t alignment, bool pre_touch, bool executable) { - if (os::commit_memory(start, size, alignment, executable)) { +static bool commit_expanded(char* start, size_t size, size_t alignment, bool pre_touch, bool executable, MEMFLAGS flag) { + if (os::commit_memory(start, size, alignment, executable, flag)) { if (pre_touch || AlwaysPreTouch) { pretouch_expanded_memory(start, start + size); } @@ -926,7 +932,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { // Commit regions if (lower_needs > 0) { assert(lower_high() + lower_needs <= lower_high_boundary(), "must not expand beyond region"); - if (!commit_expanded(lower_high(), lower_needs, _lower_alignment, pre_touch, _executable)) { + if (!commit_expanded(lower_high(), lower_needs, _lower_alignment, pre_touch, _executable, _flag)) { return false; } _lower_high += lower_needs; @@ -934,7 +940,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { if (middle_needs > 0) { assert(middle_high() + middle_needs <= middle_high_boundary(), "must not expand beyond region"); - if (!commit_expanded(middle_high(), middle_needs, _middle_alignment, pre_touch, _executable)) { + if (!commit_expanded(middle_high(), middle_needs, _middle_alignment, pre_touch, _executable, _flag)) { return false; } _middle_high += middle_needs; @@ -942,7 +948,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { if (upper_needs > 0) { assert(upper_high() + upper_needs <= upper_high_boundary(), "must not expand beyond region"); - if (!commit_expanded(upper_high(), upper_needs, _upper_alignment, pre_touch, _executable)) { + if (!commit_expanded(upper_high(), upper_needs, _upper_alignment, pre_touch, _executable, _flag)) { return false; } _upper_high += upper_needs; @@ -1014,7 +1020,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(middle_high_boundary() <= aligned_upper_new_high && aligned_upper_new_high + upper_needs <= upper_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable)) { + if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable, _flag)) { debug_only(warning("os::uncommit_memory failed")); return; } else { @@ -1025,7 +1031,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(lower_high_boundary() <= aligned_middle_new_high && aligned_middle_new_high + middle_needs <= middle_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable)) { + if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable, _flag)) { debug_only(warning("os::uncommit_memory failed")); return; } else { @@ -1036,7 +1042,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(low_boundary() <= aligned_lower_new_high && aligned_lower_new_high + lower_needs <= lower_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable)) { + if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable, _flag)) { debug_only(warning("os::uncommit_memory failed")); return; } else { diff --git a/src/hotspot/share/memory/virtualspace.hpp b/src/hotspot/share/memory/virtualspace.hpp index 046ad0cf7a420..357c4952c3456 100644 --- a/src/hotspot/share/memory/virtualspace.hpp +++ b/src/hotspot/share/memory/virtualspace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,19 +35,20 @@ class outputStream; class ReservedSpace { friend class VMStructs; protected: - char* _base; - size_t _size; - size_t _noaccess_prefix; - size_t _alignment; - size_t _page_size; - bool _special; - int _fd_for_heap; + char* _base; + size_t _size; + size_t _noaccess_prefix; + size_t _alignment; + size_t _page_size; + int _fd_for_heap; + bool _special; + bool _executable; + MEMFLAGS _flag; private: - bool _executable; // ReservedSpace ReservedSpace(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable); + size_t page_size, bool special, bool executable, MEMFLAGS flag); protected: // Helpers to clear and set members during initialization. Two members // require special treatment: @@ -58,25 +59,28 @@ class ReservedSpace { // 0 during initialization. void clear_members(); void initialize_members(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable); + size_t page_size, bool special, bool executable, MEMFLAGS flag); void initialize(size_t size, size_t alignment, size_t page_size, - char* requested_address, bool executable); + char* requested_address, bool executable, MEMFLAGS flag); void reserve(size_t size, size_t alignment, size_t page_size, char* requested_address, bool executable); public: + + MEMFLAGS nmt_flag() const { return _flag; } + // Constructor ReservedSpace(); // Initialize the reserved space with the given size. Depending on the size // a suitable page size and alignment will be used. - explicit ReservedSpace(size_t size); + explicit ReservedSpace(size_t size, MEMFLAGS flag); // Initialize the reserved space with the given size. The preferred_page_size // is used as the minimum page size/alignment. This may waste some space if // the given size is not aligned to that value, as the reservation will be // aligned up to the final alignment in this case. - ReservedSpace(size_t size, size_t preferred_page_size); - ReservedSpace(size_t size, size_t alignment, size_t page_size, + ReservedSpace(size_t size, size_t preferred_page_size, MEMFLAGS flag); + ReservedSpace(size_t size, size_t alignment, size_t page_size, MEMFLAGS flag, char* requested_address = nullptr); // Accessors @@ -112,7 +116,7 @@ class ReservedSpace { // Put a ReservedSpace over an existing range static ReservedSpace space_for_range(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable); + size_t page_size, bool special, bool executable, MEMFLAGS flag); }; ReservedSpace ReservedSpace::first_part(size_t partition_size) @@ -179,6 +183,8 @@ class VirtualSpace { // Need to know if commit should be executable. bool _executable; + MEMFLAGS _flag; + // MPSS Support // Each virtualspace region has a lower, middle, and upper region. // Each region has an end boundary and a high pointer which is the diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp index 41a8f72b52760..83880fc6dcc61 100644 --- a/src/hotspot/share/nmt/memTracker.hpp +++ b/src/hotspot/share/nmt/memTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,7 +120,7 @@ class MemTracker : AllStatic { // (we do not do any reservations before that). static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, - MEMFLAGS flag = mtNone) { + MEMFLAGS flag) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { @@ -137,32 +137,32 @@ class MemTracker : AllStatic { } } - static inline void record_virtual_memory_uncommit(address addr, size_t size) { + static inline void record_virtual_memory_uncommit(address addr, size_t size, MEMFLAGS flag) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { - VirtualMemoryTracker::remove_uncommitted_region((address)addr, size); + VirtualMemoryTracker::remove_uncommitted_region((address)addr, size, flag); } } static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, - const NativeCallStack& stack, MEMFLAGS flag = mtNone) { + const NativeCallStack& stack, MEMFLAGS flag) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { ThreadCritical tc; VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag); - VirtualMemoryTracker::add_committed_region((address)addr, size, stack); + VirtualMemoryTracker::add_committed_region((address)addr, size, stack, flag); } } static inline void record_virtual_memory_commit(void* addr, size_t size, - const NativeCallStack& stack) { + const NativeCallStack& stack, MEMFLAGS flag) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { ThreadCritical tc; - VirtualMemoryTracker::add_committed_region((address)addr, size, stack); + VirtualMemoryTracker::add_committed_region((address)addr, size, stack, flag); } } diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.cpp b/src/hotspot/share/nmt/virtualMemoryTracker.cpp index 06f9469f25e14..a96718f59ff13 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.cpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -424,20 +424,20 @@ void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) if (reserved_rgn != nullptr) { assert(reserved_rgn->contain_address(addr), "Containment"); if (reserved_rgn->flag() != flag) { - assert(reserved_rgn->flag() == mtNone, "Overwrite memory type (should be mtNone, is: \"%s\")", - NMTUtil::flag_to_name(reserved_rgn->flag())); + assert(reserved_rgn->flag() == mtNone, "Overwrite memory type (should be mtNone, is: \"%s\") wants to change to \"%s\"", + NMTUtil::flag_to_name(reserved_rgn->flag()), NMTUtil::flag_to_name(flag)); reserved_rgn->set_flag(flag); } } } bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, - const NativeCallStack& stack) { + const NativeCallStack& stack, MEMFLAGS flag) { assert(addr != nullptr, "Invalid address"); assert(size > 0, "Invalid size"); assert(_reserved_regions != nullptr, "Sanity check"); - ReservedMemoryRegion rgn(addr, size); + ReservedMemoryRegion rgn(addr, size, stack, flag); ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); if (reserved_rgn == nullptr) { @@ -452,7 +452,7 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, return result; } -bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { +bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size, MEMFLAGS flag) { assert(addr != nullptr, "Invalid address"); assert(size > 0, "Invalid size"); assert(_reserved_regions != nullptr, "Sanity check"); diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.hpp b/src/hotspot/share/nmt/virtualMemoryTracker.hpp index db49f108c84b9..6404f3fac4b2e 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.hpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -296,13 +296,16 @@ class ReservedMemoryRegion : public VirtualMemoryRegion { public: ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack, - MEMFLAGS flag = mtNone) : + MEMFLAGS flag) : VirtualMemoryRegion(base, size), _stack(stack), _flag(flag) { } ReservedMemoryRegion(address base, size_t size) : VirtualMemoryRegion(base, size), _stack(NativeCallStack::empty_stack()), _flag(mtNone) { } + ReservedMemoryRegion(address base, size_t size, MEMFLAGS flag) : + VirtualMemoryRegion(base, size), _stack(NativeCallStack::empty_stack()), _flag(flag) { } + // Copy constructor ReservedMemoryRegion(const ReservedMemoryRegion& rr) : VirtualMemoryRegion(rr.base(), rr.size()) { @@ -379,10 +382,10 @@ class VirtualMemoryTracker : AllStatic { public: static bool initialize(NMT_TrackingLevel level); - static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone); + static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag); - static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack); - static bool remove_uncommitted_region (address base_addr, size_t size); + static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag); + static bool remove_uncommitted_region (address base_addr, size_t size, MEMFLAGS flag); static bool remove_released_region (address base_addr, size_t size); static bool remove_released_region (ReservedMemoryRegion* rgn); static void set_reserved_region_type (address addr, MEMFLAGS flag); diff --git a/src/hotspot/share/oops/compressedKlass.cpp b/src/hotspot/share/oops/compressedKlass.cpp index 4a94eb9bde02d..98be5dc978141 100644 --- a/src/hotspot/share/oops/compressedKlass.cpp +++ b/src/hotspot/share/oops/compressedKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ void CompressedKlassPointers::initialize_for_given_encoding(address addr, size_t char* CompressedKlassPointers::reserve_address_space_X(uintptr_t from, uintptr_t to, size_t size, size_t alignment, bool aslr) { alignment = MAX2(Metaspace::reserve_alignment(), alignment); - return os::attempt_reserve_memory_between((char*)from, (char*)to, size, alignment, aslr); + return os::attempt_reserve_memory_between((char*)from, (char*)to, size, alignment, aslr, mtMetaspace); } char* CompressedKlassPointers::reserve_address_space_for_unscaled_encoding(size_t size, bool aslr) { diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index b6a4443a8c763..e66daa1db9ccf 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -2396,11 +2396,10 @@ static char* get_bad_address() { static char* bad_address = nullptr; if (bad_address == nullptr) { size_t size = os::vm_allocation_granularity(); - bad_address = os::reserve_memory(size); + bad_address = os::reserve_memory(size, !ExecMem, mtInternal); if (bad_address != nullptr) { os::protect_memory(bad_address, size, os::MEM_PROT_READ, /*is_committed*/false); - MemTracker::record_virtual_memory_type((void*)bad_address, mtInternal); } } return bad_address; diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 54fb62180bf17..2a99e33eaf83a 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -697,27 +697,21 @@ WB_END WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) jlong addr = 0; - - addr = (jlong)(uintptr_t)os::reserve_memory(size); - MemTracker::record_virtual_memory_type((address)addr, mtTest); - + addr = (jlong)(uintptr_t)os::reserve_memory(size, !ExecMem, mtTest); return addr; WB_END WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size)) - addr = (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size); - MemTracker::record_virtual_memory_type((address)addr, mtTest); - + addr = (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, !ExecMem, mtTest); return addr; WB_END WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) - os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem); - MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest); + os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem, mtTest); WB_END WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) - os::uncommit_memory((char *)(uintptr_t)addr, size); + os::uncommit_memory((char *)(uintptr_t)addr, size, !ExecMem, mtTest); WB_END WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) @@ -1486,7 +1480,7 @@ WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o)) static char c; static volatile char* p; - p = os::reserve_memory(os::vm_allocation_granularity()); + p = os::reserve_memory(os::vm_allocation_granularity(), !ExecMem, mtTest); if (p == nullptr) { THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory"); } diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 53c438cd20895..5197abf5b541a 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1821,7 +1821,7 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) { } char* os::reserve_memory(size_t bytes, bool executable, MEMFLAGS flags) { - char* result = pd_reserve_memory(bytes, executable); + char* result = pd_reserve_memory(bytes, executable, flags); if (result != nullptr) { MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC, flags); log_debug(os, map)("Reserved " RANGEFMT, RANGEFMTARGS(result, bytes)); @@ -1832,7 +1832,7 @@ char* os::reserve_memory(size_t bytes, bool executable, MEMFLAGS flags) { } char* os::attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MEMFLAGS flag) { - char* result = SimulateFullAddressSpace ? nullptr : pd_attempt_reserve_memory_at(addr, bytes, executable); + char* result = SimulateFullAddressSpace ? nullptr : pd_attempt_reserve_memory_at(addr, bytes, executable, flag); if (result != nullptr) { MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, flag); log_debug(os, map)("Reserved " RANGEFMT, RANGEFMTARGS(result, bytes)); @@ -1879,7 +1879,7 @@ static void hemi_split(T* arr, unsigned num) { // Given an address range [min, max), attempts to reserve memory within this area, with the given alignment. // If randomize is true, the location will be randomized. -char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize) { +char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize, MEMFLAGS flag) { // Please keep the following constants in sync with the companion gtests: @@ -2017,7 +2017,7 @@ char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, siz const unsigned candidate_offset = points[i]; char* const candidate = lo_att + candidate_offset * alignment_adjusted; assert(candidate <= hi_att, "Invalid offset %u (" ARGSFMT ")", candidate_offset, ARGSFMTARGS); - result = SimulateFullAddressSpace ? nullptr : os::pd_attempt_reserve_memory_at(candidate, bytes, false); + result = SimulateFullAddressSpace ? nullptr : os::pd_attempt_reserve_memory_at(candidate, bytes, !ExecMem, flag); if (!result) { log_trace(os, map)("Failed to attach at " PTR_FORMAT, p2i(candidate)); } @@ -2034,7 +2034,7 @@ char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, siz assert(is_aligned(result, alignment), "alignment invalid (" ERRFMT ")", ERRFMTARGS); log_trace(os, map)(ERRFMT, ERRFMTARGS); log_debug(os, map)("successfully attached at " PTR_FORMAT, p2i(result)); - MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, flag); } else { log_debug(os, map)("failed to attach anywhere in [" PTR_FORMAT "-" PTR_FORMAT ")", p2i(min), p2i(max)); } @@ -2050,11 +2050,11 @@ static void assert_nonempty_range(const char* addr, size_t bytes) { p2i(addr), p2i(addr) + bytes); } -bool os::commit_memory(char* addr, size_t bytes, bool executable) { +bool os::commit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag) { assert_nonempty_range(addr, bytes); bool res = pd_commit_memory(addr, bytes, executable); if (res) { - MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC); + MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC, flag); log_debug(os, map)("Committed " RANGEFMT, RANGEFMTARGS(addr, bytes)); } else { log_info(os, map)("Failed to commit " RANGEFMT, RANGEFMTARGS(addr, bytes)); @@ -2063,11 +2063,11 @@ bool os::commit_memory(char* addr, size_t bytes, bool executable) { } bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, - bool executable) { + bool executable, MEMFLAGS flag) { assert_nonempty_range(addr, size); bool res = os::pd_commit_memory(addr, size, alignment_hint, executable); if (res) { - MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); + MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC, flag); log_debug(os, map)("Committed " RANGEFMT, RANGEFMTARGS(addr, size)); } else { log_info(os, map)("Failed to commit " RANGEFMT, RANGEFMTARGS(addr, size)); @@ -2076,27 +2076,27 @@ bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, } void os::commit_memory_or_exit(char* addr, size_t bytes, bool executable, - const char* mesg) { + MEMFLAGS flag, const char* mesg) { assert_nonempty_range(addr, bytes); pd_commit_memory_or_exit(addr, bytes, executable, mesg); - MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC); + MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC, flag); } void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, - bool executable, const char* mesg) { + bool executable, MEMFLAGS flag, const char* mesg) { assert_nonempty_range(addr, size); os::pd_commit_memory_or_exit(addr, size, alignment_hint, executable, mesg); - MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); + MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC, flag); } -bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { +bool os::uncommit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag) { assert_nonempty_range(addr, bytes); bool res; if (MemTracker::enabled()) { ThreadCritical tc; res = pd_uncommit_memory(addr, bytes, executable); if (res) { - MemTracker::record_virtual_memory_uncommit((address)addr, bytes); + MemTracker::record_virtual_memory_uncommit((address)addr, bytes, flag); } } else { res = pd_uncommit_memory(addr, bytes, executable); @@ -2180,7 +2180,7 @@ char* os::map_memory_to_file(size_t bytes, int file_desc, MEMFLAGS flag) { } char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc, MEMFLAGS flag) { - char* result = pd_attempt_map_memory_to_file_at(addr, bytes, file_desc); + char* result = pd_attempt_map_memory_to_file_at(addr, bytes, file_desc, flag); if (result != nullptr) { MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC, flag); } @@ -2188,8 +2188,8 @@ char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc, } char* os::map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only, - bool allow_exec, MEMFLAGS flags) { + char *addr, size_t bytes, bool read_only, + bool allow_exec, MEMFLAGS flags) { char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec); if (result != nullptr) { MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC, flags); @@ -2211,8 +2211,8 @@ bool os::unmap_memory(char *addr, size_t bytes) { return result; } -void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) { - pd_free_memory(addr, bytes, alignment_hint); +void os::free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { + pd_free_memory(addr, bytes, alignment_hint, flag); } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { @@ -2220,14 +2220,14 @@ void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size, - char* addr, bool executable) { + char* addr, bool executable, MEMFLAGS flag) { assert(is_aligned(addr, alignment), "Unaligned request address"); - char* result = pd_reserve_memory_special(size, alignment, page_size, addr, executable); + char* result = pd_reserve_memory_special(size, alignment, page_size, addr, executable, flag); if (result != nullptr) { // The memory is committed - MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC, flag); log_debug(os, map)("Reserved and committed " RANGEFMT, RANGEFMTARGS(result, size)); } else { log_info(os, map)("Reserve and commit failed (%zu bytes)", size); diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 4bfcd9c2da563..29ef6d5d29d23 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -208,9 +208,9 @@ class os: AllStatic { // low enough to leave most of the valuable low-4gb address space open. static constexpr size_t _vm_min_address_default = 16 * M; - static char* pd_reserve_memory(size_t bytes, bool executable); + static char* pd_reserve_memory(size_t bytes, bool executable, MEMFLAGS flag); - static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool executable); + static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MEMFLAGS flag); static bool pd_commit_memory(char* addr, size_t bytes, bool executable); static bool pd_commit_memory(char* addr, size_t size, size_t alignment_hint, @@ -225,13 +225,13 @@ class os: AllStatic { static bool pd_uncommit_memory(char* addr, size_t bytes, bool executable); static bool pd_release_memory(char* addr, size_t bytes); - static char* pd_attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc); + static char* pd_attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc, MEMFLAGS flag); static char* pd_map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only = false, - bool allow_exec = false); + char *addr, size_t bytes, bool read_only = false, + bool allow_exec = false); static bool pd_unmap_memory(char *addr, size_t bytes); - static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint); + static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag); static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint); // Returns 0 if pretouch is done via platform dependent method, or otherwise @@ -239,8 +239,7 @@ class os: AllStatic { static size_t pd_pretouch_memory(void* first, void* last, size_t page_size); static char* pd_reserve_memory_special(size_t size, size_t alignment, size_t page_size, - - char* addr, bool executable); + char* addr, bool executable, MEMFLAGS flag); static bool pd_release_memory_special(char* addr, size_t bytes); static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); @@ -448,30 +447,30 @@ class os: AllStatic { inline static size_t cds_core_region_alignment(); // Reserves virtual memory. - static char* reserve_memory(size_t bytes, bool executable = false, MEMFLAGS flags = mtNone); + static char* reserve_memory(size_t bytes, bool executable, MEMFLAGS flags); // Reserves virtual memory that starts at an address that is aligned to 'alignment'. - static char* reserve_memory_aligned(size_t size, size_t alignment, bool executable = false); + static char* reserve_memory_aligned(size_t size, size_t alignment, bool executable, MEMFLAGS flag); // Attempts to reserve the virtual memory at [addr, addr + bytes). // Does not overwrite existing mappings. - static char* attempt_reserve_memory_at(char* addr, size_t bytes, bool executable = false, MEMFLAGS flag = mtNone); + static char* attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MEMFLAGS flag); // Given an address range [min, max), attempts to reserve memory within this area, with the given alignment. // If randomize is true, the location will be randomized. - static char* attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize); + static char* attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize, MEMFLAGS flag); - static bool commit_memory(char* addr, size_t bytes, bool executable); + static bool commit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag); static bool commit_memory(char* addr, size_t size, size_t alignment_hint, - bool executable); + bool executable, MEMFLAGS flag); // Same as commit_memory() that either succeeds or calls // vm_exit_out_of_memory() with the specified mesg. static void commit_memory_or_exit(char* addr, size_t bytes, - bool executable, const char* mesg); + bool executable, MEMFLAGS flag, const char* mesg); static void commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, - bool executable, const char* mesg); - static bool uncommit_memory(char* addr, size_t bytes, bool executable = false); + bool executable, MEMFLAGS flag, const char* mesg); + static bool uncommit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag); static bool release_memory(char* addr, size_t bytes); // Does the platform support trimming the native heap? @@ -507,18 +506,18 @@ class os: AllStatic { static int create_file_for_heap(const char* dir); // Map memory to the file referred by fd. This function is slightly different from map_memory() // and is added to be used for implementation of -XX:AllocateHeapAt - static char* map_memory_to_file(size_t size, int fd, MEMFLAGS flag = mtNone); - static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MEMFLAGS flag = mtNone); + static char* map_memory_to_file(size_t size, int fd, MEMFLAGS flag); + static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MEMFLAGS flag); static char* map_memory_to_file(char* base, size_t size, int fd); - static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MEMFLAGS flag = mtNone); + static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MEMFLAGS flag); // Replace existing reserved memory with file mapping static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd); static char* map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only = false, - bool allow_exec = false, MEMFLAGS flags = mtNone); + char *addr, size_t bytes, bool read_only, + bool allow_exec, MEMFLAGS flag); static bool unmap_memory(char *addr, size_t bytes); - static void free_memory(char *addr, size_t bytes, size_t alignment_hint); + static void free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag); static void realign_memory(char *addr, size_t bytes, size_t alignment_hint); // NUMA-specific interface @@ -540,7 +539,7 @@ class os: AllStatic { static char* non_memory_address_word(); // reserve, commit and pin the entire memory region static char* reserve_memory_special(size_t size, size_t alignment, size_t page_size, - char* addr, bool executable); + char* addr, bool executable, MEMFLAGS flag); static bool release_memory_special(char* addr, size_t bytes); static void large_page_init(); static size_t large_page_size(); diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index 624583db3d130..dcad8acb215a0 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,9 +58,8 @@ void SafepointMechanism::default_initialize() { // Polling page const size_t page_size = os::vm_page_size(); const size_t allocation_size = 2 * page_size; - char* polling_page = os::reserve_memory(allocation_size); - os::commit_memory_or_exit(polling_page, allocation_size, false, "Unable to commit Safepoint polling page"); - MemTracker::record_virtual_memory_type((address)polling_page, mtSafepoint); + char* polling_page = os::reserve_memory(allocation_size, !ExecMem, mtSafepoint); + os::commit_memory_or_exit(polling_page, allocation_size, !ExecMem, mtSafepoint, "Unable to commit Safepoint polling page"); char* bad_page = polling_page; char* good_page = polling_page + page_size; diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 9f839fc1a136b..e12e55e49845d 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -709,10 +709,9 @@ struct TestMultipleStaticAssertFormsInClassScope { static ucontext_t g_stored_assertion_context; void initialize_assert_poison() { - char* page = os::reserve_memory(os::vm_page_size()); + char* page = os::reserve_memory(os::vm_page_size(), !ExecMem, mtInternal); if (page) { - MemTracker::record_virtual_memory_type(page, mtInternal); - if (os::commit_memory(page, os::vm_page_size(), false) && + if (os::commit_memory(page, os::vm_page_size(), !ExecMem, mtInternal) && os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) { g_assert_poison = page; } diff --git a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp index 4639f1c969430..6dfde68678a29 100644 --- a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp +++ b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp @@ -50,7 +50,7 @@ TEST_OTHER_VM(FreeRegionList, length) { // the BOT. size_t bot_size = G1BlockOffsetTable::compute_size(heap.word_size()); HeapWord* bot_data = NEW_C_HEAP_ARRAY(HeapWord, bot_size, mtGC); - ReservedSpace bot_rs(G1BlockOffsetTable::compute_size(heap.word_size())); + ReservedSpace bot_rs(G1BlockOffsetTable::compute_size(heap.word_size()), mtTest); G1RegionToSpaceMapper* bot_storage = G1RegionToSpaceMapper::create_mapper(bot_rs, bot_rs.size(), diff --git a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp index 8ce98827ab2e0..2285f58d55c7f 100644 --- a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp +++ b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp @@ -81,7 +81,7 @@ TEST_VM(G1RegionToSpaceMapper, smallStressAdjacent) { size_t size = G1BlockOffsetTable::compute_size(num_regions * region_size / HeapWordSize); size_t page_size = os::vm_page_size(); - ReservedSpace rs(size, os::vm_page_size()); + ReservedSpace rs(size, os::vm_page_size(), mtTest); G1RegionToSpaceMapper* small_mapper = G1RegionToSpaceMapper::create_mapper(rs, @@ -105,7 +105,7 @@ TEST_VM(G1RegionToSpaceMapper, largeStressAdjacent) { size_t size = G1BlockOffsetTable::compute_size(num_regions * region_size / HeapWordSize); size_t page_size = os::vm_page_size(); - ReservedSpace rs(size, page_size); + ReservedSpace rs(size, page_size, mtTest); G1RegionToSpaceMapper* large_mapper = G1RegionToSpaceMapper::create_mapper(rs, diff --git a/test/hotspot/gtest/gc/z/test_zForwarding.cpp b/test/hotspot/gtest/gc/z/test_zForwarding.cpp index 622c6d9d8f4a0..570e402ccd796 100644 --- a/test/hotspot/gtest/gc/z/test_zForwarding.cpp +++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ class ZForwardingTest : public Test { const size_t increment = MAX2(align_up(unused / 100, ZGranuleSize), ZGranuleSize); for (uintptr_t start = 0; start + ZGranuleSize <= ZAddressOffsetMax; start += increment) { - char* const reserved = os::attempt_reserve_memory_at((char*)ZAddressHeapBase + start, ZGranuleSize, false /* executable */); + char* const reserved = os::attempt_reserve_memory_at((char*)ZAddressHeapBase + start, ZGranuleSize, !ExecMem /* executable */, mtTest); if (reserved != nullptr) { // Success return reserved; @@ -100,7 +100,7 @@ class ZForwardingTest : public Test { _reserved = reserved; - os::commit_memory((char*)_reserved, ZGranuleSize, false /* executable */); + os::commit_memory((char*)_reserved, ZGranuleSize, !ExecMem /* executable */, mtTest); _page_offset = uintptr_t(_reserved) - ZAddressHeapBase; } @@ -111,7 +111,7 @@ class ZForwardingTest : public Test { ZGeneration::_old = _old_old; ZGeneration::_young = _old_young; if (_reserved != nullptr) { - os::uncommit_memory((char*)_reserved, ZGranuleSize, false /* executable */); + os::uncommit_memory((char*)_reserved, ZGranuleSize, !ExecMem, mtTest); os::release_memory((char*)_reserved, ZGranuleSize); } } diff --git a/test/hotspot/gtest/memory/test_virtualspace.cpp b/test/hotspot/gtest/memory/test_virtualspace.cpp index 2240f0f4cb37d..a20f85ba6c5c2 100644 --- a/test/hotspot/gtest/memory/test_virtualspace.cpp +++ b/test/hotspot/gtest/memory/test_virtualspace.cpp @@ -64,7 +64,7 @@ namespace { static void test_reserved_size(size_t size) { ASSERT_PRED2(is_size_aligned, size, os::vm_allocation_granularity()); - ReservedSpace rs(size); + ReservedSpace rs(size, mtTest); MemoryReleaser releaser(&rs); EXPECT_TRUE(rs.base() != nullptr) << "rs.special: " << rs.special(); @@ -78,7 +78,7 @@ namespace { static void test_reserved_size_alignment(size_t size, size_t alignment) { ASSERT_PRED2(is_size_aligned, size, alignment) << "Incorrect input parameters"; size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); - ReservedSpace rs(size, alignment, page_size, (char *) nullptr); + ReservedSpace rs(size, alignment, page_size, mtTest, (char *) nullptr); ASSERT_TRUE(rs.base() != nullptr) << "rs.special = " << rs.special(); ASSERT_EQ(size, rs.size()) << "rs.special = " << rs.special(); @@ -106,7 +106,7 @@ namespace { bool large = maybe_large && UseLargePages && size >= os::large_page_size(); size_t page_size = large ? os::large_page_size() : os::vm_page_size(); - ReservedSpace rs(size, alignment, page_size); + ReservedSpace rs(size, alignment, page_size, mtTest); MemoryReleaser releaser(&rs); EXPECT_TRUE(rs.base() != nullptr) << "rs.special: " << rs.special(); @@ -215,12 +215,13 @@ namespace { default: case Default: case Reserve: - return ReservedSpace(reserve_size_aligned); + return ReservedSpace(reserve_size_aligned, mtTest); case Disable: case Commit: return ReservedSpace(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), + mtTest); } } @@ -299,7 +300,7 @@ TEST_VM(VirtualSpace, actual_committed_space_one_large_page) { size_t large_page_size = os::large_page_size(); - ReservedSpace reserved(large_page_size, large_page_size, large_page_size); + ReservedSpace reserved(large_page_size, large_page_size, large_page_size, mtTest); ReservedSpaceReleaser releaser(&reserved); ASSERT_TRUE(reserved.is_reserved()); @@ -369,6 +370,7 @@ class TestReservedSpace : AllStatic { ReservedSpace rs(size, // size alignment, // alignment page_size, // page size + mtTest, // NMT MEM Flag (char *)nullptr); // requested_address EXPECT_TRUE(rs.base() != nullptr); @@ -387,7 +389,7 @@ class TestReservedSpace : AllStatic { static void test_reserved_space2(size_t size) { ASSERT_TRUE(is_aligned(size, os::vm_allocation_granularity())) << "Must be at least AG aligned"; - ReservedSpace rs(size); + ReservedSpace rs(size, mtTest); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -412,7 +414,7 @@ class TestReservedSpace : AllStatic { bool large = maybe_large && UseLargePages && size >= os::large_page_size(); size_t page_size = large ? os::large_page_size() : os::vm_page_size(); - ReservedSpace rs(size, alignment, page_size); + ReservedSpace rs(size, alignment, page_size, mtTest); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -516,12 +518,12 @@ class TestVirtualSpace : AllStatic { default: case Default: case Reserve: - return ReservedSpace(reserve_size_aligned); + return ReservedSpace(reserve_size_aligned, mtTest); case Disable: case Commit: return ReservedSpace(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), mtTest); } } @@ -576,7 +578,7 @@ class TestVirtualSpace : AllStatic { size_t large_page_size = os::large_page_size(); - ReservedSpace reserved(large_page_size, large_page_size, large_page_size); + ReservedSpace reserved(large_page_size, large_page_size, large_page_size, mtTest); EXPECT_TRUE(reserved.is_reserved()); diff --git a/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp b/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp index 87ad2a798e004..359c492bb6a0e 100644 --- a/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp @@ -114,7 +114,7 @@ TEST_VM(NMT, DISABLED_location_printing_cheap_dead_7) { test_for_dead_c_heap_blo #endif static void test_for_mmap(size_t sz, ssize_t offset) { - char* addr = os::reserve_memory(sz, false, mtTest); + char* addr = os::reserve_memory(sz, !ExecMem, mtTest); if (MemTracker::enabled()) { test_pointer(addr + offset, true, "in mmap'd memory region"); } else { diff --git a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp index d4959cfa00854..4036c798079ef 100644 --- a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp +++ b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp @@ -93,7 +93,7 @@ class CommittedVirtualMemoryTest { const size_t page_sz = os::vm_page_size(); const size_t size = num_pages * page_sz; char* base = os::reserve_memory(size, !ExecMem, mtThreadStack); - bool result = os::commit_memory(base, size, !ExecMem); + bool result = os::commit_memory(base, size, !ExecMem, mtThreadStack); size_t index; ASSERT_NE(base, (char*)nullptr); for (index = 0; index < touch_pages; index ++) { @@ -132,7 +132,7 @@ class CommittedVirtualMemoryTest { } // Cleanup - os::free_memory(base, size, page_sz); + os::free_memory(base, size, page_sz, mtThreadStack); VirtualMemoryTracker::remove_released_region((address)base, size); rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion((address)base, size)); @@ -162,7 +162,7 @@ class CommittedVirtualMemoryTest { const size_t size = num_pages * page_sz; char* base = os::reserve_memory(size, !ExecMem, mtTest); ASSERT_NE(base, (char*)nullptr); - result = os::commit_memory(base, size, !ExecMem); + result = os::commit_memory(base, size, !ExecMem, mtTest); ASSERT_TRUE(result); // touch all pages diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index 55d30349ee5a9..3b7267b5790d8 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -367,7 +367,7 @@ TEST_VM(os, jio_snprintf) { static inline bool can_reserve_executable_memory(void) { bool executable = true; size_t len = 128; - char* p = os::reserve_memory(len, executable); + char* p = os::reserve_memory(len, executable, mtTest); bool exec_supported = (p != nullptr); if (exec_supported) { os::release_memory(p, len); @@ -405,7 +405,7 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) { for (int tries = 0; tries < 256 && p == nullptr; tries ++) { size_t total_range_len = num_stripes * stripe_len; // Reserve a large contiguous area to get the address space... - p = (address)os::reserve_memory(total_range_len); + p = (address)os::reserve_memory(total_range_len, !ExecMem, mtTest); EXPECT_NE(p, (address)nullptr); // .. release it... EXPECT_TRUE(os::release_memory((char*)p, total_range_len)); @@ -419,14 +419,14 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) { #else const bool executable = stripe % 2 == 0; #endif - q = (address)os::attempt_reserve_memory_at((char*)q, stripe_len, executable); + q = (address)os::attempt_reserve_memory_at((char*)q, stripe_len, executable, mtTest); if (q == nullptr) { // Someone grabbed that area concurrently. Cleanup, then retry. tty->print_cr("reserve_multiple: retry (%d)...", stripe); carefully_release_multiple(p, stripe, stripe_len); p = nullptr; } else { - EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, executable)); + EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, executable, mtTest)); } } } @@ -439,12 +439,12 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) { static address reserve_one_commit_multiple(int num_stripes, size_t stripe_len) { assert(is_aligned(stripe_len, os::vm_allocation_granularity()), "Sanity"); size_t total_range_len = num_stripes * stripe_len; - address p = (address)os::reserve_memory(total_range_len); + address p = (address)os::reserve_memory(total_range_len, !ExecMem, mtTest); EXPECT_NE(p, (address)nullptr); for (int stripe = 0; stripe < num_stripes; stripe++) { address q = p + (stripe * stripe_len); if (stripe % 2 == 0) { - EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, false)); + EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, !ExecMem, mtTest)); } } return p; @@ -506,7 +506,7 @@ TEST_VM(os, release_multi_mappings) { PRINT_MAPPINGS("B"); // ...re-reserve the middle stripes. This should work unless release silently failed. - address p2 = (address)os::attempt_reserve_memory_at((char*)p_middle_stripes, middle_stripe_len); + address p2 = (address)os::attempt_reserve_memory_at((char*)p_middle_stripes, middle_stripe_len, !ExecMem, mtTest); ASSERT_EQ(p2, p_middle_stripes); @@ -529,7 +529,7 @@ TEST_VM_ASSERT_MSG(os, release_bad_ranges, ".*bad release") { #else TEST_VM(os, release_bad_ranges) { #endif - char* p = os::reserve_memory(4 * M); + char* p = os::reserve_memory(4 * M, !ExecMem, mtTest); ASSERT_NE(p, (char*)nullptr); // Release part of range ASSERT_FALSE(os::release_memory(p, M)); @@ -564,7 +564,7 @@ TEST_VM(os, release_one_mapping_multi_commits) { // // make things even more difficult by trying to reserve at the border of the region address border = p + num_stripes * stripe_len; - address p2 = (address)os::attempt_reserve_memory_at((char*)border, stripe_len); + address p2 = (address)os::attempt_reserve_memory_at((char*)border, stripe_len, !ExecMem, mtTest); PRINT_MAPPINGS("B"); ASSERT_TRUE(p2 == nullptr || p2 == border); @@ -605,9 +605,9 @@ TEST_VM(os, show_mappings_small_range) { TEST_VM(os, show_mappings_full_range) { // Reserve a small range and fill it with a marker string, should show up // on implementations displaying range snippets - char* p = os::reserve_memory(1 * M, false, mtInternal); + char* p = os::reserve_memory(1 * M, !ExecMem, mtInternal); if (p != nullptr) { - if (os::commit_memory(p, 1 * M, false)) { + if (os::commit_memory(p, 1 * M, !ExecMem, mtTest)) { strcpy(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); } } @@ -629,7 +629,7 @@ TEST_VM(os, find_mapping_simple) { // A simple allocation { - address p = (address)os::reserve_memory(total_range_len); + address p = (address)os::reserve_memory(total_range_len, !ExecMem, mtTest); ASSERT_NE(p, (address)nullptr); PRINT_MAPPINGS("A"); for (size_t offset = 0; offset < total_range_len; offset += 4711) { @@ -934,9 +934,9 @@ TEST_VM(os, open_O_CLOEXEC) { } TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_smallpages) { - char* p1 = os::reserve_memory(M, false, mtTest); + char* p1 = os::reserve_memory(M, !ExecMem, mtTest); ASSERT_NE(p1, nullptr); - char* p2 = os::attempt_reserve_memory_at(p1, M); + char* p2 = os::attempt_reserve_memory_at(p1, M, !ExecMem, mtTest); ASSERT_EQ(p2, nullptr); // should have failed os::release_memory(p1, M); } @@ -944,9 +944,9 @@ TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_smallpages) { TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_largepages) { if (UseLargePages && !os::can_commit_large_page_memory()) { // aka special const size_t lpsz = os::large_page_size(); - char* p1 = os::reserve_memory_aligned(lpsz, lpsz, false); + char* p1 = os::reserve_memory_aligned(lpsz, lpsz, !ExecMem, mtTest); ASSERT_NE(p1, nullptr); - char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, false); + char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, !ExecMem, mtTest); ASSERT_EQ(p2, nullptr); // should have failed os::release_memory(p1, M); } else { @@ -958,9 +958,9 @@ TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_largepages) { // On Aix, we should fail attach attempts not aligned to segment boundaries (256m) TEST_VM(os, aix_reserve_at_non_shmlba_aligned_address) { if (Use64KPages) { - char* p = os::attempt_reserve_memory_at((char*)0x1f00000, M); + char* p = os::attempt_reserve_memory_at((char*)0x1f00000, M, !ExecMem, mtTest); ASSERT_EQ(p, nullptr); // should have failed - p = os::attempt_reserve_memory_at((char*)((64 * G) + M), M); + p = os::attempt_reserve_memory_at((char*)((64 * G) + M), M, !ExecMem, mtTest); ASSERT_EQ(p, nullptr); // should have failed } } diff --git a/test/hotspot/gtest/runtime/test_os_linux.cpp b/test/hotspot/gtest/runtime/test_os_linux.cpp index 69c3d991b2a4f..582a516465cf4 100644 --- a/test/hotspot/gtest/runtime/test_os_linux.cpp +++ b/test/hotspot/gtest/runtime/test_os_linux.cpp @@ -54,7 +54,7 @@ namespace { const size_t _size; public: static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) { - return os::reserve_memory_special(bytes, alignment, page_size, req_addr, exec); + return os::reserve_memory_special(bytes, alignment, page_size, req_addr, exec, mtTest); } HugeTlbfsMemory(char* const ptr, size_t size) : _ptr(ptr), _size(size) { } ~HugeTlbfsMemory() { @@ -224,7 +224,7 @@ class TestReserveMemorySpecial : AllStatic { if (!using_explicit_hugepages()) { return; } - char* addr = os::reserve_memory_special(size, alignment, page_size, nullptr, false); + char* addr = os::reserve_memory_special(size, alignment, page_size, nullptr, !ExecMem, mtTest); if (addr != nullptr) { small_page_write(addr, size); os::release_memory_special(addr, size); @@ -281,7 +281,7 @@ class TestReserveMemorySpecial : AllStatic { for (int i = 0; i < num_sizes; i++) { const size_t size = sizes[i]; for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { - char* p = os::reserve_memory_special(size, alignment, lp, nullptr, false); + char* p = os::reserve_memory_special(size, alignment, lp, nullptr, !ExecMem, mtTest); if (p != nullptr) { EXPECT_TRUE(is_aligned(p, alignment)); small_page_write(p, size); @@ -296,7 +296,7 @@ class TestReserveMemorySpecial : AllStatic { for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { // req_addr must be at least large page aligned. char* const req_addr = align_up(mapping1, MAX2(alignment, lp)); - char* p = os::reserve_memory_special(size, alignment, lp, req_addr, false); + char* p = os::reserve_memory_special(size, alignment, lp, req_addr, !ExecMem, mtTest); if (p != nullptr) { EXPECT_EQ(p, req_addr); small_page_write(p, size); @@ -311,7 +311,7 @@ class TestReserveMemorySpecial : AllStatic { for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { // req_addr must be at least large page aligned. char* const req_addr = align_up(mapping2, MAX2(alignment, lp)); - char* p = os::reserve_memory_special(size, alignment, lp, req_addr, false); + char* p = os::reserve_memory_special(size, alignment, lp, req_addr, !ExecMem, mtTest); // as the area around req_addr contains already existing mappings, the API should always // return nullptr (as per contract, it cannot return another address) EXPECT_TRUE(p == nullptr); @@ -355,9 +355,9 @@ TEST_VM(os_linux, pretouch_thp_and_use_concurrent) { const size_t size = 1 * G; const bool useThp = UseTransparentHugePages; UseTransparentHugePages = true; - char* const heap = os::reserve_memory(size, false, mtInternal); + char* const heap = os::reserve_memory(size, !ExecMem, mtInternal); EXPECT_NE(heap, nullptr); - EXPECT_TRUE(os::commit_memory(heap, size, false)); + EXPECT_TRUE(os::commit_memory(heap, size, !ExecMem, mtInternal)); { auto pretouch = [heap, size](Thread*, int) { @@ -379,7 +379,7 @@ TEST_VM(os_linux, pretouch_thp_and_use_concurrent) { for (int i = 0; i < 1000; i++) EXPECT_EQ(*iptr++, i); - EXPECT_TRUE(os::uncommit_memory(heap, size, false)); + EXPECT_TRUE(os::uncommit_memory(heap, size, !ExecMem, mtInternal)); EXPECT_TRUE(os::release_memory(heap, size)); UseTransparentHugePages = useThp; } diff --git a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp index aad6acc095a1e..1e052ddf65ede 100644 --- a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp +++ b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp @@ -66,7 +66,7 @@ static size_t allocation_granularity() { << " bytes: " << bytes << " alignment: " << alignment << " randomized: " << randomized static char* call_attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomized) { - char* const addr = os::attempt_reserve_memory_between(min, max, bytes, alignment, randomized); + char* const addr = os::attempt_reserve_memory_between(min, max, bytes, alignment, randomized, mtTest); if (addr != nullptr) { EXPECT_TRUE(is_aligned(addr, alignment)) << ERRINFO; EXPECT_TRUE(is_aligned(addr, allocation_granularity())) << ERRINFO; @@ -158,7 +158,7 @@ struct SpaceWithHole { // the hole. const uintptr_t candidate = nth_bit(i); if ((candidate + _len) <= ARMB_constants::absolute_max) { - _base = os::attempt_reserve_memory_at((char*)candidate, _len); + _base = os::attempt_reserve_memory_at((char*)candidate, _len, !ExecMem, mtTest); } } if (_base == nullptr) { @@ -166,8 +166,8 @@ struct SpaceWithHole { } // Release total mapping, remap the individual non-holy parts os::release_memory(_base, _len); - _p1 = os::attempt_reserve_memory_at(_base + _p1_offset, _p1_size); - _p2 = os::attempt_reserve_memory_at(_base + _p2_offset, _p2_size); + _p1 = os::attempt_reserve_memory_at(_base + _p1_offset, _p1_size, !ExecMem, mtTest); + _p2 = os::attempt_reserve_memory_at(_base + _p2_offset, _p2_size, !ExecMem, mtTest); if (_p1 == nullptr || _p2 == nullptr) { return false; } diff --git a/test/hotspot/gtest/runtime/test_os_windows.cpp b/test/hotspot/gtest/runtime/test_os_windows.cpp index 8c6f003de6f26..87ae501a08be7 100644 --- a/test/hotspot/gtest/runtime/test_os_windows.cpp +++ b/test/hotspot/gtest/runtime/test_os_windows.cpp @@ -67,7 +67,7 @@ void TestReserveMemorySpecial_test() { FLAG_SET_CMDLINE(UseNUMAInterleaving, false); const size_t large_allocation_size = os::large_page_size() * 4; - char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), os::large_page_size(), nullptr, false); + char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), os::large_page_size(), nullptr, !ExecMem, mtTest); if (result == nullptr) { // failed to allocate memory, skipping the test return; @@ -77,12 +77,12 @@ void TestReserveMemorySpecial_test() { // Reserve another page within the recently allocated memory area. This should fail const size_t expected_allocation_size = os::large_page_size(); char* expected_location = result + os::large_page_size(); - char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false); + char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, !ExecMem, mtTest); EXPECT_TRUE(actual_location == nullptr) << "Should not be allowed to reserve within present reservation"; // Instead try reserving after the first reservation. expected_location = result + large_allocation_size; - actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false); + actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, !ExecMem, mtTest); EXPECT_TRUE(actual_location != nullptr) << "Unexpected reservation failure, can’t verify correct location"; EXPECT_TRUE(actual_location == expected_location) << "Reservation must be at requested location"; MemoryReleaser m2(actual_location, os::large_page_size()); @@ -90,7 +90,7 @@ void TestReserveMemorySpecial_test() { // Now try to do a reservation with a larger alignment. const size_t alignment = os::large_page_size() * 2; const size_t new_large_size = alignment * 4; - char* aligned_request = os::reserve_memory_special(new_large_size, alignment, os::large_page_size(), nullptr, false); + char* aligned_request = os::reserve_memory_special(new_large_size, alignment, os::large_page_size(), nullptr, !ExecMem, mtTest); EXPECT_TRUE(aligned_request != nullptr) << "Unexpected reservation failure, can’t verify correct alignment"; EXPECT_TRUE(is_aligned(aligned_request, alignment)) << "Returned address must be aligned"; MemoryReleaser m3(aligned_request, new_large_size); diff --git a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp index b098416456d6c..f2b3b843c2313 100644 --- a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp +++ b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp @@ -93,7 +93,7 @@ class VirtualMemoryTrackerTest { static void test_add_committed_region_adjacent() { size_t size = 0x01000000; - ReservedSpace rs(size); + ReservedSpace rs(size, mtTest); address addr = (address)rs.base(); address frame1 = (address)0x1234; @@ -167,7 +167,7 @@ class VirtualMemoryTrackerTest { static void test_add_committed_region_adjacent_overlapping() { size_t size = 0x01000000; - ReservedSpace rs(size); + ReservedSpace rs(size, mtTest); address addr = (address)rs.base(); address frame1 = (address)0x1234; @@ -254,7 +254,7 @@ class VirtualMemoryTrackerTest { static void test_add_committed_region_overlapping() { size_t size = 0x01000000; - ReservedSpace rs(size); + ReservedSpace rs(size, mtTest); address addr = (address)rs.base(); address frame1 = (address)0x1234; @@ -425,7 +425,7 @@ class VirtualMemoryTrackerTest { static void test_remove_uncommitted_region() { size_t size = 0x01000000; - ReservedSpace rs(size); + ReservedSpace rs(size, mtTest); address addr = (address)rs.base(); address frame1 = (address)0x1234; From d3bf52628efb79e1b98749d628c4b6d035e1d511 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 2 May 2024 07:49:12 +0000 Subject: [PATCH 035/203] 8331518: Tests should not use the "Classpath" exception form of the legal header Reviewed-by: dholmes --- .../jtreg/compiler/c2/TestUninitializedKlassField.java | 4 +--- .../jtreg/compiler/codegen/TestConvertImplicitNullCheck.java | 4 +--- .../loopopts/TestPartialPeelingAtSingleInputRegion.java | 4 +--- .../org/openjdk/bench/java/lang/foreign/libToJavaString.c | 4 +--- test/micro/org/openjdk/bench/vm/compiler/MergeStores.java | 4 +--- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/TestUninitializedKlassField.java b/test/hotspot/jtreg/compiler/c2/TestUninitializedKlassField.java index 3bad2bde7b1b7..63daec895efe3 100644 --- a/test/hotspot/jtreg/compiler/c2/TestUninitializedKlassField.java +++ b/test/hotspot/jtreg/compiler/c2/TestUninitializedKlassField.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/hotspot/jtreg/compiler/codegen/TestConvertImplicitNullCheck.java b/test/hotspot/jtreg/compiler/codegen/TestConvertImplicitNullCheck.java index 0e0c354584441..c8883b9c04ef4 100644 --- a/test/hotspot/jtreg/compiler/codegen/TestConvertImplicitNullCheck.java +++ b/test/hotspot/jtreg/compiler/codegen/TestConvertImplicitNullCheck.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/hotspot/jtreg/compiler/loopopts/TestPartialPeelingAtSingleInputRegion.java b/test/hotspot/jtreg/compiler/loopopts/TestPartialPeelingAtSingleInputRegion.java index 2b2231a89f34a..9159c3627ec7a 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestPartialPeelingAtSingleInputRegion.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestPartialPeelingAtSingleInputRegion.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/libToJavaString.c b/test/micro/org/openjdk/bench/java/lang/foreign/libToJavaString.c index f4c407c1ab687..e7da435b43d86 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/libToJavaString.c +++ b/test/micro/org/openjdk/bench/java/lang/foreign/libToJavaString.c @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java b/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java index e1f0d5eaedcdf..84017573c075b 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java +++ b/test/micro/org/openjdk/bench/vm/compiler/MergeStores.java @@ -4,9 +4,7 @@ * * 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. + * 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 From dd906ffdcb7d965cd4798cb7eebd9c1b71b3c136 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 2 May 2024 08:10:59 +0000 Subject: [PATCH 036/203] 8331399: RISC-V: Don't us mv instead of la Reviewed-by: fyang, mli, tonyp --- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 4 ++-- src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 234d85ed2469a..b450d93680f3b 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -2098,7 +2098,7 @@ void MacroAssembler::movoop(Register dst, jobject obj) { RelocationHolder rspec = oop_Relocation::spec(oop_index); if (BarrierSet::barrier_set()->barrier_set_assembler()->supports_instruction_patching()) { - mv(dst, Address((address)obj, rspec)); + la(dst, Address((address)obj, rspec)); } else { address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address ld_constant(dst, Address(dummy, rspec)); @@ -2114,7 +2114,7 @@ void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { oop_index = oop_recorder()->find_index(obj); } RelocationHolder rspec = metadata_Relocation::spec(oop_index); - mv(dst, Address((address)obj, rspec)); + la(dst, Address((address)obj, rspec)); } // Writes to stack successive pages until offset reached to check for diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index a46f3d5779e09..7c77edd8711ce 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -763,13 +763,6 @@ class MacroAssembler: public Assembler { template::value)> inline void mv(Register Rd, T o) { li(Rd, (int64_t)o); } - void mv(Register Rd, Address dest) { - assert(dest.getMode() == Address::literal, "Address mode should be Address::literal"); - relocate(dest.rspec(), [&] { - movptr(Rd, dest.target()); - }); - } - void mv(Register Rd, RegisterOrConstant src) { if (src.is_register()) { mv(Rd, src.as_register()); From c4fe5bf90c2d368c29714de63a90eca444fb3ece Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 2 May 2024 08:26:09 +0000 Subject: [PATCH 037/203] 8331405: Shenandoah: Optimize ShenandoahLock with TTAS Reviewed-by: zgu, ysr --- src/hotspot/share/gc/shenandoah/shenandoahLock.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp b/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp index 39588d68bc83b..349f5415cdc0b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp @@ -54,7 +54,8 @@ template void ShenandoahLock::contended_lock_internal(JavaThread* java_thread) { int ctr = 0; int yields = 0; - while (Atomic::cmpxchg(&_state, unlocked, locked) != unlocked) { + while (Atomic::load(&_state) == locked || + Atomic::cmpxchg(&_state, unlocked, locked) != unlocked) { if ((++ctr & 0xFFF) == 0) { BlockOp block(java_thread); if (yields > 5) { From 8bcd2e61aec51f7c5b09ae162f8cca85a8bbf105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Thu, 2 May 2024 08:31:49 +0000 Subject: [PATCH 038/203] 8329088: Stack chunk thawing races with concurrent GC stack iteration Reviewed-by: stefank, pchilanomate --- src/hotspot/share/classfile/vmSymbols.hpp | 2 +- .../share/oops/instanceStackChunkKlass.cpp | 4 +- src/hotspot/share/oops/oop.hpp | 2 + src/hotspot/share/oops/oop.inline.hpp | 2 + src/hotspot/share/oops/stackChunkOop.cpp | 21 ++--- src/hotspot/share/oops/stackChunkOop.hpp | 1 + .../share/oops/stackChunkOop.inline.hpp | 17 ++-- .../share/runtime/continuationFreezeThaw.cpp | 79 ++++++++----------- .../share/runtime/continuationJavaClasses.cpp | 4 +- .../share/runtime/continuationJavaClasses.hpp | 7 +- .../continuationJavaClasses.inline.hpp | 19 +++-- .../classes/jdk/internal/vm/StackChunk.java | 4 +- 12 files changed, 85 insertions(+), 77 deletions(-) diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index f35858fe5861f..f79af705f0b0a 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -432,7 +432,7 @@ class SerializeClosure; template(yieldInfo_name, "yieldInfo") \ template(tail_name, "tail") \ template(size_name, "size") \ - template(argsize_name, "argsize") \ + template(bottom_name, "bottom") \ template(mode_name, "mode") \ template(numFrames_name, "numFrames") \ template(numOops_name, "numOops") \ diff --git a/src/hotspot/share/oops/instanceStackChunkKlass.cpp b/src/hotspot/share/oops/instanceStackChunkKlass.cpp index 0164ad0a9ba7c..8171188d35732 100644 --- a/src/hotspot/share/oops/instanceStackChunkKlass.cpp +++ b/src/hotspot/share/oops/instanceStackChunkKlass.cpp @@ -250,8 +250,8 @@ void InstanceStackChunkKlass::print_chunk(const stackChunkOop c, bool verbose, o st->print_cr(" barriers: %d gc_mode: %d bitmap: %d parent: " PTR_FORMAT, c->requires_barriers(), c->is_gc_mode(), c->has_bitmap(), p2i(c->parent())); st->print_cr(" flags mixed: %d", c->has_mixed_frames()); - st->print_cr(" size: %d argsize: %d max_size: %d sp: %d pc: " PTR_FORMAT, - c->stack_size(), c->argsize(), c->max_thawing_size(), c->sp(), p2i(c->pc())); + st->print_cr(" size: %d bottom: %d max_size: %d sp: %d pc: " PTR_FORMAT, + c->stack_size(), c->bottom(), c->max_thawing_size(), c->sp(), p2i(c->pc())); if (verbose) { st->cr(); diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 6766b68373188..2d827699b41fa 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -206,6 +206,8 @@ class oopDesc { jboolean bool_field_acquire(int offset) const; void release_bool_field_put(int offset, jboolean contents); + jint int_field_relaxed(int offset) const; + void int_field_put_relaxed(int offset, jint contents); jint int_field_acquire(int offset) const; void release_int_field_put(int offset, jint contents); diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index b7dbc7b2224b7..ffcc9af24c328 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -238,6 +238,8 @@ inline void oopDesc::short_field_put(int offset, jshort value) { *field_add inline jint oopDesc::int_field(int offset) const { return *field_addr(offset); } inline void oopDesc::int_field_put(int offset, jint value) { *field_addr(offset) = value; } +inline jint oopDesc::int_field_relaxed(int offset) const { return Atomic::load(field_addr(offset)); } +inline void oopDesc::int_field_put_relaxed(int offset, jint value) { Atomic::store(field_addr(offset), value); } inline jlong oopDesc::long_field(int offset) const { return *field_addr(offset); } inline void oopDesc::long_field_put(int offset, jlong value) { *field_addr(offset) = value; } diff --git a/src/hotspot/share/oops/stackChunkOop.cpp b/src/hotspot/share/oops/stackChunkOop.cpp index c0bef6659a3c4..8d230b334c88f 100644 --- a/src/hotspot/share/oops/stackChunkOop.cpp +++ b/src/hotspot/share/oops/stackChunkOop.cpp @@ -533,12 +533,12 @@ bool stackChunkOopDesc::verify(size_t* out_size, int* out_oops, int* out_frames, assert(oopDesc::is_oop(this), ""); assert(stack_size() >= 0, ""); - assert(argsize() >= 0, ""); assert(!has_bitmap() || is_gc_mode(), ""); if (is_empty()) { - assert(argsize() == 0, ""); assert(max_thawing_size() == 0, ""); + } else { + assert(argsize() >= 0, ""); } assert(oopDesc::is_oop_or_null(parent()), ""); @@ -547,7 +547,7 @@ bool stackChunkOopDesc::verify(size_t* out_size, int* out_oops, int* out_frames, // If argsize == 0 and the chunk isn't mixed, the chunk contains the metadata (pc, fp -- frame::sender_sp_offset) // for the top frame (below sp), and *not* for the bottom frame. - int size = stack_size() - argsize() - sp(); + int size = bottom() - sp(); assert(size >= 0, ""); assert((size == 0) == is_empty(), ""); @@ -570,12 +570,15 @@ bool stackChunkOopDesc::verify(size_t* out_size, int* out_oops, int* out_frames, assert(closure._num_interpreted_frames == 0 || has_mixed_frames(), ""); if (!concurrent) { - assert(closure._size <= size + argsize() + frame::metadata_words, - "size: %d argsize: %d closure.size: %d end sp: " PTR_FORMAT " start sp: %d chunk size: %d", - size, argsize(), closure._size, closure._sp - start_address(), sp(), stack_size()); - assert(argsize() == closure._argsize - (closure._num_frames > 0 ? frame::metadata_words_at_top : 0), - "argsize(): %d closure.argsize: %d closure.callee_interpreted: %d", - argsize(), closure._argsize, closure._callee_interpreted); + assert(closure._size <= size + (stack_size() - bottom()), + "size: %d bottom: %d closure.size: %d end sp: " PTR_FORMAT " start sp: %d chunk size: %d", + size, bottom(), closure._size, closure._sp - start_address(), sp(), stack_size()); + if (closure._num_frames > 0) { + assert(closure._argsize >= frame::metadata_words_at_top, "should be set up"); + assert(argsize() == closure._argsize - frame::metadata_words_at_top, + "argsize(): %d closure.argsize: %d closure.callee_interpreted: %d", + argsize(), closure._argsize, closure._callee_interpreted); + } int calculated_max_size = closure._size + closure._num_i2c * frame::align_wiggle diff --git a/src/hotspot/share/oops/stackChunkOop.hpp b/src/hotspot/share/oops/stackChunkOop.hpp index abfe47ad3f1c4..250acc8d16591 100644 --- a/src/hotspot/share/oops/stackChunkOop.hpp +++ b/src/hotspot/share/oops/stackChunkOop.hpp @@ -101,6 +101,7 @@ class stackChunkOopDesc : public instanceOopDesc { inline void set_cont_access(oop value); inline int bottom() const; + inline void set_bottom(int value); inline HeapWord* start_of_stack() const; diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp index c75908610324d..54f1423fd1cd9 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -60,15 +60,15 @@ inline void stackChunkOopDesc::set_parent_access(oop value) { jdk_internal_vm inline int stackChunkOopDesc::stack_size() const { return jdk_internal_vm_StackChunk::size(as_oop()); } +inline int stackChunkOopDesc::bottom() const { return jdk_internal_vm_StackChunk::bottom(as_oop()); } +inline void stackChunkOopDesc::set_bottom(int value) { jdk_internal_vm_StackChunk::set_bottom(this, value); } + inline int stackChunkOopDesc::sp() const { return jdk_internal_vm_StackChunk::sp(as_oop()); } inline void stackChunkOopDesc::set_sp(int value) { jdk_internal_vm_StackChunk::set_sp(this, value); } inline address stackChunkOopDesc::pc() const { return jdk_internal_vm_StackChunk::pc(as_oop()); } inline void stackChunkOopDesc::set_pc(address value) { jdk_internal_vm_StackChunk::set_pc(this, value); } -inline int stackChunkOopDesc::argsize() const { return jdk_internal_vm_StackChunk::argsize(as_oop()); } -inline void stackChunkOopDesc::set_argsize(int value) { jdk_internal_vm_StackChunk::set_argsize(as_oop(), value); } - inline uint8_t stackChunkOopDesc::flags() const { return jdk_internal_vm_StackChunk::flags(as_oop()); } inline void stackChunkOopDesc::set_flags(uint8_t value) { jdk_internal_vm_StackChunk::set_flags(this, value); } @@ -108,7 +108,10 @@ inline void stackChunkOopDesc::set_cont_raw(oop value) { jdk_internal_vm_Stac template inline void stackChunkOopDesc::set_cont_access(oop value) { jdk_internal_vm_StackChunk::set_cont_access(this, value); } -inline int stackChunkOopDesc::bottom() const { return stack_size() - argsize() - frame::metadata_words_at_top; } +inline int stackChunkOopDesc::argsize() const { + assert(!is_empty(), "should not ask for argsize in empty chunk"); + return stack_size() - bottom() - frame::metadata_words_at_top; +} inline HeapWord* stackChunkOopDesc::start_of_stack() const { return (HeapWord*)(cast_from_oop(as_oop()) + InstanceStackChunkKlass::offset_of_stack()); @@ -132,10 +135,8 @@ inline intptr_t* stackChunkOopDesc::from_offset(int offset) const { } inline bool stackChunkOopDesc::is_empty() const { - assert(sp() <= stack_size(), ""); - assert((sp() == stack_size()) == (sp() >= stack_size() - argsize() - frame::metadata_words_at_top), - "sp: %d size: %d argsize: %d", sp(), stack_size(), argsize()); - return sp() == stack_size(); + assert(sp() <= bottom(), ""); + return sp() == bottom(); } inline bool stackChunkOopDesc::is_in_chunk(void* p) const { diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index 527e0da15a8fa..77ec9642d48f3 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -403,7 +403,7 @@ class FreezeBase : public StackObj { inline void patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp); // slow path - virtual stackChunkOop allocate_chunk_slow(size_t stack_size) = 0; + virtual stackChunkOop allocate_chunk_slow(size_t stack_size, int argsize_md) = 0; int cont_size() { return pointer_delta_as_int(_cont_stack_bottom, _cont_stack_top); } @@ -438,20 +438,12 @@ class FreezeBase : public StackObj { protected: void freeze_fast_copy(stackChunkOop chunk, int chunk_start_sp CONT_JFR_ONLY(COMMA bool chunk_is_allocated)); bool freeze_fast_new_chunk(stackChunkOop chunk); - -#ifdef ASSERT - bool is_empty(stackChunkOop chunk) { - // during freeze, the chunk is in an intermediate state (after setting the chunk's argsize but before setting its - // ultimate sp) so we use this instead of stackChunkOopDesc::is_empty - return chunk->sp() >= chunk->stack_size() - chunk->argsize() - frame::metadata_words_at_top; - } -#endif }; template class Freeze : public FreezeBase { private: - stackChunkOop allocate_chunk(size_t stack_size); + stackChunkOop allocate_chunk(size_t stack_size, int argsize_md); public: inline Freeze(JavaThread* thread, ContinuationWrapper& cont, intptr_t* frame_sp) @@ -460,7 +452,7 @@ class Freeze : public FreezeBase { freeze_result try_freeze_fast(); protected: - virtual stackChunkOop allocate_chunk_slow(size_t stack_size) override { return allocate_chunk(stack_size); } + virtual stackChunkOop allocate_chunk_slow(size_t stack_size, int argsize_md) override { return allocate_chunk(stack_size, argsize_md); } }; FreezeBase::FreezeBase(JavaThread* thread, ContinuationWrapper& cont, intptr_t* frame_sp) : @@ -543,7 +535,7 @@ freeze_result Freeze::try_freeze_fast() { DEBUG_ONLY(_fast_freeze_size = size_if_fast_freeze_available();) assert(_fast_freeze_size == 0, ""); - stackChunkOop chunk = allocate_chunk(cont_size() + frame::metadata_words); + stackChunkOop chunk = allocate_chunk(cont_size() + frame::metadata_words, _cont.argsize() + frame::metadata_words_at_top); if (freeze_fast_new_chunk(chunk)) { return freeze_ok; } @@ -572,7 +564,7 @@ int FreezeBase::size_if_fast_freeze_available() { // so we subtract it only if we overlap with the caller, i.e. the current chunk isn't empty. // Consider leaving the chunk's argsize set when emptying it and removing the following branch, // although that would require changing stackChunkOopDesc::is_empty - if (chunk_sp < chunk->stack_size()) { + if (!chunk->is_empty()) { total_size_needed -= _cont.argsize() + frame::metadata_words_at_top; } @@ -585,14 +577,13 @@ int FreezeBase::size_if_fast_freeze_available() { void FreezeBase::freeze_fast_existing_chunk() { stackChunkOop chunk = _cont.tail(); - DEBUG_ONLY(_orig_chunk_sp = chunk->sp_address();) DEBUG_ONLY(_fast_freeze_size = size_if_fast_freeze_available();) assert(_fast_freeze_size > 0, ""); - if (chunk->sp() < chunk->stack_size()) { // we are copying into a non-empty chunk + if (!chunk->is_empty()) { // we are copying into a non-empty chunk DEBUG_ONLY(_empty = false;) - assert(chunk->sp() < (chunk->stack_size() - chunk->argsize()), ""); + DEBUG_ONLY(_orig_chunk_sp = chunk->sp_address();) #ifdef ASSERT { intptr_t* retaddr_slot = (chunk->sp_address() @@ -630,13 +621,14 @@ void FreezeBase::freeze_fast_existing_chunk() { freeze_fast_copy(chunk, chunk_start_sp CONT_JFR_ONLY(COMMA false)); } else { // the chunk is empty - DEBUG_ONLY(_empty = true;) - const int chunk_start_sp = chunk->sp(); + const int chunk_start_sp = chunk->stack_size(); - assert(chunk_start_sp == chunk->stack_size(), ""); + DEBUG_ONLY(_empty = true;) + DEBUG_ONLY(_orig_chunk_sp = chunk->start_address() + chunk_start_sp;) chunk->set_max_thawing_size(cont_size()); - chunk->set_argsize(_cont.argsize()); + chunk->set_bottom(chunk_start_sp - _cont.argsize() - frame::metadata_words_at_top); + chunk->set_sp(chunk->bottom()); freeze_fast_copy(chunk, chunk_start_sp CONT_JFR_ONLY(COMMA false)); } @@ -654,7 +646,6 @@ bool FreezeBase::freeze_fast_new_chunk(stackChunkOop chunk) { } chunk->set_max_thawing_size(cont_size()); - chunk->set_argsize(_cont.argsize()); // in a fresh chunk, we freeze *with* the bottom-most frame's stack arguments. // They'll then be stored twice: in the chunk and in the parent chunk's top frame @@ -931,7 +922,6 @@ freeze_result FreezeBase::finalize_freeze(const frame& callee, frame& caller, in int overlap = 0; // the args overlap the caller -- if there is one in this chunk and is of the same kind int unextended_sp = -1; if (chunk != nullptr) { - unextended_sp = chunk->sp(); if (!chunk->is_empty()) { StackChunkFrameStream last(chunk); unextended_sp = chunk->to_offset(StackChunkFrameStream(chunk).unextended_sp()); @@ -939,6 +929,8 @@ freeze_result FreezeBase::finalize_freeze(const frame& callee, frame& caller, in if (callee.is_interpreted_frame() == top_interpreted) { overlap = argsize_md; } + } else { + unextended_sp = chunk->stack_size() - frame::metadata_words_at_top; } } @@ -976,25 +968,21 @@ freeze_result FreezeBase::finalize_freeze(const frame& callee, frame& caller, in _freeze_size += overlap; // we're allocating a new chunk, so no overlap // overlap = 0; - chunk = allocate_chunk_slow(_freeze_size); + chunk = allocate_chunk_slow(_freeze_size, argsize_md); if (chunk == nullptr) { return freeze_exception; } // Install new chunk _cont.set_tail(chunk); - - int sp = chunk->stack_size() - argsize_md; - chunk->set_sp(sp); - chunk->set_argsize(argsize); - assert(is_empty(chunk), ""); + assert(chunk->is_empty(), ""); } else { // REUSE EXISTING CHUNK log_develop_trace(continuations)("Reusing chunk mixed: %d empty: %d", chunk->has_mixed_frames(), chunk->is_empty()); if (chunk->is_empty()) { int sp = chunk->stack_size() - argsize_md; chunk->set_sp(sp); - chunk->set_argsize(argsize); + chunk->set_bottom(sp); _freeze_size += overlap; assert(chunk->max_thawing_size() == 0, ""); } DEBUG_ONLY(else empty_chunk = false;) @@ -1004,10 +992,10 @@ freeze_result FreezeBase::finalize_freeze(const frame& callee, frame& caller, in chunk->set_has_mixed_frames(true); assert(chunk->requires_barriers() == _barriers, ""); - assert(!_barriers || is_empty(chunk), ""); + assert(!_barriers || chunk->is_empty(), ""); - assert(!is_empty(chunk) || StackChunkFrameStream(chunk).is_done(), ""); - assert(!is_empty(chunk) || StackChunkFrameStream(chunk).to_frame().is_empty(), ""); + assert(!chunk->is_empty() || StackChunkFrameStream(chunk).is_done(), ""); + assert(!chunk->is_empty() || StackChunkFrameStream(chunk).to_frame().is_empty(), ""); // We unwind frames after the last safepoint so that the GC will have found the oops in the frames, but before // writing into the chunk. This is so that an asynchronous stack walk (not at a safepoint) that suspends us here @@ -1053,7 +1041,7 @@ void FreezeBase::patch(const frame& f, frame& hf, const frame& caller, bool is_b // If we're the bottom frame, we need to replace the return barrier with the real // caller's pc. address last_pc = caller.pc(); - assert((last_pc == nullptr) == is_empty(_cont.tail()), ""); + assert((last_pc == nullptr) == _cont.tail()->is_empty(), ""); ContinuationHelper::Frame::patch_pc(caller, last_pc); } else { assert(!caller.is_empty(), ""); @@ -1306,6 +1294,7 @@ inline bool FreezeBase::stack_overflow() { // detect stack overflow in recursive class StackChunkAllocator : public MemAllocator { const size_t _stack_size; + int _argsize_md; ContinuationWrapper& _continuation_wrapper; JvmtiSampledObjectAllocEventCollector* const _jvmti_event_collector; mutable bool _took_slow_path; @@ -1321,8 +1310,11 @@ class StackChunkAllocator : public MemAllocator { const size_t hs = oopDesc::header_size(); Copy::fill_to_aligned_words(mem + hs, vmClasses::StackChunk_klass()->size_helper() - hs); + int bottom = (int)_stack_size - _argsize_md; + jdk_internal_vm_StackChunk::set_size(mem, (int)_stack_size); - jdk_internal_vm_StackChunk::set_sp(mem, (int)_stack_size); + jdk_internal_vm_StackChunk::set_bottom(mem, bottom); + jdk_internal_vm_StackChunk::set_sp(mem, bottom); return finish(mem); } @@ -1346,10 +1338,12 @@ class StackChunkAllocator : public MemAllocator { size_t word_size, Thread* thread, size_t stack_size, + int argsize_md, ContinuationWrapper& continuation_wrapper, JvmtiSampledObjectAllocEventCollector* jvmti_event_collector) : MemAllocator(klass, word_size, thread), _stack_size(stack_size), + _argsize_md(argsize_md), _continuation_wrapper(continuation_wrapper), _jvmti_event_collector(jvmti_event_collector), _took_slow_path(false) {} @@ -1383,7 +1377,7 @@ class StackChunkAllocator : public MemAllocator { }; template -stackChunkOop Freeze::allocate_chunk(size_t stack_size) { +stackChunkOop Freeze::allocate_chunk(size_t stack_size, int argsize_md) { log_develop_trace(continuations)("allocate_chunk allocating new chunk"); InstanceStackChunkKlass* klass = InstanceStackChunkKlass::cast(vmClasses::StackChunk_klass()); @@ -1405,7 +1399,7 @@ stackChunkOop Freeze::allocate_chunk(size_t stack_size) { // instrumentation have been deferred. This property is important for // some GCs, as this ensures that the allocated object is in the young // generation / newly allocated memory. - StackChunkAllocator allocator(klass, size_in_words, current, stack_size, _cont, _jvmti_event_collector); + StackChunkAllocator allocator(klass, size_in_words, current, stack_size, argsize_md, _cont, _jvmti_event_collector); stackChunkOop chunk = allocator.allocate(); if (chunk == nullptr) { @@ -1415,11 +1409,11 @@ stackChunkOop Freeze::allocate_chunk(size_t stack_size) { // assert that chunk is properly initialized assert(chunk->stack_size() == (int)stack_size, ""); assert(chunk->size() >= stack_size, "chunk->size(): %zu size: %zu", chunk->size(), stack_size); - assert(chunk->sp() == chunk->stack_size(), ""); + assert(chunk->sp() == chunk->bottom(), ""); assert((intptr_t)chunk->start_address() % 8 == 0, ""); assert(chunk->max_thawing_size() == 0, ""); assert(chunk->pc() == nullptr, ""); - assert(chunk->argsize() == 0, ""); + assert(chunk->is_empty(), ""); assert(chunk->flags() == 0, ""); assert(chunk->is_gc_mode() == false, ""); @@ -1852,12 +1846,11 @@ class ReconstructedStack : public StackObj { }; inline void ThawBase::clear_chunk(stackChunkOop chunk) { - chunk->set_sp(chunk->stack_size()); - chunk->set_argsize(0); + chunk->set_sp(chunk->bottom()); chunk->set_max_thawing_size(0); } - int ThawBase::remove_top_compiled_frame_from_chunk(stackChunkOop chunk, int &argsize) { +int ThawBase::remove_top_compiled_frame_from_chunk(stackChunkOop chunk, int &argsize) { bool empty = false; StackChunkFrameStream f(chunk); DEBUG_ONLY(intptr_t* const chunk_sp = chunk->start_address() + chunk->sp();) @@ -2104,8 +2097,7 @@ void ThawBase::finalize_thaw(frame& entry, int argsize) { chunk->set_sp(chunk->to_offset(_stream.sp())); chunk->set_pc(_stream.pc()); } else { - chunk->set_argsize(0); - chunk->set_sp(chunk->stack_size()); + chunk->set_sp(chunk->bottom()); chunk->set_pc(nullptr); } assert(_stream.is_done() == chunk->is_empty(), ""); @@ -2377,7 +2369,6 @@ void ThawBase::finish_thaw(frame& f) { chunk->set_has_mixed_frames(false); } chunk->set_max_thawing_size(0); - assert(chunk->argsize() == 0, ""); } else { chunk->set_max_thawing_size(chunk->max_thawing_size() - _align_size); } diff --git a/src/hotspot/share/runtime/continuationJavaClasses.cpp b/src/hotspot/share/runtime/continuationJavaClasses.cpp index 1185af8d6a098..d9f2d05b7e9c9 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.cpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.cpp @@ -84,7 +84,7 @@ int jdk_internal_vm_StackChunk::_parent_offset; int jdk_internal_vm_StackChunk::_size_offset; int jdk_internal_vm_StackChunk::_sp_offset; int jdk_internal_vm_StackChunk::_pc_offset; -int jdk_internal_vm_StackChunk::_argsize_offset; +int jdk_internal_vm_StackChunk::_bottom_offset; int jdk_internal_vm_StackChunk::_flags_offset; int jdk_internal_vm_StackChunk::_maxThawingSize_offset; int jdk_internal_vm_StackChunk::_cont_offset; @@ -93,7 +93,7 @@ int jdk_internal_vm_StackChunk::_cont_offset; macro(_parent_offset, k, vmSymbols::parent_name(), stackchunk_signature, false); \ macro(_size_offset, k, vmSymbols::size_name(), int_signature, false); \ macro(_sp_offset, k, vmSymbols::sp_name(), int_signature, false); \ - macro(_argsize_offset, k, vmSymbols::argsize_name(), int_signature, false); + macro(_bottom_offset, k, vmSymbols::bottom_name(), int_signature, false); void jdk_internal_vm_StackChunk::compute_offsets() { InstanceKlass* k = vmClasses::StackChunk_klass(); diff --git a/src/hotspot/share/runtime/continuationJavaClasses.hpp b/src/hotspot/share/runtime/continuationJavaClasses.hpp index 54d10d0415459..05cba90a0f5ef 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.hpp @@ -83,7 +83,7 @@ class jdk_internal_vm_StackChunk: AllStatic { static int _size_offset; static int _sp_offset; static int _pc_offset; - static int _argsize_offset; + static int _bottom_offset; static int _flags_offset; static int _maxThawingSize_offset; static int _cont_offset; @@ -112,8 +112,9 @@ class jdk_internal_vm_StackChunk: AllStatic { static inline void set_sp(HeapWord* chunk, int value); // used while allocating static inline address pc(oop chunk); static inline void set_pc(oop chunk, address value); - static inline int argsize(oop chunk); - static inline void set_argsize(oop chunk, int value); + static inline int bottom(oop chunk); + static inline void set_bottom(oop chunk, int value); + static inline void set_bottom(HeapWord* chunk, int value); static inline uint8_t flags(oop chunk); static inline void set_flags(oop chunk, uint8_t value); static inline uint8_t flags_acquire(oop chunk); diff --git a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp index 987f367303ddc..b2dea2d704acb 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp @@ -115,12 +115,19 @@ inline void jdk_internal_vm_StackChunk::set_size(HeapWord* chunk, int value) { *(int*)(((char*)chunk) + _size_offset) = (int)value; } +inline void jdk_internal_vm_StackChunk::set_bottom(HeapWord* chunk, int value) { + // Used by StackChunkAllocator before the Object has been finished, + // so don't cast too oop and use int_field_put in this function. + assert(_bottom_offset != 0, "must be set"); + *(int*)(((char*)chunk) + _bottom_offset) = (int)value; +} + inline int jdk_internal_vm_StackChunk::sp(oop chunk) { - return chunk->int_field(_sp_offset); + return chunk->int_field_relaxed(_sp_offset); } inline void jdk_internal_vm_StackChunk::set_sp(oop chunk, int value) { - chunk->int_field_put(_sp_offset, value); + chunk->int_field_put_relaxed(_sp_offset, value); } inline void jdk_internal_vm_StackChunk::set_sp(HeapWord* chunk, int value) { @@ -138,12 +145,12 @@ inline void jdk_internal_vm_StackChunk::set_pc(oop chunk, address value) { chunk->address_field_put(_pc_offset, value); } -inline int jdk_internal_vm_StackChunk::argsize(oop chunk) { - return chunk->int_field(_argsize_offset); +inline int jdk_internal_vm_StackChunk::bottom(oop chunk) { + return chunk->int_field(_bottom_offset); } -inline void jdk_internal_vm_StackChunk::set_argsize(oop chunk, int value) { - chunk->int_field_put(_argsize_offset, value); +inline void jdk_internal_vm_StackChunk::set_bottom(oop chunk, int value) { + chunk->int_field_put(_bottom_offset, value); } inline uint8_t jdk_internal_vm_StackChunk::flags(oop chunk) { diff --git a/src/java.base/share/classes/jdk/internal/vm/StackChunk.java b/src/java.base/share/classes/jdk/internal/vm/StackChunk.java index 0c48ce67934ae..ab562706c24fa 100644 --- a/src/java.base/share/classes/jdk/internal/vm/StackChunk.java +++ b/src/java.base/share/classes/jdk/internal/vm/StackChunk.java @@ -31,10 +31,10 @@ public static void init() {} private StackChunk parent; private int size; // in words private int sp; // in words - private int argsize; // bottom stack-passed arguments, in words + private int bottom; // in words // The stack itself is appended here by the VM, as well as some injected fields public StackChunk parent() { return parent; } - public boolean isEmpty() { return sp >= (size - argsize); } + public boolean isEmpty() { return sp == bottom; } } From 33243d44a96bf47066e19bb743c076cbd4ba48ed Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 2 May 2024 08:42:38 +0000 Subject: [PATCH 039/203] 8331394: G1: Remove SKIP_RETIRED_FULL_REGIONS define in G1HRPrinter Reviewed-by: gli, iwalulya --- src/hotspot/share/gc/g1/g1HRPrinter.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.hpp b/src/hotspot/share/gc/g1/g1HRPrinter.hpp index 9d6d151084fbd..3b712067e0b73 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.hpp +++ b/src/hotspot/share/gc/g1/g1HRPrinter.hpp @@ -28,8 +28,6 @@ #include "gc/g1/g1HeapRegion.hpp" #include "logging/log.hpp" -#define SKIP_RETIRED_FULL_REGIONS 1 - class FreeRegionList; class G1HRPrinter { @@ -58,9 +56,7 @@ class G1HRPrinter { void retire(HeapRegion* hr) { if (is_active()) { - if (!SKIP_RETIRED_FULL_REGIONS || hr->top() < hr->end()) { - print("RETIRE", hr); - } + print("RETIRE", hr); } } From fe23068d946181b0346e470d3172c5d29cc2e05c Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 2 May 2024 08:43:57 +0000 Subject: [PATCH 040/203] 8331392: G1: Make HRPrinter distinguish between different types of reclamation Reviewed-by: ayang, iwalulya, gli --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 2 +- src/hotspot/share/gc/g1/g1HRPrinter.cpp | 4 ++-- src/hotspot/share/gc/g1/g1HRPrinter.hpp | 16 +++++++++++++--- .../share/gc/g1/g1YoungGCPostEvacuateTasks.cpp | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 4b20bb4331799..fdb380ae99f28 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1317,7 +1317,7 @@ class G1UpdateRegionLivenessAndSelectForRebuildTask : public WorkerTask { if (!_cleanup_list.is_empty()) { log_debug(gc)("Reclaimed %u empty regions", _cleanup_list.length()); // Now print the empty regions list. - _g1h->hr_printer()->cleanup(&_cleanup_list); + _g1h->hr_printer()->mark_reclaim(&_cleanup_list); // And actually make them available. _g1h->prepend_to_freelist(&_cleanup_list); } diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.cpp b/src/hotspot/share/gc/g1/g1HRPrinter.cpp index 7ec4f2a0d96e3..99769f85390fe 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.cpp +++ b/src/hotspot/share/gc/g1/g1HRPrinter.cpp @@ -27,12 +27,12 @@ #include "gc/g1/g1HeapRegionSet.hpp" #include "gc/g1/g1HRPrinter.hpp" -void G1HRPrinter::cleanup(FreeRegionList* cleanup_list) { +void G1HRPrinter::mark_reclaim(FreeRegionList* cleanup_list) { if (is_active()) { FreeRegionListIterator iter(cleanup_list); while (iter.more_available()) { HeapRegion* hr = iter.get_next(); - cleanup(hr); + mark_reclaim(hr); } } } diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.hpp b/src/hotspot/share/gc/g1/g1HRPrinter.hpp index 3b712067e0b73..5c1736b13ab56 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.hpp +++ b/src/hotspot/share/gc/g1/g1HRPrinter.hpp @@ -40,6 +40,10 @@ class G1HRPrinter { action, hr->get_type_str(), p2i(hr->bottom()), p2i(hr->top()), p2i(hr->end())); } + void mark_reclaim(HeapRegion* hr) { + print("MARK-RECLAIM", hr); + } + public: // In some places we iterate over a list in order to generate output // for the list's elements. By exposing this we can avoid this @@ -78,13 +82,19 @@ class G1HRPrinter { } } - void cleanup(HeapRegion* hr) { + void mark_reclaim(FreeRegionList* free_list); + + void eager_reclaim(HeapRegion* hr) { if (is_active()) { - print("CLEANUP", hr); + print("EAGER-RECLAIM", hr); } } - void cleanup(FreeRegionList* free_list); + void evac_reclaim(HeapRegion* hr) { + if (is_active()) { + print("EVAC-RECLAIM", hr); + } + } void post_compaction(HeapRegion* hr) { if (is_active()) { diff --git a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp index 572f970c73f43..98f4c43d27553 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp @@ -412,7 +412,7 @@ class G1FreeHumongousRegionClosure : public HeapRegionIndexClosure { r->set_containing_set(nullptr); _humongous_regions_reclaimed++; _g1h->free_humongous_region(r, nullptr); - _g1h->hr_printer()->cleanup(r); + _g1h->hr_printer()->eager_reclaim(r); }; _g1h->humongous_obj_regions_iterate(r, free_humongous_region); @@ -760,7 +760,7 @@ class FreeCSetClosure : public HeapRegionClosure { // Free the region and its remembered set. _g1h->free_region(r, nullptr); - _g1h->hr_printer()->cleanup(r); + _g1h->hr_printer()->evac_reclaim(r); } void handle_failed_region(HeapRegion* r) { From 286cbf831c2eb76e31bd69b4a93cd5ae9a821493 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 2 May 2024 09:58:32 +0000 Subject: [PATCH 041/203] 8331546: Build failure after 8330076 Reviewed-by: mdoerr, tschatzl, shade --- src/hotspot/share/memory/virtualspace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index ffa918f099809..6811d6be8463d 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -329,7 +329,7 @@ ReservedSpace ReservedSpace::last_part(size_t partition_size, size_t alignment) ReservedSpace ReservedSpace::partition(size_t offset, size_t partition_size, size_t alignment) { assert(offset + partition_size <= size(), "partition failed"); - ReservedSpace result(base() + offset, partition_size, alignment, page_size(), special(), executable()); + ReservedSpace result(base() + offset, partition_size, alignment, page_size(), special(), executable(), nmt_flag()); return result; } From ae82405ff7a48bc6e61b1d05bf74839b7ed50c11 Mon Sep 17 00:00:00 2001 From: Adam Sotona Date: Thu, 2 May 2024 10:08:29 +0000 Subject: [PATCH 042/203] 8323058: Revisit j.l.classfile.CodeBuilder API surface Reviewed-by: briangoetz, psandoz --- .../java/lang/classfile/CodeBuilder.java | 709 +++++++----------- .../java/lang/classfile/package-info.java | 2 +- .../snippet-files/PackageSnippets.java | 4 +- .../java/lang/invoke/MethodHandleProxies.java | 12 +- .../java/lang/invoke/StringConcatFactory.java | 4 +- .../java/lang/reflect/ProxyGenerator.java | 14 +- .../java/lang/runtime/SwitchBootstraps.java | 26 +- .../classfile/impl/CatchBuilderImpl.java | 4 +- .../classfile/impl/ClassRemapperImpl.java | 12 +- .../classfile/impl/CodeLocalsShifterImpl.java | 6 +- .../classfile/impl/CodeRelabelerImpl.java | 6 +- .../foreign/abi/BindingSpecializer.java | 130 ++-- .../jfr/internal/EventInstrumentation.java | 14 +- .../internal/plugins/SystemModulesPlugin.java | 122 +-- .../internal/plugins/VersionPropsPlugin.java | 2 +- .../records/ProhibitedMethods.java | 2 +- .../records/SerialPersistentFieldsTest.java | 6 +- .../instrument/NativeMethodPrefixAgent.java | 4 +- .../lang/instrument/RetransformAgent.java | 2 +- .../lang/instrument/asmlib/Instrumentor.java | 6 +- .../WrapperHiddenClassTest.java | 2 +- .../classData/ClassDataTest.java | 12 +- .../lang/invoke/lib/InstructionHelper.java | 6 +- .../lang/invoke/condy/CondyNestedTest.java | 2 +- .../lang/invoke/lookup/SpecialStatic.java | 2 +- .../TestPrivateInterfaceMethodReflect.java | 2 +- test/jdk/jdk/classfile/AdaptCodeTest.java | 2 +- test/jdk/jdk/classfile/BSMTest.java | 2 +- test/jdk/jdk/classfile/BuilderBlockTest.java | 16 +- .../jdk/classfile/BuilderTryCatchTest.java | 44 +- .../DiscontinuedInstructionsTest.java | 4 +- test/jdk/jdk/classfile/LDCTest.java | 22 +- test/jdk/jdk/classfile/LowAdaptTest.java | 18 +- test/jdk/jdk/classfile/LvtTest.java | 58 +- test/jdk/jdk/classfile/OneToOneTest.java | 40 +- .../jdk/classfile/OpcodesValidationTest.java | 4 +- .../classfile/PrimitiveClassConstantTest.java | 2 +- test/jdk/jdk/classfile/ShortJumpsFixTest.java | 10 +- test/jdk/jdk/classfile/StackMapsTest.java | 8 +- test/jdk/jdk/classfile/StackTrackerTest.java | 4 +- .../TempConstantPoolBuilderTest.java | 6 +- test/jdk/jdk/classfile/TransformTests.java | 2 +- test/jdk/jdk/classfile/Utf8EntryTest.java | 4 +- test/jdk/jdk/classfile/WriteTest.java | 80 +- .../classfile/examples/ExampleGallery.java | 6 +- .../InstructionModelToCodeBuilder.java | 48 +- .../helpers/RebuildingTransformation.java | 16 +- .../jdk/jdk/classfile/helpers/Transforms.java | 2 +- .../separate/ClassToInterfaceConverter.java | 2 +- .../java/lang/invoke/LazyStaticColdStart.java | 2 +- .../jdk/classfile/RebuildMethodBodies.java | 6 +- .../bench/jdk/classfile/Transforms.java | 2 +- .../openjdk/bench/jdk/classfile/Write.java | 80 +- 53 files changed, 726 insertions(+), 877 deletions(-) diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java index 544d7322c1c1a..e954be079fa54 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java @@ -212,8 +212,7 @@ default CodeBuilder block(Consumer handler) { child.start(); handler.accept(child); child.end(); - labelBinding(breakLabel); - return this; + return labelBinding(breakLabel); } /** @@ -253,12 +252,11 @@ default CodeBuilder ifThen(Opcode opcode, Label breakLabel = newLabel(); BlockCodeBuilderImpl thenBlock = new BlockCodeBuilderImpl(this, breakLabel); - branchInstruction(BytecodeHelpers.reverseBranchOpcode(opcode), thenBlock.endLabel()); + branch(BytecodeHelpers.reverseBranchOpcode(opcode), thenBlock.endLabel()); thenBlock.start(); thenHandler.accept(thenBlock); thenBlock.end(); - labelBinding(breakLabel); - return this; + return labelBinding(breakLabel); } /** @@ -305,17 +303,16 @@ default CodeBuilder ifThenElse(Opcode opcode, Label breakLabel = newLabel(); BlockCodeBuilderImpl thenBlock = new BlockCodeBuilderImpl(this, breakLabel); BlockCodeBuilderImpl elseBlock = new BlockCodeBuilderImpl(this, breakLabel); - branchInstruction(BytecodeHelpers.reverseBranchOpcode(opcode), elseBlock.startLabel()); + branch(BytecodeHelpers.reverseBranchOpcode(opcode), elseBlock.startLabel()); thenBlock.start(); thenHandler.accept(thenBlock); if (thenBlock.reachable()) - thenBlock.branchInstruction(Opcode.GOTO, thenBlock.breakLabel()); + thenBlock.branch(Opcode.GOTO, thenBlock.breakLabel()); thenBlock.end(); elseBlock.start(); elseHandler.accept(elseBlock); elseBlock.end(); - labelBinding(breakLabel); - return this; + return labelBinding(breakLabel); } /** @@ -416,10 +413,10 @@ default CodeBuilder trying(Consumer tryHandler, * @param tk the load type * @param slot the local variable slot * @return this builder + * @since 23 */ - default CodeBuilder loadInstruction(TypeKind tk, int slot) { - with(LoadInstruction.of(tk, slot)); - return this; + default CodeBuilder loadLocal(TypeKind tk, int slot) { + return with(LoadInstruction.of(tk, slot)); } /** @@ -427,21 +424,10 @@ default CodeBuilder loadInstruction(TypeKind tk, int slot) { * @param tk the store type * @param slot the local variable slot * @return this builder + * @since 23 */ - default CodeBuilder storeInstruction(TypeKind tk, int slot) { - with(StoreInstruction.of(tk, slot)); - return this; - } - - /** - * Generate an instruction to increment a local variable by a constant - * @param slot the local variable slot - * @param val the increment value - * @return this builder - */ - default CodeBuilder incrementInstruction(int slot, int val) { - with(IncrementInstruction.of(slot, val)); - return this; + default CodeBuilder storeLocal(TypeKind tk, int slot) { + return with(StoreInstruction.of(tk, slot)); } /** @@ -450,53 +436,20 @@ default CodeBuilder incrementInstruction(int slot, int val) { * @param op the branch opcode * @param target the branch target * @return this builder + * @since 23 */ - default CodeBuilder branchInstruction(Opcode op, Label target) { - with(BranchInstruction.of(op, target)); - return this; - } - - /** - * Generate an instruction to access a jump table by key match and jump - * @param defaultTarget the default jump target - * @param cases the switch cases - * @return this builder - */ - default CodeBuilder lookupSwitchInstruction(Label defaultTarget, List cases) { - with(LookupSwitchInstruction.of(defaultTarget, cases)); - return this; - } - - /** - * Generate an instruction to access a jump table by index and jump - * @param lowValue the low key value - * @param highValue the high key value - * @param defaultTarget the default jump target - * @param cases the switch cases - * @return this builder - */ - default CodeBuilder tableSwitchInstruction(int lowValue, int highValue, Label defaultTarget, List cases) { - with(TableSwitchInstruction.of(lowValue, highValue, defaultTarget, cases)); - return this; + default CodeBuilder branch(Opcode op, Label target) { + return with(BranchInstruction.of(op, target)); } /** * Generate return instruction * @param tk the return type * @return this builder + * @since 23 */ - default CodeBuilder returnInstruction(TypeKind tk) { - with(ReturnInstruction.of(tk)); - return this; - } - - /** - * Generate an instruction to throw an exception or error - * @return this builder - */ - default CodeBuilder throwInstruction() { - with(ThrowInstruction.of()); - return this; + default CodeBuilder return_(TypeKind tk) { + return with(ReturnInstruction.of(tk)); } /** @@ -505,10 +458,10 @@ default CodeBuilder throwInstruction() { * @param opcode the field access opcode * @param ref the field reference * @return this builder + * @since 23 */ - default CodeBuilder fieldInstruction(Opcode opcode, FieldRefEntry ref) { - with(FieldInstruction.of(opcode, ref)); - return this; + default CodeBuilder fieldAccess(Opcode opcode, FieldRefEntry ref) { + return with(FieldInstruction.of(opcode, ref)); } /** @@ -519,9 +472,10 @@ default CodeBuilder fieldInstruction(Opcode opcode, FieldRefEntry ref) { * @param name the field name * @param type the field type * @return this builder + * @since 23 */ - default CodeBuilder fieldInstruction(Opcode opcode, ClassDesc owner, String name, ClassDesc type) { - return fieldInstruction(opcode, constantPool().fieldRefEntry(owner, name, type)); + default CodeBuilder fieldAccess(Opcode opcode, ClassDesc owner, String name, ClassDesc type) { + return fieldAccess(opcode, constantPool().fieldRefEntry(owner, name, type)); } /** @@ -530,8 +484,9 @@ default CodeBuilder fieldInstruction(Opcode opcode, ClassDesc owner, String name * @param opcode the invoke opcode * @param ref the interface method or method reference * @return this builder + * @since 23 */ - default CodeBuilder invokeInstruction(Opcode opcode, MemberRefEntry ref) { + default CodeBuilder invoke(Opcode opcode, MemberRefEntry ref) { return with(InvokeInstruction.of(opcode, ref)); } @@ -544,191 +499,101 @@ default CodeBuilder invokeInstruction(Opcode opcode, MemberRefEntry ref) { * @param desc the method type * @param isInterface the interface method invocation indication * @return this builder + * @since 23 */ - default CodeBuilder invokeInstruction(Opcode opcode, ClassDesc owner, String name, MethodTypeDesc desc, boolean isInterface) { - return invokeInstruction(opcode, + default CodeBuilder invoke(Opcode opcode, ClassDesc owner, String name, MethodTypeDesc desc, boolean isInterface) { + return invoke(opcode, isInterface ? constantPool().interfaceMethodRefEntry(owner, name, desc) : constantPool().methodRefEntry(owner, name, desc)); } - /** - * Generate an instruction to invoke a dynamically-computed call site - * @param ref the dynamic call site - * @return this builder - */ - default CodeBuilder invokeDynamicInstruction(InvokeDynamicEntry ref) { - with(InvokeDynamicInstruction.of(ref)); - return this; - } - - /** - * Generate an instruction to invoke a dynamically-computed call site - * @param desc the dynamic call site - * @return this builder - */ - default CodeBuilder invokeDynamicInstruction(DynamicCallSiteDesc desc) { - MethodHandleEntry bsMethod = handleDescToHandleInfo(constantPool(), (DirectMethodHandleDesc) desc.bootstrapMethod()); - var cpArgs = desc.bootstrapArgs(); - List bsArguments = new ArrayList<>(cpArgs.length); - for (var constantValue : cpArgs) { - bsArguments.add(BytecodeHelpers.constantEntry(constantPool(), constantValue)); - } - BootstrapMethodEntry bm = constantPool().bsmEntry(bsMethod, bsArguments); - NameAndTypeEntry nameAndType = constantPool().nameAndTypeEntry(desc.invocationName(), desc.invocationType()); - invokeDynamicInstruction(constantPool().invokeDynamicEntry(bm, nameAndType)); - return this; - } - - /** - * Generate an instruction to create a new object - * @param type the object type - * @return this builder - */ - default CodeBuilder newObjectInstruction(ClassEntry type) { - with(NewObjectInstruction.of(type)); - return this; - } - - /** - * Generate an instruction to create a new object - * @param type the object type - * @return this builder - * @throws IllegalArgumentException if {@code type} represents a primitive type - */ - default CodeBuilder newObjectInstruction(ClassDesc type) { - return newObjectInstruction(constantPool().classEntry(type)); - } - - /** - * Generate an instruction to create a new array of a primitive type - * @param typeKind the primitive component type - * @return this builder - */ - default CodeBuilder newPrimitiveArrayInstruction(TypeKind typeKind) { - with(NewPrimitiveArrayInstruction.of(typeKind)); - return this; - } - - /** - * Generate an instruction to create a new array of reference - * @param type the component type - * @return this builder - */ - default CodeBuilder newReferenceArrayInstruction(ClassEntry type) { - with(NewReferenceArrayInstruction.of(type)); - return this; - } - - /** - * Generate an instruction to create a new array of reference - * @param type the component type - * @return this builder - * @throws IllegalArgumentException if {@code type} represents a primitive type - */ - default CodeBuilder newReferenceArrayInstruction(ClassDesc type) { - return newReferenceArrayInstruction(constantPool().classEntry(type)); - } - - /** - * Generate an instruction to create a new multidimensional array - * @param dimensions the number of dimensions - * @param type the array type - * @return this builder - */ - default CodeBuilder newMultidimensionalArrayInstruction(int dimensions, - ClassEntry type) { - with(NewMultiArrayInstruction.of(type, dimensions)); - return this; - } - - /** - * Generate an instruction to create a new multidimensional array - * @param dimensions the number of dimensions - * @param type the array type - * @return this builder - */ - default CodeBuilder newMultidimensionalArrayInstruction(int dimensions, - ClassDesc type) { - return newMultidimensionalArrayInstruction(dimensions, constantPool().classEntry(type)); - } - /** * Generate an instruction to load from an array * @param tk the array element type * @return this builder + * @since 23 */ - default CodeBuilder arrayLoadInstruction(TypeKind tk) { + default CodeBuilder arrayLoad(TypeKind tk) { Opcode opcode = BytecodeHelpers.arrayLoadOpcode(tk); - with(ArrayLoadInstruction.of(opcode)); - return this; + return with(ArrayLoadInstruction.of(opcode)); } /** * Generate an instruction to store into an array * @param tk the array element type * @return this builder + * @since 23 */ - default CodeBuilder arrayStoreInstruction(TypeKind tk) { + default CodeBuilder arrayStore(TypeKind tk) { Opcode opcode = BytecodeHelpers.arrayStoreOpcode(tk); - with(ArrayStoreInstruction.of(opcode)); - return this; - } - - /** - * Generate a type checking instruction - * @see Opcode.Kind#TYPE_CHECK - * @param opcode the type check instruction opcode - * @param type the type - * @return this builder - */ - default CodeBuilder typeCheckInstruction(Opcode opcode, - ClassEntry type) { - with(TypeCheckInstruction.of(opcode, type)); - return this; - } - - /** - * Generate a type checking instruction - * @see Opcode.Kind#TYPE_CHECK - * @param opcode the type check instruction opcode - * @param type the type - * @return this builder - */ - default CodeBuilder typeCheckInstruction(Opcode opcode, ClassDesc type) { - return typeCheckInstruction(opcode, constantPool().classEntry(type)); + return with(ArrayStoreInstruction.of(opcode)); } /** - * Generate a type converting instruction + * Generate instruction(s) to convert {@code fromType} to {@code toType} * @param fromType the source type * @param toType the target type * @return this builder - */ - default CodeBuilder convertInstruction(TypeKind fromType, TypeKind toType) { - with(ConvertInstruction.of(fromType, toType)); - return this; - } - - /** - * Generate a stack manipulating instruction - * @param opcode the stack instruction opcode - * @see Opcode.Kind#STACK - * @return this builder - */ - default CodeBuilder stackInstruction(Opcode opcode) { - with(StackInstruction.of(opcode)); - return this; - } - - /** - * Generate an operator instruction - * @see Opcode.Kind#OPERATOR - * @param opcode the operator instruction opcode - * @return this builder - */ - default CodeBuilder operatorInstruction(Opcode opcode) { - with(OperatorInstruction.of(opcode)); - return this; + * @throws IllegalArgumentException for conversions of {@code VoidType} or {@code ReferenceType} + * @since 23 + */ + default CodeBuilder conversion(TypeKind fromType, TypeKind toType) { + return switch (fromType) { + case IntType, ByteType, CharType, ShortType, BooleanType -> + switch (toType) { + case IntType -> this; + case LongType -> i2l(); + case DoubleType -> i2d(); + case FloatType -> i2f(); + case ByteType -> i2b(); + case CharType -> i2c(); + case ShortType -> i2s(); + case BooleanType -> iconst_1().iand(); + case VoidType, ReferenceType -> + throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); + }; + case LongType -> + switch (toType) { + case IntType -> l2i(); + case LongType -> this; + case DoubleType -> l2d(); + case FloatType -> l2f(); + case ByteType -> l2i().i2b(); + case CharType -> l2i().i2c(); + case ShortType -> l2i().i2s(); + case BooleanType -> l2i().iconst_1().iand(); + case VoidType, ReferenceType -> + throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); + }; + case DoubleType -> + switch (toType) { + case IntType -> d2i(); + case LongType -> d2l(); + case DoubleType -> this; + case FloatType -> d2f(); + case ByteType -> d2i().i2b(); + case CharType -> d2i().i2c(); + case ShortType -> d2i().i2s(); + case BooleanType -> d2i().iconst_1().iand(); + case VoidType, ReferenceType -> + throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); + }; + case FloatType -> + switch (toType) { + case IntType -> f2i(); + case LongType -> f2l(); + case DoubleType -> f2d(); + case FloatType -> this; + case ByteType -> f2i().i2b(); + case CharType -> f2i().i2c(); + case ShortType -> f2i().i2s(); + case BooleanType -> f2i().iconst_1().iand(); + case VoidType, ReferenceType -> + throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); + }; + case VoidType, ReferenceType -> + throw new IllegalArgumentException(String.format("convert %s -> %s", fromType, toType)); + }; } /** @@ -737,8 +602,9 @@ default CodeBuilder operatorInstruction(Opcode opcode) { * @param opcode the constant instruction opcode * @param value the constant value * @return this builder + * @since 23 */ - default CodeBuilder constantInstruction(Opcode opcode, ConstantDesc value) { + default CodeBuilder loadConstant(Opcode opcode, ConstantDesc value) { BytecodeHelpers.validateValue(opcode, value); return with(switch (opcode) { case SIPUSH, BIPUSH -> ConstantInstruction.ofArgument(opcode, ((Number)value).intValue()); @@ -751,8 +617,9 @@ default CodeBuilder constantInstruction(Opcode opcode, ConstantDesc value) { * Generate an instruction pushing a constant onto the operand stack * @param value the constant value * @return this builder + * @since 23 */ - default CodeBuilder constantInstruction(ConstantDesc value) { + default CodeBuilder loadConstant(ConstantDesc value) { //avoid switch expressions here if (value == null || value == ConstantDescs.NULL) return aconst_null(); @@ -785,32 +652,12 @@ default CodeBuilder constantInstruction(ConstantDesc value) { return ldc(value); } - /** - * Generate a monitor instruction - * @see Opcode.Kind#MONITOR - * @param opcode the monitor instruction opcode - * @return this builder - */ - default CodeBuilder monitorInstruction(Opcode opcode) { - with(MonitorInstruction.of(opcode)); - return null; - } - - /** - * Generate a do nothing instruction - * @return this builder - */ - default CodeBuilder nopInstruction() { - with(NopInstruction.of()); - return this; - } - /** * Generate a do nothing instruction * @return this builder */ default CodeBuilder nop() { - return nopInstruction(); + return with(NopInstruction.of()); } // Base pseudo-instruction builder methods @@ -831,8 +678,7 @@ default Label newBoundLabel() { * @return this builder */ default CodeBuilder labelBinding(Label label) { - with((LabelImpl) label); - return this; + return with((LabelImpl) label); } /** @@ -841,8 +687,7 @@ default CodeBuilder labelBinding(Label label) { * @return this builder */ default CodeBuilder lineNumber(int line) { - with(LineNumber.of(line)); - return this; + return with(LineNumber.of(line)); } /** @@ -854,8 +699,7 @@ default CodeBuilder lineNumber(int line) { * @return this builder */ default CodeBuilder exceptionCatch(Label start, Label end, Label handler, ClassEntry catchType) { - with(ExceptionCatch.of(handler, start, end, Optional.of(catchType))); - return this; + return with(ExceptionCatch.of(handler, start, end, Optional.of(catchType))); } /** @@ -867,8 +711,7 @@ default CodeBuilder exceptionCatch(Label start, Label end, Label handler, ClassE * @return this builder */ default CodeBuilder exceptionCatch(Label start, Label end, Label handler, Optional catchType) { - with(ExceptionCatch.of(handler, start, end, catchType)); - return this; + return with(ExceptionCatch.of(handler, start, end, catchType)); } /** @@ -892,8 +735,7 @@ default CodeBuilder exceptionCatch(Label start, Label end, Label handler, ClassD * @return this builder */ default CodeBuilder exceptionCatchAll(Label start, Label end, Label handler) { - with(ExceptionCatch.of(handler, start, end)); - return this; + return with(ExceptionCatch.of(handler, start, end)); } /** @@ -906,8 +748,7 @@ default CodeBuilder exceptionCatchAll(Label start, Label end, Label handler) { * @return this builder */ default CodeBuilder characterRange(Label startScope, Label endScope, int characterRangeStart, int characterRangeEnd, int flags) { - with(CharacterRange.of(startScope, endScope, characterRangeStart, characterRangeEnd, flags)); - return this; + return with(CharacterRange.of(startScope, endScope, characterRangeStart, characterRangeEnd, flags)); } /** @@ -920,8 +761,7 @@ default CodeBuilder characterRange(Label startScope, Label endScope, int charact * @return this builder */ default CodeBuilder localVariable(int slot, Utf8Entry nameEntry, Utf8Entry descriptorEntry, Label startScope, Label endScope) { - with(LocalVariable.of(slot, nameEntry, descriptorEntry, startScope, endScope)); - return this; + return with(LocalVariable.of(slot, nameEntry, descriptorEntry, startScope, endScope)); } /** @@ -950,8 +790,7 @@ default CodeBuilder localVariable(int slot, String name, ClassDesc descriptor, L * @return this builder */ default CodeBuilder localVariableType(int slot, Utf8Entry nameEntry, Utf8Entry signatureEntry, Label startScope, Label endScope) { - with(LocalVariableType.of(slot, nameEntry, signatureEntry, startScope, endScope)); - return this; + return with(LocalVariableType.of(slot, nameEntry, signatureEntry, startScope, endScope)); } /** @@ -985,7 +824,7 @@ default CodeBuilder aconst_null() { * @return this builder */ default CodeBuilder aaload() { - return arrayLoadInstruction(TypeKind.ReferenceType); + return arrayLoad(TypeKind.ReferenceType); } /** @@ -993,7 +832,7 @@ default CodeBuilder aaload() { * @return this builder */ default CodeBuilder aastore() { - return arrayStoreInstruction(TypeKind.ReferenceType); + return arrayStore(TypeKind.ReferenceType); } /** @@ -1002,7 +841,7 @@ default CodeBuilder aastore() { * @return this builder */ default CodeBuilder aload(int slot) { - return loadInstruction(TypeKind.ReferenceType, slot); + return loadLocal(TypeKind.ReferenceType, slot); } /** @@ -1011,7 +850,7 @@ default CodeBuilder aload(int slot) { * @return this builder */ default CodeBuilder anewarray(ClassEntry classEntry) { - return newReferenceArrayInstruction(classEntry); + return with(NewReferenceArrayInstruction.of(classEntry)); } /** @@ -1021,7 +860,7 @@ default CodeBuilder anewarray(ClassEntry classEntry) { * @throws IllegalArgumentException if {@code className} represents a primitive type */ default CodeBuilder anewarray(ClassDesc className) { - return newReferenceArrayInstruction(constantPool().classEntry(className)); + return anewarray(constantPool().classEntry(className)); } /** @@ -1029,7 +868,7 @@ default CodeBuilder anewarray(ClassDesc className) { * @return this builder */ default CodeBuilder areturn() { - return returnInstruction(TypeKind.ReferenceType); + return return_(TypeKind.ReferenceType); } /** @@ -1037,7 +876,7 @@ default CodeBuilder areturn() { * @return this builder */ default CodeBuilder arraylength() { - return operatorInstruction(Opcode.ARRAYLENGTH); + return with(OperatorInstruction.of(Opcode.ARRAYLENGTH)); } /** @@ -1046,7 +885,7 @@ default CodeBuilder arraylength() { * @return this builder */ default CodeBuilder astore(int slot) { - return storeInstruction(TypeKind.ReferenceType, slot); + return storeLocal(TypeKind.ReferenceType, slot); } /** @@ -1054,7 +893,7 @@ default CodeBuilder astore(int slot) { * @return this builder */ default CodeBuilder athrow() { - return throwInstruction(); + return with(ThrowInstruction.of()); } /** @@ -1062,7 +901,7 @@ default CodeBuilder athrow() { * @return this builder */ default CodeBuilder baload() { - return arrayLoadInstruction(TypeKind.ByteType); + return arrayLoad(TypeKind.ByteType); } /** @@ -1070,7 +909,7 @@ default CodeBuilder baload() { * @return this builder */ default CodeBuilder bastore() { - return arrayStoreInstruction(TypeKind.ByteType); + return arrayStore(TypeKind.ByteType); } /** @@ -1079,7 +918,7 @@ default CodeBuilder bastore() { * @return this builder */ default CodeBuilder bipush(int b) { - return constantInstruction(Opcode.BIPUSH, b); + return loadConstant(Opcode.BIPUSH, b); } /** @@ -1087,7 +926,7 @@ default CodeBuilder bipush(int b) { * @return this builder */ default CodeBuilder caload() { - return arrayLoadInstruction(TypeKind.CharType); + return arrayLoad(TypeKind.CharType); } /** @@ -1095,7 +934,7 @@ default CodeBuilder caload() { * @return this builder */ default CodeBuilder castore() { - return arrayStoreInstruction(TypeKind.CharType); + return arrayStore(TypeKind.CharType); } /** @@ -1104,7 +943,7 @@ default CodeBuilder castore() { * @return this builder */ default CodeBuilder checkcast(ClassEntry type) { - return typeCheckInstruction(Opcode.CHECKCAST, type); + return with(TypeCheckInstruction.of(Opcode.CHECKCAST, type)); } /** @@ -1114,7 +953,7 @@ default CodeBuilder checkcast(ClassEntry type) { * @throws IllegalArgumentException if {@code type} represents a primitive type */ default CodeBuilder checkcast(ClassDesc type) { - return typeCheckInstruction(Opcode.CHECKCAST, type); + return checkcast(constantPool().classEntry(type)); } /** @@ -1122,7 +961,7 @@ default CodeBuilder checkcast(ClassDesc type) { * @return this builder */ default CodeBuilder d2f() { - return convertInstruction(TypeKind.DoubleType, TypeKind.FloatType); + return with(ConvertInstruction.of(Opcode.D2F)); } /** @@ -1130,7 +969,7 @@ default CodeBuilder d2f() { * @return this builder */ default CodeBuilder d2i() { - return convertInstruction(TypeKind.DoubleType, TypeKind.IntType); + return with(ConvertInstruction.of(Opcode.D2I)); } /** @@ -1138,7 +977,7 @@ default CodeBuilder d2i() { * @return this builder */ default CodeBuilder d2l() { - return convertInstruction(TypeKind.DoubleType, TypeKind.LongType); + return with(ConvertInstruction.of(Opcode.D2L)); } /** @@ -1146,7 +985,7 @@ default CodeBuilder d2l() { * @return this builder */ default CodeBuilder dadd() { - return operatorInstruction(Opcode.DADD); + return with(OperatorInstruction.of(Opcode.DADD)); } /** @@ -1154,7 +993,7 @@ default CodeBuilder dadd() { * @return this builder */ default CodeBuilder daload() { - return arrayLoadInstruction(TypeKind.DoubleType); + return arrayLoad(TypeKind.DoubleType); } /** @@ -1162,7 +1001,7 @@ default CodeBuilder daload() { * @return this builder */ default CodeBuilder dastore() { - return arrayStoreInstruction(TypeKind.DoubleType); + return arrayStore(TypeKind.DoubleType); } /** @@ -1170,7 +1009,7 @@ default CodeBuilder dastore() { * @return this builder */ default CodeBuilder dcmpg() { - return operatorInstruction(Opcode.DCMPG); + return with(OperatorInstruction.of(Opcode.DCMPG)); } /** @@ -1178,7 +1017,7 @@ default CodeBuilder dcmpg() { * @return this builder */ default CodeBuilder dcmpl() { - return operatorInstruction(Opcode.DCMPL); + return with(OperatorInstruction.of(Opcode.DCMPL)); } /** @@ -1202,7 +1041,7 @@ default CodeBuilder dconst_1() { * @return this builder */ default CodeBuilder ddiv() { - return operatorInstruction(Opcode.DDIV); + return with(OperatorInstruction.of(Opcode.DDIV)); } /** @@ -1211,7 +1050,7 @@ default CodeBuilder ddiv() { * @return this builder */ default CodeBuilder dload(int slot) { - return loadInstruction(TypeKind.DoubleType, slot); + return loadLocal(TypeKind.DoubleType, slot); } /** @@ -1219,7 +1058,7 @@ default CodeBuilder dload(int slot) { * @return this builder */ default CodeBuilder dmul() { - return operatorInstruction(Opcode.DMUL); + return with(OperatorInstruction.of(Opcode.DMUL)); } /** @@ -1227,7 +1066,7 @@ default CodeBuilder dmul() { * @return this builder */ default CodeBuilder dneg() { - return operatorInstruction(Opcode.DNEG); + return with(OperatorInstruction.of(Opcode.DNEG)); } /** @@ -1235,7 +1074,7 @@ default CodeBuilder dneg() { * @return this builder */ default CodeBuilder drem() { - return operatorInstruction(Opcode.DREM); + return with(OperatorInstruction.of(Opcode.DREM)); } /** @@ -1243,7 +1082,7 @@ default CodeBuilder drem() { * @return this builder */ default CodeBuilder dreturn() { - return returnInstruction(TypeKind.DoubleType); + return return_(TypeKind.DoubleType); } /** @@ -1252,7 +1091,7 @@ default CodeBuilder dreturn() { * @return this builder */ default CodeBuilder dstore(int slot) { - return storeInstruction(TypeKind.DoubleType, slot); + return storeLocal(TypeKind.DoubleType, slot); } /** @@ -1260,7 +1099,7 @@ default CodeBuilder dstore(int slot) { * @return this builder */ default CodeBuilder dsub() { - return operatorInstruction(Opcode.DSUB); + return with(OperatorInstruction.of(Opcode.DSUB)); } /** @@ -1268,7 +1107,7 @@ default CodeBuilder dsub() { * @return this builder */ default CodeBuilder dup() { - return stackInstruction(Opcode.DUP); + return with(StackInstruction.of(Opcode.DUP)); } /** @@ -1276,7 +1115,7 @@ default CodeBuilder dup() { * @return this builder */ default CodeBuilder dup2() { - return stackInstruction(Opcode.DUP2); + return with(StackInstruction.of(Opcode.DUP2)); } /** @@ -1285,7 +1124,7 @@ default CodeBuilder dup2() { * @return this builder */ default CodeBuilder dup2_x1() { - return stackInstruction(Opcode.DUP2_X1); + return with(StackInstruction.of(Opcode.DUP2_X1)); } /** @@ -1294,7 +1133,7 @@ default CodeBuilder dup2_x1() { * @return this builder */ default CodeBuilder dup2_x2() { - return stackInstruction(Opcode.DUP2_X2); + return with(StackInstruction.of(Opcode.DUP2_X2)); } /** @@ -1302,7 +1141,7 @@ default CodeBuilder dup2_x2() { * @return this builder */ default CodeBuilder dup_x1() { - return stackInstruction(Opcode.DUP_X1); + return with(StackInstruction.of(Opcode.DUP_X1)); } /** @@ -1310,7 +1149,7 @@ default CodeBuilder dup_x1() { * @return this builder */ default CodeBuilder dup_x2() { - return stackInstruction(Opcode.DUP_X2); + return with(StackInstruction.of(Opcode.DUP_X2)); } /** @@ -1318,7 +1157,7 @@ default CodeBuilder dup_x2() { * @return this builder */ default CodeBuilder f2d() { - return convertInstruction(TypeKind.FloatType, TypeKind.DoubleType); + return with(ConvertInstruction.of(Opcode.F2D)); } /** @@ -1326,7 +1165,7 @@ default CodeBuilder f2d() { * @return this builder */ default CodeBuilder f2i() { - return convertInstruction(TypeKind.FloatType, TypeKind.IntType); + return with(ConvertInstruction.of(Opcode.F2I)); } /** @@ -1334,7 +1173,7 @@ default CodeBuilder f2i() { * @return this builder */ default CodeBuilder f2l() { - return convertInstruction(TypeKind.FloatType, TypeKind.LongType); + return with(ConvertInstruction.of(Opcode.F2L)); } /** @@ -1342,7 +1181,7 @@ default CodeBuilder f2l() { * @return this builder */ default CodeBuilder fadd() { - return operatorInstruction(Opcode.FADD); + return with(OperatorInstruction.of(Opcode.FADD)); } /** @@ -1350,7 +1189,7 @@ default CodeBuilder fadd() { * @return this builder */ default CodeBuilder faload() { - return arrayLoadInstruction(TypeKind.FloatType); + return arrayLoad(TypeKind.FloatType); } /** @@ -1358,7 +1197,7 @@ default CodeBuilder faload() { * @return this builder */ default CodeBuilder fastore() { - return arrayStoreInstruction(TypeKind.FloatType); + return arrayStore(TypeKind.FloatType); } /** @@ -1366,7 +1205,7 @@ default CodeBuilder fastore() { * @return this builder */ default CodeBuilder fcmpg() { - return operatorInstruction(Opcode.FCMPG); + return with(OperatorInstruction.of(Opcode.FCMPG)); } /** @@ -1374,7 +1213,7 @@ default CodeBuilder fcmpg() { * @return this builder */ default CodeBuilder fcmpl() { - return operatorInstruction(Opcode.FCMPL); + return with(OperatorInstruction.of(Opcode.FCMPL)); } /** @@ -1406,7 +1245,7 @@ default CodeBuilder fconst_2() { * @return this builder */ default CodeBuilder fdiv() { - return operatorInstruction(Opcode.FDIV); + return with(OperatorInstruction.of(Opcode.FDIV)); } /** @@ -1415,7 +1254,7 @@ default CodeBuilder fdiv() { * @return this builder */ default CodeBuilder fload(int slot) { - return loadInstruction(TypeKind.FloatType, slot); + return loadLocal(TypeKind.FloatType, slot); } /** @@ -1423,7 +1262,7 @@ default CodeBuilder fload(int slot) { * @return this builder */ default CodeBuilder fmul() { - return operatorInstruction(Opcode.FMUL); + return with(OperatorInstruction.of(Opcode.FMUL)); } /** @@ -1431,7 +1270,7 @@ default CodeBuilder fmul() { * @return this builder */ default CodeBuilder fneg() { - return operatorInstruction(Opcode.FNEG); + return with(OperatorInstruction.of(Opcode.FNEG)); } /** @@ -1439,7 +1278,7 @@ default CodeBuilder fneg() { * @return this builder */ default CodeBuilder frem() { - return operatorInstruction(Opcode.FREM); + return with(OperatorInstruction.of(Opcode.FREM)); } /** @@ -1447,7 +1286,7 @@ default CodeBuilder frem() { * @return this builder */ default CodeBuilder freturn() { - return returnInstruction(TypeKind.FloatType); + return return_(TypeKind.FloatType); } /** @@ -1456,7 +1295,7 @@ default CodeBuilder freturn() { * @return this builder */ default CodeBuilder fstore(int slot) { - return storeInstruction(TypeKind.FloatType, slot); + return storeLocal(TypeKind.FloatType, slot); } /** @@ -1464,7 +1303,7 @@ default CodeBuilder fstore(int slot) { * @return this builder */ default CodeBuilder fsub() { - return operatorInstruction(Opcode.FSUB); + return with(OperatorInstruction.of(Opcode.FSUB)); } /** @@ -1473,7 +1312,7 @@ default CodeBuilder fsub() { * @return this builder */ default CodeBuilder getfield(FieldRefEntry ref) { - return fieldInstruction(Opcode.GETFIELD, ref); + return fieldAccess(Opcode.GETFIELD, ref); } /** @@ -1485,7 +1324,7 @@ default CodeBuilder getfield(FieldRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder getfield(ClassDesc owner, String name, ClassDesc type) { - return fieldInstruction(Opcode.GETFIELD, owner, name, type); + return fieldAccess(Opcode.GETFIELD, owner, name, type); } /** @@ -1494,7 +1333,7 @@ default CodeBuilder getfield(ClassDesc owner, String name, ClassDesc type) { * @return this builder */ default CodeBuilder getstatic(FieldRefEntry ref) { - return fieldInstruction(Opcode.GETSTATIC, ref); + return fieldAccess(Opcode.GETSTATIC, ref); } /** @@ -1506,7 +1345,7 @@ default CodeBuilder getstatic(FieldRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder getstatic(ClassDesc owner, String name, ClassDesc type) { - return fieldInstruction(Opcode.GETSTATIC, owner, name, type); + return fieldAccess(Opcode.GETSTATIC, owner, name, type); } /** @@ -1515,7 +1354,7 @@ default CodeBuilder getstatic(ClassDesc owner, String name, ClassDesc type) { * @return this builder */ default CodeBuilder goto_(Label target) { - return branchInstruction(Opcode.GOTO, target); + return branch(Opcode.GOTO, target); } /** @@ -1524,7 +1363,7 @@ default CodeBuilder goto_(Label target) { * @return this builder */ default CodeBuilder goto_w(Label target) { - return branchInstruction(Opcode.GOTO_W, target); + return branch(Opcode.GOTO_W, target); } /** @@ -1532,7 +1371,7 @@ default CodeBuilder goto_w(Label target) { * @return this builder */ default CodeBuilder i2b() { - return convertInstruction(TypeKind.IntType, TypeKind.ByteType); + return with(ConvertInstruction.of(Opcode.I2B)); } /** @@ -1540,7 +1379,7 @@ default CodeBuilder i2b() { * @return this builder */ default CodeBuilder i2c() { - return convertInstruction(TypeKind.IntType, TypeKind.CharType); + return with(ConvertInstruction.of(Opcode.I2C)); } /** @@ -1548,7 +1387,7 @@ default CodeBuilder i2c() { * @return this builder */ default CodeBuilder i2d() { - return convertInstruction(TypeKind.IntType, TypeKind.DoubleType); + return with(ConvertInstruction.of(Opcode.I2D)); } /** @@ -1556,7 +1395,7 @@ default CodeBuilder i2d() { * @return this builder */ default CodeBuilder i2f() { - return convertInstruction(TypeKind.IntType, TypeKind.FloatType); + return with(ConvertInstruction.of(Opcode.I2F)); } /** @@ -1564,7 +1403,7 @@ default CodeBuilder i2f() { * @return this builder */ default CodeBuilder i2l() { - return convertInstruction(TypeKind.IntType, TypeKind.LongType); + return with(ConvertInstruction.of(Opcode.I2L)); } /** @@ -1572,7 +1411,7 @@ default CodeBuilder i2l() { * @return this builder */ default CodeBuilder i2s() { - return convertInstruction(TypeKind.IntType, TypeKind.ShortType); + return with(ConvertInstruction.of(Opcode.I2S)); } /** @@ -1580,7 +1419,7 @@ default CodeBuilder i2s() { * @return this builder */ default CodeBuilder iadd() { - return operatorInstruction(Opcode.IADD); + return with(OperatorInstruction.of(Opcode.IADD)); } /** @@ -1588,7 +1427,7 @@ default CodeBuilder iadd() { * @return this builder */ default CodeBuilder iaload() { - return arrayLoadInstruction(TypeKind.IntType); + return arrayLoad(TypeKind.IntType); } /** @@ -1596,7 +1435,7 @@ default CodeBuilder iaload() { * @return this builder */ default CodeBuilder iand() { - return operatorInstruction(Opcode.IAND); + return with(OperatorInstruction.of(Opcode.IAND)); } /** @@ -1604,7 +1443,7 @@ default CodeBuilder iand() { * @return this builder */ default CodeBuilder iastore() { - return arrayStoreInstruction(TypeKind.IntType); + return arrayStore(TypeKind.IntType); } /** @@ -1668,7 +1507,7 @@ default CodeBuilder iconst_m1() { * @return this builder */ default CodeBuilder idiv() { - return operatorInstruction(Opcode.IDIV); + return with(OperatorInstruction.of(Opcode.IDIV)); } /** @@ -1677,7 +1516,7 @@ default CodeBuilder idiv() { * @return this builder */ default CodeBuilder if_acmpeq(Label target) { - return branchInstruction(Opcode.IF_ACMPEQ, target); + return branch(Opcode.IF_ACMPEQ, target); } /** @@ -1686,7 +1525,7 @@ default CodeBuilder if_acmpeq(Label target) { * @return this builder */ default CodeBuilder if_acmpne(Label target) { - return branchInstruction(Opcode.IF_ACMPNE, target); + return branch(Opcode.IF_ACMPNE, target); } /** @@ -1695,7 +1534,7 @@ default CodeBuilder if_acmpne(Label target) { * @return this builder */ default CodeBuilder if_icmpeq(Label target) { - return branchInstruction(Opcode.IF_ICMPEQ, target); + return branch(Opcode.IF_ICMPEQ, target); } /** @@ -1704,7 +1543,7 @@ default CodeBuilder if_icmpeq(Label target) { * @return this builder */ default CodeBuilder if_icmpge(Label target) { - return branchInstruction(Opcode.IF_ICMPGE, target); + return branch(Opcode.IF_ICMPGE, target); } /** @@ -1713,7 +1552,7 @@ default CodeBuilder if_icmpge(Label target) { * @return this builder */ default CodeBuilder if_icmpgt(Label target) { - return branchInstruction(Opcode.IF_ICMPGT, target); + return branch(Opcode.IF_ICMPGT, target); } /** @@ -1722,7 +1561,7 @@ default CodeBuilder if_icmpgt(Label target) { * @return this builder */ default CodeBuilder if_icmple(Label target) { - return branchInstruction(Opcode.IF_ICMPLE, target); + return branch(Opcode.IF_ICMPLE, target); } /** @@ -1731,7 +1570,7 @@ default CodeBuilder if_icmple(Label target) { * @return this builder */ default CodeBuilder if_icmplt(Label target) { - return branchInstruction(Opcode.IF_ICMPLT, target); + return branch(Opcode.IF_ICMPLT, target); } /** @@ -1740,7 +1579,7 @@ default CodeBuilder if_icmplt(Label target) { * @return this builder */ default CodeBuilder if_icmpne(Label target) { - return branchInstruction(Opcode.IF_ICMPNE, target); + return branch(Opcode.IF_ICMPNE, target); } /** @@ -1749,7 +1588,7 @@ default CodeBuilder if_icmpne(Label target) { * @return this builder */ default CodeBuilder if_nonnull(Label target) { - return branchInstruction(Opcode.IFNONNULL, target); + return branch(Opcode.IFNONNULL, target); } /** @@ -1758,7 +1597,7 @@ default CodeBuilder if_nonnull(Label target) { * @return this builder */ default CodeBuilder if_null(Label target) { - return branchInstruction(Opcode.IFNULL, target); + return branch(Opcode.IFNULL, target); } /** @@ -1767,7 +1606,7 @@ default CodeBuilder if_null(Label target) { * @return this builder */ default CodeBuilder ifeq(Label target) { - return branchInstruction(Opcode.IFEQ, target); + return branch(Opcode.IFEQ, target); } /** @@ -1776,7 +1615,7 @@ default CodeBuilder ifeq(Label target) { * @return this builder */ default CodeBuilder ifge(Label target) { - return branchInstruction(Opcode.IFGE, target); + return branch(Opcode.IFGE, target); } /** @@ -1785,7 +1624,7 @@ default CodeBuilder ifge(Label target) { * @return this builder */ default CodeBuilder ifgt(Label target) { - return branchInstruction(Opcode.IFGT, target); + return branch(Opcode.IFGT, target); } /** @@ -1794,7 +1633,7 @@ default CodeBuilder ifgt(Label target) { * @return this builder */ default CodeBuilder ifle(Label target) { - return branchInstruction(Opcode.IFLE, target); + return branch(Opcode.IFLE, target); } /** @@ -1803,7 +1642,7 @@ default CodeBuilder ifle(Label target) { * @return this builder */ default CodeBuilder iflt(Label target) { - return branchInstruction(Opcode.IFLT, target); + return branch(Opcode.IFLT, target); } /** @@ -1812,7 +1651,7 @@ default CodeBuilder iflt(Label target) { * @return this builder */ default CodeBuilder ifne(Label target) { - return branchInstruction(Opcode.IFNE, target); + return branch(Opcode.IFNE, target); } /** @@ -1822,7 +1661,7 @@ default CodeBuilder ifne(Label target) { * @return this builder */ default CodeBuilder iinc(int slot, int val) { - return incrementInstruction(slot, val); + return with(IncrementInstruction.of(slot, val)); } /** @@ -1831,7 +1670,7 @@ default CodeBuilder iinc(int slot, int val) { * @return this builder */ default CodeBuilder iload(int slot) { - return loadInstruction(TypeKind.IntType, slot); + return loadLocal(TypeKind.IntType, slot); } /** @@ -1839,7 +1678,7 @@ default CodeBuilder iload(int slot) { * @return this builder */ default CodeBuilder imul() { - return operatorInstruction(Opcode.IMUL); + return with(OperatorInstruction.of(Opcode.IMUL)); } /** @@ -1847,16 +1686,17 @@ default CodeBuilder imul() { * @return this builder */ default CodeBuilder ineg() { - return operatorInstruction(Opcode.INEG); + return with(OperatorInstruction.of(Opcode.INEG)); } /** * Generate an instruction to determine if an object is of the given type * @param target the target type * @return this builder + * @since 23 */ - default CodeBuilder instanceof_(ClassEntry target) { - return typeCheckInstruction(Opcode.INSTANCEOF, target); + default CodeBuilder instanceOf(ClassEntry target) { + return with(TypeCheckInstruction.of(Opcode.INSTANCEOF, target)); } /** @@ -1864,9 +1704,10 @@ default CodeBuilder instanceof_(ClassEntry target) { * @param target the target type * @return this builder * @throws IllegalArgumentException if {@code target} represents a primitive type + * @since 23 */ - default CodeBuilder instanceof_(ClassDesc target) { - return typeCheckInstruction(Opcode.INSTANCEOF, constantPool().classEntry(target)); + default CodeBuilder instanceOf(ClassDesc target) { + return instanceOf(constantPool().classEntry(target)); } /** @@ -1875,7 +1716,7 @@ default CodeBuilder instanceof_(ClassDesc target) { * @return this builder */ default CodeBuilder invokedynamic(InvokeDynamicEntry ref) { - return invokeDynamicInstruction(ref); + return with(InvokeDynamicInstruction.of(ref)); } /** @@ -1884,7 +1725,15 @@ default CodeBuilder invokedynamic(InvokeDynamicEntry ref) { * @return this builder */ default CodeBuilder invokedynamic(DynamicCallSiteDesc ref) { - return invokeDynamicInstruction(ref); + MethodHandleEntry bsMethod = handleDescToHandleInfo(constantPool(), (DirectMethodHandleDesc) ref.bootstrapMethod()); + var cpArgs = ref.bootstrapArgs(); + List bsArguments = new ArrayList<>(cpArgs.length); + for (var constantValue : cpArgs) { + bsArguments.add(BytecodeHelpers.constantEntry(constantPool(), constantValue)); + } + BootstrapMethodEntry bm = constantPool().bsmEntry(bsMethod, bsArguments); + NameAndTypeEntry nameAndType = constantPool().nameAndTypeEntry(ref.invocationName(), ref.invocationType()); + return invokedynamic(constantPool().invokeDynamicEntry(bm, nameAndType)); } /** @@ -1893,7 +1742,7 @@ default CodeBuilder invokedynamic(DynamicCallSiteDesc ref) { * @return this builder */ default CodeBuilder invokeinterface(InterfaceMethodRefEntry ref) { - return invokeInstruction(Opcode.INVOKEINTERFACE, ref); + return invoke(Opcode.INVOKEINTERFACE, ref); } /** @@ -1905,7 +1754,7 @@ default CodeBuilder invokeinterface(InterfaceMethodRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder invokeinterface(ClassDesc owner, String name, MethodTypeDesc type) { - return invokeInstruction(Opcode.INVOKEINTERFACE, constantPool().interfaceMethodRefEntry(owner, name, type)); + return invoke(Opcode.INVOKEINTERFACE, constantPool().interfaceMethodRefEntry(owner, name, type)); } /** @@ -1915,7 +1764,7 @@ default CodeBuilder invokeinterface(ClassDesc owner, String name, MethodTypeDesc * @return this builder */ default CodeBuilder invokespecial(InterfaceMethodRefEntry ref) { - return invokeInstruction(Opcode.INVOKESPECIAL, ref); + return invoke(Opcode.INVOKESPECIAL, ref); } /** @@ -1925,7 +1774,7 @@ default CodeBuilder invokespecial(InterfaceMethodRefEntry ref) { * @return this builder */ default CodeBuilder invokespecial(MethodRefEntry ref) { - return invokeInstruction(Opcode.INVOKESPECIAL, ref); + return invoke(Opcode.INVOKESPECIAL, ref); } /** @@ -1938,7 +1787,7 @@ default CodeBuilder invokespecial(MethodRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder invokespecial(ClassDesc owner, String name, MethodTypeDesc type) { - return invokeInstruction(Opcode.INVOKESPECIAL, owner, name, type, false); + return invoke(Opcode.INVOKESPECIAL, owner, name, type, false); } /** @@ -1952,7 +1801,7 @@ default CodeBuilder invokespecial(ClassDesc owner, String name, MethodTypeDesc t * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder invokespecial(ClassDesc owner, String name, MethodTypeDesc type, boolean isInterface) { - return invokeInstruction(Opcode.INVOKESPECIAL, owner, name, type, isInterface); + return invoke(Opcode.INVOKESPECIAL, owner, name, type, isInterface); } /** @@ -1961,7 +1810,7 @@ default CodeBuilder invokespecial(ClassDesc owner, String name, MethodTypeDesc t * @return this builder */ default CodeBuilder invokestatic(InterfaceMethodRefEntry ref) { - return invokeInstruction(Opcode.INVOKESTATIC, ref); + return invoke(Opcode.INVOKESTATIC, ref); } /** @@ -1970,7 +1819,7 @@ default CodeBuilder invokestatic(InterfaceMethodRefEntry ref) { * @return this builder */ default CodeBuilder invokestatic(MethodRefEntry ref) { - return invokeInstruction(Opcode.INVOKESTATIC, ref); + return invoke(Opcode.INVOKESTATIC, ref); } /** @@ -1982,7 +1831,7 @@ default CodeBuilder invokestatic(MethodRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder invokestatic(ClassDesc owner, String name, MethodTypeDesc type) { - return invokeInstruction(Opcode.INVOKESTATIC, owner, name, type, false); + return invoke(Opcode.INVOKESTATIC, owner, name, type, false); } /** @@ -1995,7 +1844,7 @@ default CodeBuilder invokestatic(ClassDesc owner, String name, MethodTypeDesc ty * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder invokestatic(ClassDesc owner, String name, MethodTypeDesc type, boolean isInterface) { - return invokeInstruction(Opcode.INVOKESTATIC, owner, name, type, isInterface); + return invoke(Opcode.INVOKESTATIC, owner, name, type, isInterface); } /** @@ -2004,7 +1853,7 @@ default CodeBuilder invokestatic(ClassDesc owner, String name, MethodTypeDesc ty * @return this builder */ default CodeBuilder invokevirtual(MethodRefEntry ref) { - return invokeInstruction(Opcode.INVOKEVIRTUAL, ref); + return invoke(Opcode.INVOKEVIRTUAL, ref); } /** @@ -2016,7 +1865,7 @@ default CodeBuilder invokevirtual(MethodRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder invokevirtual(ClassDesc owner, String name, MethodTypeDesc type) { - return invokeInstruction(Opcode.INVOKEVIRTUAL, owner, name, type, false); + return invoke(Opcode.INVOKEVIRTUAL, owner, name, type, false); } /** @@ -2024,7 +1873,7 @@ default CodeBuilder invokevirtual(ClassDesc owner, String name, MethodTypeDesc t * @return this builder */ default CodeBuilder ior() { - return operatorInstruction(Opcode.IOR); + return with(OperatorInstruction.of(Opcode.IOR)); } /** @@ -2032,7 +1881,7 @@ default CodeBuilder ior() { * @return this builder */ default CodeBuilder irem() { - return operatorInstruction(Opcode.IREM); + return with(OperatorInstruction.of(Opcode.IREM)); } /** @@ -2040,7 +1889,7 @@ default CodeBuilder irem() { * @return this builder */ default CodeBuilder ireturn() { - return returnInstruction(TypeKind.IntType); + return return_(TypeKind.IntType); } /** @@ -2048,7 +1897,7 @@ default CodeBuilder ireturn() { * @return this builder */ default CodeBuilder ishl() { - return operatorInstruction(Opcode.ISHL); + return with(OperatorInstruction.of(Opcode.ISHL)); } /** @@ -2056,7 +1905,7 @@ default CodeBuilder ishl() { * @return this builder */ default CodeBuilder ishr() { - return operatorInstruction(Opcode.ISHR); + return with(OperatorInstruction.of(Opcode.ISHR)); } /** @@ -2065,7 +1914,7 @@ default CodeBuilder ishr() { * @return this builder */ default CodeBuilder istore(int slot) { - return storeInstruction(TypeKind.IntType, slot); + return storeLocal(TypeKind.IntType, slot); } /** @@ -2073,7 +1922,7 @@ default CodeBuilder istore(int slot) { * @return this builder */ default CodeBuilder isub() { - return operatorInstruction(Opcode.ISUB); + return with(OperatorInstruction.of(Opcode.ISUB)); } /** @@ -2081,7 +1930,7 @@ default CodeBuilder isub() { * @return this builder */ default CodeBuilder iushr() { - return operatorInstruction(Opcode.IUSHR); + return with(OperatorInstruction.of(Opcode.IUSHR)); } /** @@ -2089,7 +1938,7 @@ default CodeBuilder iushr() { * @return this builder */ default CodeBuilder ixor() { - return operatorInstruction(Opcode.IXOR); + return with(OperatorInstruction.of(Opcode.IXOR)); } /** @@ -2099,7 +1948,7 @@ default CodeBuilder ixor() { * @return this builder */ default CodeBuilder lookupswitch(Label defaultTarget, List cases) { - return lookupSwitchInstruction(defaultTarget, cases); + return with(LookupSwitchInstruction.of(defaultTarget, cases)); } /** @@ -2107,7 +1956,7 @@ default CodeBuilder lookupswitch(Label defaultTarget, List cases) { * @return this builder */ default CodeBuilder l2d() { - return convertInstruction(TypeKind.LongType, TypeKind.DoubleType); + return with(ConvertInstruction.of(Opcode.L2D)); } /** @@ -2115,7 +1964,7 @@ default CodeBuilder l2d() { * @return this builder */ default CodeBuilder l2f() { - return convertInstruction(TypeKind.LongType, TypeKind.FloatType); + return with(ConvertInstruction.of(Opcode.L2F)); } /** @@ -2123,7 +1972,7 @@ default CodeBuilder l2f() { * @return this builder */ default CodeBuilder l2i() { - return convertInstruction(TypeKind.LongType, TypeKind.IntType); + return with(ConvertInstruction.of(Opcode.L2I)); } /** @@ -2131,7 +1980,7 @@ default CodeBuilder l2i() { * @return this builder */ default CodeBuilder ladd() { - return operatorInstruction(Opcode.LADD); + return with(OperatorInstruction.of(Opcode.LADD)); } /** @@ -2139,7 +1988,7 @@ default CodeBuilder ladd() { * @return this builder */ default CodeBuilder laload() { - return arrayLoadInstruction(TypeKind.LongType); + return arrayLoad(TypeKind.LongType); } /** @@ -2147,7 +1996,7 @@ default CodeBuilder laload() { * @return this builder */ default CodeBuilder land() { - return operatorInstruction(Opcode.LAND); + return with(OperatorInstruction.of(Opcode.LAND)); } /** @@ -2155,7 +2004,7 @@ default CodeBuilder land() { * @return this builder */ default CodeBuilder lastore() { - return arrayStoreInstruction(TypeKind.LongType); + return arrayStore(TypeKind.LongType); } /** @@ -2163,7 +2012,7 @@ default CodeBuilder lastore() { * @return this builder */ default CodeBuilder lcmp() { - return operatorInstruction(Opcode.LCMP); + return with(OperatorInstruction.of(Opcode.LCMP)); } /** @@ -2208,7 +2057,7 @@ default CodeBuilder ldc(LoadableConstantEntry entry) { * @return this builder */ default CodeBuilder ldiv() { - return operatorInstruction(Opcode.LDIV); + return with(OperatorInstruction.of(Opcode.LDIV)); } /** @@ -2217,7 +2066,7 @@ default CodeBuilder ldiv() { * @return this builder */ default CodeBuilder lload(int slot) { - return loadInstruction(TypeKind.LongType, slot); + return loadLocal(TypeKind.LongType, slot); } /** @@ -2225,7 +2074,7 @@ default CodeBuilder lload(int slot) { * @return this builder */ default CodeBuilder lmul() { - return operatorInstruction(Opcode.LMUL); + return with(OperatorInstruction.of(Opcode.LMUL)); } /** @@ -2233,7 +2082,7 @@ default CodeBuilder lmul() { * @return this builder */ default CodeBuilder lneg() { - return operatorInstruction(Opcode.LNEG); + return with(OperatorInstruction.of(Opcode.LNEG)); } /** @@ -2241,7 +2090,7 @@ default CodeBuilder lneg() { * @return this builder */ default CodeBuilder lor() { - return operatorInstruction(Opcode.LOR); + return with(OperatorInstruction.of(Opcode.LOR)); } /** @@ -2249,7 +2098,7 @@ default CodeBuilder lor() { * @return this builder */ default CodeBuilder lrem() { - return operatorInstruction(Opcode.LREM); + return with(OperatorInstruction.of(Opcode.LREM)); } /** @@ -2257,7 +2106,7 @@ default CodeBuilder lrem() { * @return this builder */ default CodeBuilder lreturn() { - return returnInstruction(TypeKind.LongType); + return return_(TypeKind.LongType); } /** @@ -2265,7 +2114,7 @@ default CodeBuilder lreturn() { * @return this builder */ default CodeBuilder lshl() { - return operatorInstruction(Opcode.LSHL); + return with(OperatorInstruction.of(Opcode.LSHL)); } /** @@ -2273,7 +2122,7 @@ default CodeBuilder lshl() { * @return this builder */ default CodeBuilder lshr() { - return operatorInstruction(Opcode.LSHR); + return with(OperatorInstruction.of(Opcode.LSHR)); } /** @@ -2282,7 +2131,7 @@ default CodeBuilder lshr() { * @return this builder */ default CodeBuilder lstore(int slot) { - return storeInstruction(TypeKind.LongType, slot); + return storeLocal(TypeKind.LongType, slot); } /** @@ -2290,7 +2139,7 @@ default CodeBuilder lstore(int slot) { * @return this builder */ default CodeBuilder lsub() { - return operatorInstruction(Opcode.LSUB); + return with(OperatorInstruction.of(Opcode.LSUB)); } /** @@ -2298,7 +2147,7 @@ default CodeBuilder lsub() { * @return this builder */ default CodeBuilder lushr() { - return operatorInstruction(Opcode.LUSHR); + return with(OperatorInstruction.of(Opcode.LUSHR)); } /** @@ -2306,7 +2155,7 @@ default CodeBuilder lushr() { * @return this builder */ default CodeBuilder lxor() { - return operatorInstruction(Opcode.LXOR); + return with(OperatorInstruction.of(Opcode.LXOR)); } /** @@ -2314,7 +2163,7 @@ default CodeBuilder lxor() { * @return this builder */ default CodeBuilder monitorenter() { - return monitorInstruction(Opcode.MONITORENTER); + return with(MonitorInstruction.of(Opcode.MONITORENTER)); } /** @@ -2322,7 +2171,7 @@ default CodeBuilder monitorenter() { * @return this builder */ default CodeBuilder monitorexit() { - return monitorInstruction(Opcode.MONITOREXIT); + return with(MonitorInstruction.of(Opcode.MONITOREXIT)); } /** @@ -2332,7 +2181,7 @@ default CodeBuilder monitorexit() { * @return this builder */ default CodeBuilder multianewarray(ClassEntry array, int dims) { - return newMultidimensionalArrayInstruction(dims, array); + return with(NewMultiArrayInstruction.of(array, dims)); } /** @@ -2343,7 +2192,7 @@ default CodeBuilder multianewarray(ClassEntry array, int dims) { * @throws IllegalArgumentException if {@code array} represents a primitive type */ default CodeBuilder multianewarray(ClassDesc array, int dims) { - return newMultidimensionalArrayInstruction(dims, constantPool().classEntry(array)); + return multianewarray(constantPool().classEntry(array), dims); } /** @@ -2352,7 +2201,7 @@ default CodeBuilder multianewarray(ClassDesc array, int dims) { * @return this builder */ default CodeBuilder new_(ClassEntry clazz) { - return newObjectInstruction(clazz); + return with(NewObjectInstruction.of(clazz)); } /** @@ -2362,7 +2211,7 @@ default CodeBuilder new_(ClassEntry clazz) { * @throws IllegalArgumentException if {@code clazz} represents a primitive type */ default CodeBuilder new_(ClassDesc clazz) { - return newObjectInstruction(constantPool().classEntry(clazz)); + return new_(constantPool().classEntry(clazz)); } /** @@ -2371,7 +2220,7 @@ default CodeBuilder new_(ClassDesc clazz) { * @return this builder */ default CodeBuilder newarray(TypeKind typeKind) { - return newPrimitiveArrayInstruction(typeKind); + return with(NewPrimitiveArrayInstruction.of(typeKind)); } /** @@ -2379,7 +2228,7 @@ default CodeBuilder newarray(TypeKind typeKind) { * @return this builder */ default CodeBuilder pop() { - return stackInstruction(Opcode.POP); + return with(StackInstruction.of(Opcode.POP)); } /** @@ -2387,7 +2236,7 @@ default CodeBuilder pop() { * @return this builder */ default CodeBuilder pop2() { - return stackInstruction(Opcode.POP2); + return with(StackInstruction.of(Opcode.POP2)); } /** @@ -2396,7 +2245,7 @@ default CodeBuilder pop2() { * @return this builder */ default CodeBuilder putfield(FieldRefEntry ref) { - return fieldInstruction(Opcode.PUTFIELD, ref); + return fieldAccess(Opcode.PUTFIELD, ref); } /** @@ -2408,7 +2257,7 @@ default CodeBuilder putfield(FieldRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder putfield(ClassDesc owner, String name, ClassDesc type) { - return fieldInstruction(Opcode.PUTFIELD, owner, name, type); + return fieldAccess(Opcode.PUTFIELD, owner, name, type); } /** @@ -2417,7 +2266,7 @@ default CodeBuilder putfield(ClassDesc owner, String name, ClassDesc type) { * @return this builder */ default CodeBuilder putstatic(FieldRefEntry ref) { - return fieldInstruction(Opcode.PUTSTATIC, ref); + return fieldAccess(Opcode.PUTSTATIC, ref); } /** @@ -2429,7 +2278,7 @@ default CodeBuilder putstatic(FieldRefEntry ref) { * @throws IllegalArgumentException if {@code owner} represents a primitive type */ default CodeBuilder putstatic(ClassDesc owner, String name, ClassDesc type) { - return fieldInstruction(Opcode.PUTSTATIC, owner, name, type); + return fieldAccess(Opcode.PUTSTATIC, owner, name, type); } /** @@ -2437,7 +2286,7 @@ default CodeBuilder putstatic(ClassDesc owner, String name, ClassDesc type) { * @return this builder */ default CodeBuilder return_() { - return returnInstruction(TypeKind.VoidType); + return return_(TypeKind.VoidType); } /** @@ -2445,7 +2294,7 @@ default CodeBuilder return_() { * @return this builder */ default CodeBuilder saload() { - return arrayLoadInstruction(TypeKind.ShortType); + return arrayLoad(TypeKind.ShortType); } /** @@ -2453,7 +2302,7 @@ default CodeBuilder saload() { * @return this builder */ default CodeBuilder sastore() { - return arrayStoreInstruction(TypeKind.ShortType); + return arrayStore(TypeKind.ShortType); } /** @@ -2462,7 +2311,7 @@ default CodeBuilder sastore() { * @return this builder */ default CodeBuilder sipush(int s) { - return constantInstruction(Opcode.SIPUSH, s); + return loadConstant(Opcode.SIPUSH, s); } /** @@ -2470,7 +2319,7 @@ default CodeBuilder sipush(int s) { * @return this builder */ default CodeBuilder swap() { - return stackInstruction(Opcode.SWAP); + return with(StackInstruction.of(Opcode.SWAP)); } /** @@ -2482,7 +2331,7 @@ default CodeBuilder swap() { * @return this builder */ default CodeBuilder tableswitch(int low, int high, Label defaultTarget, List cases) { - return tableSwitchInstruction(low, high, defaultTarget, cases); + return with(TableSwitchInstruction.of(low, high, defaultTarget, cases)); } /** @@ -2499,6 +2348,6 @@ default CodeBuilder tableswitch(Label defaultTarget, List cases) { if (i < low) low = i; if (i > high) high = i; } - return tableSwitchInstruction(low, high, defaultTarget, cases); + return tableswitch(low, high, defaultTarget, cases); } } diff --git a/src/java.base/share/classes/java/lang/classfile/package-info.java b/src/java.base/share/classes/java/lang/classfile/package-info.java index edeafc439d370..49413d356607c 100644 --- a/src/java.base/share/classes/java/lang/classfile/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/package-info.java @@ -228,7 +228,7 @@ * instruction invoking {@code println} could have been generated with {@link * java.lang.classfile.CodeBuilder#invokevirtual(java.lang.constant.ClassDesc, * java.lang.String, java.lang.constant.MethodTypeDesc) CodeBuilder.invokevirtual}, {@link - * java.lang.classfile.CodeBuilder#invokeInstruction(java.lang.classfile.Opcode, + * java.lang.classfile.CodeBuilder#invoke(java.lang.classfile.Opcode, * java.lang.constant.ClassDesc, java.lang.String, java.lang.constant.MethodTypeDesc, * boolean) CodeBuilder.invokeInstruction}, or {@link * java.lang.classfile.CodeBuilder#with(java.lang.classfile.ClassFileElement) diff --git a/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java b/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java index 3776c6f66e965..5073e108465ad 100644 --- a/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java +++ b/src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java @@ -213,7 +213,7 @@ void fooToBarTransform() { if (e instanceof InvokeInstruction i && i.owner().asInternalName().equals("Foo") && i.opcode() == Opcode.INVOKESTATIC) - b.invokeInstruction(i.opcode(), CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface()); + b.invoke(i.opcode(), CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface()); else b.with(e); }; // @end @@ -327,7 +327,7 @@ void fooToBarUnrolled(ClassModel classModel) { for (CodeElement e : xm) { if (e instanceof InvokeInstruction i && i.owner().asInternalName().equals("Foo") && i.opcode() == Opcode.INVOKESTATIC) - codeBuilder.invokeInstruction(i.opcode(), CD_Bar, + codeBuilder.invoke(i.opcode(), CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface()); else codeBuilder.with(e); }}); diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index 15dc1301db5d1..5ca45e3fe529d 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -382,7 +382,7 @@ private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, Cl // clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> { - cob.constantInstruction(ifaceDesc); + cob.loadConstant(ifaceDesc); cob.putstatic(proxyDesc, TYPE_NAME, CD_Class); cob.return_(); }); @@ -406,7 +406,7 @@ private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, Cl // this.m = callerBoundTarget.asType(xxType); cob.aload(0); cob.aload(3); - cob.constantInstruction(mi.desc); + cob.loadConstant(mi.desc); cob.invokevirtual(CD_MethodHandle, "asType", MTD_MethodHandle_MethodType); cob.putfield(proxyDesc, mi.fieldName, CD_MethodHandle); } @@ -423,12 +423,12 @@ private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, Cl // check lookupClass cob.aload(0); cob.invokevirtual(CD_MethodHandles_Lookup, "lookupClass", MTD_Class); - cob.constantInstruction(proxyDesc); + cob.loadConstant(proxyDesc); cob.if_acmpne(failLabel); // check original access cob.aload(0); cob.invokevirtual(CD_MethodHandles_Lookup, "lookupModes", MTD_int); - cob.constantInstruction(Lookup.ORIGINAL); + cob.loadConstant(Lookup.ORIGINAL); cob.iand(); cob.ifeq(failLabel); // success @@ -452,11 +452,11 @@ private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, Cl bcb.aload(0); bcb.getfield(proxyDesc, mi.fieldName, CD_MethodHandle); for (int j = 0; j < mi.desc.parameterCount(); j++) { - bcb.loadInstruction(TypeKind.from(mi.desc.parameterType(j)), + bcb.loadLocal(TypeKind.from(mi.desc.parameterType(j)), bcb.parameterSlot(j)); } bcb.invokevirtual(CD_MethodHandle, "invokeExact", mi.desc); - bcb.returnInstruction(TypeKind.from(mi.desc.returnType())); + bcb.return_(TypeKind.from(mi.desc.returnType())); }, ctb -> ctb // catch (Error | RuntimeException | Declared ex) { throw ex; } .catchingMulti(mi.thrown, CodeBuilder::athrow) diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index cd2f7ec170a5c..3499fd8352595 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -1124,7 +1124,7 @@ public void accept(CodeBuilder cb) { } } len += args.parameterCount() * ARGUMENT_SIZE_FACTOR; - cb.constantInstruction(len); + cb.loadConstant(len); cb.invokespecial(STRING_BUILDER, "", INT_CONSTRUCTOR_TYPE); // At this point, we have a blank StringBuilder on stack, fill it in with .append calls. @@ -1137,7 +1137,7 @@ public void accept(CodeBuilder cb) { } Class cl = args.parameterType(c); TypeKind kind = TypeKind.from(cl); - cb.loadInstruction(kind, off); + cb.loadLocal(kind, off); off += kind.slotSize(); MethodTypeDesc desc = getSBAppendDesc(cl); cb.invokevirtual(STRING_BUILDER, "append", desc); diff --git a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java index 9637af4b2515e..08f971b0902f7 100644 --- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java +++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java @@ -689,7 +689,7 @@ private static void generateLookupAccessor(ClassBuilder clb) { .block(blockBuilder -> blockBuilder .aload(cob.parameterSlot(0)) .invokevirtual(CD_MethodHandles_Lookup, "lookupClass", MTD_Class) - .constantInstruction(Opcode.LDC, CD_Proxy) + .ldc(CD_Proxy) .if_acmpne(blockBuilder.breakLabel()) .aload(cob.parameterSlot(0)) .invokevirtual(CD_MethodHandles_Lookup, "hasFullPrivilegeAccess", MTD_boolean) @@ -763,11 +763,11 @@ private void generateMethod(ClassBuilder clb, ClassEntry className) { if (parameterTypes.length > 0) { // Create an array and fill with the parameters converting primitives to wrappers - cob.constantInstruction(parameterTypes.length) + cob.loadConstant(parameterTypes.length) .anewarray(CE_Object); for (int i = 0; i < parameterTypes.length; i++) { cob.dup() - .constantInstruction(i); + .loadConstant(i); codeWrapArgument(cob, parameterTypes[i], cob.parameterSlot(i)); cob.aastore(); } @@ -811,7 +811,7 @@ private void generateMethod(ClassBuilder clb, ClassEntry className) { */ private void codeWrapArgument(CodeBuilder cob, Class type, int slot) { if (type.isPrimitive()) { - cob.loadInstruction(TypeKind.from(type).asLoadable(), slot); + cob.loadLocal(TypeKind.from(type).asLoadable(), slot); PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type); cob.invokestatic(prim.wrapperMethodRef); } else { @@ -830,7 +830,7 @@ private void codeUnwrapReturnValue(CodeBuilder cob, Class type) { cob.checkcast(prim.wrapperClass) .invokevirtual(prim.unwrapMethodRef) - .returnInstruction(TypeKind.from(type).asLoadable()); + .return_(TypeKind.from(type).asLoadable()); } else { cob.checkcast(toClassDesc(type)) .areturn(); @@ -847,13 +847,13 @@ private void codeFieldInitialization(CodeBuilder cob, ClassEntry className) { codeClassForName(cob, fromClass); cob.ldc(method.getName()) - .constantInstruction(parameterTypes.length) + .loadConstant(parameterTypes.length) .anewarray(CE_Class); // Construct an array with the parameter types mapping primitives to Wrapper types for (int i = 0; i < parameterTypes.length; i++) { cob.dup() - .constantInstruction(i); + .loadConstant(i); if (parameterTypes[i].isPrimitive()) { PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(parameterTypes[i]); cob.getstatic(prim.typeFieldRef); diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index f91a9ad4de3b4..9ec60d9a1522d 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -414,7 +414,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto cb.ireturn(); cb.labelBinding(nonNullLabel); if (labelConstants.length == 0) { - cb.constantInstruction(0) + cb.loadConstant(0) .ireturn(); return; } @@ -454,7 +454,7 @@ record Element(Label target, Label next, Object caseLabel) { } // Object o = ... // o instanceof Wrapped(float) cb.aload(SELECTOR_OBJ); - cb.instanceof_(Wrapper.forBasicType(classLabel) + cb.instanceOf(Wrapper.forBasicType(classLabel) .wrapperType() .describeConstable() .orElseThrow()); @@ -464,7 +464,7 @@ record Element(Label target, Label next, Object caseLabel) { } // o instanceof float Label notNumber = cb.newLabel(); cb.aload(SELECTOR_OBJ); - cb.instanceof_(ConstantDescs.CD_Number); + cb.instanceOf(ConstantDescs.CD_Number); if (selectorType == long.class || selectorType == float.class || selectorType == double.class || selectorType == Long.class || selectorType == Float.class || selectorType == Double.class) { cb.ifeq(next); @@ -493,7 +493,7 @@ record Element(Label target, Label next, Object caseLabel) { } cb.goto_(compare); cb.labelBinding(notNumber); cb.aload(SELECTOR_OBJ); - cb.instanceof_(ConstantDescs.CD_Character); + cb.instanceOf(ConstantDescs.CD_Character); cb.ifeq(next); cb.aload(SELECTOR_OBJ); cb.checkcast(ConstantDescs.CD_Character); @@ -514,11 +514,11 @@ record Element(Label target, Label next, Object caseLabel) { } Optional classLabelConstableOpt = classLabel.describeConstable(); if (classLabelConstableOpt.isPresent()) { cb.aload(SELECTOR_OBJ); - cb.instanceof_(classLabelConstableOpt.orElseThrow()); + cb.instanceOf(classLabelConstableOpt.orElseThrow()); cb.ifeq(next); } else { cb.aload(EXTRA_CLASS_LABELS); - cb.constantInstruction(extraClassLabels.size()); + cb.loadConstant(extraClassLabels.size()); cb.invokeinterface(ConstantDescs.CD_List, "get", MethodTypeDesc.of(ConstantDescs.CD_Object, @@ -537,7 +537,7 @@ record Element(Label target, Label next, Object caseLabel) { } int enumIdx = enumDescs.size(); enumDescs.add(enumLabel); cb.aload(ENUM_CACHE); - cb.constantInstruction(enumIdx); + cb.loadConstant(enumIdx); cb.invokestatic(ConstantDescs.CD_Integer, "valueOf", MethodTypeDesc.of(ConstantDescs.CD_Integer, @@ -561,7 +561,7 @@ record Element(Label target, Label next, Object caseLabel) { } Label compare = cb.newLabel(); Label notNumber = cb.newLabel(); cb.aload(SELECTOR_OBJ); - cb.instanceof_(ConstantDescs.CD_Number); + cb.instanceOf(ConstantDescs.CD_Number); cb.ifeq(notNumber); cb.aload(SELECTOR_OBJ); cb.checkcast(ConstantDescs.CD_Number); @@ -571,7 +571,7 @@ record Element(Label target, Label next, Object caseLabel) { } cb.goto_(compare); cb.labelBinding(notNumber); cb.aload(SELECTOR_OBJ); - cb.instanceof_(ConstantDescs.CD_Character); + cb.instanceOf(ConstantDescs.CD_Character); cb.ifeq(next); cb.aload(SELECTOR_OBJ); cb.checkcast(ConstantDescs.CD_Character); @@ -587,9 +587,9 @@ record Element(Label target, Label next, Object caseLabel) { } element.caseLabel() instanceof Double || element.caseLabel() instanceof Boolean)) { if (element.caseLabel() instanceof Boolean c) { - cb.constantInstruction(c ? 1 : 0); + cb.loadConstant(c ? 1 : 0); } else { - cb.constantInstruction((ConstantDesc) element.caseLabel()); + cb.loadConstant((ConstantDesc) element.caseLabel()); } cb.invokestatic(element.caseLabel().getClass().describeConstable().orElseThrow(), "valueOf", @@ -605,11 +605,11 @@ record Element(Label target, Label next, Object caseLabel) { } throw new InternalError("Unsupported label type: " + element.caseLabel().getClass()); } - cb.constantInstruction(idx); + cb.loadConstant(idx); cb.ireturn(); } cb.labelBinding(dflt); - cb.constantInstruction(cases.size()); + cb.loadConstant(cases.size()); cb.ireturn(); }; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CatchBuilderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CatchBuilderImpl.java index 0878682ae568a..5d262c397f6ba 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CatchBuilderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CatchBuilderImpl.java @@ -62,7 +62,7 @@ public CodeBuilder.CatchBuilder catchingMulti(List exceptionTypes, Co if (catchBlock == null) { if (tryBlock.reachable()) { - b.branchInstruction(Opcode.GOTO, tryCatchEnd); + b.branch(Opcode.GOTO, tryCatchEnd); } } @@ -76,7 +76,7 @@ public CodeBuilder.CatchBuilder catchingMulti(List exceptionTypes, Co if (catchBlock != null) { catchBlock.end(); if (catchBlock.reachable()) { - b.branchInstruction(Opcode.GOTO, tryCatchEnd); + b.branch(Opcode.GOTO, tryCatchEnd); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java index 8f35b85b5de03..6e80e289064ac 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java @@ -231,25 +231,25 @@ public CodeTransform asCodeTransform() { return (CodeBuilder cob, CodeElement coe) -> { switch (coe) { case FieldInstruction fai -> - cob.fieldInstruction(fai.opcode(), map(fai.owner().asSymbol()), + cob.fieldAccess(fai.opcode(), map(fai.owner().asSymbol()), fai.name().stringValue(), map(fai.typeSymbol())); case InvokeInstruction ii -> - cob.invokeInstruction(ii.opcode(), map(ii.owner().asSymbol()), + cob.invoke(ii.opcode(), map(ii.owner().asSymbol()), ii.name().stringValue(), mapMethodDesc(ii.typeSymbol()), ii.isInterface()); case InvokeDynamicInstruction idi -> - cob.invokeDynamicInstruction(DynamicCallSiteDesc.of( + cob.invokedynamic(DynamicCallSiteDesc.of( idi.bootstrapMethod(), idi.name().stringValue(), mapMethodDesc(idi.typeSymbol()), idi.bootstrapArgs().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new))); case NewObjectInstruction c -> - cob.newObjectInstruction(map(c.className().asSymbol())); + cob.new_(map(c.className().asSymbol())); case NewReferenceArrayInstruction c -> cob.anewarray(map(c.componentType().asSymbol())); case NewMultiArrayInstruction c -> cob.multianewarray(map(c.arrayType().asSymbol()), c.dimensions()); case TypeCheckInstruction c -> - cob.typeCheckInstruction(c.opcode(), map(c.type().asSymbol())); + cob.with(TypeCheckInstruction.of(c.opcode(), map(c.type().asSymbol()))); case ExceptionCatch c -> cob.exceptionCatch(c.tryStart(), c.tryEnd(), c.handler(),c.catchType() .map(d -> TemporaryConstantPool.INSTANCE.classEntry(map(d.asSymbol())))); @@ -260,7 +260,7 @@ public CodeTransform asCodeTransform() { cob.localVariableType(c.slot(), c.name().stringValue(), mapSignature(c.signatureSymbol()), c.startScope(), c.endScope()); case LoadConstantInstruction ldc -> - cob.constantInstruction(ldc.opcode(), + cob.loadConstant(ldc.opcode(), mapConstantValue(ldc.constantValue())); case RuntimeVisibleTypeAnnotationsAttribute aa -> cob.with(RuntimeVisibleTypeAnnotationsAttribute.of( diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java index 9b301ccc82203..a68225fbf2751 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeLocalsShifterImpl.java @@ -50,15 +50,15 @@ public CodeLocalsShifterImpl(int fixed) { public void accept(CodeBuilder cob, CodeElement coe) { switch (coe) { case LoadInstruction li -> - cob.loadInstruction( + cob.loadLocal( li.typeKind(), shift(cob, li.slot(), li.typeKind())); case StoreInstruction si -> - cob.storeInstruction( + cob.storeLocal( si.typeKind(), shift(cob, si.slot(), si.typeKind())); case IncrementInstruction ii -> - cob.incrementInstruction( + cob.iinc( shift(cob, ii.slot(), TypeKind.IntType), ii.constant()); case LocalVariable lv -> diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeRelabelerImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeRelabelerImpl.java index 0e9bacd1cd959..f191cbf3c1f04 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeRelabelerImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeRelabelerImpl.java @@ -51,18 +51,18 @@ public Label relabel(Label label, CodeBuilder cob) { public void accept(CodeBuilder cob, CodeElement coe) { switch (coe) { case BranchInstruction bi -> - cob.branchInstruction( + cob.branch( bi.opcode(), relabel(bi.target(), cob)); case LookupSwitchInstruction lsi -> - cob.lookupSwitchInstruction( + cob.lookupswitch( relabel(lsi.defaultTarget(), cob), lsi.cases().stream().map(c -> SwitchCase.of( c.caseValue(), relabel(c.target(), cob))).toList()); case TableSwitchInstruction tsi -> - cob.tableSwitchInstruction( + cob.tableswitch( tsi.lowValue(), tsi.highValue(), relabel(tsi.defaultTarget(), cob), diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index a399b815ee614..7f5ef54bdcab1 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -274,8 +274,8 @@ private void specialize() { if (shouldAcquire(i)) { int scopeLocal = cb.allocateLocal(ReferenceType); initialScopeSlots[numScopes++] = scopeLocal; - cb.constantInstruction(null); - cb.storeInstruction(ReferenceType, scopeLocal); // need to initialize all scope locals here in case an exception occurs + cb.loadConstant(null); + cb.storeLocal(ReferenceType, scopeLocal); // need to initialize all scope locals here in case an exception occurs } } scopeSlots = Arrays.copyOf(initialScopeSlots, numScopes); // fit to size @@ -284,7 +284,7 @@ private void specialize() { // create a Binding.Context for this call if (callingSequence.allocationSize() != 0) { - cb.constantInstruction(callingSequence.allocationSize()); + cb.loadConstant(callingSequence.allocationSize()); cb.invokestatic(CD_SharedUtils, "newBoundedArena", MTD_NEW_BOUNDED_ARENA); } else if (callingSequence.forUpcall() && needsSession()) { cb.invokestatic(CD_SharedUtils, "newEmptyArena", MTD_NEW_EMPTY_ARENA); @@ -292,7 +292,7 @@ private void specialize() { cb.getstatic(CD_SharedUtils, "DUMMY_ARENA", CD_Arena); } contextIdx = cb.allocateLocal(ReferenceType); - cb.storeInstruction(ReferenceType, contextIdx); + cb.storeLocal(ReferenceType, contextIdx); // in case the call needs a return buffer, allocate it here. // for upcalls the VM wrapper stub allocates the buffer. @@ -300,7 +300,7 @@ private void specialize() { emitLoadInternalAllocator(); emitAllocateCall(callingSequence.returnBufferSize(), 1); returnBufferIdx = cb.allocateLocal(ReferenceType); - cb.storeInstruction(ReferenceType, returnBufferIdx); + cb.storeLocal(ReferenceType, returnBufferIdx); } Label tryStart = cb.newLabel(); @@ -323,7 +323,7 @@ private void specialize() { // for downcalls, recipes have an input value, which we set up here if (callingSequence.needsReturnBuffer() && i == 0) { assert returnBufferIdx != -1; - cb.loadInstruction(ReferenceType, returnBufferIdx); + cb.loadLocal(ReferenceType, returnBufferIdx); pushType(MemorySegment.class); } else { emitGetInput(); @@ -339,7 +339,7 @@ private void specialize() { // return buffer ptr is wrapped in a MemorySegment above, but not passed to the leaf handle popType(MemorySegment.class); returnBufferIdx = cb.allocateLocal(ReferenceType); - cb.storeInstruction(ReferenceType, returnBufferIdx); + cb.storeLocal(ReferenceType, returnBufferIdx); } else { // for upcalls the recipe result is an argument to the leaf handle emitSetOutput(typeStack.pop()); @@ -352,14 +352,14 @@ private void specialize() { // load the leaf MethodHandle if (callingSequence.forDowncall()) { - cb.constantInstruction(CLASS_DATA_DESC); + cb.loadConstant(CLASS_DATA_DESC); } else { - cb.loadInstruction(ReferenceType, 0); // load target arg + cb.loadLocal(ReferenceType, 0); // load target arg } cb.checkcast(CD_MethodHandle); // load all the leaf args for (int i = 0; i < leafArgSlots.length; i++) { - cb.loadInstruction(TypeKind.from(leafArgTypes.get(i)), leafArgSlots[i]); + cb.loadLocal(TypeKind.from(leafArgTypes.get(i)), leafArgSlots[i]); } // call leaf MH cb.invokevirtual(CD_MethodHandle, "invokeExact", desc(leafType)); @@ -396,7 +396,7 @@ private void specialize() { } else { popType(callerMethodType.returnType()); assert typeStack.isEmpty(); - cb.returnInstruction(TypeKind.from(callerMethodType.returnType())); + cb.return_(TypeKind.from(callerMethodType.returnType())); } } else { assert callerMethodType.returnType() == void.class; @@ -411,13 +411,13 @@ private void specialize() { // finally emitCleanup(); if (callingSequence.forDowncall()) { - cb.throwInstruction(); + cb.athrow(); } else { cb.invokestatic(CD_SharedUtils, "handleUncaughtException", MTD_HANDLE_UNCAUGHT_EXCEPTION); if (callerMethodType.returnType() != void.class) { TypeKind returnTypeKind = TypeKind.from(callerMethodType.returnType()); emitConstZero(returnTypeKind); - cb.returnInstruction(returnTypeKind); + cb.return_(returnTypeKind); } else { cb.return_(); } @@ -477,13 +477,13 @@ private void doBindings(List bindings) { } private void emitSetOutput(Class storeType) { - cb.storeInstruction(TypeKind.from(storeType), leafArgSlots[leafArgTypes.size()]); + cb.storeLocal(TypeKind.from(storeType), leafArgSlots[leafArgTypes.size()]); leafArgTypes.add(storeType); } private void emitGetInput() { Class highLevelType = callerMethodType.parameterType(paramIndex); - cb.loadInstruction(TypeKind.from(highLevelType), cb.parameterSlot(paramIndex)); + cb.loadLocal(TypeKind.from(highLevelType), cb.parameterSlot(paramIndex)); if (shouldAcquire(paramIndex)) { cb.dup(); @@ -505,7 +505,7 @@ private void emitAcquireScope() { boolean hasOtherScopes = curScopeLocalIdx != 0; for (int i = 0; i < curScopeLocalIdx; i++) { cb.dup(); // dup for comparison - cb.loadInstruction(ReferenceType, scopeSlots[i]); + cb.loadLocal(ReferenceType, scopeSlots[i]); cb.if_acmpeq(skipAcquire); } @@ -514,7 +514,7 @@ private void emitAcquireScope() { int nextScopeLocal = scopeSlots[curScopeLocalIdx++]; // call acquire first here. So that if it fails, we don't call release cb.invokevirtual(CD_MemorySessionImpl, "acquire0", MTD_ACQUIRE0); // call acquire on the other - cb.storeInstruction(ReferenceType, nextScopeLocal); // store off one to release later + cb.storeLocal(ReferenceType, nextScopeLocal); // store off one to release later if (hasOtherScopes) { // avoid ASM generating a bunch of nops for the dead code cb.goto_(end); @@ -528,9 +528,9 @@ private void emitAcquireScope() { private void emitReleaseScopes() { for (int scopeLocal : scopeSlots) { - cb.loadInstruction(ReferenceType, scopeLocal); + cb.loadLocal(ReferenceType, scopeLocal); cb.ifThen(Opcode.IFNONNULL, ifCb -> { - ifCb.loadInstruction(ReferenceType, scopeLocal); + ifCb.loadLocal(ReferenceType, scopeLocal); ifCb.invokevirtual(CD_MemorySessionImpl, "release0", MTD_RELEASE0); }); } @@ -539,18 +539,18 @@ private void emitReleaseScopes() { private void emitSaveReturnValue(Class storeType) { TypeKind typeKind = TypeKind.from(storeType); retValIdx = cb.allocateLocal(typeKind); - cb.storeInstruction(typeKind, retValIdx); + cb.storeLocal(typeKind, retValIdx); } private void emitRestoreReturnValue(Class loadType) { assert retValIdx != -1; - cb.loadInstruction(TypeKind.from(loadType), retValIdx); + cb.loadLocal(TypeKind.from(loadType), retValIdx); pushType(loadType); } private void emitLoadInternalSession() { assert contextIdx != -1; - cb.loadInstruction(ReferenceType, contextIdx); + cb.loadLocal(ReferenceType, contextIdx); cb.checkcast(CD_Arena); cb.invokeinterface(CD_Arena, "scope", MTD_SCOPE); cb.checkcast(CD_MemorySessionImpl); @@ -558,20 +558,20 @@ private void emitLoadInternalSession() { private void emitLoadInternalAllocator() { assert contextIdx != -1; - cb.loadInstruction(ReferenceType, contextIdx); + cb.loadLocal(ReferenceType, contextIdx); } private void emitCloseContext() { assert contextIdx != -1; - cb.loadInstruction(ReferenceType, contextIdx); + cb.loadLocal(ReferenceType, contextIdx); cb.checkcast(CD_Arena); cb.invokeinterface(CD_Arena, "close", MTD_CLOSE); } private void emitBoxAddress(BoxAddress boxAddress) { popType(long.class); - cb.constantInstruction(boxAddress.size()); - cb.constantInstruction(boxAddress.align()); + cb.loadConstant(boxAddress.size()); + cb.loadConstant(boxAddress.align()); if (needsSession()) { emitLoadInternalSession(); cb.invokestatic(CD_Utils, "longToAddress", MTD_LONG_TO_ADDRESS_SCOPE); @@ -584,7 +584,7 @@ private void emitBoxAddress(BoxAddress boxAddress) { private void emitAllocBuffer(Allocate binding) { if (callingSequence.forDowncall()) { assert returnAllocatorIdx != -1; - cb.loadInstruction(ReferenceType, returnAllocatorIdx); + cb.loadLocal(ReferenceType, returnAllocatorIdx); } else { emitLoadInternalAllocator(); } @@ -603,11 +603,11 @@ private void emitBufferStore(BufferStore bufferStore) { if (SharedUtils.isPowerOfTwo(byteWidth)) { int valueIdx = cb.allocateLocal(storeTypeKind); - cb.storeInstruction(storeTypeKind, valueIdx); + cb.storeLocal(storeTypeKind, valueIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType); - cb.constantInstruction(offset); - cb.loadInstruction(storeTypeKind, valueIdx); + cb.loadConstant(offset); + cb.loadLocal(storeTypeKind, valueIdx); MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType)); cb.invokeinterface(CD_MemorySegment, "set", descriptor); } else { @@ -618,9 +618,9 @@ private void emitBufferStore(BufferStore bufferStore) { assert storeType == long.class; // chunking only for int and long } int longValueIdx = cb.allocateLocal(LongType); - cb.storeInstruction(LongType, longValueIdx); + cb.storeLocal(LongType, longValueIdx); int writeAddrIdx = cb.allocateLocal(ReferenceType); - cb.storeInstruction(ReferenceType, writeAddrIdx); + cb.storeLocal(ReferenceType, writeAddrIdx); int remaining = byteWidth; int chunkOffset = 0; @@ -647,25 +647,25 @@ private void emitBufferStore(BufferStore bufferStore) { //int writeChunk = (int) (((0xFFFF_FFFFL << shiftAmount) & longValue) >>> shiftAmount); int shiftAmount = chunkOffset * Byte.SIZE; mask = mask << shiftAmount; - cb.loadInstruction(LongType, longValueIdx); - cb.constantInstruction(mask); + cb.loadLocal(LongType, longValueIdx); + cb.loadConstant(mask); cb.land(); if (shiftAmount != 0) { - cb.constantInstruction(shiftAmount); + cb.loadConstant(shiftAmount); cb.lushr(); } cb.l2i(); TypeKind chunkStoreTypeKind = TypeKind.from(chunkStoreType); int chunkIdx = cb.allocateLocal(chunkStoreTypeKind); - cb.storeInstruction(chunkStoreTypeKind, chunkIdx); + cb.storeLocal(chunkStoreTypeKind, chunkIdx); // chunk done, now write it //writeAddress.set(JAVA_SHORT_UNALIGNED, offset, writeChunk); - cb.loadInstruction(ReferenceType, writeAddrIdx); + cb.loadLocal(ReferenceType, writeAddrIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkStoreType); long writeOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize); - cb.constantInstruction(writeOffset); - cb.loadInstruction(chunkStoreTypeKind, chunkIdx); + cb.loadConstant(writeOffset); + cb.loadLocal(chunkStoreTypeKind, chunkIdx); MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(chunkStoreType)); cb.invokeinterface(CD_MemorySegment, "set", descriptor); @@ -690,13 +690,13 @@ private void emitVMStore(VMStore vmStore) { emitSaveReturnValue(storeType); } else { int valueIdx = cb.allocateLocal(storeTypeKind); - cb.storeInstruction(storeTypeKind, valueIdx); // store away the stored value, need it later + cb.storeLocal(storeTypeKind, valueIdx); // store away the stored value, need it later assert returnBufferIdx != -1; - cb.loadInstruction(ReferenceType, returnBufferIdx); + cb.loadLocal(ReferenceType, returnBufferIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType); - cb.constantInstruction(retBufOffset); - cb.loadInstruction(storeTypeKind, valueIdx); + cb.loadConstant(retBufOffset); + cb.loadLocal(storeTypeKind, valueIdx); MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType)); cb.invokeinterface(CD_MemorySegment, "set", descriptor); retBufOffset += abi.arch.typeSize(vmStore.storage().type()); @@ -713,9 +713,9 @@ private void emitVMLoad(VMLoad vmLoad) { emitRestoreReturnValue(loadType); } else { assert returnBufferIdx != -1; - cb.loadInstruction(ReferenceType, returnBufferIdx); + cb.loadLocal(ReferenceType, returnBufferIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType); - cb.constantInstruction(retBufOffset); + cb.loadConstant(retBufOffset); MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long); cb.invokeinterface(CD_MemorySegment, "get", descriptor); retBufOffset += abi.arch.typeSize(vmLoad.storage().type()); @@ -735,14 +735,14 @@ private void emitDupBinding() { private void emitShiftLeft(ShiftLeft shiftLeft) { popType(long.class); - cb.constantInstruction(shiftLeft.shiftAmount() * Byte.SIZE); + cb.loadConstant(shiftLeft.shiftAmount() * Byte.SIZE); cb.lshl(); pushType(long.class); } private void emitShiftRight(ShiftRight shiftRight) { popType(long.class); - cb.constantInstruction(shiftRight.shiftAmount() * Byte.SIZE); + cb.loadConstant(shiftRight.shiftAmount() * Byte.SIZE); cb.lushr(); pushType(long.class); } @@ -757,7 +757,7 @@ private void emitCast(Cast cast) { // implement least significant byte non-zero test // select first byte - cb.constantInstruction(0xFF); + cb.loadConstant(0xFF); cb.iand(); // convert to boolean @@ -808,17 +808,17 @@ private void emitBufferLoad(BufferLoad bufferLoad) { if (SharedUtils.isPowerOfTwo(byteWidth)) { ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType); - cb.constantInstruction(offset); + cb.loadConstant(offset); MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long); cb.invokeinterface(CD_MemorySegment, "get", descriptor); } else { // chunked int readAddrIdx = cb.allocateLocal(ReferenceType); - cb.storeInstruction(ReferenceType, readAddrIdx); + cb.storeLocal(ReferenceType, readAddrIdx); - cb.constantInstruction(0L); // result + cb.loadConstant(0L); // result int resultIdx = cb.allocateLocal(LongType); - cb.storeInstruction(LongType, resultIdx); + cb.storeLocal(LongType, resultIdx); int remaining = byteWidth; int chunkOffset = 0; @@ -847,30 +847,30 @@ private void emitBufferLoad(BufferLoad bufferLoad) { throw new IllegalStateException("Unexpected chunk size for chunked write: " + chunkSize); } // read from segment - cb.loadInstruction(ReferenceType, readAddrIdx); + cb.loadLocal(ReferenceType, readAddrIdx); ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkType); MethodTypeDesc descriptor = MethodTypeDesc.of(desc(chunkType), valueLayoutType, CD_long); long readOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize); - cb.constantInstruction(readOffset); + cb.loadConstant(readOffset); cb.invokeinterface(CD_MemorySegment, "get", descriptor); cb.invokestatic(toULongHolder, "toUnsignedLong", toULongDescriptor); // shift to right offset int shiftAmount = chunkOffset * Byte.SIZE; if (shiftAmount != 0) { - cb.constantInstruction(shiftAmount); + cb.loadConstant(shiftAmount); cb.lshl(); } // add to result - cb.loadInstruction(LongType, resultIdx); + cb.loadLocal(LongType, resultIdx); cb.lor(); - cb.storeInstruction(LongType, resultIdx); + cb.storeLocal(LongType, resultIdx); remaining -= chunkSize; chunkOffset += chunkSize; } while (remaining != 0); - cb.loadInstruction(LongType, resultIdx); + cb.loadLocal(LongType, resultIdx); if (loadType == int.class) { cb.l2i(); } else { @@ -890,25 +890,25 @@ private void emitCopyBuffer(Copy copy) { // operand/srcSegment is on the stack // generating a call to: // MemorySegment::copy(MemorySegment srcSegment, long srcOffset, MemorySegment dstSegment, long dstOffset, long bytes) - cb.constantInstruction(0L); + cb.loadConstant(0L); // create the dstSegment by allocating it. Similar to: // context.allocator().allocate(size, alignment) emitLoadInternalAllocator(); emitAllocateCall(size, alignment); cb.dup(); int storeIdx = cb.allocateLocal(ReferenceType); - cb.storeInstruction(ReferenceType, storeIdx); - cb.constantInstruction(0L); - cb.constantInstruction(size); + cb.storeLocal(ReferenceType, storeIdx); + cb.loadConstant(0L); + cb.loadConstant(size); cb.invokestatic(CD_MemorySegment, "copy", MTD_COPY, true); - cb.loadInstruction(ReferenceType, storeIdx); + cb.loadLocal(ReferenceType, storeIdx); pushType(MemorySegment.class); } private void emitAllocateCall(long size, long alignment) { - cb.constantInstruction(size); - cb.constantInstruction(alignment); + cb.loadConstant(size); + cb.loadConstant(alignment); cb.invokeinterface(CD_SegmentAllocator, "allocate", MTD_ALLOCATE); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java index 9e99c90788ca8..cf7e162a42e43 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -470,7 +470,7 @@ private void makeInstrumented() { // stack:[ex] [EW] catchAllHandler.pop(); // stack:[ex] - catchAllHandler.throwInstruction(); + catchAllHandler.athrow(); }); }); codeBuilder.labelBinding(excluded); @@ -562,7 +562,7 @@ void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) { // write begin event getEventConfiguration(blockCodeBuilder); // stack: [EW], [EW], [EventConfiguration] - blockCodeBuilder.constantInstruction(Opcode.LDC2_W, eventTypeId); + blockCodeBuilder.loadConstant(Opcode.LDC2_W, eventTypeId); // stack: [EW], [EW], [EventConfiguration] [long] invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.BEGIN_EVENT.method()); // stack: [EW], [integer] @@ -572,7 +572,7 @@ void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) { blockCodeBuilder.dup(); // stack: [EW], [EW] tk = TypeKind.from(argumentTypes[argIndex++]); - blockCodeBuilder.loadInstruction(tk, slotIndex); + blockCodeBuilder.loadLocal(tk, slotIndex); // stack: [EW], [EW], [long] slotIndex += tk.slotSize(); invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.method()); @@ -583,7 +583,7 @@ void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) { blockCodeBuilder.dup(); // stack: [EW], [EW] tk = TypeKind.from(argumentTypes[argIndex++]); - blockCodeBuilder.loadInstruction(tk, slotIndex); + blockCodeBuilder.loadLocal(tk, slotIndex); // stack: [EW], [EW], [long] slotIndex += tk.slotSize(); invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.method()); @@ -609,7 +609,7 @@ void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) { blockCodeBuilder.dup(); // stack: [EW], [EW] tk = TypeKind.from(argumentTypes[argIndex++]); - blockCodeBuilder.loadInstruction(tk, slotIndex); + blockCodeBuilder.loadLocal(tk, slotIndex); // stack:[EW], [EW], [field] slotIndex += tk.slotSize(); FieldDesc field = fieldDescs.get(fieldIndex); @@ -676,7 +676,7 @@ void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end, Label ex // stack: [EW] [EW] getEventConfiguration(blockCodeBuilder); // stack: [EW] [EW] [EC] - blockCodeBuilder.constantInstruction(Opcode.LDC2_W, eventTypeId); + blockCodeBuilder.loadConstant(Opcode.LDC2_W, eventTypeId); invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.BEGIN_EVENT.method()); // stack: [EW] [int] blockCodeBuilder.ifeq(excluded); @@ -738,7 +738,7 @@ private void updateEnabledMethod(MethodDesc method) { Label nullLabel = codeBuilder.newLabel(); if (guardEventConfiguration) { getEventConfiguration(codeBuilder); - codeBuilder.branchInstruction(Opcode.IFNULL, nullLabel); + codeBuilder.if_null(nullLabel); } getEventConfiguration(codeBuilder); invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_IS_ENABLED); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java index 40693b33d6db2..96b7c76f24ddd 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java @@ -668,7 +668,7 @@ private void genHasSplitPackages(ClassBuilder clb) { "hasSplitPackages", MTD_boolean, ACC_PUBLIC, - cob -> cob.constantInstruction(hasSplitPackages ? 1 : 0) + cob -> cob.loadConstant(hasSplitPackages ? 1 : 0) .ireturn()); } @@ -686,7 +686,7 @@ private void genIncubatorModules(ClassBuilder clb) { "hasIncubatorModules", MTD_boolean, ACC_PUBLIC, - cob -> cob.constantInstruction(hasIncubatorModules ? 1 : 0) + cob -> cob.loadConstant(hasIncubatorModules ? 1 : 0) .ireturn()); } @@ -700,7 +700,7 @@ private void genModuleDescriptorsMethod(ClassBuilder clb) { MTD_ModuleDescriptorArray, ACC_PUBLIC, cob -> { - cob.constantInstruction(moduleInfos.size()) + cob.loadConstant(moduleInfos.size()) .anewarray(CD_MODULE_DESCRIPTOR) .astore(MD_VAR); @@ -764,13 +764,13 @@ private void genModuleDescriptorsMethod(ClassBuilder clb) { MTD_ModuleDescriptorArray, ACC_PUBLIC, cob -> { - cob.constantInstruction(moduleInfos.size()) + cob.loadConstant(moduleInfos.size()) .anewarray(CD_MODULE_DESCRIPTOR) .dup() .astore(MD_VAR); cob.new_(arrayListClassDesc) .dup() - .constantInstruction(moduleInfos.size()) + .loadConstant(moduleInfos.size()) .invokespecial(arrayListClassDesc, INIT_NAME, MethodTypeDesc.of(CD_void, CD_int)) .astore(DEDUP_LIST_VAR); cob.aload(0) @@ -797,7 +797,7 @@ private void genModuleDescriptorsMethod(ClassBuilder clb) { if (curDedupVar > dedupVarStart) { for (int i = dedupVarStart; i < curDedupVar; i++) { cob.aload(DEDUP_LIST_VAR) - .constantInstruction(i - dedupVarStart) + .loadConstant(i - dedupVarStart) .invokevirtual(arrayListClassDesc, "get", MethodTypeDesc.of(CD_Object, CD_int)) .astore(i); } @@ -845,7 +845,7 @@ private void genModuleTargetsMethod(ClassBuilder clb) { MTD_ModuleTargetArray, ACC_PUBLIC, cob -> { - cob.constantInstruction(moduleInfos.size()) + cob.loadConstant(moduleInfos.size()) .anewarray(CD_MODULE_TARGET) .astore(MT_VAR); @@ -868,12 +868,12 @@ private void genModuleTargetsMethod(ClassBuilder clb) { ModuleInfo minfo = moduleInfos.get(index); if (minfo.target() != null) { cob.aload(MT_VAR) - .constantInstruction(index); + .loadConstant(index); // new ModuleTarget(String) cob.new_(CD_MODULE_TARGET) .dup() - .constantInstruction(minfo.target().targetPlatform()) + .loadConstant(minfo.target().targetPlatform()) .invokespecial(CD_MODULE_TARGET, INIT_NAME, MTD_void_String); @@ -896,7 +896,7 @@ private void genModuleHashesMethod(ClassBuilder clb) { MTD_ModuleHashesArray, ACC_PUBLIC, cob -> { - cob.constantInstruction(moduleInfos.size()) + cob.loadConstant(moduleInfos.size()) .anewarray(CD_MODULE_HASHES) .astore(MH_VAR); @@ -923,7 +923,7 @@ private void genModuleResolutionsMethod(ClassBuilder clb) { MTD_ModuleResolutionArray, ACC_PUBLIC, cob -> { - cob.constantInstruction(moduleInfos.size()) + cob.loadConstant(moduleInfos.size()) .anewarray(CD_MODULE_RESOLUTION) .astore(0); @@ -931,10 +931,10 @@ private void genModuleResolutionsMethod(ClassBuilder clb) { ModuleInfo minfo = moduleInfos.get(index); if (minfo.moduleResolution() != null) { cob.aload(0) - .constantInstruction(index) + .loadConstant(index) .new_(CD_MODULE_RESOLUTION) .dup() - .constantInstruction(minfo.moduleResolution().value()) + .loadConstant(minfo.moduleResolution().value()) .invokespecial(CD_MODULE_RESOLUTION, INIT_NAME, MTD_void_int) @@ -1000,7 +1000,7 @@ private void generate(ClassBuilder clb, } // new Map$Entry[size] - cob.constantInstruction(map.size()) + cob.loadConstant(map.size()) .anewarray(CD_Map_Entry); int index = 0; @@ -1009,8 +1009,8 @@ private void generate(ClassBuilder clb, Set s = e.getValue(); cob.dup() - .constantInstruction(index) - .constantInstruction(name); + .loadConstant(index) + .loadConstant(name); // if de-duplicated then load the local, otherwise generate code Integer varIndex = locals.get(s); @@ -1046,13 +1046,13 @@ private void genImmutableSet(CodeBuilder cob, Set set) { // use Set.of(Object[]) when there are more than 2 elements // use Set.of(Object) or Set.of(Object, Object) when fewer if (size > 2) { - cob.constantInstruction(size) + cob.loadConstant(size) .anewarray(CD_String); int i = 0; for (String element : sorted(set)) { cob.dup() - .constantInstruction(i) - .constantInstruction(element) + .loadConstant(i) + .loadConstant(element) .aastore(); i++; } @@ -1062,7 +1062,7 @@ private void genImmutableSet(CodeBuilder cob, Set set) { true); } else { for (String element : sorted(set)) { - cob.constantInstruction(element); + cob.loadConstant(element); } var mtdArgs = new ClassDesc[size]; Arrays.fill(mtdArgs, CD_Object); @@ -1166,7 +1166,7 @@ void build() { void newBuilder() { cob.new_(CD_MODULE_BUILDER) .dup() - .constantInstruction(md.name()) + .loadConstant(md.name()) .invokespecial(CD_MODULE_BUILDER, INIT_NAME, MTD_void_String) @@ -1188,7 +1188,7 @@ void newBuilder() { */ void setModuleBit(String methodName, boolean value) { cob.aload(BUILDER_VAR) - .constantInstruction(value ? 1 : 0) + .loadConstant(value ? 1 : 0) .invokevirtual(CD_MODULE_BUILDER, methodName, MTD_BOOLEAN) @@ -1200,9 +1200,9 @@ void setModuleBit(String methodName, boolean value) { */ void putModuleDescriptor() { cob.aload(MD_VAR) - .constantInstruction(index) + .loadConstant(index) .aload(BUILDER_VAR) - .constantInstruction(md.hashCode()) + .loadConstant(md.hashCode()) .invokevirtual(CD_MODULE_BUILDER, "build", MTD_ModuleDescriptor_int) @@ -1217,7 +1217,7 @@ void putModuleDescriptor() { */ void requires(Set requires) { cob.aload(BUILDER_VAR) - .constantInstruction(requires.size()) + .loadConstant(requires.size()) .anewarray(CD_REQUIRES); int arrayIndex = 0; for (Requires require : sorted(requires)) { @@ -1227,7 +1227,7 @@ void requires(Set requires) { } cob.dup() // arrayref - .constantInstruction(arrayIndex++); + .loadConstant(arrayIndex++); newRequires(require.modifiers(), require.name(), compiledVersion); cob.aastore(); } @@ -1246,9 +1246,9 @@ void requires(Set requires) { void newRequires(Set mods, String name, String compiledVersion) { int varIndex = dedupSetBuilder.indexOfRequiresModifiers(cob, mods); cob.aload(varIndex) - .constantInstruction(name); + .loadConstant(name); if (compiledVersion != null) { - cob.constantInstruction(compiledVersion) + cob.loadConstant(compiledVersion) .invokestatic(CD_MODULE_BUILDER, "newRequires", MTD_REQUIRES_SET_STRING_STRING); @@ -1267,12 +1267,12 @@ void newRequires(Set mods, String name, String compiledVersio */ void exports(Set exports) { cob.aload(BUILDER_VAR) - .constantInstruction(exports.size()) + .loadConstant(exports.size()) .anewarray(CD_EXPORTS); int arrayIndex = 0; for (Exports export : sorted(exports)) { cob.dup() // arrayref - .constantInstruction(arrayIndex++); + .loadConstant(arrayIndex++); newExports(export.modifiers(), export.source(), export.targets()); cob.aastore(); } @@ -1302,14 +1302,14 @@ void newExports(Set ms, String pn, Set targets) { if (!targets.isEmpty()) { int stringSetIndex = dedupSetBuilder.indexOfStringSet(cob, targets); cob.aload(modifiersSetIndex) - .constantInstruction(pn) + .loadConstant(pn) .aload(stringSetIndex) .invokestatic(CD_MODULE_BUILDER, "newExports", MTD_EXPORTS_MODIFIER_SET_STRING_SET); } else { cob.aload(modifiersSetIndex) - .constantInstruction(pn) + .loadConstant(pn) .invokestatic(CD_MODULE_BUILDER, "newExports", MTD_EXPORTS_MODIFIER_SET_STRING); @@ -1324,12 +1324,12 @@ void newExports(Set ms, String pn, Set targets) { */ void opens(Set opens) { cob.aload(BUILDER_VAR) - .constantInstruction(opens.size()) + .loadConstant(opens.size()) .anewarray(CD_OPENS); int arrayIndex = 0; for (Opens open : sorted(opens)) { cob.dup() // arrayref - .constantInstruction(arrayIndex++); + .loadConstant(arrayIndex++); newOpens(open.modifiers(), open.source(), open.targets()); cob.aastore(); } @@ -1359,14 +1359,14 @@ void newOpens(Set ms, String pn, Set targets) { if (!targets.isEmpty()) { int stringSetIndex = dedupSetBuilder.indexOfStringSet(cob, targets); cob.aload(modifiersSetIndex) - .constantInstruction(pn) + .loadConstant(pn) .aload(stringSetIndex) .invokestatic(CD_MODULE_BUILDER, "newOpens", MTD_OPENS_MODIFIER_SET_STRING_SET); } else { cob.aload(modifiersSetIndex) - .constantInstruction(pn) + .loadConstant(pn) .invokestatic(CD_MODULE_BUILDER, "newOpens", MTD_OPENS_MODIFIER_SET_STRING); @@ -1394,12 +1394,12 @@ void uses(Set uses) { */ void provides(Collection provides) { cob.aload(BUILDER_VAR) - .constantInstruction(provides.size()) + .loadConstant(provides.size()) .anewarray(CD_PROVIDES); int arrayIndex = 0; for (Provides provide : sorted(provides)) { cob.dup() // arrayref - .constantInstruction(arrayIndex++); + .loadConstant(arrayIndex++); newProvides(provide.service(), provide.providers()); cob.aastore(); } @@ -1419,14 +1419,14 @@ void provides(Collection provides) { * Builder.newProvides(service, providers); */ void newProvides(String service, List providers) { - cob.constantInstruction(service) - .constantInstruction(providers.size()) + cob.loadConstant(service) + .loadConstant(providers.size()) .anewarray(CD_String); int arrayIndex = 0; for (String provider : providers) { cob.dup() // arrayref - .constantInstruction(arrayIndex++) - .constantInstruction(provider) + .loadConstant(arrayIndex++) + .loadConstant(provider) .aastore(); } cob.invokestatic(CD_List, @@ -1456,7 +1456,7 @@ void packages(Set packages) { */ void mainClass(String cn) { cob.aload(BUILDER_VAR) - .constantInstruction(cn) + .loadConstant(cn) .invokevirtual(CD_MODULE_BUILDER, "mainClass", MTD_STRING) @@ -1468,7 +1468,7 @@ void mainClass(String cn) { */ void version(Version v) { cob.aload(BUILDER_VAR) - .constantInstruction(v.toString()) + .loadConstant(v.toString()) .invokevirtual(CD_MODULE_BUILDER, "version", MTD_STRING) @@ -1477,7 +1477,7 @@ void version(Version v) { void invokeBuilderMethod(String methodName, String value) { cob.aload(BUILDER_VAR) - .constantInstruction(value) + .loadConstant(value) .invokevirtual(CD_MODULE_BUILDER, methodName, MTD_STRING) @@ -1531,8 +1531,8 @@ void build() { void newModuleHashesBuilder() { cob.new_(MODULE_HASHES_BUILDER) .dup() - .constantInstruction(recordedHashes.algorithm()) - .constantInstruction(((4 * recordedHashes.names().size()) / 3) + 1) + .loadConstant(recordedHashes.algorithm()) + .loadConstant(((4 * recordedHashes.names().size()) / 3) + 1) .invokespecial(MODULE_HASHES_BUILDER, INIT_NAME, MTD_void_String_int) @@ -1547,7 +1547,7 @@ void newModuleHashesBuilder() { */ void pushModuleHashes() { cob.aload(MH_VAR) - .constantInstruction(index) + .loadConstant(index) .aload(BUILDER_VAR) .invokevirtual(MODULE_HASHES_BUILDER, "build", @@ -1560,13 +1560,13 @@ void pushModuleHashes() { */ void hashForModule(String name, byte[] hash) { cob.aload(BUILDER_VAR) - .constantInstruction(name) - .constantInstruction(hash.length) + .loadConstant(name) + .loadConstant(hash.length) .newarray(TypeKind.ByteType); for (int i = 0; i < hash.length; i++) { cob.dup() // arrayref - .constantInstruction(i) - .constantInstruction((int)hash[i]) + .loadConstant(i) + .loadConstant((int)hash[i]) .bastore(); } @@ -1729,7 +1729,7 @@ final void increment() { * to the element onto the stack. */ void visitElement(T element, CodeBuilder cob) { - cob.constantInstruction((ConstantDesc)element); + cob.loadConstant((ConstantDesc)element); } /* @@ -1772,12 +1772,12 @@ private void generateSetOf(CodeBuilder cob, int index) { true); } else { // call Set.of(E... elements) - cob.constantInstruction(elements.size()) + cob.loadConstant(elements.size()) .anewarray(CD_String); int arrayIndex = 0; for (T t : sorted(elements)) { cob.dup() // arrayref - .constantInstruction(arrayIndex); + .loadConstant(arrayIndex); visitElement(t, cob); // value cob.aastore(); arrayIndex++; @@ -1876,14 +1876,14 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules, MTD_StringArray, ACC_STATIC, cob -> { - cob.constantInstruction(map.size()); + cob.loadConstant(map.size()); cob.anewarray(CD_String); int index = 0; for (Map.Entry entry : systemModulesMap) { cob.dup() // arrayref - .constantInstruction(index) - .constantInstruction(entry.getKey()) + .loadConstant(index) + .loadConstant(entry.getKey()) .aastore(); index++; } @@ -1897,14 +1897,14 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules, MTD_StringArray, ACC_STATIC, cob -> { - cob.constantInstruction(map.size()) + cob.loadConstant(map.size()) .anewarray(CD_String); int index = 0; for (Map.Entry entry : systemModulesMap) { cob.dup() // arrayref - .constantInstruction(index) - .constantInstruction(entry.getValue().replace('/', '.')) + .loadConstant(index) + .loadConstant(entry.getValue().replace('/', '.')) .aastore(); index++; } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java index 42b6357866f57..973fa4d126851 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/VersionPropsPlugin.java @@ -143,7 +143,7 @@ public void accept(CodeBuilder cob, CodeElement coe) { // forget about it pendingLDC = null; // and add an ldc for the new value - cob.constantInstruction(value); + cob.loadConstant(value); redefined = true; } else { flushPendingLDC(cob); diff --git a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java index 371500497f945..53252aaf5586c 100644 --- a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java +++ b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java @@ -245,7 +245,7 @@ static byte[] addMethod(byte[] classBytes, var cf = ClassFile.of(); return cf.transform(cf.parse(classBytes), ClassTransform.endHandler(clb -> { clb.withMethodBody(name, desc, ACC_PRIVATE, cob -> { - cob.constantInstruction(name + " should not be invoked"); + cob.loadConstant(name + " should not be invoked"); cob.invokestatic(Assert.class.describeConstable().orElseThrow(), "fail", MethodTypeDesc.of(CD_void, CD_String)); cob.return_(); diff --git a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java index 31397ad60cb0e..4ff15aa84d48e 100644 --- a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java @@ -270,13 +270,13 @@ public void atEnd(ClassBuilder builder) { cob.bipush(i); cob.new_(CD_ObjectStreamField); cob.dup(); - cob.constantInstruction(osf.getName()); + cob.loadConstant(osf.getName()); if (osf.isPrimitive()) { - cob.constantInstruction(DynamicConstantDesc.ofNamed( + cob.loadConstant(DynamicConstantDesc.ofNamed( ConstantDescs.BSM_PRIMITIVE_CLASS, String.valueOf(osf.getTypeCode()), CD_Class)); } else { // Currently Classfile API cannot encode primitive classdescs as condy - cob.constantInstruction(osf.getType().describeConstable().orElseThrow()); + cob.loadConstant(osf.getType().describeConstable().orElseThrow()); } cob.invokespecial(CD_ObjectStreamField, INIT_NAME, MethodTypeDesc.of(CD_void, CD_String, CD_Class)); cob.aastore(); diff --git a/test/jdk/java/lang/instrument/NativeMethodPrefixAgent.java b/test/jdk/java/lang/instrument/NativeMethodPrefixAgent.java index e8b5bbe7dd9fd..daf36c2c0b598 100644 --- a/test/jdk/java/lang/instrument/NativeMethodPrefixAgent.java +++ b/test/jdk/java/lang/instrument/NativeMethodPrefixAgent.java @@ -83,8 +83,8 @@ static class Tr implements ClassFileTransformer { byte[] newcf = Instrumentor.instrFor(classfileBuffer) .addNativeMethodTrackingInjection( "wrapped_" + trname + "_", (name, h) -> { - h.constantInstruction(name); - h.constantInstruction(transformId); + h.loadConstant(name); + h.loadConstant(transformId); h.invokestatic( CD_StringIdCallbackReporter, "tracker", diff --git a/test/jdk/java/lang/instrument/RetransformAgent.java b/test/jdk/java/lang/instrument/RetransformAgent.java index f5eadabad16ad..89300a43a7dd7 100644 --- a/test/jdk/java/lang/instrument/RetransformAgent.java +++ b/test/jdk/java/lang/instrument/RetransformAgent.java @@ -91,7 +91,7 @@ public byte[] transform(Module module, .addMethodEntryInjection( nname, cb -> { - cb.constantInstruction(fixedIndex); + cb.loadConstant(fixedIndex); cb.invokestatic( CD_RetransformAgent, "callTracker", MTD_void_int); diff --git a/test/jdk/java/lang/instrument/asmlib/Instrumentor.java b/test/jdk/java/lang/instrument/asmlib/Instrumentor.java index ed5e219dd4dee..29f2740a874cf 100644 --- a/test/jdk/java/lang/instrument/asmlib/Instrumentor.java +++ b/test/jdk/java/lang/instrument/asmlib/Instrumentor.java @@ -122,13 +122,13 @@ public void atEnd(MethodBuilder mb) { // load method parameters for (int i = 0; i < mt.parameterCount(); i++) { TypeKind kind = TypeKind.from(mt.parameterType(i)); - cb.loadInstruction(kind, ptr); + cb.loadLocal(kind, ptr); ptr += kind.slotSize(); } - cb.invokeInstruction(isStatic ? Opcode.INVOKESTATIC : Opcode.INVOKESPECIAL, + cb.invoke(isStatic ? Opcode.INVOKESTATIC : Opcode.INVOKESPECIAL, model.thisClass().asSymbol(), newName, mt, false); - cb.returnInstruction(TypeKind.from(mt.returnType())); + cb.return_(TypeKind.from(mt.returnType())); })); } })); diff --git a/test/jdk/java/lang/invoke/MethodHandleProxies/WrapperHiddenClassTest.java b/test/jdk/java/lang/invoke/MethodHandleProxies/WrapperHiddenClassTest.java index 435f59fe755c4..3e1f0f41d6f85 100644 --- a/test/jdk/java/lang/invoke/MethodHandleProxies/WrapperHiddenClassTest.java +++ b/test/jdk/java/lang/invoke/MethodHandleProxies/WrapperHiddenClassTest.java @@ -95,7 +95,7 @@ private Comparator createHostileInstance() throws Throwable { // clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> { - cob.constantInstruction(CD_Comparator); + cob.loadConstant(CD_Comparator); cob.putstatic(CD_HostileWrapper, TYPE, CD_Class); cob.return_(); }); diff --git a/test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java b/test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java index edcc095c77bcb..af35d0edd03fe 100644 --- a/test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java +++ b/test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java @@ -390,8 +390,8 @@ ClassByteBuilder classData(int accessFlags, Class returnType) { MethodTypeDesc mt = MethodTypeDesc.of(returnDesc); cw = cw.andThen(clb -> { clb.withMethodBody("classData", mt, accessFlags, cob -> { - cob.constantInstruction(DynamicConstantDesc.ofNamed(BSM_CLASS_DATA, DEFAULT_NAME, returnDesc)); - cob.returnInstruction(TypeKind.from(returnType)); + cob.loadConstant(DynamicConstantDesc.ofNamed(BSM_CLASS_DATA, DEFAULT_NAME, returnDesc)); + cob.return_(TypeKind.from(returnType)); }); }); return this; @@ -405,8 +405,8 @@ ClassByteBuilder classDataAt(int accessFlags, Class returnType, int index) { MethodTypeDesc mt = MethodTypeDesc.of(returnDesc); cw = cw.andThen(clb -> { clb.withMethodBody("classData", mt, accessFlags, cob -> { - cob.constantInstruction(DynamicConstantDesc.ofNamed(BSM_CLASS_DATA_AT, DEFAULT_NAME, returnDesc, index)); - cob.returnInstruction(TypeKind.from(returnType)); + cob.loadConstant(DynamicConstantDesc.ofNamed(BSM_CLASS_DATA_AT, DEFAULT_NAME, returnDesc, index)); + cob.return_(TypeKind.from(returnType)); }); }); return this; @@ -417,8 +417,8 @@ ClassByteBuilder classData(int accessFlags, String name, Class returnType, Dy MethodTypeDesc mt = MethodTypeDesc.of(returnDesc); cw = cw.andThen(clb -> { clb.withMethodBody(name, mt, accessFlags, cob -> { - cob.constantInstruction(dynamic); - cob.returnInstruction(TypeKind.from(returnType)); + cob.loadConstant(dynamic); + cob.return_(TypeKind.from(returnType)); }); }); return this; diff --git a/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java b/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java index 722f0ee4d8f10..4b9a4fa8f8b1c 100644 --- a/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java +++ b/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java @@ -62,7 +62,7 @@ public static MethodHandle invokedynamic(MethodHandles.Lookup l, String name, Me ClassFile.ACC_PUBLIC + ClassFile.ACC_STATIC, methodBuilder -> methodBuilder .withCode(codeBuilder -> { for (int i = 0; i < type.parameterCount(); i++) { - codeBuilder.loadInstruction(TypeKind.from(type.parameterType(i)), i); + codeBuilder.loadLocal(TypeKind.from(type.parameterType(i)), i); } codeBuilder.invokedynamic(DynamicCallSiteDesc.of( MethodHandleDesc.ofMethod( @@ -74,7 +74,7 @@ public static MethodHandle invokedynamic(MethodHandles.Lookup l, String name, Me name, MethodTypeDesc.ofDescriptor(type.toMethodDescriptorString()), boostrapArgs)); - codeBuilder.returnInstruction(TypeKind.from(type.returnType())); + codeBuilder.return_(TypeKind.from(type.returnType())); })); }); Class gc = l.defineClass(byteArray); @@ -116,7 +116,7 @@ public static MethodHandle ldcDynamicConstant(MethodHandles.Lookup l, String nam name, ClassDesc.ofDescriptor(type), bootstrapArgs)) - .returnInstruction(TypeKind.fromDescriptor(type)))); + .return_(TypeKind.fromDescriptor(type)))); }); Class gc = l.defineClass(bytes); return l.findStatic(gc, "m", fromMethodDescriptorString(methodType, l.lookupClass().getClassLoader())); diff --git a/test/jdk/java/lang/invoke/condy/CondyNestedTest.java b/test/jdk/java/lang/invoke/condy/CondyNestedTest.java index 53275905abb96..2cdbff4ffdd1c 100644 --- a/test/jdk/java/lang/invoke/condy/CondyNestedTest.java +++ b/test/jdk/java/lang/invoke/condy/CondyNestedTest.java @@ -138,7 +138,7 @@ public class CondyNestedTest { // .withCode(codeBuilder -> { // codeBuilder // .aload(2) -// .instanceof_(ConstantDescs.CD_MethodType) +// .instanceOf(ConstantDescs.CD_MethodType) // .iconst_0(); // Label condy = codeBuilder.newLabel(); // codeBuilder diff --git a/test/jdk/java/lang/invoke/lookup/SpecialStatic.java b/test/jdk/java/lang/invoke/lookup/SpecialStatic.java index 59db5d29788a4..4a44a898a770b 100644 --- a/test/jdk/java/lang/invoke/lookup/SpecialStatic.java +++ b/test/jdk/java/lang/invoke/lookup/SpecialStatic.java @@ -164,7 +164,7 @@ public static byte[] dumpT3() { }); clb.withMethodBody("getMethodHandle", MethodTypeDesc.of(CD_MethodHandle), ACC_PUBLIC | ACC_STATIC, cob -> { - cob.constantInstruction(MethodHandleDesc.ofMethod(SPECIAL, CD_T1, METHOD_NAME, MTD_int)); + cob.loadConstant(MethodHandleDesc.ofMethod(SPECIAL, CD_T1, METHOD_NAME, MTD_int)); cob.areturn(); }); clb.withMethodBody("getLookup", MTD_Lookup, diff --git a/test/jdk/java/lang/reflect/Method/invoke/TestPrivateInterfaceMethodReflect.java b/test/jdk/java/lang/reflect/Method/invoke/TestPrivateInterfaceMethodReflect.java index 17f9c6665c125..2b19189ceed41 100644 --- a/test/jdk/java/lang/reflect/Method/invoke/TestPrivateInterfaceMethodReflect.java +++ b/test/jdk/java/lang/reflect/Method/invoke/TestPrivateInterfaceMethodReflect.java @@ -68,7 +68,7 @@ private byte[] loadClassData(String name) { clb.withFlags(AccessFlag.ABSTRACT, AccessFlag.INTERFACE, AccessFlag.PUBLIC); clb.withSuperclass(CD_Object); clb.withMethodBody("privInstance", MethodTypeDesc.of(CD_int), ACC_PRIVATE, cob -> { - cob.constantInstruction(EXPECTED); + cob.loadConstant(EXPECTED); cob.ireturn(); }); }); diff --git a/test/jdk/jdk/classfile/AdaptCodeTest.java b/test/jdk/jdk/classfile/AdaptCodeTest.java index 2fd9fcb2c9589..2a75cd7e02069 100644 --- a/test/jdk/jdk/classfile/AdaptCodeTest.java +++ b/test/jdk/jdk/classfile/AdaptCodeTest.java @@ -95,7 +95,7 @@ void testSevenOfThirteenIterator() throws Exception { if ((val instanceof Integer) && ((Integer) val) == 13) { val = 7; } - codeB.constantInstruction(i.opcode(), val); + codeB.loadConstant(i.opcode(), val); } default -> codeB.with(codeE); } diff --git a/test/jdk/jdk/classfile/BSMTest.java b/test/jdk/jdk/classfile/BSMTest.java index 79ecfb2f53e68..927549f021069 100644 --- a/test/jdk/jdk/classfile/BSMTest.java +++ b/test/jdk/jdk/classfile/BSMTest.java @@ -78,7 +78,7 @@ void testSevenOfThirteenIterator() throws Exception { BootstrapMethodEntry bme = cpb.bsmEntry(methodHandleEntry, staticArgs); ConstantDynamicEntry cde = cpb.constantDynamicEntry(bme, cpb.nameAndTypeEntry("name", CD_String)); - codeB.constantInstruction(Opcode.LDC, cde.constantValue()); + codeB.ldc(cde.constantValue()); } default -> codeB.with(codeE); } diff --git a/test/jdk/jdk/classfile/BuilderBlockTest.java b/test/jdk/jdk/classfile/BuilderBlockTest.java index c75869f740fa1..c8e13b79f7280 100644 --- a/test/jdk/jdk/classfile/BuilderBlockTest.java +++ b/test/jdk/jdk/classfile/BuilderBlockTest.java @@ -64,7 +64,7 @@ void testStartEnd() throws Exception { mb -> mb.withCode(xb -> { startEnd[0] = xb.startLabel(); startEnd[1] = xb.endLabel(); - xb.returnInstruction(TypeKind.VoidType); + xb.return_(); assertEquals(((LabelImpl) startEnd[0]).getBCI(), 0); assertEquals(((LabelImpl) startEnd[1]).getBCI(), -1); })); @@ -83,13 +83,13 @@ void testStartEndBlock() throws Exception { mb -> mb.withCode(xb -> { startEnd[0] = xb.startLabel(); startEnd[1] = xb.endLabel(); - xb.nopInstruction(); + xb.nop(); xb.block(xxb -> { startEnd[2] = xxb.startLabel(); startEnd[3] = xxb.endLabel(); - xxb.nopInstruction(); + xxb.nop(); }); - xb.returnInstruction(TypeKind.VoidType); + xb.return_(); })); }); @@ -106,9 +106,9 @@ void testIfThenReturn() throws Exception { cb.withMethod("foo", MethodTypeDesc.of(CD_int, CD_int), AccessFlags.ofMethod(AccessFlag.PUBLIC, AccessFlag.STATIC).flagsMask(), mb -> mb.withCode(xb -> xb.iload(0) - .ifThen(xxb -> xxb.iconst_1().returnInstruction(TypeKind.IntType)) + .ifThen(xxb -> xxb.iconst_1().ireturn()) .iconst_2() - .returnInstruction(TypeKind.IntType))); + .ireturn())); }); Method fooMethod = new ByteArrayClassLoader(BuilderBlockTest.class.getClassLoader(), "Foo", bytes) @@ -125,8 +125,8 @@ void testIfThenElseReturn() throws Exception { cb.withMethod("foo", MethodTypeDesc.of(CD_int, CD_int), AccessFlags.ofMethod(AccessFlag.PUBLIC, AccessFlag.STATIC).flagsMask(), mb -> mb.withCode(xb -> xb.iload(0) - .ifThenElse(xxb -> xxb.iconst_1().returnInstruction(TypeKind.IntType), - xxb -> xxb.iconst_2().returnInstruction(TypeKind.IntType)))); + .ifThenElse(xxb -> xxb.iconst_1().ireturn(), + xxb -> xxb.iconst_2().ireturn()))); }); Method fooMethod = new ByteArrayClassLoader(BuilderBlockTest.class.getClassLoader(), "Foo", bytes) diff --git a/test/jdk/jdk/classfile/BuilderTryCatchTest.java b/test/jdk/jdk/classfile/BuilderTryCatchTest.java index 89117d4abd15b..666b36e11a796 100644 --- a/test/jdk/jdk/classfile/BuilderTryCatchTest.java +++ b/test/jdk/jdk/classfile/BuilderTryCatchTest.java @@ -66,13 +66,13 @@ void testTryCatchCatchAll() throws Throwable { catchBuilder.catching(CD_IOOBE, tb -> { tb.pop(); - tb.constantInstruction(Opcode.LDC, "IndexOutOfBoundsException"); - tb.returnInstruction(TypeKind.ReferenceType); + tb.ldc("IndexOutOfBoundsException"); + tb.areturn(); }).catchingAll(tb -> { tb.pop(); - tb.constantInstruction(Opcode.LDC, "any"); - tb.returnInstruction(TypeKind.ReferenceType); + tb.ldc("any"); + tb.areturn(); }); }); @@ -91,12 +91,12 @@ void testTryCatchCatchAllReachable() throws Throwable { catchBuilder.catching(CD_IOOBE, tb -> { tb.pop(); - tb.constantInstruction(Opcode.LDC, "IndexOutOfBoundsException"); + tb.ldc("IndexOutOfBoundsException"); tb.astore(1); }).catchingAll(tb -> { tb.pop(); - tb.constantInstruction(Opcode.LDC, "any"); + tb.ldc("any"); tb.astore(1); }); }); @@ -132,8 +132,8 @@ void testTryCatch() throws Throwable { catchBuilder.catching(CD_IOOBE, tb -> { tb.pop(); - tb.constantInstruction(Opcode.LDC, "IndexOutOfBoundsException"); - tb.returnInstruction(TypeKind.ReferenceType); + tb.ldc("IndexOutOfBoundsException"); + tb.areturn(); }); }); @@ -153,8 +153,8 @@ void testTryCatchAll() throws Throwable { catchBuilder.catchingAll(tb -> { tb.pop(); - tb.constantInstruction(Opcode.LDC, "any"); - tb.returnInstruction(TypeKind.ReferenceType); + tb.ldc("any"); + tb.areturn(); }); }); @@ -187,7 +187,7 @@ void testEmptyTry() { AccessFlags.ofMethod(AccessFlag.PUBLIC, AccessFlag.STATIC).flagsMask(), mb -> { mb.withCode(xb -> { int stringSlot = xb.allocateLocal(TypeKind.ReferenceType); - xb.constantInstruction("S"); + xb.loadConstant("S"); xb.astore(stringSlot); assertThrows(IllegalArgumentException.class, () -> { @@ -198,14 +198,14 @@ void testEmptyTry() { catchBuilder.catchingAll(tb -> { tb.pop(); - tb.constantInstruction(Opcode.LDC, "any"); - tb.returnInstruction(TypeKind.ReferenceType); + tb.ldc("any"); + tb.areturn(); }); }); }); xb.aload(stringSlot); - xb.returnInstruction(TypeKind.ReferenceType); + xb.areturn(); }); }); }); @@ -218,14 +218,14 @@ void testLocalAllocation() throws Throwable { AccessFlags.ofMethod(AccessFlag.PUBLIC, AccessFlag.STATIC).flagsMask(), mb -> { mb.withCode(xb -> { int stringSlot = xb.allocateLocal(TypeKind.ReferenceType); - xb.constantInstruction("S"); + xb.loadConstant("S"); xb.astore(stringSlot); xb.trying(tb -> { int intSlot = tb.allocateLocal(TypeKind.IntType); tb.aload(0); - tb.constantInstruction(0); + tb.loadConstant(0); // IndexOutOfBoundsException tb.aaload(); // NullPointerException @@ -240,7 +240,7 @@ void testLocalAllocation() throws Throwable { tb.pop(); int doubleSlot = tb.allocateLocal(TypeKind.DoubleType); - tb.constantInstruction(Math.PI); + tb.loadConstant(Math.PI); tb.dstore(doubleSlot); tb.dload(doubleSlot); @@ -250,7 +250,7 @@ void testLocalAllocation() throws Throwable { tb.pop(); int refSlot = tb.allocateLocal(TypeKind.ReferenceType); - tb.constantInstruction("REF"); + tb.loadConstant("REF"); tb.astore(refSlot); tb.aload(refSlot); @@ -260,7 +260,7 @@ void testLocalAllocation() throws Throwable { }); xb.aload(stringSlot); - xb.returnInstruction(TypeKind.ReferenceType); + xb.areturn(); }); }); }); @@ -281,12 +281,12 @@ static byte[] generateTryCatchMethod(Consumer c) { AccessFlags.ofMethod(AccessFlag.PUBLIC, AccessFlag.STATIC).flagsMask(), mb -> { mb.withCode(xb -> { int stringSlot = xb.allocateLocal(TypeKind.ReferenceType); - xb.constantInstruction("S"); + xb.loadConstant("S"); xb.astore(stringSlot); xb.trying(tb -> { tb.aload(0); - tb.constantInstruction(0); + tb.loadConstant(0); // IndexOutOfBoundsException tb.aaload(); // NullPointerException @@ -295,7 +295,7 @@ static byte[] generateTryCatchMethod(Consumer c) { }, c); xb.aload(stringSlot); - xb.returnInstruction(TypeKind.ReferenceType); + xb.areturn(); }); }); }); diff --git a/test/jdk/jdk/classfile/DiscontinuedInstructionsTest.java b/test/jdk/jdk/classfile/DiscontinuedInstructionsTest.java index 8d5b11c28e6f2..be7e425c694dd 100644 --- a/test/jdk/jdk/classfile/DiscontinuedInstructionsTest.java +++ b/test/jdk/jdk/classfile/DiscontinuedInstructionsTest.java @@ -50,9 +50,9 @@ void testJsrAndRetProcessing() throws Exception { .withVersion(JAVA_5_VERSION, 0) .withMethodBody(testMethod, MethodTypeDesc.of(CD_void, cd_list), ACC_PUBLIC | ACC_STATIC, cob -> cob .block(bb -> { - bb.constantInstruction("Hello") + bb.loadConstant("Hello") .with(DiscontinuedInstruction.JsrInstruction.of(bb.breakLabel())); - bb.constantInstruction("World") + bb.loadConstant("World") .with(DiscontinuedInstruction.JsrInstruction.of(Opcode.JSR_W, bb.breakLabel())) .return_(); }) diff --git a/test/jdk/jdk/classfile/LDCTest.java b/test/jdk/jdk/classfile/LDCTest.java index 1ece89675767f..1e7639de4bb99 100644 --- a/test/jdk/jdk/classfile/LDCTest.java +++ b/test/jdk/jdk/classfile/LDCTest.java @@ -49,9 +49,9 @@ void testLDCisConvertedToLDCW() throws Exception { cb.withFlags(AccessFlag.PUBLIC); cb.withVersion(52, 0); cb.withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(TypeKind.ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, "", MTD_VOID, false) - .returnInstruction(VoidType) + .withCode(codeb -> codeb.aload(0) + .invokespecial(CD_Object, "", MTD_VOID, false) + .return_() ) ) @@ -62,15 +62,15 @@ void testLDCisConvertedToLDCW() throws Exception { for (int i = 0; i <= 256/2 + 2; i++) { // two entries per String StringEntry s = cpb.stringEntry("string" + i); } - c0.constantInstruction(LDC, "string0") - .constantInstruction(LDC, "string131") - .constantInstruction(LDC, "string50") - .constantInstruction(-0.0f) - .constantInstruction(-0.0d) + c0.loadConstant(LDC, "string0") + .loadConstant(LDC, "string131") + .loadConstant(LDC, "string50") + .loadConstant(-0.0f) + .loadConstant(-0.0d) //non-LDC test cases - .constantInstruction(0.0f) - .constantInstruction(0.0d) - .returnInstruction(VoidType); + .loadConstant(0.0f) + .loadConstant(0.0d) + .return_(); })); }); diff --git a/test/jdk/jdk/classfile/LowAdaptTest.java b/test/jdk/jdk/classfile/LowAdaptTest.java index 4be4a259ac060..46d033a8676e8 100644 --- a/test/jdk/jdk/classfile/LowAdaptTest.java +++ b/test/jdk/jdk/classfile/LowAdaptTest.java @@ -80,15 +80,15 @@ void testAdapt() throws Exception { cb.withMethod("doit", MethodTypeDesc.of(CD_int, CD_int), AccessFlags.ofMethod(AccessFlag.PUBLIC, AccessFlag.STATIC).flagsMask(), mb -> mb.withCode(xb -> { - xb.invokeDynamicInstruction(indy); - xb.storeInstruction(TypeKind.ReferenceType, 1); - xb.loadInstruction(TypeKind.ReferenceType, 1); - xb.loadInstruction(TypeKind.IntType, 0); - xb.invokeInstruction(Opcode.INVOKEINTERFACE, ClassDesc.of("java.util.function.IntUnaryOperator"), - "applyAsInt", MethodTypeDesc.ofDescriptor("(I)I"), true); - xb.storeInstruction(TypeKind.IntType, 2); - xb.loadInstruction(TypeKind.IntType, 2); - xb.returnInstruction(TypeKind.IntType); + xb.invokedynamic(indy); + xb.astore(1); + xb.aload(1); + xb.iload(0); + xb.invokeinterface(ClassDesc.of("java.util.function.IntUnaryOperator"), + "applyAsInt", MethodTypeDesc.ofDescriptor("(I)I")); + xb.istore(2); + xb.iload(2); + xb.ireturn(); })); }); diff --git a/test/jdk/jdk/classfile/LvtTest.java b/test/jdk/jdk/classfile/LvtTest.java index 1c35b071cc206..35ec8dfcfa358 100644 --- a/test/jdk/jdk/classfile/LvtTest.java +++ b/test/jdk/jdk/classfile/LvtTest.java @@ -122,9 +122,9 @@ void testCreateLoadLVT() throws Exception { cb.withVersion(52, 0); cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(TypeKind.ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, "", MTD_VOID, false) - .returnInstruction(VoidType) + .withCode(codeb -> codeb.aload(0) + .invokespecial(CD_Object, "", MTD_VOID, false) + .return_() ) ) .withMethod("main", MethodTypeDesc.of(CD_void, CD_String.arrayType()), @@ -146,27 +146,27 @@ void testCreateLoadLVT() throws Exception { c0.localVariable(1, i1n, intSig, i1, preEnd) // LV Entries can be added before the labels .localVariable(2, i2, intSig, loopTop, preEnd) .labelBinding(start) - .constantInstruction(ICONST_1, 1) // 0 - .storeInstruction(TypeKind.IntType, 1) // 1 + .iconst_1() // 0 + .istore(1) // 1 .labelBinding(i1) - .constantInstruction(ICONST_1, 1) // 2 - .storeInstruction(TypeKind.IntType, 2) // 3 + .iconst_1() // 2 + .istore(2) // 3 .labelBinding(loopTop) - .loadInstruction(TypeKind.IntType, 2) // 4 - .constantInstruction(BIPUSH, 10) // 5 - .branchInstruction(IF_ICMPGE, loopEnd) // 6 - .loadInstruction(TypeKind.IntType, 1) // 7 - .loadInstruction(TypeKind.IntType, 2) // 8 - .operatorInstruction(IMUL) // 9 - .storeInstruction(TypeKind.IntType, 1) // 10 - .incrementInstruction(2, 1) // 11 - .branchInstruction(GOTO, loopTop) // 12 + .iload(2) // 4 + .bipush(10) // 5 + .if_icmpge(loopEnd) // 6 + .iload(1) // 7 + .iload(2) // 8 + .imul() // 9 + .istore(1) // 10 + .iinc(2, 1) // 11 + .goto_(loopTop) // 12 .labelBinding(loopEnd) - .fieldInstruction(GETSTATIC, CD_System, "out", CD_PrintStream) // 13 - .loadInstruction(TypeKind.IntType, 1) - .invokeInstruction(INVOKEVIRTUAL, CD_PrintStream, "println", MTD_INT_VOID, false) // 15 + .getstatic(CD_System, "out", CD_PrintStream) // 13 + .iload(1) + .invokevirtual(CD_PrintStream, "println", MTD_INT_VOID) // 15 .labelBinding(preEnd) - .returnInstruction(VoidType) + .return_() .labelBinding(end) .localVariable(0, slotName, desc, start, end); // and lv entries can be added after the labels })); @@ -236,9 +236,9 @@ void testCreateLoadLVTT() throws Exception { cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(TypeKind.ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, "", MTD_VOID, false) - .returnInstruction(VoidType) + .withCode(codeb -> codeb.aload(0) + .invokespecial(CD_Object, "", MTD_VOID, false) + .return_() ) ) @@ -263,14 +263,14 @@ void testCreateLoadLVTT() throws Exception { c0.localVariable(2, l, juList, beforeRet, end) .localVariableType(1, u, TU, start, end) .labelBinding(start) - .newObjectInstruction(ClassDesc.of("java.util.ArrayList")) - .stackInstruction(DUP) - .invokeInstruction(INVOKESPECIAL, CD_ArrayList, "", MTD_VOID, false) - .storeInstruction(TypeKind.ReferenceType, 2) + .new_(ClassDesc.of("java.util.ArrayList")) + .dup() + .invokespecial(CD_ArrayList, "", MTD_VOID, false) + .astore(2) .labelBinding(beforeRet) .localVariableType(2, l, sig, beforeRet, end) - .loadInstruction(TypeKind.ReferenceType, 1) - .returnInstruction(TypeKind.ReferenceType) + .aload(1) + .areturn() .labelBinding(end) .localVariable(0, slotName, desc, start, end) .localVariable(1, u, jlObject, start, end); diff --git a/test/jdk/jdk/classfile/OneToOneTest.java b/test/jdk/jdk/classfile/OneToOneTest.java index 5db0489ac3e32..b20d07025e620 100644 --- a/test/jdk/jdk/classfile/OneToOneTest.java +++ b/test/jdk/jdk/classfile/OneToOneTest.java @@ -68,9 +68,9 @@ void testClassWriteRead() { cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(TypeKind.ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, "", MTD_VOID, false) - .returnInstruction(TypeKind.VoidType) + .withCode(codeb -> codeb.aload(0) + .invokespecial(CD_Object, "", MTD_VOID, false) + .return_() ) ) .withMethod("main", MethodTypeDesc.of(CD_void, CD_String.arrayType()), @@ -80,25 +80,25 @@ void testClassWriteRead() { Label loopEnd = c0.newLabel(); int fac = 1; int i = 2; - c0.constantInstruction(ICONST_1, 1) // 0 - .storeInstruction(TypeKind.IntType, fac) // 1 - .constantInstruction(ICONST_1, 1) // 2 - .storeInstruction(TypeKind.IntType, i) // 3 + c0.iconst_1() // 0 + .istore(fac) // 1 + .iconst_1() // 2 + .istore(i) // 3 .labelBinding(loopTop) - .loadInstruction(TypeKind.IntType, i) // 4 - .constantInstruction(BIPUSH, 10) // 5 - .branchInstruction(IF_ICMPGE, loopEnd) // 6 - .loadInstruction(TypeKind.IntType, fac) // 7 - .loadInstruction(TypeKind.IntType, i) // 8 - .operatorInstruction(IMUL) // 9 - .storeInstruction(TypeKind.IntType, fac) // 10 - .incrementInstruction(i, 1) // 11 - .branchInstruction(GOTO, loopTop) // 12 + .iload(i) // 4 + .bipush(10) // 5 + .if_icmpge(loopEnd) // 6 + .iload(fac) // 7 + .iload(i) // 8 + .imul() // 9 + .istore(fac) // 10 + .iinc(i, 1) // 11 + .goto_(loopTop) // 12 .labelBinding(loopEnd) - .fieldInstruction(GETSTATIC, CD_System, "out", CD_PrintStream) // 13 - .loadInstruction(TypeKind.IntType, fac) - .invokeInstruction(INVOKEVIRTUAL, CD_PrintStream, "println", MTD_INT_VOID, false) // 15 - .returnInstruction(TypeKind.VoidType); + .getstatic(CD_System, "out", CD_PrintStream) // 13 + .iload(fac) + .invokevirtual(CD_PrintStream, "println", MTD_INT_VOID) // 15 + .return_(); } ) ); diff --git a/test/jdk/jdk/classfile/OpcodesValidationTest.java b/test/jdk/jdk/classfile/OpcodesValidationTest.java index 085ba631349b5..f44bdfd272559 100644 --- a/test/jdk/jdk/classfile/OpcodesValidationTest.java +++ b/test/jdk/jdk/classfile/OpcodesValidationTest.java @@ -107,7 +107,7 @@ private void testPositiveCase(Opcode opcode, Object constant) { cb -> cb.withFlags(AccessFlag.PUBLIC) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb.withCode( - codeb -> codeb.constantInstruction(opcode, (ConstantDesc) constant)))); + codeb -> codeb.loadConstant(opcode, (ConstantDesc) constant)))); } @@ -124,6 +124,6 @@ private void testNegativeCase(Opcode opcode, Object constant) { cb -> cb.withFlags(AccessFlag.PUBLIC) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb .withCode( - codeb -> codeb.constantInstruction(opcode, (ConstantDesc)constant)))); + codeb -> codeb.loadConstant(opcode, (ConstantDesc)constant)))); } } diff --git a/test/jdk/jdk/classfile/PrimitiveClassConstantTest.java b/test/jdk/jdk/classfile/PrimitiveClassConstantTest.java index 376fe3898269b..89cf43751f82f 100644 --- a/test/jdk/jdk/classfile/PrimitiveClassConstantTest.java +++ b/test/jdk/jdk/classfile/PrimitiveClassConstantTest.java @@ -60,7 +60,7 @@ public void test() throws Throwable { cob.return_(); }); clb.withMethodBody("get", MethodTypeDesc.of(CD_Object), ACC_PUBLIC, cob -> { - cob.constantInstruction(CD_int); + cob.loadConstant(CD_int); cob.areturn(); }); clb.withMethodBody("get2", MethodTypeDesc.of(CD_Class), ACC_PUBLIC, cob -> { diff --git a/test/jdk/jdk/classfile/ShortJumpsFixTest.java b/test/jdk/jdk/classfile/ShortJumpsFixTest.java index 15a777bf713f4..a259795b5519d 100644 --- a/test/jdk/jdk/classfile/ShortJumpsFixTest.java +++ b/test/jdk/jdk/classfile/ShortJumpsFixTest.java @@ -211,9 +211,9 @@ private static ClassModel generateFwd(ClassFile cc, Sample sample, boolean overf for (int i = 0; i < sample.expected.length - 4; i++) //cherry-pick XCONST_ instructions from expected output cob.with(ConstantInstruction.ofIntrinsic(sample.expected[i])); var target = cob.newLabel(); - cob.branchInstruction(sample.jumpCode, target); + cob.branch(sample.jumpCode, target); for (int i = overflow ? 40000 : 1; i > 0; i--) - cob.nopInstruction(); + cob.nop(); cob.labelBinding(target); cob.return_(); })))); @@ -228,12 +228,12 @@ private static ClassModel generateBack(ClassFile cc, Sample sample, boolean over cob.goto_w(fwd); cob.labelBinding(target); for (int i = overflow ? 40000 : 1; i > 0; i--) - cob.nopInstruction(); + cob.nop(); cob.return_(); cob.labelBinding(fwd); for (int i = 3; i < sample.expected.length - 3; i++) //cherry-pick XCONST_ instructions from expected output cob.with(ConstantInstruction.ofIntrinsic(sample.expected[i])); - cob.branchInstruction(sample.jumpCode, target); + cob.branch(sample.jumpCode, target); cob.return_(); })))); } @@ -244,7 +244,7 @@ private static ClassTransform overflow() { (cob, coe) -> { if (coe instanceof NopInstruction) for (int i = 0; i < 40000; i++) //cause label overflow during transform - cob.nopInstruction(); + cob.nop(); cob.with(coe); })); } diff --git a/test/jdk/jdk/classfile/StackMapsTest.java b/test/jdk/jdk/classfile/StackMapsTest.java index 88858ce839481..b3df31291bcf0 100644 --- a/test/jdk/jdk/classfile/StackMapsTest.java +++ b/test/jdk/jdk/classfile/StackMapsTest.java @@ -286,10 +286,10 @@ void testInvalidStack() throws Exception { Label next = cb.newLabel(); cb.iload(0); cb.ifeq(next); - cb.constantInstruction(0.0d); + cb.loadConstant(0.0d); cb.goto_(target); cb.labelBinding(next); - cb.constantInstruction(0); + cb.loadConstant(0); cb.labelBinding(target); cb.pop(); }))); @@ -304,10 +304,10 @@ void testInvalidStack() throws Exception { Label next = cb.newLabel(); cb.iload(0); cb.ifeq(next); - cb.constantInstruction(0.0f); + cb.loadConstant(0.0f); cb.goto_(target); cb.labelBinding(next); - cb.constantInstruction(0); + cb.loadConstant(0); cb.labelBinding(target); cb.pop(); }))); diff --git a/test/jdk/jdk/classfile/StackTrackerTest.java b/test/jdk/jdk/classfile/StackTrackerTest.java index 15a5fe490ba9e..ba47223107941 100644 --- a/test/jdk/jdk/classfile/StackTrackerTest.java +++ b/test/jdk/jdk/classfile/StackTrackerTest.java @@ -58,7 +58,7 @@ void testStackTracker() { assertIterableEquals(stackTracker.stack().get(), List.of(IntType, LongType, ReferenceType, DoubleType, FloatType)); tryb.ifThen(thb -> { assertIterableEquals(stackTracker.stack().get(), List.of(LongType, ReferenceType, DoubleType, FloatType)); - thb.constantInstruction(ClassDesc.of("Phee")); + thb.loadConstant(ClassDesc.of("Phee")); assertIterableEquals(stackTracker.stack().get(), List.of(ReferenceType, LongType, ReferenceType, DoubleType, FloatType)); thb.athrow(); assertFalse(stackTracker.stack().isPresent()); @@ -91,7 +91,7 @@ void testTrackingLost() { var l2 = stcb.newBoundLabel(); //back jump target assertFalse(stackTracker.stack().isPresent()); //no stack assertTrue(stackTracker.maxStackSize().isPresent()); //however still tracking - stcb.constantInstruction(ClassDesc.of("Phee")); //stack instruction on unknown stack cause tracking lost + stcb.loadConstant(ClassDesc.of("Phee")); //stack instruction on unknown stack cause tracking lost assertFalse(stackTracker.stack().isPresent()); //no stack assertFalse(stackTracker.maxStackSize().isPresent()); //because tracking lost stcb.athrow(); diff --git a/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java b/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java index 0c3248466479d..f2debf041e4d1 100644 --- a/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java +++ b/test/jdk/jdk/classfile/TempConstantPoolBuilderTest.java @@ -58,9 +58,9 @@ void addAnno() { cb.withFlags(AccessFlag.PUBLIC) .with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(TypeKind.ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, "", MTD_VOID, false) - .returnInstruction(VoidType) + .withCode(codeb -> codeb.aload(0) + .invokespecial(CD_Object, "", MTD_VOID, false) + .return_() ) .with(RuntimeVisibleAnnotationsAttribute.of(Annotation.of(INTERFACE, AnnotationElement.ofString("foo", "bar")))) diff --git a/test/jdk/jdk/classfile/TransformTests.java b/test/jdk/jdk/classfile/TransformTests.java index 31e75dc2ef22f..13abca0ec5240 100644 --- a/test/jdk/jdk/classfile/TransformTests.java +++ b/test/jdk/jdk/classfile/TransformTests.java @@ -59,7 +59,7 @@ class TransformTests { static CodeTransform swapLdc(String x, String y) { return (b, e) -> { if (e instanceof ConstantInstruction ci && ci.constantValue().equals(x)) { - b.constantInstruction(y); + b.loadConstant(y); } else b.with(e); diff --git a/test/jdk/jdk/classfile/Utf8EntryTest.java b/test/jdk/jdk/classfile/Utf8EntryTest.java index e4cc566499222..8281575576112 100644 --- a/test/jdk/jdk/classfile/Utf8EntryTest.java +++ b/test/jdk/jdk/classfile/Utf8EntryTest.java @@ -196,7 +196,7 @@ static StringEntry obtainStringEntry(ConstantPool cp) { static byte[] createClassFile(String s) { return ClassFile.of().build(ClassDesc.of("C"), clb -> clb.withMethod("m", MethodTypeDesc.of(CD_void), 0, - mb -> mb.withCode(cb -> cb.constantInstruction(s) - .returnInstruction(VoidType)))); + mb -> mb.withCode(cb -> cb.loadConstant(s) + .return_()))); } } diff --git a/test/jdk/jdk/classfile/WriteTest.java b/test/jdk/jdk/classfile/WriteTest.java index afd5c9f5e3499..b4af9135d12bd 100644 --- a/test/jdk/jdk/classfile/WriteTest.java +++ b/test/jdk/jdk/classfile/WriteTest.java @@ -54,10 +54,10 @@ void testJavapWrite() { cb.withFlags(AccessFlag.PUBLIC); cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(TypeKind.ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, "", + .withCode(codeb -> codeb.aload(0) + .invokespecial(CD_Object, "", MethodTypeDesc.ofDescriptor("()V"), false) - .returnInstruction(VoidType) + .return_() ) ) .withMethod("main", MethodTypeDesc.of(CD_void, CD_String.arrayType()), @@ -66,25 +66,25 @@ void testJavapWrite() { Label loopTop = c0.newLabel(); Label loopEnd = c0.newLabel(); c0 - .constantInstruction(ICONST_1, 1) // 0 - .storeInstruction(TypeKind.IntType, 1) // 1 - .constantInstruction(ICONST_1, 1) // 2 - .storeInstruction(TypeKind.IntType, 2) // 3 + .iconst_1() // 0 + .istore(1) // 1 + .iconst_1() // 2 + .istore(2) // 3 .labelBinding(loopTop) - .loadInstruction(TypeKind.IntType, 2) // 4 - .constantInstruction(BIPUSH, 10) // 5 - .branchInstruction(IF_ICMPGE, loopEnd) // 6 - .loadInstruction(TypeKind.IntType, 1) // 7 - .loadInstruction(TypeKind.IntType, 2) // 8 - .operatorInstruction(IMUL) // 9 - .storeInstruction(TypeKind.IntType, 1) // 10 - .incrementInstruction(2, 1) // 11 - .branchInstruction(GOTO, loopTop) // 12 + .iload(2) // 4 + .bipush(10) // 5 + .if_icmpge(loopEnd) // 6 + .iload(1) // 7 + .iload(2) // 8 + .imul() // 9 + .istore(1) // 10 + .iinc(2, 1) // 11 + .goto_(loopTop) // 12 .labelBinding(loopEnd) - .fieldInstruction(GETSTATIC, TestConstants.CD_System, "out", TestConstants.CD_PrintStream) // 13 - .loadInstruction(TypeKind.IntType, 1) - .invokeInstruction(INVOKEVIRTUAL, TestConstants.CD_PrintStream, "println", TestConstants.MTD_INT_VOID, false) // 15 - .returnInstruction(VoidType); + .getstatic(TestConstants.CD_System, "out", TestConstants.CD_PrintStream) // 13 + .iload(1) + .invokevirtual(TestConstants.CD_PrintStream, "println", TestConstants.MTD_INT_VOID) // 15 + .return_(); })); }); } @@ -96,9 +96,9 @@ void testPrimitiveWrite() { cb.withFlags(AccessFlag.PUBLIC) .with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod("", MethodTypeDesc.of(CD_void), 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, "", MTD_VOID, false) - .returnInstruction(VoidType) + .withCode(codeb -> codeb.aload(0) + .invokespecial(CD_Object, "", MTD_VOID, false) + .return_() ) ) .withMethod("main", MethodTypeDesc.of(CD_void, CD_String.arrayType()), @@ -107,25 +107,25 @@ void testPrimitiveWrite() { Label loopTop = c0.newLabel(); Label loopEnd = c0.newLabel(); c0 - .constantInstruction(ICONST_1, 1) // 0 - .storeInstruction(IntType, 1) // 1 - .constantInstruction(ICONST_1, 1) // 2 - .storeInstruction(IntType, 2) // 3 + .iconst_1() // 0 + .istore(1) // 1 + .iconst_1() // 2 + .istore(2) // 3 .labelBinding(loopTop) - .loadInstruction(IntType, 2) // 4 - .constantInstruction(BIPUSH, 10) // 5 - .branchInstruction(IF_ICMPGE, loopEnd) // 6 - .loadInstruction(IntType, 1) // 7 - .loadInstruction(IntType, 2) // 8 - .operatorInstruction(IMUL) // 9 - .storeInstruction(IntType, 1) // 10 - .incrementInstruction(2, 1) // 11 - .branchInstruction(GOTO, loopTop) // 12 + .iload(2) // 4 + .bipush(10) // 5 + .if_icmpge(loopEnd) // 6 + .iload(1) // 7 + .iload(2) // 8 + .imul() // 9 + .istore(1) // 10 + .iinc(2, 1) // 11 + .goto_(loopTop) // 12 .labelBinding(loopEnd) - .fieldInstruction(GETSTATIC, TestConstants.CD_System, "out", TestConstants.CD_PrintStream) // 13 - .loadInstruction(IntType, 1) - .invokeInstruction(INVOKEVIRTUAL, TestConstants.CD_PrintStream, "println", TestConstants.MTD_INT_VOID, false) // 15 - .returnInstruction(VoidType); + .getstatic(TestConstants.CD_System, "out", TestConstants.CD_PrintStream) // 13 + .iload(1) + .invokevirtual(TestConstants.CD_PrintStream, "println", TestConstants.MTD_INT_VOID) // 15 + .return_(); })); }); } diff --git a/test/jdk/jdk/classfile/examples/ExampleGallery.java b/test/jdk/jdk/classfile/examples/ExampleGallery.java index cb155e6f64a14..736725eeebe84 100644 --- a/test/jdk/jdk/classfile/examples/ExampleGallery.java +++ b/test/jdk/jdk/classfile/examples/ExampleGallery.java @@ -251,7 +251,7 @@ public byte[] addInstrumentation(ClassModel cm) { @Override public void accept(CodeBuilder codeB, CodeElement codeE) { if (found) { - codeB.nopInstruction(); + codeB.nop(); found = false; } codeB.with(codeE); @@ -265,7 +265,7 @@ public byte[] addInstrumentationBeforeInvoke(ClassModel cm) { return ClassFile.of().transform(cm, ClassTransform.transformingMethodBodies((codeB, codeE) -> { switch (codeE) { case InvokeInstruction i -> { - codeB.nopInstruction(); + codeB.nop(); codeB.with(codeE); } default -> codeB.with(codeE); @@ -277,7 +277,7 @@ public byte[] replaceIntegerConstant(ClassModel cm) { return ClassFile.of().transform(cm, ClassTransform.transformingMethodBodies((codeB, codeE) -> { switch (codeE) { case ConstantInstruction ci -> { - if (ci.constantValue() instanceof Integer i) codeB.constantInstruction(i + 1); + if (ci.constantValue() instanceof Integer i) codeB.loadConstant(i + 1); else codeB.with(codeE); } default -> codeB.with(codeE); diff --git a/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java b/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java index 828862ef2cc6a..d7d9e9c267f51 100644 --- a/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java +++ b/test/jdk/jdk/classfile/helpers/InstructionModelToCodeBuilder.java @@ -35,53 +35,53 @@ public class InstructionModelToCodeBuilder { public static void toBuilder(CodeElement model, CodeBuilder cb) { switch (model) { case LoadInstruction im -> - cb.loadInstruction(im.typeKind(), im.slot()); + cb.loadLocal(im.typeKind(), im.slot()); case StoreInstruction im -> - cb.storeInstruction(im.typeKind(), im.slot()); + cb.storeLocal(im.typeKind(), im.slot()); case IncrementInstruction im -> - cb.incrementInstruction(im.slot(), im.constant()); + cb.iinc(im.slot(), im.constant()); case BranchInstruction im -> - cb.branchInstruction(im.opcode(), im.target()); + cb.branch(im.opcode(), im.target()); case LookupSwitchInstruction im -> - cb.lookupSwitchInstruction(im.defaultTarget(), im.cases()); + cb.lookupswitch(im.defaultTarget(), im.cases()); case TableSwitchInstruction im -> - cb.tableSwitchInstruction(im.lowValue(), im.highValue(), im.defaultTarget(), im.cases()); + cb.tableswitch(im.lowValue(), im.highValue(), im.defaultTarget(), im.cases()); case ReturnInstruction im -> - cb.returnInstruction(im.typeKind()); + cb.return_(im.typeKind()); case ThrowInstruction im -> - cb.throwInstruction(); + cb.athrow(); case FieldInstruction im -> - cb.fieldInstruction(im.opcode(), im.owner().asSymbol(), im.name().stringValue(), im.typeSymbol()); + cb.fieldAccess(im.opcode(), im.owner().asSymbol(), im.name().stringValue(), im.typeSymbol()); case InvokeInstruction im -> - cb.invokeInstruction(im.opcode(), im.owner().asSymbol(), im.name().stringValue(), im.typeSymbol(), im.isInterface()); + cb.invoke(im.opcode(), im.owner().asSymbol(), im.name().stringValue(), im.typeSymbol(), im.isInterface()); case InvokeDynamicInstruction im -> - cb.invokeDynamicInstruction(DynamicCallSiteDesc.of(im.bootstrapMethod(), im.name().stringValue(), MethodTypeDesc.ofDescriptor(im.type().stringValue()), im.bootstrapArgs().toArray(ConstantDesc[]::new))); + cb.invokedynamic(DynamicCallSiteDesc.of(im.bootstrapMethod(), im.name().stringValue(), MethodTypeDesc.ofDescriptor(im.type().stringValue()), im.bootstrapArgs().toArray(ConstantDesc[]::new))); case NewObjectInstruction im -> - cb.newObjectInstruction(im.className().asSymbol()); + cb.new_(im.className().asSymbol()); case NewPrimitiveArrayInstruction im -> - cb.newPrimitiveArrayInstruction(im.typeKind()); + cb.newarray(im.typeKind()); case NewReferenceArrayInstruction im -> - cb.newReferenceArrayInstruction(im.componentType()); + cb.anewarray(im.componentType()); case NewMultiArrayInstruction im -> - cb.newMultidimensionalArrayInstruction(im.dimensions(), im.arrayType()); + cb.multianewarray(im.arrayType(), im.dimensions()); case TypeCheckInstruction im -> - cb.typeCheckInstruction(im.opcode(), im.type().asSymbol()); + cb.with(TypeCheckInstruction.of(im.opcode(), im.type().asSymbol())); case ArrayLoadInstruction im -> - cb.arrayLoadInstruction(im.typeKind()); + cb.arrayLoad(im.typeKind()); case ArrayStoreInstruction im -> - cb.arrayStoreInstruction(im.typeKind()); + cb.arrayStore(im.typeKind()); case StackInstruction im -> - cb.stackInstruction(im.opcode()); + cb.with(StackInstruction.of(im.opcode())); case ConvertInstruction im -> - cb.convertInstruction(im.fromType(), im.toType()); + cb.conversion(im.fromType(), im.toType()); case OperatorInstruction im -> - cb.operatorInstruction(im.opcode()); + cb.with(OperatorInstruction.of(im.opcode())); case ConstantInstruction im -> - cb.constantInstruction(im.opcode(), im.constantValue()); + cb.loadConstant(im.opcode(), im.constantValue()); case MonitorInstruction im -> - cb.monitorInstruction(im.opcode()); + cb.with(MonitorInstruction.of(im.opcode())); case NopInstruction im -> - cb.nopInstruction(); + cb.nop(); case LabelTarget im -> cb.labelBinding(im.label()); case ExceptionCatch im -> diff --git a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java index 889589393173a..85fac4940665a 100644 --- a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java +++ b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java @@ -271,7 +271,7 @@ public void accept(CodeBuilder cob, CodeElement coe) { case ConstantInstruction i -> { if (i.constantValue() == null) if (pathSwitch.nextBoolean()) cob.aconst_null(); - else cob.constantInstruction(null); + else cob.loadConstant(null); else switch (i.constantValue()) { case Integer iVal -> { if (iVal == 1 && pathSwitch.nextBoolean()) cob.iconst_1(); @@ -282,25 +282,25 @@ else switch (i.constantValue()) { else if (iVal == -1 && pathSwitch.nextBoolean()) cob.iconst_m1(); else if (iVal >= -128 && iVal <= 127 && pathSwitch.nextBoolean()) cob.bipush(iVal); else if (iVal >= -32768 && iVal <= 32767 && pathSwitch.nextBoolean()) cob.sipush(iVal); - else cob.constantInstruction(iVal); + else cob.loadConstant(iVal); } case Long lVal -> { if (lVal == 0 && pathSwitch.nextBoolean()) cob.lconst_0(); else if (lVal == 1 && pathSwitch.nextBoolean()) cob.lconst_1(); - else cob.constantInstruction(lVal); + else cob.loadConstant(lVal); } case Float fVal -> { if (fVal == 0.0 && pathSwitch.nextBoolean()) cob.fconst_0(); else if (fVal == 1.0 && pathSwitch.nextBoolean()) cob.fconst_1(); else if (fVal == 2.0 && pathSwitch.nextBoolean()) cob.fconst_2(); - else cob.constantInstruction(fVal); + else cob.loadConstant(fVal); } case Double dVal -> { if (dVal == 0.0d && pathSwitch.nextBoolean()) cob.dconst_0(); else if (dVal == 1.0d && pathSwitch.nextBoolean()) cob.dconst_1(); - else cob.constantInstruction(dVal); + else cob.loadConstant(dVal); } - default -> cob.constantInstruction(i.constantValue()); + default -> cob.loadConstant(i.constantValue()); } } case ConvertInstruction i -> { @@ -549,13 +549,13 @@ else switch (i.constantValue()) { if (pathSwitch.nextBoolean()) { switch (i.opcode()) { case CHECKCAST -> cob.checkcast(i.type().asSymbol()); - case INSTANCEOF -> cob.instanceof_(i.type().asSymbol()); + case INSTANCEOF -> cob.instanceOf(i.type().asSymbol()); default -> throw new AssertionError("Should not reach here"); } } else { switch (i.opcode()) { case CHECKCAST -> cob.checkcast(i.type()); - case INSTANCEOF -> cob.instanceof_(i.type()); + case INSTANCEOF -> cob.instanceOf(i.type()); default -> throw new AssertionError("Should not reach here"); } } diff --git a/test/jdk/jdk/classfile/helpers/Transforms.java b/test/jdk/jdk/classfile/helpers/Transforms.java index a08c5d2571774..64b4836d50ad5 100644 --- a/test/jdk/jdk/classfile/helpers/Transforms.java +++ b/test/jdk/jdk/classfile/helpers/Transforms.java @@ -217,7 +217,7 @@ public enum InjectNopTransform { cb.transformMethod(mm, (mb, me) -> { if (me instanceof CodeModel xm) { mb.withCode(xb -> { - xb.nopInstruction(); + xb.nop(); xm.forEachElement(new Consumer<>() { @Override public void accept(CodeElement e) { diff --git a/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java b/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java index 44c5c6ab17913..26c1790128140 100644 --- a/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java +++ b/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java @@ -43,7 +43,7 @@ private byte[] convertToInterface(ClassModel classModel) { CodeTransform ct = (b, e) -> { if (e instanceof InvokeInstruction i && i.owner() == classModel.thisClass()) { Opcode opcode = i.opcode() == Opcode.INVOKEVIRTUAL ? Opcode.INVOKEINTERFACE : i.opcode(); - b.invokeInstruction(opcode, i.owner().asSymbol(), + b.invoke(opcode, i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol(), true); } else { b.with(e); diff --git a/test/micro/org/openjdk/bench/java/lang/invoke/LazyStaticColdStart.java b/test/micro/org/openjdk/bench/java/lang/invoke/LazyStaticColdStart.java index 45fc67aea25a2..fb73901adf4b3 100644 --- a/test/micro/org/openjdk/bench/java/lang/invoke/LazyStaticColdStart.java +++ b/test/micro/org/openjdk/bench/java/lang/invoke/LazyStaticColdStart.java @@ -76,7 +76,7 @@ class Holder { static final byte[] classBytes = ClassFile.of().build(describedClass, clb -> { clb.withField("v", CD_long, ACC_STATIC); clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, cob -> { - cob.constantInstruction(100L); + cob.loadConstant(100L); cob.invokestatic(CD_Blackhole, "consumeCPU", MTD_void_long); cob.invokestatic(CD_ThreadLocalRandom, "current", MTD_ThreadLocalRandom); cob.invokevirtual(CD_ThreadLocalRandom, "nextLong", MTD_long); diff --git a/test/micro/org/openjdk/bench/jdk/classfile/RebuildMethodBodies.java b/test/micro/org/openjdk/bench/jdk/classfile/RebuildMethodBodies.java index 4c657b961b191..d5e77c1a2a7e7 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/RebuildMethodBodies.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/RebuildMethodBodies.java @@ -91,11 +91,11 @@ private static void transform(ClassFile cc, ClassModel clm) { cc.transform(clm, ClassTransform.transformingMethodBodies((cob, coe) -> { switch (coe) { case FieldInstruction i -> - cob.fieldInstruction(i.opcode(), i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); + cob.fieldAccess(i.opcode(), i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); case InvokeDynamicInstruction i -> cob.invokedynamic(i.invokedynamic().asSymbol()); case InvokeInstruction i -> - cob.invokeInstruction(i.opcode(), i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol(), i.isInterface()); + cob.invoke(i.opcode(), i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol(), i.isInterface()); case NewMultiArrayInstruction i -> cob.multianewarray(i.arrayType().asSymbol(), i.dimensions()); case NewObjectInstruction i -> @@ -103,7 +103,7 @@ private static void transform(ClassFile cc, ClassModel clm) { case NewReferenceArrayInstruction i -> cob.anewarray(i.componentType().asSymbol()); case TypeCheckInstruction i -> - cob.typeCheckInstruction(i.opcode(), i.type().asSymbol()); + cob.with(TypeCheckInstruction.of(i.opcode(), i.type().asSymbol())); default -> cob.with(coe); } })); diff --git a/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java b/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java index b5582bcf52e5d..def55b5f20c40 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/Transforms.java @@ -203,7 +203,7 @@ public enum InjectNopTransform { cb.transformMethod(mm, (mb, me) -> { if (me instanceof CodeModel xm) { mb.withCode(xb -> { - xb.nopInstruction(); + xb.nop(); xm.forEachElement(new Consumer<>() { @Override public void accept(CodeElement e) { diff --git a/test/micro/org/openjdk/bench/jdk/classfile/Write.java b/test/micro/org/openjdk/bench/jdk/classfile/Write.java index 96aafb6f38e8f..59d07b05927b7 100644 --- a/test/micro/org/openjdk/bench/jdk/classfile/Write.java +++ b/test/micro/org/openjdk/bench/jdk/classfile/Write.java @@ -141,9 +141,9 @@ public byte[] jdkTree() { cb.withVersion(52, 0); cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod(INIT_NAME, MTD_void, 0, mb -> mb - .withCode(codeb -> codeb.loadInstruction(TypeKind.ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, INIT_NAME, MTD_void, false) - .returnInstruction(VoidType) + .withCode(codeb -> codeb.loadLocal(TypeKind.ReferenceType, 0) + .invoke(INVOKESPECIAL, CD_Object, INIT_NAME, MTD_void, false) + .return_(VoidType) ) ); for (int xi = 0; xi < 40; ++xi) { @@ -154,25 +154,25 @@ public byte[] jdkTree() { java.lang.classfile.Label loopEnd = c0.newLabel(); int vFac = 1; int vI = 2; - c0.constantInstruction(ICONST_1, 1) // 0 - .storeInstruction(IntType, vFac) // 1 - .constantInstruction(ICONST_1, 1) // 2 - .storeInstruction(IntType, vI) // 3 + c0.iconst_1() // 0 + .istore(vFac) // 1 + .iconst_1() // 2 + .istore(vI) // 3 .labelBinding(loopTop) - .loadInstruction(IntType, vI) // 4 - .constantInstruction(BIPUSH, 10) // 5 - .branchInstruction(IF_ICMPGE, loopEnd) // 6 - .loadInstruction(IntType, vFac) // 7 - .loadInstruction(IntType, vI) // 8 - .operatorInstruction(IMUL) // 9 - .storeInstruction(IntType, vFac) // 10 - .incrementInstruction(vI, 1) // 11 - .branchInstruction(GOTO, loopTop) // 12 + .iload(vI) // 4 + .bipush(10) // 5 + .if_icmpge(loopEnd) // 6 + .iload(vFac) // 7 + .iload(vI) // 8 + .imul() // 9 + .istore(vFac) // 10 + .iinc(vI, 1) // 11 + .goto_(loopTop) // 12 .labelBinding(loopEnd) - .fieldInstruction(GETSTATIC, CD_System, "out", CD_PrintStream) // 13 - .loadInstruction(IntType, vFac) - .invokeInstruction(INVOKEVIRTUAL, CD_PrintStream, "println", MTD_void_int, false) // 15 - .returnInstruction(VoidType); + .getstatic(CD_System, "out", CD_PrintStream) // 13 + .iload(vFac) + .invokevirtual(CD_PrintStream, "println", MTD_void_int) // 15 + .return_(); })); } }); @@ -189,9 +189,9 @@ public byte[] jdkTreePrimitive() { cb.withVersion(52, 0); cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java")))) .withMethod(INIT_NAME, MTD_void, 0, - mb -> mb.withCode(codeb -> codeb.loadInstruction(ReferenceType, 0) - .invokeInstruction(INVOKESPECIAL, CD_Object, INIT_NAME, MTD_void, false) - .returnInstruction(VoidType) + mb -> mb.withCode(codeb -> codeb.loadLocal(ReferenceType, 0) + .invokespecial(CD_Object, INIT_NAME, MTD_void, false) + .return_() ) ); for (int xi = 0; xi < 40; ++xi) { @@ -202,25 +202,25 @@ public byte[] jdkTreePrimitive() { java.lang.classfile.Label loopEnd = c0.newLabel(); int vFac = 1; int vI = 2; - c0.constantInstruction(ICONST_1, 1) // 0 - .storeInstruction(IntType, 1) // 1 - .constantInstruction(ICONST_1, 1) // 2 - .storeInstruction(IntType, 2) // 3 + c0.iconst_1() // 0 + .istore(1) // 1 + .iconst_1() // 2 + .istore(2) // 3 .labelBinding(loopTop) - .loadInstruction(IntType, 2) // 4 - .constantInstruction(BIPUSH, 10) // 5 - .branchInstruction(IF_ICMPGE, loopEnd) // 6 - .loadInstruction(IntType, 1) // 7 - .loadInstruction(IntType, 2) // 8 - .operatorInstruction(IMUL) // 9 - .storeInstruction(IntType, 1) // 10 - .incrementInstruction(2, 1) // 11 - .branchInstruction(GOTO, loopTop) // 12 + .iload(2) // 4 + .bipush(10) // 5 + .if_icmpge(loopEnd) // 6 + .iload(1) // 7 + .iload(2) // 8 + .imul() // 9 + .istore(1) // 10 + .iinc(2, 1) // 11 + .goto_(loopTop) // 12 .labelBinding(loopEnd) - .fieldInstruction(GETSTATIC, CD_System, "out", CD_PrintStream) // 13 - .loadInstruction(IntType, 1) - .invokeInstruction(INVOKEVIRTUAL, CD_PrintStream, "println", MTD_void_int, false) // 15 - .returnInstruction(VoidType); + .getstatic(CD_System, "out", CD_PrintStream) // 13 + .iload(1) + .invokevirtual(CD_PrintStream, "println", MTD_void_int) // 15 + .return_(); })); } }); From beebce044db97e50a7aea3f83d70e134b2128d0a Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Thu, 2 May 2024 10:21:21 +0000 Subject: [PATCH 043/203] 8331421: ubsan: vmreg.cpp checking error member call on misaligned address Reviewed-by: mbaesken, lucy --- src/hotspot/share/code/vmreg.cpp | 2 +- src/hotspot/share/code/vmreg.hpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/code/vmreg.cpp b/src/hotspot/share/code/vmreg.cpp index 37c3137a10270..ba30c114c6c4b 100644 --- a/src/hotspot/share/code/vmreg.cpp +++ b/src/hotspot/share/code/vmreg.cpp @@ -30,7 +30,7 @@ // used by SA and jvmti, but it's a leaky abstraction: SA and jvmti // "know" that stack0 is an integer masquerading as a pointer. For the // sake of those clients, we preserve this interface. -VMReg VMRegImpl::stack0 = (VMReg)(intptr_t)VMRegImpl::stack_0()->value(); +VMReg VMRegImpl::stack0 = (VMReg)(intptr_t)FIRST_STACK; // VMRegs are 4 bytes wide on all platforms const int VMRegImpl::stack_slot_size = 4; diff --git a/src/hotspot/share/code/vmreg.hpp b/src/hotspot/share/code/vmreg.hpp index 78f52b8d57af5..41e40e9a0178e 100644 --- a/src/hotspot/share/code/vmreg.hpp +++ b/src/hotspot/share/code/vmreg.hpp @@ -54,7 +54,8 @@ friend class OptoReg; // friend class Location; private: enum { - BAD_REG = -1 + BAD_REG = -1, + FIRST_STACK = (ConcreteRegisterImpl::number_of_registers + 7) & ~7 }; // Despite being private, this field is exported to the @@ -71,7 +72,7 @@ friend class OptoReg; public: static constexpr VMReg stack_0() { - return first() + ((ConcreteRegisterImpl::number_of_registers + 7) & ~7); + return first() + FIRST_STACK; } static VMReg as_VMReg(int val, bool bad_ok = false) { From c9255f3f5d3b826b9502e21aa953f0cf9f9abdec Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Thu, 2 May 2024 10:46:29 +0000 Subject: [PATCH 044/203] 8331514: Tests should not use the "Classpath" exception form of the legal header Reviewed-by: dfuchs --- test/jdk/java/lang/ProcessBuilder/JspawnhelperWarnings.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/jdk/java/lang/ProcessBuilder/JspawnhelperWarnings.java b/test/jdk/java/lang/ProcessBuilder/JspawnhelperWarnings.java index daffb4b8c84ff..d9896f16e0056 100644 --- a/test/jdk/java/lang/ProcessBuilder/JspawnhelperWarnings.java +++ b/test/jdk/java/lang/ProcessBuilder/JspawnhelperWarnings.java @@ -4,9 +4,7 @@ * * 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. + * 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 From 2056968777f3c8e3f783a8d52ff8a537c52fa8b1 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Thu, 2 May 2024 10:46:41 +0000 Subject: [PATCH 045/203] 8331513: Tests should not use the "Classpath" exception form of the legal header Reviewed-by: dfuchs --- test/jdk/java/net/httpclient/RedirectTimeoutTest.java | 4 +--- .../java/net/httpclient/http2/ExpectContinueResetTest.java | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/test/jdk/java/net/httpclient/RedirectTimeoutTest.java b/test/jdk/java/net/httpclient/RedirectTimeoutTest.java index e907bcd8228a0..f549898386c92 100644 --- a/test/jdk/java/net/httpclient/RedirectTimeoutTest.java +++ b/test/jdk/java/net/httpclient/RedirectTimeoutTest.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java b/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java index faab08e28626b..b733eb180ebdb 100644 --- a/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java +++ b/test/jdk/java/net/httpclient/http2/ExpectContinueResetTest.java @@ -4,9 +4,7 @@ * * 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. + * 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 From 4a78906db1ebb56a759b43c2dfa909215491d4c0 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Thu, 2 May 2024 11:13:41 +0000 Subject: [PATCH 046/203] 8331537: Test code should not use the "Classpath" exception clause Reviewed-by: jpai --- .../tools/javac/launcher/BasicSourceLauncherTests.java | 4 +--- .../tools/javac/launcher/ModuleSourceLauncherTests.java | 4 +--- .../tools/javac/launcher/MultiFileSourceLauncherTests.java | 4 +--- .../tools/javac/launcher/ProgramDescriptorTests.java | 4 +--- test/langtools/tools/javac/launcher/Run.java | 4 +--- test/langtools/tools/javac/launcher/src/p/q/CLTest.java | 4 +--- 6 files changed, 6 insertions(+), 18 deletions(-) diff --git a/test/langtools/tools/javac/launcher/BasicSourceLauncherTests.java b/test/langtools/tools/javac/launcher/BasicSourceLauncherTests.java index bf44a704b315a..eb000276e142d 100644 --- a/test/langtools/tools/javac/launcher/BasicSourceLauncherTests.java +++ b/test/langtools/tools/javac/launcher/BasicSourceLauncherTests.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/langtools/tools/javac/launcher/ModuleSourceLauncherTests.java b/test/langtools/tools/javac/launcher/ModuleSourceLauncherTests.java index d5103525f571a..908674eb6920a 100644 --- a/test/langtools/tools/javac/launcher/ModuleSourceLauncherTests.java +++ b/test/langtools/tools/javac/launcher/ModuleSourceLauncherTests.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/langtools/tools/javac/launcher/MultiFileSourceLauncherTests.java b/test/langtools/tools/javac/launcher/MultiFileSourceLauncherTests.java index 6148bcaf67c83..dbf6be5b121d0 100644 --- a/test/langtools/tools/javac/launcher/MultiFileSourceLauncherTests.java +++ b/test/langtools/tools/javac/launcher/MultiFileSourceLauncherTests.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/langtools/tools/javac/launcher/ProgramDescriptorTests.java b/test/langtools/tools/javac/launcher/ProgramDescriptorTests.java index 8e0f1cdba90cf..93dd7a4207292 100644 --- a/test/langtools/tools/javac/launcher/ProgramDescriptorTests.java +++ b/test/langtools/tools/javac/launcher/ProgramDescriptorTests.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/langtools/tools/javac/launcher/Run.java b/test/langtools/tools/javac/launcher/Run.java index 4d40d9d6a4cd5..f6fd6abb0e39f 100644 --- a/test/langtools/tools/javac/launcher/Run.java +++ b/test/langtools/tools/javac/launcher/Run.java @@ -4,9 +4,7 @@ * * 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. + * 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 diff --git a/test/langtools/tools/javac/launcher/src/p/q/CLTest.java b/test/langtools/tools/javac/launcher/src/p/q/CLTest.java index e4517e78fc449..9f7e557784726 100644 --- a/test/langtools/tools/javac/launcher/src/p/q/CLTest.java +++ b/test/langtools/tools/javac/launcher/src/p/q/CLTest.java @@ -4,9 +4,7 @@ * * 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. + * 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 From cccc95358d5c38cbcabc7f79abc53674deb1e6d8 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 2 May 2024 11:38:00 +0000 Subject: [PATCH 047/203] 8329258: TailCall should not use frame pointer register for jump target Co-authored-by: Fei Yang Reviewed-by: rcastanedalo, aph --- src/hotspot/cpu/aarch64/aarch64.ad | 28 ++++++++- src/hotspot/cpu/riscv/riscv.ad | 31 +++++++++- src/hotspot/cpu/x86/x86_32.ad | 2 + src/hotspot/cpu/x86/x86_64.ad | 2 + .../TestTailCallInArrayCopyStub.java | 58 +++++++++++++++++++ 5 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/arraycopy/TestTailCallInArrayCopyStub.java diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index bb7f7370c5f92..a82a1b396e0a6 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -694,6 +694,11 @@ reg_class no_special_ptr_reg %{ return _NO_SPECIAL_PTR_REG_mask; %} +// Class for all non_special pointer registers (excluding rfp) +reg_class no_special_no_rfp_ptr_reg %{ + return _NO_SPECIAL_NO_RFP_PTR_REG_mask; +%} + // Class for all float registers reg_class float_reg( V0, @@ -1125,6 +1130,7 @@ extern RegMask _PTR_REG_mask; extern RegMask _NO_SPECIAL_REG32_mask; extern RegMask _NO_SPECIAL_REG_mask; extern RegMask _NO_SPECIAL_PTR_REG_mask; +extern RegMask _NO_SPECIAL_NO_RFP_PTR_REG_mask; class CallStubImpl { @@ -1213,6 +1219,7 @@ source %{ RegMask _NO_SPECIAL_REG32_mask; RegMask _NO_SPECIAL_REG_mask; RegMask _NO_SPECIAL_PTR_REG_mask; + RegMask _NO_SPECIAL_NO_RFP_PTR_REG_mask; void reg_mask_init() { // We derive below RegMask(s) from the ones which are auto-generated from @@ -1249,6 +1256,9 @@ source %{ _NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg())); _NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg())); } + + _NO_SPECIAL_NO_RFP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask; + _NO_SPECIAL_NO_RFP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg())); } // Optimizaton of volatile gets and puts @@ -4690,6 +4700,18 @@ operand iRegPNoSp() interface(REG_INTER); %} +// This operand is not allowed to use rfp even if +// rfp is not used to hold the frame pointer. +operand iRegPNoSpNoRfp() +%{ + constraint(ALLOC_IN_RC(no_special_no_rfp_ptr_reg)); + match(RegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + // Pointer 64 bit Register R0 only operand iRegP_R0() %{ @@ -16087,7 +16109,9 @@ instruct CallLeafNoFPDirect(method meth) // Also known as an 'interprocedural jump'. // Target of jump will eventually return to caller. // TailJump below removes the return address. -instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_ptr) +// Don't use rfp for 'jump_target' because a MachEpilogNode has already been +// emitted just above the TailCall which has reset rfp to the caller state. +instruct TailCalljmpInd(iRegPNoSpNoRfp jump_target, inline_cache_RegP method_ptr) %{ match(TailCall jump_target method_ptr); @@ -16100,7 +16124,7 @@ instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_ptr) ins_pipe(pipe_class_call); %} -instruct TailjmpInd(iRegPNoSp jump_target, iRegP_R0 ex_oop) +instruct TailjmpInd(iRegPNoSpNoRfp jump_target, iRegP_R0 ex_oop) %{ match(TailJump jump_target ex_oop); diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index f9d66f158fb2b..826049f4b8a77 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -649,10 +649,12 @@ reg_class non_allocatable_reg( R23, R23_H // java thread ); +// Class for all non-special integer registers reg_class no_special_reg32 %{ return _NO_SPECIAL_REG32_mask; %} +// Class for all non-special long integer registers reg_class no_special_reg %{ return _NO_SPECIAL_REG_mask; %} @@ -661,10 +663,16 @@ reg_class ptr_reg %{ return _PTR_REG_mask; %} +// Class for all non_special pointer registers reg_class no_special_ptr_reg %{ return _NO_SPECIAL_PTR_REG_mask; %} +// Class for all non_special pointer registers (excluding fp) +reg_class no_special_no_fp_ptr_reg %{ + return _NO_SPECIAL_NO_FP_PTR_REG_mask; +%} + // Class for 64 bit register r10 reg_class r10_reg( R10, R10_H @@ -1037,6 +1045,7 @@ extern RegMask _PTR_REG_mask; extern RegMask _NO_SPECIAL_REG32_mask; extern RegMask _NO_SPECIAL_REG_mask; extern RegMask _NO_SPECIAL_PTR_REG_mask; +extern RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask; class CallStubImpl { @@ -1099,6 +1108,7 @@ RegMask _PTR_REG_mask; RegMask _NO_SPECIAL_REG32_mask; RegMask _NO_SPECIAL_REG_mask; RegMask _NO_SPECIAL_PTR_REG_mask; +RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask; void reg_mask_init() { @@ -1133,6 +1143,9 @@ void reg_mask_init() { _NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); _NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); } + + _NO_SPECIAL_NO_FP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask; + _NO_SPECIAL_NO_FP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); } void PhaseOutput::pd_perform_mach_node_analysis() { @@ -3175,6 +3188,18 @@ operand iRegPNoSp() interface(REG_INTER); %} +// This operand is not allowed to use fp even if +// fp is not used to hold the frame pointer. +operand iRegPNoSpNoFp() +%{ + constraint(ALLOC_IN_RC(no_special_no_fp_ptr_reg)); + match(RegP); + match(iRegPNoSp); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + operand iRegP_R10() %{ constraint(ALLOC_IN_RC(r10_reg)); @@ -10506,7 +10531,9 @@ instruct cmpFastUnlockLightweight(rFlagsReg cr, iRegP object, iRegP_R10 box, iRe // Also known as an 'interprocedural jump'. // Target of jump will eventually return to caller. // TailJump below removes the return address. -instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_oop) +// Don't use fp for 'jump_target' because a MachEpilogNode has already been +// emitted just above the TailCall which has reset fp to the caller state. +instruct TailCalljmpInd(iRegPNoSpNoFp jump_target, inline_cache_RegP method_oop) %{ match(TailCall jump_target method_oop); @@ -10519,7 +10546,7 @@ instruct TailCalljmpInd(iRegPNoSp jump_target, inline_cache_RegP method_oop) ins_pipe(pipe_class_call); %} -instruct TailjmpInd(iRegPNoSp jump_target, iRegP_R10 ex_oop) +instruct TailjmpInd(iRegPNoSpNoFp jump_target, iRegP_R10 ex_oop) %{ match(TailJump jump_target ex_oop); diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 39c09efc49ce3..240e9b10323bd 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -13558,6 +13558,8 @@ instruct Ret() %{ // Also known as an 'interprocedural jump'. // Target of jump will eventually return to caller. // TailJump below removes the return address. +// Don't use ebp for 'jump_target' because a MachEpilogNode has already been +// emitted just above the TailCall which has reset ebp to the caller state. instruct TailCalljmpInd(eRegP_no_EBP jump_target, eBXRegP method_ptr) %{ match(TailCall jump_target method_ptr); ins_cost(300); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 288212d6d13de..5d1c513b10f1a 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -12469,6 +12469,8 @@ instruct Ret() // Also known as an 'interprocedural jump'. // Target of jump will eventually return to caller. // TailJump below removes the return address. +// Don't use rbp for 'jump_target' because a MachEpilogNode has already been +// emitted just above the TailCall which has reset rbp to the caller state. instruct TailCalljmpInd(no_rbp_RegP jump_target, rbx_RegP method_ptr) %{ match(TailCall jump_target method_ptr); diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestTailCallInArrayCopyStub.java b/test/hotspot/jtreg/compiler/arraycopy/TestTailCallInArrayCopyStub.java new file mode 100644 index 0000000000000..19ea82509bc0e --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/TestTailCallInArrayCopyStub.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8329258 + * @summary Test correct execution of the tail call at the end of the arraycopy stub. + * @requires vm.compiler2.enabled + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbatch -XX:-TieredCompilation + * -XX:+StressGCM -XX:+StressLCM + * -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,*::test + * compiler.arraycopy.TestTailCallInArrayCopyStub + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbatch -XX:-TieredCompilation + * -XX:+StressGCM -XX:+StressLCM -XX:StressSeed=75451718 + * -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,*::test + * compiler.arraycopy.TestTailCallInArrayCopyStub + */ + +package compiler.arraycopy; + +public class TestTailCallInArrayCopyStub { + + public static void test(byte[] src, byte[] dst) { + try { + System.arraycopy(src, -1, dst, 0, src.length); + } catch (Exception e) { + // Expected + } + } + + public static void main(String[] args) { + byte[] array = new byte[5]; + for (int i = 0; i < 10_000; ++i) { + test(array, array); + } + } +} From c21672d8c94da6aa613174744ceaa945ca2a474a Mon Sep 17 00:00:00 2001 From: Weibing Xiao Date: Thu, 2 May 2024 11:48:41 +0000 Subject: [PATCH 048/203] 8331077: nroff man page update for jar tool Reviewed-by: jjg, coffeys --- src/jdk.jartool/share/man/jar.1 | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/jdk.jartool/share/man/jar.1 b/src/jdk.jartool/share/man/jar.1 index 26d2c422b2df3..49a028e0f293b 100644 --- a/src/jdk.jartool/share/man/jar.1 +++ b/src/jdk.jartool/share/man/jar.1 @@ -186,7 +186,8 @@ created or a non-modular JAR file being updated. Specifies the location of module dependence for generating the hash. .TP \f[V]\[at]\f[R]\f[I]file\f[R] -Reads \f[V]jar\f[R] options and file names from a text file. +Reads \f[V]jar\f[R] options and file names from a text file as if they +were supplied on the command line .SH OPERATION MODIFIERS VALID ONLY IN CREATE, UPDATE, AND GENERATE-INDEX MODES .PP You can use the following options to customize the actions of the create @@ -330,11 +331,14 @@ class files from the file \f[V]classes.list\f[R]. .PP \f[B]Note:\f[R] .PP -To shorten or simplify the \f[V]jar\f[R] command, you can specify -arguments in a separate text file and pass it to the \f[V]jar\f[R] -command with the at sign (\f[V]\[at]\f[R]) as a prefix. +To shorten or simplify the \f[V]jar\f[R] command, you can provide an arg +file that lists the files to include in the JAR file and pass it to the +\f[V]jar\f[R] command with the at sign (\f[V]\[at]\f[R]) as a prefix. .RS .PP \f[V]jar --create --file my.jar \[at]classes.list\f[R] .RE +.PP +If one or more entries in the arg file cannot be found then the jar +command fails without creating the JAR file. .RE From 257a07d5ca4d876f7f79a5f2598054ca261777ee Mon Sep 17 00:00:00 2001 From: Adam Sotona Date: Thu, 2 May 2024 12:20:07 +0000 Subject: [PATCH 049/203] 8331511: Tests should not use the "Classpath" exception form of the legal header Reviewed-by: jpai --- test/jdk/jdk/classfile/OptionsTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/jdk/jdk/classfile/OptionsTest.java b/test/jdk/jdk/classfile/OptionsTest.java index 4a47c899d8ec2..eecc2d7a3853e 100644 --- a/test/jdk/jdk/classfile/OptionsTest.java +++ b/test/jdk/jdk/classfile/OptionsTest.java @@ -4,9 +4,7 @@ * * 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. + * 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 From 9912abf586f4e0f76591639ae18d5c074edaa2c5 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 2 May 2024 12:20:18 +0000 Subject: [PATCH 050/203] 8331011: [XWayland] TokenStorage fails under Security Manager Reviewed-by: prr, honkar, serb --- .../sun/awt/screencast/TokenStorage.java | 66 +++++++++++++------ 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java index 2f31611cf5f57..3daf9b2a8b8e8 100644 --- a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java +++ b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,8 @@ import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.attribute.PosixFilePermission; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashSet; @@ -58,6 +60,7 @@ * The restore token allows the ScreenCast session to be restored * with previously granted screen access permissions. */ +@SuppressWarnings("removal") final class TokenStorage { private TokenStorage() {} @@ -69,8 +72,24 @@ private TokenStorage() {} private static final Path PROPS_PATH; private static final Path PROP_FILENAME; + private static void doPrivilegedRunnable(Runnable runnable) { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + runnable.run(); + return null; + } + }); + } + static { - PROPS_PATH = setupPath(); + PROPS_PATH = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Path run() { + return setupPath(); + } + }); + if (PROPS_PATH != null) { PROP_FILENAME = PROPS_PATH.getFileName(); if (SCREENCAST_DEBUG) { @@ -192,9 +211,9 @@ public void run() { } if (kind == ENTRY_CREATE) { - setFilePermission(PROPS_PATH); + doPrivilegedRunnable(() -> setFilePermission(PROPS_PATH)); } else if (kind == ENTRY_MODIFY) { - readTokens(PROPS_PATH); + doPrivilegedRunnable(() -> readTokens(PROPS_PATH)); } else if (kind == ENTRY_DELETE) { synchronized (PROPS) { PROPS.clear(); @@ -207,24 +226,31 @@ public void run() { } } + private static WatchService watchService; + private static void setupWatch() { - try { - WatchService watchService = - FileSystems.getDefault().newWatchService(); + doPrivilegedRunnable(() -> { + try { + watchService = + FileSystems.getDefault().newWatchService(); - PROPS_PATH - .getParent() - .register(watchService, - ENTRY_CREATE, - ENTRY_DELETE, - ENTRY_MODIFY); + PROPS_PATH + .getParent() + .register(watchService, + ENTRY_CREATE, + ENTRY_DELETE, + ENTRY_MODIFY); - new WatcherThread(watchService).start(); - } catch (Exception e) { - if (SCREENCAST_DEBUG) { - System.err.printf("Token storage: failed to setup " + - "file watch %s\n", e); + } catch (Exception e) { + if (SCREENCAST_DEBUG) { + System.err.printf("Token storage: failed to setup " + + "file watch %s\n", e); + } } + }); + + if (watchService != null) { + new WatcherThread(watchService).start(); } } @@ -276,7 +302,7 @@ private static void storeTokenFromNative(String oldToken, } if (changed) { - store("save tokens"); + doPrivilegedRunnable(() -> store("save tokens")); } } } @@ -331,7 +357,7 @@ static Set getTokens(List affectedScreenBounds) { .toList(); } - removeMalformedRecords(malformed); + doPrivilegedRunnable(() -> removeMalformedRecords(malformed)); // 1. Try to find exact matches for (TokenItem tokenItem : allTokenItems) { From a024eed7384828643e302f021a253717f53e3778 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 2 May 2024 12:42:59 +0000 Subject: [PATCH 051/203] 8331478: JFR: Rename printHelp methods for jdk.jfr.internal.dcmd classes Reviewed-by: mgronlun --- src/hotspot/share/jfr/dcmd/jfrDcmds.cpp | 10 +++++----- .../classes/jdk/jfr/internal/dcmd/AbstractDCmd.java | 6 +++--- .../share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java | 4 ++-- .../classes/jdk/jfr/internal/dcmd/DCmdConfigure.java | 4 ++-- .../share/classes/jdk/jfr/internal/dcmd/DCmdDump.java | 4 ++-- .../share/classes/jdk/jfr/internal/dcmd/DCmdQuery.java | 4 ++-- .../share/classes/jdk/jfr/internal/dcmd/DCmdStart.java | 4 ++-- .../share/classes/jdk/jfr/internal/dcmd/DCmdStop.java | 4 ++-- .../share/classes/jdk/jfr/internal/dcmd/DCmdView.java | 4 ++-- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 34ccef434d05a..c6944cfa21993 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -221,7 +221,7 @@ void JfrDCmd::execute(DCmdSource source, TRAPS) { return; } if (source == DCmd_Source_Internal && _args != nullptr && strcmp(_args, "help") == 0) { - print_java_help("printStartupHelp"); + print_java_help("getStartupHelp"); vm_exit(0); } @@ -246,17 +246,17 @@ void JfrDCmd::execute(DCmdSource source, TRAPS) { handle_dcmd_result(output(), result.get_oop(), source, THREAD); } -void JfrDCmd::print_java_help(const char* help_method) const { +void JfrDCmd::print_java_help(const char* get_help_method) const { static const char signature[] = "()[Ljava/lang/String;"; JavaThread* thread = JavaThread::current(); JavaValue result(T_OBJECT); - JfrJavaArguments printHelp(&result, javaClass(), help_method, signature, thread); - invoke(printHelp, thread); + JfrJavaArguments java_method(&result, javaClass(), get_help_method, signature, thread); + invoke(java_method, thread); handle_dcmd_result(output(), result.get_oop(), DCmd_Source_MBean, thread); } void JfrDCmd::print_help(const char* name) const { - print_java_help("printHelp"); + print_java_help("getHelp"); } static void initialize_dummy_descriptors(GrowableArray* array) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java index 21a33481fe845..d0b95df848474 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ abstract class AbstractDCmd { private String source; // Called by native - public abstract String[] printHelp(); + public abstract String[] getHelp(); // Called by native. The number of arguments for each command is // reported to the DCmdFramework as a hardcoded number in native. @@ -233,7 +233,7 @@ protected final void printPath(SafePath path) { } protected final void printHelpText() { - for (String line : printHelp()) { + for (String line : getHelp()) { println(line); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java index fdf077fa6c922..998cca461315f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,7 +139,7 @@ private static List sortByEventPath(Collection events) { } @Override - public String[] printHelp() { + public String[] getHelp() { // 0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890 return """ Syntax : JFR.check [options] 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 c67c8a756c71c..8ea49cbd3a52c 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, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,7 +248,7 @@ private void printMaxChunkSize() { } @Override - public String[] printHelp() { + public String[] getHelp() { throw new InternalError("Should not reach here!"); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java index 594e78bdbbf4b..605eb4bc745d7 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -194,7 +194,7 @@ private PlatformRecording newSnapShot(PlatformRecorder recorder, Recording recor } @Override - public String[] printHelp() { + public String[] getHelp() { // 0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890 return """ Syntax : JFR.dump [options] diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdQuery.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdQuery.java index e892477bb45f1..4c296d8a78fa7 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdQuery.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdQuery.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ private String stripQuotes(String text) { } @Override - public String[] printHelp() { + public String[] getHelp() { List lines = new ArrayList<>(); lines.addAll(getOptions().lines().toList()); lines.add(""); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 692ab5784780b..0dbd70801d2ba 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -318,7 +318,7 @@ private boolean hasJDKEvents(Map settings) { return false; } - public String[] printStartupHelp() { + public String[] getStartupHelp() { Map parameters = Map.of( "$SYNTAX", "-XX:StartFlightRecording:[options]", "$SOURCE", "-XX:StartFlightRecording:", @@ -331,7 +331,7 @@ public String[] printStartupHelp() { } @Override - public String[] printHelp() { + public String[] getHelp() { Map parameters = Map.of( "$SYNTAX", "JFR.start [options]", "$SOURCE", "$ jcmd JFR.start ", diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java index baa45396a4b6a..92d2d28b4721a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ protected void execute(ArgumentParser parser) throws DCmdException { } @Override - public String[] printHelp() { + public String[] getHelp() { // 0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890 return """ Syntax : JFR.stop [options] diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdView.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdView.java index cc8a381de0b74..1d6f6e3dd2398 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdView.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,7 @@ protected final boolean isInteractive() { } @Override - public String[] printHelp() { + public String[] getHelp() { List lines = new ArrayList<>(); lines.addAll(getOptions().lines().toList()); lines.add(""); From 389f6fe97c348e28d8573fe4754138d2a0bd6c0d Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 2 May 2024 13:41:29 +0000 Subject: [PATCH 052/203] 8331344: No compiler replay file with CompilerCommand MemLimit Reviewed-by: kvn, asmehra --- .../share/compiler/compilationMemoryStatistic.cpp | 11 +++++++++-- .../share/compiler/compilationMemoryStatistic.hpp | 4 ++++ .../compiler/print/CompileCommandMemLimit.java | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp index ae3c2c75fdbb8..585d55febb8e7 100644 --- a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp +++ b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp @@ -54,7 +54,7 @@ ArenaStatCounter::ArenaStatCounter() : _current(0), _start(0), _peak(0), _na(0), _ra(0), - _limit(0), _hit_limit(false), + _limit(0), _hit_limit(false), _limit_in_process(false), _na_at_peak(0), _ra_at_peak(0), _live_nodes_at_peak(0) {} @@ -483,18 +483,23 @@ void CompilationMemoryStatistic::on_arena_change(ssize_t diff, const Arena* aren CompilerThread* const th = Thread::current()->as_Compiler_thread(); ArenaStatCounter* const arena_stat = th->arena_stat(); + if (arena_stat->limit_in_process()) { + return; // avoid recursion on limit hit + } + bool hit_limit_before = arena_stat->hit_limit(); if (arena_stat->account(diff, (int)arena->get_tag())) { // new peak? // Limit handling if (arena_stat->hit_limit()) { - char name[1024] = ""; bool print = false; bool crash = false; CompilerType ct = compiler_none; + arena_stat->set_limit_in_process(true); // prevent recursive limit hits + // get some more info const CompileTask* const task = th->task(); if (task != nullptr) { @@ -533,6 +538,8 @@ void CompilationMemoryStatistic::on_arena_change(ssize_t diff, const Arena* aren } else { inform_compilation_about_oom(ct); } + + arena_stat->set_limit_in_process(false); } } } diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.hpp b/src/hotspot/share/compiler/compilationMemoryStatistic.hpp index 625875f05f4d6..d7cccad17fda8 100644 --- a/src/hotspot/share/compiler/compilationMemoryStatistic.hpp +++ b/src/hotspot/share/compiler/compilationMemoryStatistic.hpp @@ -50,6 +50,7 @@ class ArenaStatCounter : public CHeapObj { // MemLimit handling size_t _limit; bool _hit_limit; + bool _limit_in_process; // Peak composition: // Size of node arena when total peaked (c2 only) @@ -86,6 +87,9 @@ class ArenaStatCounter : public CHeapObj { size_t limit() const { return _limit; } bool hit_limit() const { return _hit_limit; } + bool limit_in_process() const { return _limit_in_process; } + void set_limit_in_process(bool v) { _limit_in_process = v; } + }; class CompilationMemoryStatistic : public AllStatic { diff --git a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java index d9f9aa3f7d4e4..c3ac0ae9c81b1 100644 --- a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java +++ b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java @@ -58,6 +58,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import java.io.File; import java.util.ArrayList; import java.util.List; @@ -123,6 +124,20 @@ private static void test(String include, String exclude) throws Exception { oa.shouldMatch("# *Internal Error.*"); oa.shouldMatch("# *fatal error: " + ct + " *" + expectedNameIncl + ".*: Hit MemLimit .*limit: 4096.*"); oa.shouldNotMatch(".*" + expectedNameExcl + ".*"); + // Make sure we get a non-zero-sized replay file (JDK-8331314) + oa.shouldContain("# Compiler replay data is saved as:"); + String replayfile = oa.firstMatch("# (\\S+replay_pid\\d+\\.log)", 1); + if (replayfile == null) { + throw new RuntimeException("Found no replay file in output"); + } + File f = new File(replayfile); + if (!f.exists()) { + throw new RuntimeException("Replayfile " + replayfile + " not found"); + } + if (f.length() == 0) { + throw new RuntimeException("Replayfile " + replayfile + " has size 0"); + } + } else { // Should see trace output when methods are compiled oa.shouldHaveExitValue(0) From dd0b6418191c765a92bfd03ec4d4206e0da7ee45 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 2 May 2024 13:48:36 +0000 Subject: [PATCH 053/203] 8330813: Don't call methods from Compressed(Oops|Klass) if the associated mode is inactive Reviewed-by: stefank, asmehra --- .../share/jvmci/jvmciCompilerToVMInit.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp index 8822aed0cbe00..a2ba0f2b3e578 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp @@ -175,10 +175,20 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) { Universe_collectedHeap = Universe::heap(); Universe_base_vtable_size = Universe::base_vtable_size(); - Universe_narrow_oop_base = CompressedOops::base(); - Universe_narrow_oop_shift = CompressedOops::shift(); - Universe_narrow_klass_base = CompressedKlassPointers::base(); - Universe_narrow_klass_shift = CompressedKlassPointers::shift(); + if (UseCompressedOops) { + Universe_narrow_oop_base = CompressedOops::base(); + Universe_narrow_oop_shift = CompressedOops::shift(); + } else { + Universe_narrow_oop_base = nullptr; + Universe_narrow_oop_shift = 0; + } + if (UseCompressedClassPointers) { + Universe_narrow_klass_base = CompressedKlassPointers::base(); + Universe_narrow_klass_shift = CompressedKlassPointers::shift(); + } else { + Universe_narrow_klass_base = nullptr; + Universe_narrow_klass_shift = 0; + } Universe_non_oop_bits = Universe::non_oop_word(); Universe_verify_oop_mask = Universe::verify_oop_mask(); Universe_verify_oop_bits = Universe::verify_oop_bits(); From 553d45b11460a794613651373f34c8379c11729b Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Thu, 2 May 2024 13:53:45 +0000 Subject: [PATCH 054/203] 8323724: Remove potential re-inflation from FastHashCode under LM_LIGHTWEIGHT Reviewed-by: aboldtch, coleenp --- src/hotspot/share/runtime/synchronizer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 356be7cba435d..f8d4b32315665 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1077,9 +1077,11 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { // Inflate the monitor to set the hash. - // An async deflation can race after the inflate() call and before we - // can update the ObjectMonitor's header with the hash value below. - monitor = inflate(current, obj, inflate_cause_hash_code); + // There's no need to inflate if the mark has already got a monitor. + // NOTE: an async deflation can race after we get the monitor and + // before we can update the ObjectMonitor's header with the hash + // value below. + monitor = mark.has_monitor() ? mark.monitor() : inflate(current, obj, inflate_cause_hash_code); // Load ObjectMonitor's header/dmw field and see if it has a hash. mark = monitor->header(); assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); From 8771015d7e3c4349ad58b58150a49217b1ffb902 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Thu, 2 May 2024 14:32:03 +0000 Subject: [PATCH 055/203] 8331027: JDK's ct.sym file packs corrupted module-info classes Reviewed-by: asotona --- .../tools/symbolgenerator/CreateSymbols.java | 4 +- .../javac/platform/VerifyCTSymClassFiles.java | 86 ++++++++++ .../createsymbols/CreateSymbolsTest.java | 8 +- .../createsymbols/CreateSymbolsTestImpl.java | 162 +++++++++++++++--- 4 files changed, 228 insertions(+), 32 deletions(-) create mode 100644 test/langtools/tools/javac/platform/VerifyCTSymClassFiles.java diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 154810e20f2d2..a88eabe01b27e 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -970,7 +970,7 @@ private void addAttributes(ModuleDescription md, } if (header.moduleMainClass != null) { int attrIdx = addString(cp, Attribute.ModuleMainClass); - int targetIdx = addString(cp, header.moduleMainClass); + int targetIdx = addClassName(cp, header.moduleMainClass); attributes.put(Attribute.ModuleMainClass, new ModuleMainClass_attribute(attrIdx, targetIdx)); } diff --git a/test/langtools/tools/javac/platform/VerifyCTSymClassFiles.java b/test/langtools/tools/javac/platform/VerifyCTSymClassFiles.java new file mode 100644 index 0000000000000..c97b15a2b15fe --- /dev/null +++ b/test/langtools/tools/javac/platform/VerifyCTSymClassFiles.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8331027 + * @summary Verify classfile inside ct.sym + * @enablePreview + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.platform + * jdk.compiler/com.sun.tools.javac.util:+open + * @build toolbox.ToolBox VerifyCTSymClassFiles + * @run main VerifyCTSymClassFiles + */ + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.classfile.ClassFile; +import java.lang.classfile.attribute.ModuleMainClassAttribute; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class VerifyCTSymClassFiles { + + public static void main(String... args) throws IOException, URISyntaxException { + VerifyCTSymClassFiles t = new VerifyCTSymClassFiles(); + + t.checkClassFiles(); + } + + void checkClassFiles() throws IOException { + Path ctSym = Paths.get(System.getProperty("java.home"), "lib", "ct.sym"); + + if (!Files.exists(ctSym)) { + //no ct.sym, nothing to check: + return ; + } + try (FileSystem fs = FileSystems.newFileSystem(ctSym)) { + Files.walk(fs.getRootDirectories().iterator().next()) + .filter(p -> Files.isRegularFile(p)) + .forEach(p -> checkClassFile(p)); + } + } + + void checkClassFile(Path p) { + if (!"module-info.sig".equals(p.getFileName().toString())) { + return ; + } + try { + ClassFile.of().parse(p).attributes().forEach(attr -> { + if (attr instanceof ModuleMainClassAttribute mmca) { + mmca.mainClass(); + } + }); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + +} diff --git a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java index c54c21bfc0d7a..7f7400a65b475 100644 --- a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java +++ b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,9 @@ /** * @test - * @bug 8072480 8277106 + * @bug 8072480 8277106 8331027 * @summary Unit test for CreateSymbols + * @enablePreview * @modules java.compiler * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.jvm @@ -101,6 +102,9 @@ void doRun() throws Exception { null, List.of("-d", compileDir.toAbsolutePath().toString(), + "--enable-preview", + "--source", + "" + System.getProperty("java.specification.version"), "-g", "--add-modules", "jdk.jdeps", "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", diff --git a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java index be9137226b428..3a4fd85e54ecb 100644 --- a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java +++ b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java @@ -26,6 +26,11 @@ import java.io.Writer; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.attribute.ModuleAttribute; +import java.lang.classfile.attribute.ModulePackagesAttribute; +import java.lang.constant.PackageDesc; import java.lang.reflect.Method; import java.util.Arrays; import java.util.ArrayList; @@ -58,14 +63,11 @@ 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; +import java.io.UncheckedIOException; +import java.lang.classfile.attribute.ModuleMainClassAttribute; +import java.lang.constant.ClassDesc; +import java.util.Objects; +import java.util.function.Consumer; public class CreateSymbolsTestImpl { @@ -981,14 +983,19 @@ void doTestIncluded(String code, String... includedClasses) throws Exception { } Path prepareVersionedCTSym(String[] code7, String[] code8) throws Exception { + return prepareVersionedCTSym(code7, code8, _ -> {}); + } + + Path prepareVersionedCTSym(String[] code7, String[] code8, + Consumer adjustClassFiles) throws Exception { String testClasses = System.getProperty("test.classes"); Path output = Paths.get(testClasses, "test-data" + i++); deleteRecursively(output); Files.createDirectories(output); Path ver7Jar = output.resolve("7.jar"); - compileAndPack(output, ver7Jar, code7); + compileAndPack(output, ver7Jar, adjustClassFiles, code7); Path ver8Jar = output.resolve("8.jar"); - compileAndPack(output, ver8Jar, code8); + compileAndPack(output, ver8Jar, adjustClassFiles, code8); Path classes = output.resolve("classes.zip"); @@ -1048,7 +1055,112 @@ protected boolean includeEffectiveAccess(ClassList classes, ClassDescription cla new CreateSymbols().createSymbols(null, symbolsDesc.toAbsolutePath().toString(), classDest, 0, "8", "", modules.toString(), modulesList.toString()); } + @Test + void testModuleMainClass() throws Exception { + ClassFile cf = ClassFile.of(); + 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, + classesDir -> { + try { + Path moduleInfo = classesDir.resolve("module-info.class"); + byte[] newClassData = + cf.transform(cf.parse(moduleInfo), + (builder, element) -> { + builder.with(element); + if (element instanceof ModuleAttribute) { + builder.with(ModuleMainClassAttribute.of(ClassDesc.of("main.Main"))); + } + }); + try (OutputStream out = Files.newOutputStream(moduleInfo)) { + out.write(newClassData); + } + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }, + """ + module m { + } + """, + """ + package main; + public class Main {} + """); + + + Path ctSym = output.resolve("ct.sym"); + + deleteRecursively(ctSym); + + CreateSymbols.ALLOW_NON_EXISTING_CLASSES = true; + CreateSymbols.EXTENSION = ".class"; + + 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 modules = ctSym.resolve("modules"); + Path modulesList = ctSym.resolve("modules-list"); + + Files.createDirectories(modules); + try (Writer w = Files.newBufferedWriter(modulesList)) {} + + Path classesZip = output.resolve("classes.zip"); + Path classesDir = output.resolve("classes"); + + new CreateSymbols().createSymbols(null, symbolsDesc.toAbsolutePath().toString(), classesZip.toAbsolutePath().toString(), 0, "9", "", modules.toString(), modulesList.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 moduleInfo = classesDir.resolve("9") + .resolve("m") + .resolve("module-info.class"); + + cf.parse(moduleInfo) + .attributes() + .stream() + .filter(attr -> attr instanceof ModuleMainClassAttribute) + .forEach(attr -> { + String expectedMain = "Lmain/Main;"; + String mainClass = + ((ModuleMainClassAttribute) attr).mainClass() + .asSymbol() + .descriptorString(); + if (!Objects.equals(expectedMain, mainClass)) { + throw new AssertionError("Expected " + expectedMain + " as a main class, " + + "but got: " + mainClass); + } + }); + } + void compileAndPack(Path output, Path outputFile, String... code) throws Exception { + compileAndPack(output, outputFile, _ -> {}, code); + } + + void compileAndPack(Path output, Path outputFile, + Consumer adjustClassFiles, String... code) throws Exception { ToolBox tb = new ToolBox(); Path scratch = output.resolve("temp"); deleteRecursively(scratch); @@ -1065,27 +1177,21 @@ void compileAndPack(Path output, Path outputFile, String... code) throws Excepti 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)); + ClassFile cf = ClassFile.of(); + ClassModel cm = cf.parse(moduleInfo); + byte[] newData = cf.transform(cm, (builder, element) -> { + builder.with(element); + if (element instanceof ModuleAttribute) { + builder.with(ModulePackagesAttribute.ofNames(packages.stream() + .map(pack -> PackageDesc.of(pack)) + .toList())); + } + }); try (OutputStream out = Files.newOutputStream(moduleInfo)) { - new ClassWriter().write(newFile, out); + out.write(newData); } } + adjustClassFiles.accept(scratch); try (Writer out = Files.newBufferedWriter(outputFile)) { for (String classFile : classFiles) { try (InputStream in = Files.newInputStream(scratch.resolve(classFile))) { From 3383ad6397d5a2d8fb232ffd3e29a54e0b37b686 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 2 May 2024 14:41:30 +0000 Subject: [PATCH 056/203] 8331253: 16 bits is not enough for nmethod::_skipped_instructions_size field Reviewed-by: dlong, thartmann --- .../aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp | 2 -- .../cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp | 4 +--- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp | 4 +--- src/hotspot/share/asm/codeBuffer.cpp | 2 ++ src/hotspot/share/asm/codeBuffer.hpp | 7 +++++++ src/hotspot/share/ci/ciMethod.cpp | 5 +++-- src/hotspot/share/code/nmethod.cpp | 15 ++++++++++++++- src/hotspot/share/code/nmethod.hpp | 5 +++-- src/hotspot/share/opto/output.cpp | 14 ++++++++------ 9 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp index 466e77a4460d0..306ff5f8c6e5e 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp @@ -1141,7 +1141,6 @@ class ZSetupArguments { #define __ masm-> void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { - Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); BLOCK_COMMENT("ZLoadBarrierStubC2"); // Stub entry @@ -1160,7 +1159,6 @@ void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, Z } void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const { - Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); BLOCK_COMMENT("ZStoreBarrierStubC2"); // Stub entry diff --git a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp index 5696b78eba858..a54e2844e39f1 100644 --- a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, 2023 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -887,7 +887,6 @@ class ZSetupArguments { #define __ masm-> void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { - Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); __ block_comment("generate_c2_load_barrier_stub (zgc) {"); __ bind(*stub->entry()); @@ -911,7 +910,6 @@ void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, Z } void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const { - Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); __ block_comment("ZStoreBarrierStubC2"); // Stub entry diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index f5f0d6c884198..c30b139c7ef71 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1213,7 +1213,6 @@ class ZSetupArguments { #define __ masm-> void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { - Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); BLOCK_COMMENT("ZLoadBarrierStubC2"); // Stub entry @@ -1233,7 +1232,6 @@ void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, Z } void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const { - Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); BLOCK_COMMENT("ZStoreBarrierStubC2"); // Stub entry diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 4bc33cc89a63b..e818853870e55 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -1012,6 +1012,8 @@ void CodeBuffer::log_section_sizes(const char* name) { } bool CodeBuffer::finalize_stubs() { + // Record size of code before we generate stubs in instructions section + _main_code_size = _insts.size(); if (_finalize_stubs && !pd_finalize_stubs()) { // stub allocation failure return false; diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp index 48476bedfe2f6..5cff78a96cc83 100644 --- a/src/hotspot/share/asm/codeBuffer.hpp +++ b/src/hotspot/share/asm/codeBuffer.hpp @@ -427,6 +427,9 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { address _total_start; // first address of combined memory buffer csize_t _total_size; // size in bytes of combined memory buffer + // Size of code without stubs generated at the end of instructions section + csize_t _main_code_size; + OopRecorder* _oop_recorder; OopRecorder _default_oop_recorder; // override with initialize_oop_recorder @@ -457,6 +460,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { _oop_recorder = nullptr; _overflow_arena = nullptr; _last_insn = nullptr; + _main_code_size = 0; _finalize_stubs = false; _shared_stub_to_interp_requests = nullptr; _shared_trampoline_requests = nullptr; @@ -630,6 +634,9 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { // number of bytes remaining in the insts section csize_t insts_remaining() const { return _insts.remaining(); } + // size of code without stubs in instruction section + csize_t main_code_size() const { return _main_code_size; } + // is a given address in the insts section? (2nd version is end-inclusive) bool insts_contains(address pc) const { return _insts.contains(pc); } bool insts_contains2(address pc) const { return _insts.contains2(pc); } diff --git a/src/hotspot/share/ci/ciMethod.cpp b/src/hotspot/share/ci/ciMethod.cpp index aac2a553cda31..532ac7856b83f 100644 --- a/src/hotspot/share/ci/ciMethod.cpp +++ b/src/hotspot/share/ci/ciMethod.cpp @@ -1126,13 +1126,14 @@ int ciMethod::code_size_for_inlining() { // not highly relevant to an inlined method. So we use the more // specific accessor nmethod::insts_size. // Also some instructions inside the code are excluded from inline -// heuristic (e.g. post call nop instructions; see InlineSkippedInstructionsCounter) +// heuristic (e.g. post call nop instructions and GC barriers; +// see InlineSkippedInstructionsCounter). int ciMethod::inline_instructions_size() { if (_inline_instructions_size == -1) { GUARDED_VM_ENTRY( nmethod* code = get_Method()->code(); if (code != nullptr && (code->comp_level() == CompLevel_full_optimization)) { - int isize = code->insts_end() - code->verified_entry_point() - code->skipped_instructions_size(); + int isize = code->inline_insts_size(); _inline_instructions_size = isize > 0 ? isize : 0; } else { _inline_instructions_size = 0; diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 26d393d06db45..8cc36ba1b64ad 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -131,6 +131,7 @@ struct java_nmethod_stats_struct { uint relocation_size; uint consts_size; uint insts_size; + uint inline_insts_size; uint stub_size; uint oops_size; uint metadata_size; @@ -151,6 +152,7 @@ struct java_nmethod_stats_struct { relocation_size += nm->relocation_size(); consts_size += nm->consts_size(); insts_size += nm->insts_size(); + inline_insts_size += nm->inline_insts_size(); stub_size += nm->stub_size(); oops_size += nm->oops_size(); metadata_size += nm->metadata_size(); @@ -185,6 +187,9 @@ struct java_nmethod_stats_struct { if (insts_size != 0) { tty->print_cr(" main code = %u (%f%%)", insts_size, (insts_size * 100.0f)/total_nm_size); } + if (inline_insts_size != 0) { + tty->print_cr(" inline code = %u (%f%%)", inline_insts_size, (inline_insts_size * 100.0f)/total_nm_size); + } if (stub_size != 0) { tty->print_cr(" stub code = %u (%f%%)", stub_size, (stub_size * 100.0f)/total_nm_size); } @@ -1253,7 +1258,15 @@ void nmethod::init_defaults(CodeBuffer *code_buffer, CodeOffsets* offsets) { CHECKED_CAST(_entry_offset, uint16_t, (offsets->value(CodeOffsets::Entry))); CHECKED_CAST(_verified_entry_offset, uint16_t, (offsets->value(CodeOffsets::Verified_Entry))); - CHECKED_CAST(_skipped_instructions_size, uint16_t, (code_buffer->total_skipped_instructions_size())); + + int size = code_buffer->main_code_size(); + assert(size >= 0, "should be initialized"); + // Use instructions section size if it is 0 (e.g. native wrapper) + if (size == 0) size = code_size(); // requires _stub_offset to be set + assert(size <= code_size(), "incorrect size: %d > %d", size, code_size()); + _inline_insts_size = size - _verified_entry_offset + - code_buffer->total_skipped_instructions_size(); + assert(_inline_insts_size >= 0, "sanity"); } // Post initialization diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 22e38afeebd67..0677aeec14e1b 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -218,6 +218,8 @@ class nmethod : public CodeBlob { // _consts_offset == _content_offset because SECT_CONSTS is first in code buffer + int _inline_insts_size; + int _stub_offset; // Offsets for different stubs section parts @@ -232,7 +234,6 @@ class nmethod : public CodeBlob { int16_t _unwind_handler_offset; // Number of arguments passed on the stack uint16_t _num_stack_arg_slots; - uint16_t _skipped_instructions_size; // Offsets in mutable data section // _oops_offset == _data_offset, offset where embedded oop table begins (inside data) @@ -589,7 +590,7 @@ class nmethod : public CodeBlob { int oops_count() const { assert(oops_size() % oopSize == 0, ""); return (oops_size() / oopSize) + 1; } int metadata_count() const { assert(metadata_size() % wordSize == 0, ""); return (metadata_size() / wordSize) + 1; } - int skipped_instructions_size () const { return _skipped_instructions_size; } + int inline_insts_size() const { return _inline_insts_size; } int total_size() const; // Containment diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index a3b9926346942..4d623144a8407 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -1324,8 +1324,9 @@ CodeBuffer* PhaseOutput::init_buffer() { int pad_req = NativeCall::instruction_size; + // GC barrier stubs are generated in code section BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - stub_req += bs->estimate_stub_size(); + code_req += bs->estimate_stub_size(); // nmethod and CodeBuffer count stubs & constants as part of method's code. // class HandlerImpl is platform-specific and defined in the *.ad files. @@ -1334,9 +1335,9 @@ CodeBuffer* PhaseOutput::init_buffer() { stub_req += MAX_stubs_size; // ensure per-stub margin code_req += MAX_inst_size; // ensure per-instruction margin - if (StressCodeBuffers) + if (StressCodeBuffers) { code_req = const_req = stub_req = exception_handler_req = deopt_handler_req = 0x10; // force expansion - + } int total_req = const_req + code_req + @@ -1345,9 +1346,10 @@ CodeBuffer* PhaseOutput::init_buffer() { exception_handler_req + deopt_handler_req; // deopt handler - if (C->has_method_handle_invokes()) - total_req += deopt_handler_req; // deopt MH handler - + if (C->has_method_handle_invokes()) { + total_req += deopt_handler_req; // deopt MH handler + stub_req += deopt_handler_req; + } CodeBuffer* cb = code_buffer(); cb->initialize(total_req, _buf_sizes._reloc); From 7a41a525deb796396ade1456f1d0a101ac705014 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 2 May 2024 15:03:48 +0000 Subject: [PATCH 057/203] 8331549: Inline MemAllocator::mem_allocate_slow Reviewed-by: stefank, gli --- src/hotspot/share/gc/shared/memAllocator.cpp | 20 ++++++++------------ src/hotspot/share/gc/shared/memAllocator.hpp | 3 --- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp index 971feed6aaf7a..ed38c44859072 100644 --- a/src/hotspot/share/gc/shared/memAllocator.cpp +++ b/src/hotspot/share/gc/shared/memAllocator.cpp @@ -318,31 +318,27 @@ HeapWord* MemAllocator::mem_allocate_inside_tlab_slow(Allocation& allocation) co return mem; } -HeapWord* MemAllocator::mem_allocate_slow(Allocation& allocation) const { - // Allocation of an oop can always invoke a safepoint. - debug_only(allocation._thread->check_for_valid_safepoint_state()); - +HeapWord* MemAllocator::mem_allocate(Allocation& allocation) const { if (UseTLAB) { - // Try refilling the TLAB and allocating the object in it. - HeapWord* mem = mem_allocate_inside_tlab_slow(allocation); + // Try allocating from an existing TLAB. + HeapWord* mem = mem_allocate_inside_tlab_fast(); if (mem != nullptr) { return mem; } } - return mem_allocate_outside_tlab(allocation); -} + // Allocation of an oop can always invoke a safepoint. + debug_only(allocation._thread->check_for_valid_safepoint_state()); -HeapWord* MemAllocator::mem_allocate(Allocation& allocation) const { if (UseTLAB) { - // Try allocating from an existing TLAB. - HeapWord* mem = mem_allocate_inside_tlab_fast(); + // Try refilling the TLAB and allocating the object in it. + HeapWord* mem = mem_allocate_inside_tlab_slow(allocation); if (mem != nullptr) { return mem; } } - return mem_allocate_slow(allocation); + return mem_allocate_outside_tlab(allocation); } oop MemAllocator::allocate() const { diff --git a/src/hotspot/share/gc/shared/memAllocator.hpp b/src/hotspot/share/gc/shared/memAllocator.hpp index dca1add31b6b0..5d3f892ca14fd 100644 --- a/src/hotspot/share/gc/shared/memAllocator.hpp +++ b/src/hotspot/share/gc/shared/memAllocator.hpp @@ -52,9 +52,6 @@ class MemAllocator: StackObj { // Allocate outside a TLAB. Could safepoint. HeapWord* mem_allocate_outside_tlab(Allocation& allocation) const; - // Fast-path TLAB allocation failed. Takes a slow-path and potentially safepoint. - HeapWord* mem_allocate_slow(Allocation& allocation) const; - protected: MemAllocator(Klass* klass, size_t word_size, Thread* thread) : _thread(thread), From 6969a9e0b2143eee5a7cfa02460a8ab6dfa08cda Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Thu, 2 May 2024 15:36:10 +0000 Subject: [PATCH 058/203] 8328999: Update GIFlib to 5.2.2 Reviewed-by: tr, dnguyen, prr --- src/java.desktop/share/legal/giflib.md | 26 +- .../native/libsplashscreen/giflib/dgif_lib.c | 755 ++++++++++-------- .../native/libsplashscreen/giflib/gif_err.c | 52 +- .../native/libsplashscreen/giflib/gif_hash.h | 24 +- .../native/libsplashscreen/giflib/gif_lib.h | 213 +++-- .../libsplashscreen/giflib/gif_lib_private.h | 70 +- .../native/libsplashscreen/giflib/gifalloc.c | 255 +++--- .../giflib/openbsd-reallocarray.c | 13 +- 8 files changed, 741 insertions(+), 667 deletions(-) diff --git a/src/java.desktop/share/legal/giflib.md b/src/java.desktop/share/legal/giflib.md index 0be4fb8226e2d..8b8fde8706d92 100644 --- a/src/java.desktop/share/legal/giflib.md +++ b/src/java.desktop/share/legal/giflib.md @@ -1,4 +1,4 @@ -## GIFLIB v5.2.1 +## GIFLIB v5.2.2 ### GIFLIB License ``` @@ -24,7 +24,27 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -https://sourceforge.net/p/giflib/code/ci/master/tree/openbsd-reallocarray.c +tree/README -Copyright (c) 2008 Otto Moerbeek +== Authors == + +Gershon Elber +original giflib code + +Toshio Kuratomi +uncompressed gif writing code +former maintainer + +Eric Raymond +current as well as long time former maintainer of giflib code + +There have been many other contributors; see the attributions in the +version-control history to learn more. + + +tree/openbsd-reallocarray.c + +Copyright (C) 2008 Otto Moerbeek SPDX-License-Identifier: MIT + +``` diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c b/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c index 6ddfb46060de4..0b2860b4b509d 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c @@ -34,11 +34,11 @@ SPDX-License-Identifier: MIT *****************************************************************************/ -#include +#include #include #include -#include #include +#include #include #ifdef _WIN32 @@ -55,18 +55,19 @@ SPDX-License-Identifier: MIT /* avoid extra function call in case we use fread (TVT) */ static int InternalRead(GifFileType *gif, GifByteType *buf, int len) { - //fprintf(stderr, "### Read: %d\n", len); - return - (((GifFilePrivateType*)gif->Private)->Read ? - ((GifFilePrivateType*)gif->Private)->Read(gif,buf,len) : - fread(buf,1,len,((GifFilePrivateType*)gif->Private)->File)); + // fprintf(stderr, "### Read: %d\n", len); + return (((GifFilePrivateType *)gif->Private)->Read + ? ((GifFilePrivateType *)gif->Private)->Read(gif, buf, len) + : fread(buf, 1, len, + ((GifFilePrivateType *)gif->Private)->File)); } static int DGifGetWord(GifFileType *GifFile, GifWord *Word); static int DGifSetupDecompress(GifFileType *GifFile); static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen); -static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode); +static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, + int ClearCode); static int DGifDecompressInput(GifFileType *GifFile, int *Code); static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte); @@ -76,15 +77,14 @@ static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, Returns dynamically allocated GifFileType pointer which serves as the GIF info record. ******************************************************************************/ -GifFileType * -DGifOpenFileName(const char *FileName, int *Error) -{ +GifFileType *DGifOpenFileName(const char *FileName, int *Error) { int FileHandle; GifFileType *GifFile; if ((FileHandle = open(FileName, O_RDONLY)) == -1) { - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_OPEN_FAILED; + } return NULL; } @@ -97,9 +97,7 @@ DGifOpenFileName(const char *FileName, int *Error) Returns dynamically allocated GifFileType pointer which serves as the GIF info record. ******************************************************************************/ -GifFileType * -DGifOpenFileHandle(int FileHandle, int *Error) -{ +GifFileType *DGifOpenFileHandle(int FileHandle, int *Error) { char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; @@ -107,13 +105,14 @@ DGifOpenFileHandle(int FileHandle, int *Error) GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } (void)close(FileHandle); return NULL; } - /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType)); + /*@i1@*/ memset(GifFile, '\0', sizeof(GifFileType)); /* Belt and suspenders, in case the null pointer isn't zero */ GifFile->SavedImages = NULL; @@ -121,35 +120,38 @@ DGifOpenFileHandle(int FileHandle, int *Error) Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType)); if (Private == NULL) { - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } (void)close(FileHandle); free((char *)GifFile); return NULL; } - /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType)); + /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType)); #ifdef _WIN32 - _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ -#endif /* _WIN32 */ + _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ +#endif /* _WIN32 */ - f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ + f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ /*@-mustfreeonly@*/ GifFile->Private = (void *)Private; Private->FileHandle = FileHandle; Private->File = f; Private->FileState = FILE_STATE_READ; - Private->Read = NULL; /* don't use alternate input method (TVT) */ - GifFile->UserData = NULL; /* TVT */ + Private->Read = NULL; /* don't use alternate input method (TVT) */ + GifFile->UserData = NULL; /* TVT */ /*@=mustfreeonly@*/ /* Let's see if this is a GIF file: */ /* coverity[check_return] */ - if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - if (Error != NULL) + if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != + GIF_STAMP_LEN) { + if (Error != NULL) { *Error = D_GIF_ERR_READ_FAILED; + } (void)fclose(f); free((char *)Private); free((char *)GifFile); @@ -159,8 +161,9 @@ DGifOpenFileHandle(int FileHandle, int *Error) /* Check for GIF prefix at start of file */ Buf[GIF_STAMP_LEN] = 0; if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_NOT_GIF_FILE; + } (void)fclose(f); free((char *)Private); free((char *)GifFile); @@ -177,7 +180,7 @@ DGifOpenFileHandle(int FileHandle, int *Error) GifFile->Error = 0; /* What version of GIF? */ - Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); + Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9'); return GifFile; } @@ -185,17 +188,16 @@ DGifOpenFileHandle(int FileHandle, int *Error) /****************************************************************************** GifFileType constructor with user supplied input function (TVT) ******************************************************************************/ -GifFileType * -DGifOpen(void *userData, InputFunc readFunc, int *Error) -{ +GifFileType *DGifOpen(void *userData, InputFunc readFunc, int *Error) { char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } return NULL; } @@ -207,26 +209,29 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType)); if (!Private) { - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } free((char *)GifFile); return NULL; } - /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType)); + /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType)); GifFile->Private = (void *)Private; Private->FileHandle = 0; Private->File = NULL; Private->FileState = FILE_STATE_READ; - Private->Read = readFunc; /* TVT */ - GifFile->UserData = userData; /* TVT */ + Private->Read = readFunc; /* TVT */ + GifFile->UserData = userData; /* TVT */ /* Lets see if this is a GIF file: */ /* coverity[check_return] */ - if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - if (Error != NULL) + if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != + GIF_STAMP_LEN) { + if (Error != NULL) { *Error = D_GIF_ERR_READ_FAILED; + } free((char *)Private); free((char *)GifFile); return NULL; @@ -235,8 +240,9 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) /* Check for GIF prefix at start of file */ Buf[GIF_STAMP_LEN] = '\0'; if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_NOT_GIF_FILE; + } free((char *)Private); free((char *)GifFile); return NULL; @@ -245,15 +251,16 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { free((char *)Private); free((char *)GifFile); - if (Error != NULL) + if (Error != NULL) { *Error = D_GIF_ERR_NO_SCRN_DSCR; + } return NULL; } GifFile->Error = 0; /* What version of GIF? */ - Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); + Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9'); return GifFile; } @@ -262,9 +269,7 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) This routine should be called before any other DGif calls. Note that this routine is called automatically from DGif file open routines. ******************************************************************************/ -int -DGifGetScreenDesc(GifFileType *GifFile) -{ +int DGifGetScreenDesc(GifFileType *GifFile) { int BitsPerPixel; bool SortFlag; GifByteType Buf[3]; @@ -278,8 +283,9 @@ DGifGetScreenDesc(GifFileType *GifFile) /* Put the screen descriptor into the file: */ if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) + DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) { return GIF_ERROR; + } if (InternalRead(GifFile, Buf, 3) != 3) { GifFile->Error = D_GIF_ERR_READ_FAILED; @@ -292,7 +298,7 @@ DGifGetScreenDesc(GifFileType *GifFile) BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; GifFile->AspectByte = Buf[2]; - if (Buf[0] & 0x80) { /* Do we have global color map? */ + if (Buf[0] & 0x80) { /* Do we have global color map? */ int i; GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); @@ -327,23 +333,20 @@ DGifGetScreenDesc(GifFileType *GifFile) return GIF_OK; } -const char * -DGifGetGifVersion(GifFileType *GifFile) -{ - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; +const char *DGifGetGifVersion(GifFileType *GifFile) { + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (Private->gif89) + if (Private->gif89) { return GIF89_STAMP; - else + } else { return GIF87_STAMP; + } } /****************************************************************************** This routine should be called before any attempt to read an image. ******************************************************************************/ -int -DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type) -{ +int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type) { GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; @@ -359,29 +362,27 @@ DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type) return GIF_ERROR; } - //fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf); + // fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf); switch (Buf) { - case DESCRIPTOR_INTRODUCER: - *Type = IMAGE_DESC_RECORD_TYPE; - break; - case EXTENSION_INTRODUCER: - *Type = EXTENSION_RECORD_TYPE; - break; - case TERMINATOR_INTRODUCER: - *Type = TERMINATE_RECORD_TYPE; - break; - default: - *Type = UNDEFINED_RECORD_TYPE; - GifFile->Error = D_GIF_ERR_WRONG_RECORD; - return GIF_ERROR; + case DESCRIPTOR_INTRODUCER: + *Type = IMAGE_DESC_RECORD_TYPE; + break; + case EXTENSION_INTRODUCER: + *Type = EXTENSION_RECORD_TYPE; + break; + case TERMINATOR_INTRODUCER: + *Type = TERMINATE_RECORD_TYPE; + break; + default: + *Type = UNDEFINED_RECORD_TYPE; + GifFile->Error = D_GIF_ERR_WRONG_RECORD; + return GIF_ERROR; } return GIF_OK; } -int -DGifGetImageHeader(GifFileType *GifFile) -{ +int DGifGetImageHeader(GifFileType *GifFile) { unsigned int BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; @@ -395,8 +396,9 @@ DGifGetImageHeader(GifFileType *GifFile) if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) + DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) { return GIF_ERROR; + } if (InternalRead(GifFile, Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; GifFreeMapObject(GifFile->Image.ColorMap); @@ -415,7 +417,8 @@ DGifGetImageHeader(GifFileType *GifFile) if (Buf[0] & 0x80) { unsigned int i; - GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); + GifFile->Image.ColorMap = + GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; @@ -436,8 +439,8 @@ DGifGetImageHeader(GifFileType *GifFile) } } - Private->PixelCount = (long)GifFile->Image.Width * - (long)GifFile->Image.Height; + Private->PixelCount = + (long)GifFile->Image.Width * (long)GifFile->Image.Height; /* Reset decompress algorithm parameters. */ return DGifSetupDecompress(GifFile); @@ -447,9 +450,7 @@ DGifGetImageHeader(GifFileType *GifFile) This routine should be called before any attempt to read an image. Note it is assumed the Image desc. header has been read. ******************************************************************************/ -int -DGifGetImageDesc(GifFileType *GifFile) -{ +int DGifGetImageDesc(GifFileType *GifFile) { GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; SavedImage *sp; @@ -464,9 +465,9 @@ DGifGetImageDesc(GifFileType *GifFile) } if (GifFile->SavedImages) { - SavedImage* new_saved_images = - (SavedImage *)reallocarray(GifFile->SavedImages, - (GifFile->ImageCount + 1), sizeof(SavedImage)); + SavedImage *new_saved_images = (SavedImage *)reallocarray( + GifFile->SavedImages, (GifFile->ImageCount + 1), + sizeof(SavedImage)); if (new_saved_images == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; @@ -474,7 +475,7 @@ DGifGetImageDesc(GifFileType *GifFile) GifFile->SavedImages = new_saved_images; } else { if ((GifFile->SavedImages = - (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { + (SavedImage *)malloc(sizeof(SavedImage))) == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } @@ -483,9 +484,9 @@ DGifGetImageDesc(GifFileType *GifFile) sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { - sp->ImageDesc.ColorMap = GifMakeMapObject( - GifFile->Image.ColorMap->ColorCount, - GifFile->Image.ColorMap->Colors); + sp->ImageDesc.ColorMap = + GifMakeMapObject(GifFile->Image.ColorMap->ColorCount, + GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; @@ -493,7 +494,7 @@ DGifGetImageDesc(GifFileType *GifFile) } sp->RasterBits = (unsigned char *)NULL; sp->ExtensionBlockCount = 0; - sp->ExtensionBlocks = (ExtensionBlock *) NULL; + sp->ExtensionBlocks = (ExtensionBlock *)NULL; GifFile->ImageCount++; @@ -503,11 +504,9 @@ DGifGetImageDesc(GifFileType *GifFile) /****************************************************************************** Get one full scanned line (Line) of length LineLen from GIF file. ******************************************************************************/ -int -DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) -{ +int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) { GifByteType *Dummy; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ @@ -515,8 +514,9 @@ DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) return GIF_ERROR; } - if (!LineLen) + if (!LineLen) { LineLen = GifFile->Image.Width; + } if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; @@ -525,56 +525,59 @@ DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { if (Private->PixelCount == 0) { - /* We probably won't be called any more, so let's clean up - * everything before we return: need to flush out all the - * rest of image until an empty block (size 0) + /* We probably won't be called any more, so let's clean + * up everything before we return: need to flush out all + * the rest of image until an empty block (size 0) * detected. We use GetCodeNext. */ - do - if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) + do { + if (DGifGetCodeNext(GifFile, &Dummy) == + GIF_ERROR) { return GIF_ERROR; - while (Dummy != NULL) ; + } + } while (Dummy != NULL); } return GIF_OK; - } else + } else { return GIF_ERROR; + } } /****************************************************************************** Put one pixel (Pixel) into GIF file. ******************************************************************************/ -int -DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) -{ +int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) { GifByteType *Dummy; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } - if (--Private->PixelCount > 0xffff0000UL) - { + if (--Private->PixelCount > 0xffff0000UL) { GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { if (Private->PixelCount == 0) { - /* We probably won't be called any more, so let's clean up - * everything before we return: need to flush out all the - * rest of image until an empty block (size 0) + /* We probably won't be called any more, so let's clean + * up everything before we return: need to flush out all + * the rest of image until an empty block (size 0) * detected. We use GetCodeNext. */ - do - if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) + do { + if (DGifGetCodeNext(GifFile, &Dummy) == + GIF_ERROR) { return GIF_ERROR; - while (Dummy != NULL) ; + } + } while (Dummy != NULL); } return GIF_OK; - } else + } else { return GIF_ERROR; + } } /****************************************************************************** @@ -584,13 +587,12 @@ DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) The Extension should NOT be freed by the user (not dynamically allocated). Note it is assumed the Extension description header has been read. ******************************************************************************/ -int -DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) -{ +int DGifGetExtension(GifFileType *GifFile, int *ExtCode, + GifByteType **Extension) { GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - //fprintf(stderr, "### -> DGifGetExtension:\n"); + // fprintf(stderr, "### -> DGifGetExtension:\n"); if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ GifFile->Error = D_GIF_ERR_NOT_READABLE; @@ -603,7 +605,8 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) return GIF_ERROR; } *ExtCode = Buf; - //fprintf(stderr, "### <- DGifGetExtension: %02x, about to call next\n", Buf); + // fprintf(stderr, "### <- DGifGetExtension: %02x, about to call + // next\n", Buf); return DGifGetExtensionNext(GifFile, Extension); } @@ -613,30 +616,30 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) routine should be called until NULL Extension is returned. The Extension should NOT be freed by the user (not dynamically allocated). ******************************************************************************/ -int -DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension) -{ +int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) { GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - //fprintf(stderr, "### -> DGifGetExtensionNext\n"); + // fprintf(stderr, "### -> DGifGetExtensionNext\n"); if (InternalRead(GifFile, &Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } - //fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf); + // fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf); if (Buf > 0) { - *Extension = Private->Buf; /* Use private unused buffer. */ - (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - /* coverity[tainted_data,check_return] */ + *Extension = Private->Buf; /* Use private unused buffer. */ + (*Extension)[0] = + Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data,check_return] */ if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } - } else + } else { *Extension = NULL; - //fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension); + } + // fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension); return GIF_OK; } @@ -647,19 +650,20 @@ DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension) int DGifExtensionToGCB(const size_t GifExtensionLength, const GifByteType *GifExtension, - GraphicsControlBlock *GCB) -{ + GraphicsControlBlock *GCB) { if (GifExtensionLength != 4) { return GIF_ERROR; } GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07; GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0; - GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); - if (GifExtension[0] & 0x01) + GCB->DelayTime = + UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); + if (GifExtension[0] & 0x01) { GCB->TransparentColor = (int)GifExtension[3]; - else + } else { GCB->TransparentColor = NO_TRANSPARENT_COLOR; + } return GIF_OK; } @@ -668,23 +672,27 @@ int DGifExtensionToGCB(const size_t GifExtensionLength, Extract the Graphics Control Block for a saved image, if it exists. ******************************************************************************/ -int DGifSavedExtensionToGCB(GifFileType *GifFile, - int ImageIndex, GraphicsControlBlock *GCB) -{ +int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex, + GraphicsControlBlock *GCB) { int i; - if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) + if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) { return GIF_ERROR; + } GCB->DisposalMode = DISPOSAL_UNSPECIFIED; GCB->UserInputFlag = false; GCB->DelayTime = 0; GCB->TransparentColor = NO_TRANSPARENT_COLOR; - for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) { - ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; - if (ep->Function == GRAPHICS_EXT_FUNC_CODE) - return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB); + for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; + i++) { + ExtensionBlock *ep = + &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; + if (ep->Function == GRAPHICS_EXT_FUNC_CODE) { + return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, + GCB); + } } return GIF_ERROR; @@ -693,13 +701,12 @@ int DGifSavedExtensionToGCB(GifFileType *GifFile, /****************************************************************************** This routine should be called last, to close the GIF file. ******************************************************************************/ -int -DGifCloseFile(GifFileType *GifFile, int *ErrorCode) -{ +int DGifCloseFile(GifFileType *GifFile, int *ErrorCode) { GifFilePrivateType *Private; - if (GifFile == NULL || GifFile->Private == NULL) + if (GifFile == NULL || GifFile->Private == NULL) { return GIF_ERROR; + } if (GifFile->Image.ColorMap) { GifFreeMapObject(GifFile->Image.ColorMap); @@ -716,22 +723,25 @@ DGifCloseFile(GifFileType *GifFile, int *ErrorCode) GifFile->SavedImages = NULL; } - GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks); + GifFreeExtensions(&GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks); - Private = (GifFilePrivateType *) GifFile->Private; + Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - if (ErrorCode != NULL) + if (ErrorCode != NULL) { *ErrorCode = D_GIF_ERR_NOT_READABLE; + } free((char *)GifFile->Private); free(GifFile); return GIF_ERROR; } if (Private->File && (fclose(Private->File) != 0)) { - if (ErrorCode != NULL) + if (ErrorCode != NULL) { *ErrorCode = D_GIF_ERR_CLOSE_FAILED; + } free((char *)GifFile->Private); free(GifFile); return GIF_ERROR; @@ -739,17 +749,16 @@ DGifCloseFile(GifFileType *GifFile, int *ErrorCode) free((char *)GifFile->Private); free(GifFile); - if (ErrorCode != NULL) + if (ErrorCode != NULL) { *ErrorCode = D_GIF_SUCCEEDED; + } return GIF_OK; } /****************************************************************************** Get 2 bytes (word) from the given file: ******************************************************************************/ -static int -DGifGetWord(GifFileType *GifFile, GifWord *Word) -{ +static int DGifGetWord(GifFileType *GifFile, GifWord *Word) { unsigned char c[2]; /* coverity[check_return] */ @@ -769,9 +778,7 @@ DGifGetWord(GifFileType *GifFile, GifWord *Word) to DGifGetCodeNext, until NULL block is returned. The block should NOT be freed by the user (not dynamically allocated). ******************************************************************************/ -int -DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) -{ +int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) { GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { @@ -790,9 +797,7 @@ DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) called until NULL block is returned. The block should NOT be freed by the user (not dynamically allocated). ******************************************************************************/ -int -DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) -{ +int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) { GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; @@ -805,17 +810,19 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) /* coverity[lower_bounds] */ if (Buf > 0) { - *CodeBlock = Private->Buf; /* Use private unused buffer. */ - (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - /* coverity[tainted_data] */ + *CodeBlock = Private->Buf; /* Use private unused buffer. */ + (*CodeBlock)[0] = + Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data] */ if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else { *CodeBlock = NULL; - Private->Buf[0] = 0; /* Make sure the buffer is empty! */ - Private->PixelCount = 0; /* And local info. indicate image read. */ + Private->Buf[0] = 0; /* Make sure the buffer is empty! */ + Private->PixelCount = + 0; /* And local info. indicate image read. */ } return GIF_OK; @@ -824,41 +831,43 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) /****************************************************************************** Setup the LZ decompression for this image: ******************************************************************************/ -static int -DGifSetupDecompress(GifFileType *GifFile) -{ +static int DGifSetupDecompress(GifFileType *GifFile) { int i, BitsPerPixel; GifByteType CodeSize; GifPrefixType *Prefix; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; /* coverity[check_return] */ - if (InternalRead(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */ - return GIF_ERROR; /* Failed to read Code size. */ + if (InternalRead(GifFile, &CodeSize, 1) < + 1) { /* Read Code size from file. */ + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; /* Failed to read Code size. */ } BitsPerPixel = CodeSize; /* this can only happen on a severely malformed GIF */ if (BitsPerPixel > 8) { - GifFile->Error = D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */ - return GIF_ERROR; /* Failed to read Code size. */ + GifFile->Error = + D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */ + return GIF_ERROR; /* Failed to read Code size. */ } - Private->Buf[0] = 0; /* Input Buffer empty. */ + Private->Buf[0] = 0; /* Input Buffer empty. */ Private->BitsPerPixel = BitsPerPixel; Private->ClearCode = (1 << BitsPerPixel); Private->EOFCode = Private->ClearCode + 1; Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ - Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ - Private->StackPtr = 0; /* No pixels on the pixel stack. */ + Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ + Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ + Private->StackPtr = 0; /* No pixels on the pixel stack. */ Private->LastCode = NO_SUCH_CODE; - Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ + Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ Private->CrntShiftDWord = 0; Prefix = Private->Prefix; - for (i = 0; i <= LZ_MAX_CODE; i++) + for (i = 0; i <= LZ_MAX_CODE; i++) { Prefix[i] = NO_SUCH_CODE; + } return GIF_OK; } @@ -869,14 +878,13 @@ DGifSetupDecompress(GifFileType *GifFile) This routine can be called few times (one per scan line, for example), in order the complete the whole image. ******************************************************************************/ -static int -DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) -{ +static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, + int LineLen) { int i = 0; int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; GifByteType *Stack, *Suffix; GifPrefixType *Prefix; - GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; StackPtr = Private->StackPtr; Prefix = Private->Prefix; @@ -891,72 +899,88 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) } if (StackPtr != 0) { - /* Let pop the stack off before continueing to read the GIF file: */ - while (StackPtr != 0 && i < LineLen) + /* Let pop the stack off before continueing to read the GIF + * file: */ + while (StackPtr != 0 && i < LineLen) { Line[i++] = Stack[--StackPtr]; + } } - while (i < LineLen) { /* Decode LineLen items. */ - if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) + while (i < LineLen) { /* Decode LineLen items. */ + if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) { return GIF_ERROR; + } if (CrntCode == EOFCode) { - /* Note however that usually we will not be here as we will stop - * decoding as soon as we got all the pixel, or EOF code will - * not be read at all, and DGifGetLine/Pixel clean everything. */ + /* Note however that usually we will not be here as we + * will stop decoding as soon as we got all the pixel, + * or EOF code will not be read at all, and + * DGifGetLine/Pixel clean everything. */ GifFile->Error = D_GIF_ERR_EOF_TOO_SOON; return GIF_ERROR; } else if (CrntCode == ClearCode) { /* We need to start over again: */ - for (j = 0; j <= LZ_MAX_CODE; j++) + for (j = 0; j <= LZ_MAX_CODE; j++) { Prefix[j] = NO_SUCH_CODE; + } Private->RunningCode = Private->EOFCode + 1; Private->RunningBits = Private->BitsPerPixel + 1; Private->MaxCode1 = 1 << Private->RunningBits; LastCode = Private->LastCode = NO_SUCH_CODE; } else { - /* Its regular code - if in pixel range simply add it to output - * stream, otherwise trace to codes linked list until the prefix - * is in pixel range: */ + /* Its regular code - if in pixel range simply add it to + * output stream, otherwise trace to codes linked list + * until the prefix is in pixel range: */ if (CrntCode < ClearCode) { - /* This is simple - its pixel scalar, so add it to output: */ + /* This is simple - its pixel scalar, so add it + * to output: */ Line[i++] = CrntCode; } else { - /* Its a code to needed to be traced: trace the linked list - * until the prefix is a pixel, while pushing the suffix - * pixels on our stack. If we done, pop the stack in reverse - * (thats what stack is good for!) order to output. */ + /* Its a code to needed to be traced: trace the + * linked list until the prefix is a pixel, + * while pushing the suffix pixels on our stack. + * If we done, pop the stack in reverse (thats + * what stack is good for!) order to output. */ if (Prefix[CrntCode] == NO_SUCH_CODE) { CrntPrefix = LastCode; - /* Only allowed if CrntCode is exactly the running code: - * In that case CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the suffix char is - * exactly the prefix of last code! */ - if (CrntCode == Private->RunningCode - 2) { - Suffix[Private->RunningCode - 2] = - Stack[StackPtr++] = DGifGetPrefixChar(Prefix, - LastCode, - ClearCode); + /* Only allowed if CrntCode is exactly + * the running code: In that case + * CrntCode = XXXCode, CrntCode or the + * prefix code is last code and the + * suffix char is exactly the prefix of + * last code! */ + if (CrntCode == + Private->RunningCode - 2) { + Suffix[Private->RunningCode - + 2] = Stack[StackPtr++] = + DGifGetPrefixChar( + Prefix, LastCode, + ClearCode); } else { - Suffix[Private->RunningCode - 2] = - Stack[StackPtr++] = DGifGetPrefixChar(Prefix, - CrntCode, - ClearCode); + Suffix[Private->RunningCode - + 2] = Stack[StackPtr++] = + DGifGetPrefixChar( + Prefix, CrntCode, + ClearCode); } - } else + } else { CrntPrefix = CrntCode; + } - /* Now (if image is O.K.) we should not get a NO_SUCH_CODE - * during the trace. As we might loop forever, in case of - * defective image, we use StackPtr as loop counter and stop - * before overflowing Stack[]. */ + /* Now (if image is O.K.) we should not get a + * NO_SUCH_CODE during the trace. As we might + * loop forever, in case of defective image, we + * use StackPtr as loop counter and stop before + * overflowing Stack[]. */ while (StackPtr < LZ_MAX_CODE && - CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) { + CrntPrefix > ClearCode && + CrntPrefix <= LZ_MAX_CODE) { Stack[StackPtr++] = Suffix[CrntPrefix]; CrntPrefix = Prefix[CrntPrefix]; } - if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { + if (StackPtr >= LZ_MAX_CODE || + CrntPrefix > LZ_MAX_CODE) { GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } @@ -964,22 +988,29 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) Stack[StackPtr++] = CrntPrefix; /* Now lets pop all the stack into output: */ - while (StackPtr != 0 && i < LineLen) + while (StackPtr != 0 && i < LineLen) { Line[i++] = Stack[--StackPtr]; + } } - if (LastCode != NO_SUCH_CODE && Private->RunningCode - 2 < (LZ_MAX_CODE+1) && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { + if (LastCode != NO_SUCH_CODE && + Private->RunningCode - 2 < (LZ_MAX_CODE + 1) && + Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { Prefix[Private->RunningCode - 2] = LastCode; if (CrntCode == Private->RunningCode - 2) { - /* Only allowed if CrntCode is exactly the running code: - * In that case CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the suffix char is - * exactly the prefix of last code! */ + /* Only allowed if CrntCode is exactly + * the running code: In that case + * CrntCode = XXXCode, CrntCode or the + * prefix code is last code and the + * suffix char is exactly the prefix of + * last code! */ Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, LastCode, ClearCode); + DGifGetPrefixChar(Prefix, LastCode, + ClearCode); } else { Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, CrntCode, ClearCode); + DGifGetPrefixChar(Prefix, CrntCode, + ClearCode); } } LastCode = CrntCode; @@ -998,9 +1029,8 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) If image is defective, we might loop here forever, so we limit the loops to the maximum possible if image O.k. - LZ_MAX_CODE times. ******************************************************************************/ -static int -DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode) -{ +static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, + int ClearCode) { int i = 0; while (Code > ClearCode && i++ <= LZ_MAX_CODE) { @@ -1016,9 +1046,7 @@ DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode) Interface for accessing the LZ codes directly. Set Code to the real code (12bits), or to -1 if EOF code is returned. ******************************************************************************/ -int -DGifGetLZCodes(GifFileType *GifFile, int *Code) -{ +int DGifGetLZCodes(GifFileType *GifFile, int *Code) { GifByteType *CodeBlock; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; @@ -1028,15 +1056,18 @@ DGifGetLZCodes(GifFileType *GifFile, int *Code) return GIF_ERROR; } - if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) + if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) { return GIF_ERROR; + } if (*Code == Private->EOFCode) { - /* Skip rest of codes (hopefully only NULL terminating block): */ + /* Skip rest of codes (hopefully only NULL terminating block): + */ do { - if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) + if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) { return GIF_ERROR; - } while (CodeBlock != NULL) ; + } + } while (CodeBlock != NULL); *Code = -1; } else if (*Code == Private->ClearCode) { @@ -1055,15 +1086,10 @@ DGifGetLZCodes(GifFileType *GifFile, int *Code) 8 bits (bytes) packets, into the real codes. Returns GIF_OK if read successfully. ******************************************************************************/ -static int -DGifDecompressInput(GifFileType *GifFile, int *Code) -{ +static int DGifDecompressInput(GifFileType *GifFile, int *Code) { static const unsigned short CodeMasks[] = { - 0x0000, 0x0001, 0x0003, 0x0007, - 0x000f, 0x001f, 0x003f, 0x007f, - 0x00ff, 0x01ff, 0x03ff, 0x07ff, - 0x0fff - }; + 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, + 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff}; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; @@ -1077,11 +1103,12 @@ DGifDecompressInput(GifFileType *GifFile, int *Code) while (Private->CrntShiftState < Private->RunningBits) { /* Needs to get more bytes from input stream for next code: */ - if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) { + if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == + GIF_ERROR) { return GIF_ERROR; } - Private->CrntShiftDWord |= - ((unsigned long)NextByte) << Private->CrntShiftState; + Private->CrntShiftDWord |= ((unsigned long)NextByte) + << Private->CrntShiftState; Private->CrntShiftState += 8; } *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; @@ -1109,9 +1136,8 @@ DGifDecompressInput(GifFileType *GifFile, int *Code) The routine returns the next byte from its internal buffer (or read next block in if buffer empty) and returns GIF_OK if succesful. ******************************************************************************/ -static int -DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) -{ +static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, + GifByteType *NextByte) { if (Buf[0] == 0) { /* Needs to read the next buffer - this one is empty: */ /* coverity[check_return] */ @@ -1120,8 +1146,8 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) return GIF_ERROR; } /* There shouldn't be any empty data blocks here as the LZW spec - * says the LZW termination code should come first. Therefore we - * shouldn't be inside this routine at that point. + * says the LZW termination code should come first. Therefore + * we shouldn't be inside this routine at that point. */ if (Buf[0] == 0) { GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; @@ -1132,7 +1158,7 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) return GIF_ERROR; } *NextByte = Buf[1]; - Buf[1] = 2; /* We use now the second place as last char read! */ + Buf[1] = 2; /* We use now the second place as last char read! */ Buf[0]--; } else { *NextByte = Buf[Buf[1]++]; @@ -1142,14 +1168,32 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) return GIF_OK; } +/****************************************************************************** + This routine is called in case of error during parsing image. We need to + decrease image counter and reallocate memory for saved images. Not decreasing + ImageCount may lead to null pointer dereference, because the last element in + SavedImages may point to the spoilt image and null pointer buffers. +*******************************************************************************/ +void DGifDecreaseImageCounter(GifFileType *GifFile) { + GifFile->ImageCount--; + if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) { + free(GifFile->SavedImages[GifFile->ImageCount].RasterBits); + } + + // Realloc array according to the new image counter. + SavedImage *correct_saved_images = (SavedImage *)reallocarray( + GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage)); + if (correct_saved_images != NULL) { + GifFile->SavedImages = correct_saved_images; + } +} + /****************************************************************************** This routine reads an entire GIF into core, hanging all its state info off the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() first to initialize I/O. Its inverse is EGifSpew(). *******************************************************************************/ -int -DGifSlurp(GifFileType *GifFile) -{ +int DGifSlurp(GifFileType *GifFile) { size_t ImageSize; GifRecordType RecordType; SavedImage *sp; @@ -1160,103 +1204,130 @@ DGifSlurp(GifFileType *GifFile) GifFile->ExtensionBlockCount = 0; do { - if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) + if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { return (GIF_ERROR); + } switch (RecordType) { - case IMAGE_DESC_RECORD_TYPE: - if (DGifGetImageDesc(GifFile) == GIF_ERROR) - return (GIF_ERROR); - - sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; - /* Allocate memory for the image */ - if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 || - sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) { - return GIF_ERROR; - } - ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; - - if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { - return GIF_ERROR; - } - sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize, - sizeof(GifPixelType)); - - if (sp->RasterBits == NULL) { - return GIF_ERROR; - } - - if (sp->ImageDesc.Interlace) { - int i, j; - /* - * The way an interlaced image should be read - - * offsets and jumps... - */ - int InterlacedOffset[] = { 0, 4, 2, 1 }; - int InterlacedJumps[] = { 8, 8, 4, 2 }; - /* Need to perform 4 passes on the image */ - for (i = 0; i < 4; i++) - for (j = InterlacedOffset[i]; - j < sp->ImageDesc.Height; - j += InterlacedJumps[i]) { - if (DGifGetLine(GifFile, - sp->RasterBits+j*sp->ImageDesc.Width, - sp->ImageDesc.Width) == GIF_ERROR) - return GIF_ERROR; - } - } - else { - if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) - return (GIF_ERROR); - } - - if (GifFile->ExtensionBlocks) { - sp->ExtensionBlocks = GifFile->ExtensionBlocks; - sp->ExtensionBlockCount = GifFile->ExtensionBlockCount; - - GifFile->ExtensionBlocks = NULL; - GifFile->ExtensionBlockCount = 0; - } - break; - - case EXTENSION_RECORD_TYPE: - if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR) - return (GIF_ERROR); - /* Create an extension block with our data */ - if (ExtData != NULL) { - if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, - ExtFunction, ExtData[0], &ExtData[1]) - == GIF_ERROR) - return (GIF_ERROR); - } - for (;;) { - if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) - return (GIF_ERROR); - if (ExtData == NULL) - break; - /* Continue the extension block */ - if (ExtData != NULL) - if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, - CONTINUE_EXT_FUNC_CODE, - ExtData[0], &ExtData[1]) == GIF_ERROR) - return (GIF_ERROR); - } - break; - - case TERMINATE_RECORD_TYPE: - break; - - default: /* Should be trapped by DGifGetRecordType */ - break; + case IMAGE_DESC_RECORD_TYPE: + if (DGifGetImageDesc(GifFile) == GIF_ERROR) { + return (GIF_ERROR); + } + + sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; + /* Allocate memory for the image */ + if (sp->ImageDesc.Width <= 0 || + sp->ImageDesc.Height <= 0 || + sp->ImageDesc.Width > + (INT_MAX / sp->ImageDesc.Height)) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; + + if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + sp->RasterBits = (unsigned char *)reallocarray( + NULL, ImageSize, sizeof(GifPixelType)); + + if (sp->RasterBits == NULL) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + + if (sp->ImageDesc.Interlace) { + int i, j; + /* + * The way an interlaced image should be read - + * offsets and jumps... + */ + static const int InterlacedOffset[] = {0, 4, 2, + 1}; + static const int InterlacedJumps[] = {8, 8, 4, + 2}; + /* Need to perform 4 passes on the image */ + for (i = 0; i < 4; i++) { + for (j = InterlacedOffset[i]; + j < sp->ImageDesc.Height; + j += InterlacedJumps[i]) { + if (DGifGetLine( + GifFile, + sp->RasterBits + + j * sp->ImageDesc + .Width, + sp->ImageDesc.Width) == + GIF_ERROR) { + DGifDecreaseImageCounter( + GifFile); + return GIF_ERROR; + } + } + } + } else { + if (DGifGetLine(GifFile, sp->RasterBits, + ImageSize) == GIF_ERROR) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + } + + if (GifFile->ExtensionBlocks) { + sp->ExtensionBlocks = GifFile->ExtensionBlocks; + sp->ExtensionBlockCount = + GifFile->ExtensionBlockCount; + + GifFile->ExtensionBlocks = NULL; + GifFile->ExtensionBlockCount = 0; + } + break; + + case EXTENSION_RECORD_TYPE: + if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) == + GIF_ERROR) { + return (GIF_ERROR); + } + /* Create an extension block with our data */ + if (ExtData != NULL) { + if (GifAddExtensionBlock( + &GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks, ExtFunction, + ExtData[0], &ExtData[1]) == GIF_ERROR) { + return (GIF_ERROR); + } + } + for (;;) { + if (DGifGetExtensionNext(GifFile, &ExtData) == + GIF_ERROR) { + return (GIF_ERROR); + } + if (ExtData == NULL) { + break; + } + /* Continue the extension block */ + if (GifAddExtensionBlock( + &GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks, + CONTINUE_EXT_FUNC_CODE, ExtData[0], + &ExtData[1]) == GIF_ERROR) { + return (GIF_ERROR); + } + } + break; + + case TERMINATE_RECORD_TYPE: + break; + + default: /* Should be trapped by DGifGetRecordType */ + break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* Sanity check for corrupted file */ if (GifFile->ImageCount == 0) { GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR; - return(GIF_ERROR); + return (GIF_ERROR); } return (GIF_OK); diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c b/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c index db08838efff84..3b6785f7c6323 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c @@ -38,82 +38,80 @@ SPDX-License-Identifier: MIT /***************************************************************************** Return a string description of the last GIF error *****************************************************************************/ -const char * -GifErrorString(int ErrorCode) -{ +const char *GifErrorString(int ErrorCode) { const char *Err; switch (ErrorCode) { - case E_GIF_ERR_OPEN_FAILED: + case E_GIF_ERR_OPEN_FAILED: Err = "Failed to open given file"; break; - case E_GIF_ERR_WRITE_FAILED: + case E_GIF_ERR_WRITE_FAILED: Err = "Failed to write to given file"; break; - case E_GIF_ERR_HAS_SCRN_DSCR: + case E_GIF_ERR_HAS_SCRN_DSCR: Err = "Screen descriptor has already been set"; break; - case E_GIF_ERR_HAS_IMAG_DSCR: + case E_GIF_ERR_HAS_IMAG_DSCR: Err = "Image descriptor is still active"; break; - case E_GIF_ERR_NO_COLOR_MAP: + case E_GIF_ERR_NO_COLOR_MAP: Err = "Neither global nor local color map"; break; - case E_GIF_ERR_DATA_TOO_BIG: + case E_GIF_ERR_DATA_TOO_BIG: Err = "Number of pixels bigger than width * height"; break; - case E_GIF_ERR_NOT_ENOUGH_MEM: + case E_GIF_ERR_NOT_ENOUGH_MEM: Err = "Failed to allocate required memory"; break; - case E_GIF_ERR_DISK_IS_FULL: + case E_GIF_ERR_DISK_IS_FULL: Err = "Write failed (disk full?)"; break; - case E_GIF_ERR_CLOSE_FAILED: + case E_GIF_ERR_CLOSE_FAILED: Err = "Failed to close given file"; break; - case E_GIF_ERR_NOT_WRITEABLE: + case E_GIF_ERR_NOT_WRITEABLE: Err = "Given file was not opened for write"; break; - case D_GIF_ERR_OPEN_FAILED: + case D_GIF_ERR_OPEN_FAILED: Err = "Failed to open given file"; break; - case D_GIF_ERR_READ_FAILED: + case D_GIF_ERR_READ_FAILED: Err = "Failed to read from given file"; break; - case D_GIF_ERR_NOT_GIF_FILE: + case D_GIF_ERR_NOT_GIF_FILE: Err = "Data is not in GIF format"; break; - case D_GIF_ERR_NO_SCRN_DSCR: + case D_GIF_ERR_NO_SCRN_DSCR: Err = "No screen descriptor detected"; break; - case D_GIF_ERR_NO_IMAG_DSCR: + case D_GIF_ERR_NO_IMAG_DSCR: Err = "No Image Descriptor detected"; break; - case D_GIF_ERR_NO_COLOR_MAP: + case D_GIF_ERR_NO_COLOR_MAP: Err = "Neither global nor local color map"; break; - case D_GIF_ERR_WRONG_RECORD: + case D_GIF_ERR_WRONG_RECORD: Err = "Wrong record type detected"; break; - case D_GIF_ERR_DATA_TOO_BIG: + case D_GIF_ERR_DATA_TOO_BIG: Err = "Number of pixels bigger than width * height"; break; - case D_GIF_ERR_NOT_ENOUGH_MEM: + case D_GIF_ERR_NOT_ENOUGH_MEM: Err = "Failed to allocate required memory"; break; - case D_GIF_ERR_CLOSE_FAILED: + case D_GIF_ERR_CLOSE_FAILED: Err = "Failed to close given file"; break; - case D_GIF_ERR_NOT_READABLE: + case D_GIF_ERR_NOT_READABLE: Err = "Given file was not opened for read"; break; - case D_GIF_ERR_IMAGE_DEFECT: + case D_GIF_ERR_IMAGE_DEFECT: Err = "Image is defective, decoding aborted"; break; - case D_GIF_ERR_EOF_TOO_SOON: + case D_GIF_ERR_EOF_TOO_SOON: Err = "Image EOF detected before image complete"; break; - default: + default: Err = NULL; break; } diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h index 6cabd0866ed1e..bd00af64161db 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h @@ -33,27 +33,25 @@ SPDX-License-Identifier: MIT #ifndef _GIF_HASH_H_ #define _GIF_HASH_H_ -/** Begin JDK modifications to support building on Windows **/ #ifndef _WIN32 #include -#endif -/** End JDK modifications to support building on Windows **/ +#endif /* _WIN32 */ #include -#define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */ -#define HT_KEY_MASK 0x1FFF /* 13bits keys */ -#define HT_KEY_NUM_BITS 13 /* 13bits keys */ -#define HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */ -#define HT_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ +#define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */ +#define HT_KEY_MASK 0x1FFF /* 13bits keys */ +#define HT_KEY_NUM_BITS 13 /* 13bits keys */ +#define HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */ +#define HT_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ /* The 32 bits of the long are divided into two parts for the key & code: */ /* 1. The code is 12 bits as our compression algorithm is limited to 12bits */ -/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */ +/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */ /* The key is the upper 20 bits. The code is the lower 12. */ -#define HT_GET_KEY(l) (l >> 12) -#define HT_GET_CODE(l) (l & 0x0FFF) -#define HT_PUT_KEY(l) (l << 12) -#define HT_PUT_CODE(l) (l & 0x0FFF) +#define HT_GET_KEY(l) (l >> 12) +#define HT_GET_CODE(l) (l & 0x0FFF) +#define HT_PUT_KEY(l) (l << 12) +#define HT_PUT_CODE(l) (l & 0x0FFF) typedef struct GifHashTableType { uint32_t HTable[HT_SIZE]; diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h index f739b36adfd0f..74a2e969c0dea 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h @@ -39,27 +39,19 @@ extern "C" { #define GIFLIB_MAJOR 5 #define GIFLIB_MINOR 2 -#define GIFLIB_RELEASE 1 +#define GIFLIB_RELEASE 2 -#define GIF_ERROR 0 -#define GIF_OK 1 +#define GIF_ERROR 0 +#define GIF_OK 1 +#include #include -/** Begin JDK modifications to support building using old compilers**/ -//#include -#ifdef bool -#undef bool -#endif -typedef int bool; -#define false 0 -#define true 1 -/** End JDK modifications to support building using old compilers**/ - -#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ + +#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1 -#define GIF_VERSION_POS 3 /* Version first character in stamp. */ -#define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp. */ -#define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp. */ +#define GIF_VERSION_POS 3 /* Version first character in stamp. */ +#define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp. */ +#define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp. */ typedef unsigned char GifPixelType; typedef unsigned char *GifRowType; @@ -75,24 +67,24 @@ typedef struct ColorMapObject { int ColorCount; int BitsPerPixel; bool SortFlag; - GifColorType *Colors; /* on malloc(3) heap */ + GifColorType *Colors; /* on malloc(3) heap */ } ColorMapObject; typedef struct GifImageDesc { - GifWord Left, Top, Width, Height; /* Current image dimensions. */ - bool Interlace; /* Sequential/Interlaced lines. */ - ColorMapObject *ColorMap; /* The local color map */ + GifWord Left, Top, Width, Height; /* Current image dimensions. */ + bool Interlace; /* Sequential/Interlaced lines. */ + ColorMapObject *ColorMap; /* The local color map */ } GifImageDesc; typedef struct ExtensionBlock { int ByteCount; - GifByteType *Bytes; /* on malloc(3) heap */ - int Function; /* The block function code */ -#define CONTINUE_EXT_FUNC_CODE 0x00 /* continuation subblock */ -#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ -#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */ -#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ -#define APPLICATION_EXT_FUNC_CODE 0xff /* application block (GIF89) */ + GifByteType *Bytes; /* on malloc(3) heap */ + int Function; /* The block function code */ +#define CONTINUE_EXT_FUNC_CODE 0x00 /* continuation subblock */ +#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ +#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */ +#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ +#define APPLICATION_EXT_FUNC_CODE 0xff /* application block (GIF89) */ } ExtensionBlock; typedef struct SavedImage { @@ -103,22 +95,22 @@ typedef struct SavedImage { } SavedImage; typedef struct GifFileType { - GifWord SWidth, SHeight; /* Size of virtual canvas */ - GifWord SColorResolution; /* How many colors can we generate? */ - GifWord SBackGroundColor; /* Background color for virtual canvas */ - GifByteType AspectByte; /* Used to compute pixel aspect ratio */ - ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */ - int ImageCount; /* Number of current image (both APIs) */ - GifImageDesc Image; /* Current image (low-level API) */ - SavedImage *SavedImages; /* Image sequence (high-level API) */ - int ExtensionBlockCount; /* Count extensions past last image */ + GifWord SWidth, SHeight; /* Size of virtual canvas */ + GifWord SColorResolution; /* How many colors can we generate? */ + GifWord SBackGroundColor; /* Background color for virtual canvas */ + GifByteType AspectByte; /* Used to compute pixel aspect ratio */ + ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */ + int ImageCount; /* Number of current image (both APIs) */ + GifImageDesc Image; /* Current image (low-level API) */ + SavedImage *SavedImages; /* Image sequence (high-level API) */ + int ExtensionBlockCount; /* Count extensions past last image */ ExtensionBlock *ExtensionBlocks; /* Extensions past last image */ int Error; /* Last error condition reported */ void *UserData; /* hook to attach user data (TVT) */ void *Private; /* Don't mess with this! */ } GifFileType; -#define GIF_ASPECT_RATIO(n) ((n)+15.0/64.0) +#define GIF_ASPECT_RATIO(n) ((n) + 15.0 / 64.0) typedef enum { UNDEFINED_RECORD_TYPE, @@ -129,12 +121,12 @@ typedef enum { } GifRecordType; /* func type to read gif data from arbitrary sources (TVT) */ -typedef int (*InputFunc) (GifFileType *, GifByteType *, int); +typedef int (*InputFunc)(GifFileType *, GifByteType *, int); /* func type to write gif data to arbitrary targets. * Returns count of bytes written. (MRB) */ -typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int); +typedef int (*OutputFunc)(GifFileType *, const GifByteType *, int); /****************************************************************************** GIF89 structures @@ -142,14 +134,14 @@ typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int); typedef struct GraphicsControlBlock { int DisposalMode; -#define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */ -#define DISPOSE_DO_NOT 1 /* Leave image in place */ -#define DISPOSE_BACKGROUND 2 /* Set area too background color */ -#define DISPOSE_PREVIOUS 3 /* Restore to previous content */ - bool UserInputFlag; /* User confirmation required before disposal */ - int DelayTime; /* pre-display delay in 0.01sec units */ - int TransparentColor; /* Palette index for transparency, -1 if none */ -#define NO_TRANSPARENT_COLOR -1 +#define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */ +#define DISPOSE_DO_NOT 1 /* Leave image in place */ +#define DISPOSE_BACKGROUND 2 /* Set area too background color */ +#define DISPOSE_PREVIOUS 3 /* Restore to previous content */ + bool UserInputFlag; /* User confirmation required before disposal */ + int DelayTime; /* pre-display delay in 0.01sec units */ + int TransparentColor; /* Palette index for transparency, -1 if none */ +#define NO_TRANSPARENT_COLOR -1 } GraphicsControlBlock; /****************************************************************************** @@ -161,49 +153,44 @@ GifFileType *EGifOpenFileName(const char *GifFileName, const bool GifTestExistence, int *Error); GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error); GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error); -int EGifSpew(GifFileType * GifFile); +int EGifSpew(GifFileType *GifFile); const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */ int EGifCloseFile(GifFileType *GifFile, int *ErrorCode); -#define E_GIF_SUCCEEDED 0 -#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */ -#define E_GIF_ERR_WRITE_FAILED 2 -#define E_GIF_ERR_HAS_SCRN_DSCR 3 -#define E_GIF_ERR_HAS_IMAG_DSCR 4 -#define E_GIF_ERR_NO_COLOR_MAP 5 -#define E_GIF_ERR_DATA_TOO_BIG 6 +#define E_GIF_SUCCEEDED 0 +#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */ +#define E_GIF_ERR_WRITE_FAILED 2 +#define E_GIF_ERR_HAS_SCRN_DSCR 3 +#define E_GIF_ERR_HAS_IMAG_DSCR 4 +#define E_GIF_ERR_NO_COLOR_MAP 5 +#define E_GIF_ERR_DATA_TOO_BIG 6 #define E_GIF_ERR_NOT_ENOUGH_MEM 7 -#define E_GIF_ERR_DISK_IS_FULL 8 -#define E_GIF_ERR_CLOSE_FAILED 9 -#define E_GIF_ERR_NOT_WRITEABLE 10 +#define E_GIF_ERR_DISK_IS_FULL 8 +#define E_GIF_ERR_CLOSE_FAILED 9 +#define E_GIF_ERR_NOT_WRITEABLE 10 /* These are legacy. You probably do not want to call them directly */ -int EGifPutScreenDesc(GifFileType *GifFile, - const int GifWidth, const int GifHeight, - const int GifColorRes, +int EGifPutScreenDesc(GifFileType *GifFile, const int GifWidth, + const int GifHeight, const int GifColorRes, const int GifBackGround, const ColorMapObject *GifColorMap); -int EGifPutImageDesc(GifFileType *GifFile, - const int GifLeft, const int GifTop, +int EGifPutImageDesc(GifFileType *GifFile, const int GifLeft, const int GifTop, const int GifWidth, const int GifHeight, const bool GifInterlace, const ColorMapObject *GifColorMap); void EGifSetGifVersion(GifFileType *GifFile, const bool gif89); -int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine, - int GifLineLen); +int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen); int EGifPutPixel(GifFileType *GifFile, const GifPixelType GifPixel); int EGifPutComment(GifFileType *GifFile, const char *GifComment); int EGifPutExtensionLeader(GifFileType *GifFile, const int GifExtCode); -int EGifPutExtensionBlock(GifFileType *GifFile, - const int GifExtLen, const void *GifExtension); +int EGifPutExtensionBlock(GifFileType *GifFile, const int GifExtLen, + const void *GifExtension); int EGifPutExtensionTrailer(GifFileType *GifFile); int EGifPutExtension(GifFileType *GifFile, const int GifExtCode, - const int GifExtLen, - const void *GifExtension); + const int GifExtLen, const void *GifExtension); int EGifPutCode(GifFileType *GifFile, int GifCodeSize, const GifByteType *GifCodeBlock); -int EGifPutCodeNext(GifFileType *GifFile, - const GifByteType *GifCodeBlock); +int EGifPutCodeNext(GifFileType *GifFile, const GifByteType *GifCodeBlock); /****************************************************************************** GIF decoding routines @@ -212,24 +199,25 @@ int EGifPutCodeNext(GifFileType *GifFile, /* Main entry points */ GifFileType *DGifOpenFileName(const char *GifFileName, int *Error); GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error); -int DGifSlurp(GifFileType * GifFile); -GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */ - int DGifCloseFile(GifFileType * GifFile, int *ErrorCode); - -#define D_GIF_SUCCEEDED 0 -#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ -#define D_GIF_ERR_READ_FAILED 102 -#define D_GIF_ERR_NOT_GIF_FILE 103 -#define D_GIF_ERR_NO_SCRN_DSCR 104 -#define D_GIF_ERR_NO_IMAG_DSCR 105 -#define D_GIF_ERR_NO_COLOR_MAP 106 -#define D_GIF_ERR_WRONG_RECORD 107 -#define D_GIF_ERR_DATA_TOO_BIG 108 +int DGifSlurp(GifFileType *GifFile); +GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, + int *Error); /* new one (TVT) */ +int DGifCloseFile(GifFileType *GifFile, int *ErrorCode); + +#define D_GIF_SUCCEEDED 0 +#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ +#define D_GIF_ERR_READ_FAILED 102 +#define D_GIF_ERR_NOT_GIF_FILE 103 +#define D_GIF_ERR_NO_SCRN_DSCR 104 +#define D_GIF_ERR_NO_IMAG_DSCR 105 +#define D_GIF_ERR_NO_COLOR_MAP 106 +#define D_GIF_ERR_WRONG_RECORD 107 +#define D_GIF_ERR_DATA_TOO_BIG 108 #define D_GIF_ERR_NOT_ENOUGH_MEM 109 -#define D_GIF_ERR_CLOSE_FAILED 110 -#define D_GIF_ERR_NOT_READABLE 111 -#define D_GIF_ERR_IMAGE_DEFECT 112 -#define D_GIF_ERR_EOF_TOO_SOON 113 +#define D_GIF_ERR_CLOSE_FAILED 110 +#define D_GIF_ERR_NOT_READABLE 111 +#define D_GIF_ERR_IMAGE_DEFECT 112 +#define D_GIF_ERR_EOF_TOO_SOON 113 /* These are legacy. You probably do not want to call them directly */ int DGifGetScreenDesc(GifFileType *GifFile); @@ -247,11 +235,10 @@ int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock); int DGifGetLZCodes(GifFileType *GifFile, int *GifCode); const char *DGifGetGifVersion(GifFileType *GifFile); - /****************************************************************************** Error handling and reporting. ******************************************************************************/ -extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */ +extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */ /***************************************************************************** Everything below this point is new after version 1.2, supporting `slurp @@ -263,26 +250,26 @@ extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */ ******************************************************************************/ extern ColorMapObject *GifMakeMapObject(int ColorCount, - const GifColorType *ColorMap); + const GifColorType *ColorMap); extern void GifFreeMapObject(ColorMapObject *Object); extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1, - const ColorMapObject *ColorIn2, - GifPixelType ColorTransIn2[]); + const ColorMapObject *ColorIn2, + GifPixelType ColorTransIn2[]); extern int GifBitSize(int n); /****************************************************************************** Support for the in-core structures allocation (slurp mode). ******************************************************************************/ -extern void GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]); +extern void GifApplyTranslation(SavedImage *Image, + const GifPixelType Translation[]); extern int GifAddExtensionBlock(int *ExtensionBlock_Count, - ExtensionBlock **ExtensionBlocks, - int Function, + ExtensionBlock **ExtensionBlocks, int Function, unsigned int Len, unsigned char ExtData[]); extern void GifFreeExtensions(int *ExtensionBlock_Count, ExtensionBlock **ExtensionBlocks); extern SavedImage *GifMakeSavedImage(GifFileType *GifFile, - const SavedImage *CopyFrom); + const SavedImage *CopyFrom); extern void GifFreeSavedImages(GifFileType *GifFile); /****************************************************************************** @@ -295,37 +282,31 @@ int DGifExtensionToGCB(const size_t GifExtensionLength, size_t EGifGCBToExtension(const GraphicsControlBlock *GCB, GifByteType *GifExtension); -int DGifSavedExtensionToGCB(GifFileType *GifFile, - int ImageIndex, +int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex, GraphicsControlBlock *GCB); int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB, - GifFileType *GifFile, - int ImageIndex); + GifFileType *GifFile, int ImageIndex); /****************************************************************************** The library's internal utility font ******************************************************************************/ -#define GIF_FONT_WIDTH 8 +#define GIF_FONT_WIDTH 8 #define GIF_FONT_HEIGHT 8 extern const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH]; -extern void GifDrawText8x8(SavedImage *Image, - const int x, const int y, - const char *legend, const int color); +extern void GifDrawText8x8(SavedImage *Image, const int x, const int y, + const char *legend, const int color); -extern void GifDrawBox(SavedImage *Image, - const int x, const int y, - const int w, const int d, const int color); +extern void GifDrawBox(SavedImage *Image, const int x, const int y, const int w, + const int d, const int color); -extern void GifDrawRectangle(SavedImage *Image, - const int x, const int y, - const int w, const int d, const int color); +extern void GifDrawRectangle(SavedImage *Image, const int x, const int y, + const int w, const int d, const int color); -extern void GifDrawBoxedText8x8(SavedImage *Image, - const int x, const int y, - const char *legend, - const int border, const int bg, const int fg); +extern void GifDrawBoxedText8x8(SavedImage *Image, const int x, const int y, + const char *legend, const int border, + const int bg, const int fg); #ifdef __cplusplus } diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h index 4f832676ffcd5..f905e0d7b4809 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h @@ -33,52 +33,54 @@ SPDX-License-Identifier: MIT #ifndef _GIF_LIB_PRIVATE_H #define _GIF_LIB_PRIVATE_H -#include "gif_lib.h" #include "gif_hash.h" +#include "gif_lib.h" #ifndef SIZE_MAX - #define SIZE_MAX UINTPTR_MAX +#define SIZE_MAX UINTPTR_MAX #endif -#define EXTENSION_INTRODUCER 0x21 -#define DESCRIPTOR_INTRODUCER 0x2c -#define TERMINATOR_INTRODUCER 0x3b +#define EXTENSION_INTRODUCER 0x21 +#define DESCRIPTOR_INTRODUCER 0x2c +#define TERMINATOR_INTRODUCER 0x3b -#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ -#define LZ_BITS 12 +#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ +#define LZ_BITS 12 -#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */ -#define FIRST_CODE 4097 /* Impossible code, to signal first. */ -#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ +#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */ +#define FIRST_CODE 4097 /* Impossible code, to signal first. */ +#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ -#define FILE_STATE_WRITE 0x01 -#define FILE_STATE_SCREEN 0x02 -#define FILE_STATE_IMAGE 0x04 -#define FILE_STATE_READ 0x08 +#define FILE_STATE_WRITE 0x01 +#define FILE_STATE_SCREEN 0x02 +#define FILE_STATE_IMAGE 0x04 +#define FILE_STATE_READ 0x08 -#define IS_READABLE(Private) (Private->FileState & FILE_STATE_READ) -#define IS_WRITEABLE(Private) (Private->FileState & FILE_STATE_WRITE) +#define IS_READABLE(Private) (Private->FileState & FILE_STATE_READ) +#define IS_WRITEABLE(Private) (Private->FileState & FILE_STATE_WRITE) typedef struct GifFilePrivateType { - GifWord FileState, FileHandle, /* Where all this data goes to! */ - BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */ - ClearCode, /* The CLEAR LZ code. */ - EOFCode, /* The EOF LZ code. */ - RunningCode, /* The next code algorithm can generate. */ - RunningBits, /* The number of bits required to represent RunningCode. */ - MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */ - LastCode, /* The code before the current code. */ - CrntCode, /* Current algorithm code. */ - StackPtr, /* For character stack (see below). */ - CrntShiftState; /* Number of bits in CrntShiftDWord. */ - unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ - unsigned long PixelCount; /* Number of pixels in image. */ - FILE *File; /* File as stream. */ - InputFunc Read; /* function to read gif input (TVT) */ - OutputFunc Write; /* function to write gif output (MRB) */ - GifByteType Buf[256]; /* Compressed input is buffered here. */ + GifWord FileState, FileHandle, /* Where all this data goes to! */ + BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */ + ClearCode, /* The CLEAR LZ code. */ + EOFCode, /* The EOF LZ code. */ + RunningCode, /* The next code algorithm can generate. */ + RunningBits, /* The number of bits required to represent + RunningCode. */ + MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. + */ + LastCode, /* The code before the current code. */ + CrntCode, /* Current algorithm code. */ + StackPtr, /* For character stack (see below). */ + CrntShiftState; /* Number of bits in CrntShiftDWord. */ + unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ + unsigned long PixelCount; /* Number of pixels in image. */ + FILE *File; /* File as stream. */ + InputFunc Read; /* function to read gif input (TVT) */ + OutputFunc Write; /* function to write gif output (MRB) */ + GifByteType Buf[256]; /* Compressed input is buffered here. */ GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ - GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ + GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ GifPrefixType Prefix[LZ_MAX_CODE + 1]; GifHashTableType *HashTable; bool gif89; diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c b/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c index 75b74b4fba0a2..5aef304455813 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c @@ -30,59 +30,59 @@ SPDX-License-Identifier: MIT ****************************************************************************/ -#include #include +#include #include #include "gif_lib.h" #include "gif_lib_private.h" -#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) /****************************************************************************** Miscellaneous utility functions ******************************************************************************/ /* return smallest bitfield size n will fit in */ -int -GifBitSize(int n) -{ +int GifBitSize(int n) { register int i; - for (i = 1; i <= 8; i++) - if ((1 << i) >= n) + for (i = 1; i <= 8; i++) { + if ((1 << i) >= n) { break; + } + } return (i); } /****************************************************************************** - Color map object functions + Color map object functions ******************************************************************************/ /* * Allocate a color map of given size; initialize with contents of * ColorMap if that pointer is non-NULL. */ -ColorMapObject * -GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) -{ +ColorMapObject *GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) { ColorMapObject *Object; /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to - * make the user know that or should we automatically round up instead? */ + * make the user know that or should we automatically round up instead? + */ if (ColorCount != (1 << GifBitSize(ColorCount))) { - return ((ColorMapObject *) NULL); + return ((ColorMapObject *)NULL); } Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); - if (Object == (ColorMapObject *) NULL) { - return ((ColorMapObject *) NULL); + if (Object == (ColorMapObject *)NULL) { + return ((ColorMapObject *)NULL); } - Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); - if (Object->Colors == (GifColorType *) NULL) { + Object->Colors = + (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); + if (Object->Colors == (GifColorType *)NULL) { free(Object); - return ((ColorMapObject *) NULL); + return ((ColorMapObject *)NULL); } Object->ColorCount = ColorCount; @@ -90,19 +90,17 @@ GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) Object->SortFlag = false; if (ColorMap != NULL) { - memcpy((char *)Object->Colors, - (char *)ColorMap, ColorCount * sizeof(GifColorType)); + memcpy((char *)Object->Colors, (char *)ColorMap, + ColorCount * sizeof(GifColorType)); } return (Object); } /******************************************************************************* -Free a color map object + Free a color map object *******************************************************************************/ -void -GifFreeMapObject(ColorMapObject *Object) -{ +void GifFreeMapObject(ColorMapObject *Object) { if (Object != NULL) { (void)free(Object->Colors); (void)free(Object); @@ -110,17 +108,14 @@ GifFreeMapObject(ColorMapObject *Object) } #ifdef DEBUG -void -DumpColorMap(ColorMapObject *Object, - FILE * fp) -{ +void DumpColorMap(ColorMapObject *Object, FILE *fp) { if (Object != NULL) { int i, j, Len = Object->ColorCount; for (i = 0; i < Len; i += 4) { for (j = 0; j < 4 && j < Len; j++) { - (void)fprintf(fp, "%3d: %02x %02x %02x ", i + j, - Object->Colors[i + j].Red, + (void)fprintf(fp, "%3d: %02x %02x %02x ", + i + j, Object->Colors[i + j].Red, Object->Colors[i + j].Green, Object->Colors[i + j].Blue); } @@ -137,11 +132,9 @@ DumpColorMap(ColorMapObject *Object, copied iff they didn't exist before. ColorTransIn2 maps the old ColorIn2 into the ColorUnion color map table./ *******************************************************************************/ -ColorMapObject * -GifUnionColorMap(const ColorMapObject *ColorIn1, - const ColorMapObject *ColorIn2, - GifPixelType ColorTransIn2[]) -{ +ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1, + const ColorMapObject *ColorIn2, + GifPixelType ColorTransIn2[]) { int i, j, CrntSlot, RoundUpTo, NewGifBitSize; ColorMapObject *ColorUnion; @@ -152,17 +145,19 @@ GifUnionColorMap(const ColorMapObject *ColorIn1, */ /* Allocate table which will hold the result for sure. */ - ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount, - ColorIn2->ColorCount) * 2, NULL); + ColorUnion = GifMakeMapObject( + MAX(ColorIn1->ColorCount, ColorIn2->ColorCount) * 2, NULL); - if (ColorUnion == NULL) + if (ColorUnion == NULL) { return (NULL); + } /* * Copy ColorIn1 to ColorUnion. */ - for (i = 0; i < ColorIn1->ColorCount; i++) + for (i = 0; i < ColorIn1->ColorCount; i++) { ColorUnion->Colors[i] = ColorIn1->Colors[i]; + } CrntSlot = ColorIn1->ColorCount; /* @@ -172,22 +167,25 @@ GifUnionColorMap(const ColorMapObject *ColorIn1, * of table 1. This is very useful if your display is limited to * 16 colors. */ - while (ColorIn1->Colors[CrntSlot - 1].Red == 0 - && ColorIn1->Colors[CrntSlot - 1].Green == 0 - && ColorIn1->Colors[CrntSlot - 1].Blue == 0) + while (ColorIn1->Colors[CrntSlot - 1].Red == 0 && + ColorIn1->Colors[CrntSlot - 1].Green == 0 && + ColorIn1->Colors[CrntSlot - 1].Blue == 0) { CrntSlot--; + } /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { /* Let's see if this color already exists: */ - for (j = 0; j < ColorIn1->ColorCount; j++) - if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], - sizeof(GifColorType)) == 0) + for (j = 0; j < ColorIn1->ColorCount; j++) { + if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], + sizeof(GifColorType)) == 0) { break; + } + } - if (j < ColorIn1->ColorCount) - ColorTransIn2[i] = j; /* color exists in Color1 */ - else { + if (j < ColorIn1->ColorCount) { + ColorTransIn2[i] = j; /* color exists in Color1 */ + } else { /* Color is new - copy it to a new slot: */ ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; ColorTransIn2[i] = CrntSlot++; @@ -196,7 +194,7 @@ GifUnionColorMap(const ColorMapObject *ColorIn1, if (CrntSlot > 256) { GifFreeMapObject(ColorUnion); - return ((ColorMapObject *) NULL); + return ((ColorMapObject *)NULL); } NewGifBitSize = GifBitSize(CrntSlot); @@ -210,16 +208,17 @@ GifUnionColorMap(const ColorMapObject *ColorIn1, * We know these slots exist because of the way ColorUnion's * start dimension was computed. */ - for (j = CrntSlot; j < RoundUpTo; j++) + for (j = CrntSlot; j < RoundUpTo; j++) { Map[j].Red = Map[j].Green = Map[j].Blue = 0; + } /* perhaps we can shrink the map? */ if (RoundUpTo < ColorUnion->ColorCount) { - GifColorType *new_map = (GifColorType *)reallocarray(Map, - RoundUpTo, sizeof(GifColorType)); - if( new_map == NULL ) { + GifColorType *new_map = (GifColorType *)reallocarray( + Map, RoundUpTo, sizeof(GifColorType)); + if (new_map == NULL) { GifFreeMapObject(ColorUnion); - return ((ColorMapObject *) NULL); + return ((ColorMapObject *)NULL); } ColorUnion->Colors = new_map; } @@ -234,49 +233,49 @@ GifUnionColorMap(const ColorMapObject *ColorIn1, /******************************************************************************* Apply a given color translation to the raster bits of an image *******************************************************************************/ -void -GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]) -{ +void GifApplyTranslation(SavedImage *Image, const GifPixelType Translation[]) { register int i; - register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; + register int RasterSize = + Image->ImageDesc.Height * Image->ImageDesc.Width; - for (i = 0; i < RasterSize; i++) + for (i = 0; i < RasterSize; i++) { Image->RasterBits[i] = Translation[Image->RasterBits[i]]; + } } /****************************************************************************** Extension record functions ******************************************************************************/ -int -GifAddExtensionBlock(int *ExtensionBlockCount, - ExtensionBlock **ExtensionBlocks, - int Function, - unsigned int Len, - unsigned char ExtData[]) -{ +int GifAddExtensionBlock(int *ExtensionBlockCount, + ExtensionBlock **ExtensionBlocks, int Function, + unsigned int Len, unsigned char ExtData[]) { ExtensionBlock *ep; - if (*ExtensionBlocks == NULL) - *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); - else { - ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray - (*ExtensionBlocks, (*ExtensionBlockCount + 1), - sizeof(ExtensionBlock)); - if( ep_new == NULL ) + if (*ExtensionBlocks == NULL) { + *ExtensionBlocks = + (ExtensionBlock *)malloc(sizeof(ExtensionBlock)); + } else { + ExtensionBlock *ep_new = (ExtensionBlock *)reallocarray( + *ExtensionBlocks, (*ExtensionBlockCount + 1), + sizeof(ExtensionBlock)); + if (ep_new == NULL) { return (GIF_ERROR); + } *ExtensionBlocks = ep_new; } - if (*ExtensionBlocks == NULL) + if (*ExtensionBlocks == NULL) { return (GIF_ERROR); + } ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; ep->Function = Function; - ep->ByteCount=Len; + ep->ByteCount = Len; ep->Bytes = (GifByteType *)malloc(ep->ByteCount); - if (ep->Bytes == NULL) + if (ep->Bytes == NULL) { return (GIF_ERROR); + } if (ExtData != NULL) { memcpy(ep->Bytes, ExtData, Len); @@ -285,38 +284,36 @@ GifAddExtensionBlock(int *ExtensionBlockCount, return (GIF_OK); } -void -GifFreeExtensions(int *ExtensionBlockCount, - ExtensionBlock **ExtensionBlocks) -{ +void GifFreeExtensions(int *ExtensionBlockCount, + ExtensionBlock **ExtensionBlocks) { ExtensionBlock *ep; - if (*ExtensionBlocks == NULL) + if (*ExtensionBlocks == NULL) { return; + } for (ep = *ExtensionBlocks; - ep < (*ExtensionBlocks + *ExtensionBlockCount); - ep++) + ep < (*ExtensionBlocks + *ExtensionBlockCount); ep++) { (void)free((char *)ep->Bytes); + } (void)free((char *)*ExtensionBlocks); *ExtensionBlocks = NULL; *ExtensionBlockCount = 0; } /****************************************************************************** - Image block allocation functions + Image block allocation functions ******************************************************************************/ /* Private Function: * Frees the last image in the GifFile->SavedImages array */ -void -FreeLastSavedImage(GifFileType *GifFile) -{ +void FreeLastSavedImage(GifFileType *GifFile) { SavedImage *sp; - if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) + if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { return; + } /* Remove one SavedImage from the GifFile */ GifFile->ImageCount--; @@ -329,54 +326,58 @@ FreeLastSavedImage(GifFileType *GifFile) } /* Deallocate the image data */ - if (sp->RasterBits != NULL) + if (sp->RasterBits != NULL) { free((char *)sp->RasterBits); + } /* Deallocate any extensions */ GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); /*** FIXME: We could realloc the GifFile->SavedImages structure but is * there a point to it? Saves some memory but we'd have to do it every - * time. If this is used in GifFreeSavedImages then it would be inefficient - * (The whole array is going to be deallocated.) If we just use it when - * we want to free the last Image it's convenient to do it here. + * time. If this is used in GifFreeSavedImages then it would be + * inefficient (The whole array is going to be deallocated.) If we just + * use it when we want to free the last Image it's convenient to do it + * here. */ } /* * Append an image block to the SavedImages array */ -SavedImage * -GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) -{ - if (GifFile->SavedImages == NULL) +SavedImage *GifMakeSavedImage(GifFileType *GifFile, + const SavedImage *CopyFrom) { + // cppcheck-suppress ctunullpointer + if (GifFile->SavedImages == NULL) { GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); - else { - SavedImage* newSavedImages = (SavedImage *)reallocarray(GifFile->SavedImages, - (GifFile->ImageCount + 1), sizeof(SavedImage)); - if( newSavedImages == NULL) + } else { + SavedImage *newSavedImages = (SavedImage *)reallocarray( + GifFile->SavedImages, (GifFile->ImageCount + 1), + sizeof(SavedImage)); + if (newSavedImages == NULL) { return ((SavedImage *)NULL); + } GifFile->SavedImages = newSavedImages; } - if (GifFile->SavedImages == NULL) + if (GifFile->SavedImages == NULL) { return ((SavedImage *)NULL); - else { + } else { SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; if (CopyFrom != NULL) { memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); /* - * Make our own allocated copies of the heap fields in the - * copied record. This guards against potential aliasing - * problems. + * Make our own allocated copies of the heap fields in + * the copied record. This guards against potential + * aliasing problems. */ /* first, the local color map */ if (CopyFrom->ImageDesc.ColorMap != NULL) { sp->ImageDesc.ColorMap = GifMakeMapObject( - CopyFrom->ImageDesc.ColorMap->ColorCount, - CopyFrom->ImageDesc.ColorMap->Colors); + CopyFrom->ImageDesc.ColorMap->ColorCount, + CopyFrom->ImageDesc.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); @@ -384,32 +385,36 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) } /* next, the raster */ - sp->RasterBits = (unsigned char *)reallocarray(NULL, - (CopyFrom->ImageDesc.Height * - CopyFrom->ImageDesc.Width), - sizeof(GifPixelType)); + sp->RasterBits = (unsigned char *)reallocarray( + NULL, + (CopyFrom->ImageDesc.Height * + CopyFrom->ImageDesc.Width), + sizeof(GifPixelType)); if (sp->RasterBits == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } memcpy(sp->RasterBits, CopyFrom->RasterBits, - sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * - CopyFrom->ImageDesc.Width); + sizeof(GifPixelType) * + CopyFrom->ImageDesc.Height * + CopyFrom->ImageDesc.Width); /* finally, the extension blocks */ if (CopyFrom->ExtensionBlocks != NULL) { - sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL, - CopyFrom->ExtensionBlockCount, - sizeof(ExtensionBlock)); + sp->ExtensionBlocks = + (ExtensionBlock *)reallocarray( + NULL, CopyFrom->ExtensionBlockCount, + sizeof(ExtensionBlock)); if (sp->ExtensionBlocks == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } - memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, - sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); + memcpy(sp->ExtensionBlocks, + CopyFrom->ExtensionBlocks, + sizeof(ExtensionBlock) * + CopyFrom->ExtensionBlockCount); } - } - else { + } else { memset((char *)sp, '\0', sizeof(SavedImage)); } @@ -417,9 +422,7 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) } } -void -GifFreeSavedImages(GifFileType *GifFile) -{ +void GifFreeSavedImages(GifFileType *GifFile) { SavedImage *sp; if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { @@ -432,10 +435,12 @@ GifFreeSavedImages(GifFileType *GifFile) sp->ImageDesc.ColorMap = NULL; } - if (sp->RasterBits != NULL) + if (sp->RasterBits != NULL) { free((char *)sp->RasterBits); + } - GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); + GifFreeExtensions(&sp->ExtensionBlockCount, + &sp->ExtensionBlocks); } free((char *)GifFile->SavedImages); GifFile->SavedImages = NULL; diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c b/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c index 452df69d7cd4f..7420af674c530 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c @@ -28,24 +28,22 @@ * SPDX-License-Identifier: MIT */ -#include #include #include #include +#include #ifndef SIZE_MAX - #define SIZE_MAX UINTPTR_MAX +#define SIZE_MAX UINTPTR_MAX #endif /* * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW */ -#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) -void * -openbsd_reallocarray(void *optr, size_t nmemb, size_t size) -{ +void *openbsd_reallocarray(void *optr, size_t nmemb, size_t size) { if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) { errno = ENOMEM; @@ -93,7 +91,8 @@ openbsd_reallocarray(void *optr, size_t nmemb, size_t size) * fuzzing on one platform may not detect zero-size allocation * problems on other platforms. */ - if (size == 0 || nmemb == 0) + if (size == 0 || nmemb == 0) { return NULL; + } return realloc(optr, size * nmemb); } From 6f98d8f58f98827ae454c7ce4839de4071d95767 Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Thu, 2 May 2024 16:10:55 +0000 Subject: [PATCH 059/203] 8329692: Add more details to FrameStateTest.java test instructions Reviewed-by: tr, azvegint --- .../Frame/FrameStateTest/FrameStateTest.java | 80 +++++++++---------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/test/jdk/java/awt/Frame/FrameStateTest/FrameStateTest.java b/test/jdk/java/awt/Frame/FrameStateTest/FrameStateTest.java index 496be463513ea..439332e2ce9c8 100644 --- a/test/jdk/java/awt/Frame/FrameStateTest/FrameStateTest.java +++ b/test/jdk/java/awt/Frame/FrameStateTest/FrameStateTest.java @@ -21,15 +21,6 @@ * questions. */ -/* - * FrameStateTest.java - * - * summary: Checks that when setState(Frame.ICONIFIED) is called before - * setVisible(true) the Frame is shown in the proper iconified state. - * The problem was that it did not honor the initial iconic state, but - * instead was shown in the NORMAL state. - */ - import java.awt.Button; import java.awt.Checkbox; import java.awt.CheckboxGroup; @@ -52,9 +43,9 @@ * @test * @bug 4157271 * @summary Checks that when a Frame is created it honors the state it - * was set to. The bug was that if setState(Frame.ICONIFIED) was - * called before setVisible(true) the Frame would be shown in NORMAL - * state instead of ICONIFIED. + * was set to. The bug was that if setState(Frame.ICONIFIED) was + * called before setVisible(true) the Frame would be shown in NORMAL + * state instead of ICONIFIED. * @library /java/awt/regtesthelpers * @build PassFailJFrame * @run main/manual FrameStateTest @@ -68,29 +59,33 @@ This test checks that when setState(Frame.ICONIFIED) is called before setVisible(true) the Frame is shown in the proper iconified state. The problem was that it did not honor the initial iconic state, but instead was shown in the NORMAL state. -


- +


Steps to try to reproduce this problem: -

+

Select the different options for the Frame:

    -
  • {Normal, Non-resizalbe}
  • +
  • {Normal, Non-resizable}
  • {Normal, Resizable}
  • {Iconified, Resizable}
  • -
  • {Iconified, Non-resizalbe}
  • +
  • {Iconified, Non-resizable}
After choosing the Frame's state click the Create Frame button.
- After the Frame (Frame State Test (Window2)) comes - up make sure the proper behavior occurred
- (Frame shown in proper state).
+ After the Frame (Frame State Test (Window2)) comes up make sure the + proper behavior occurred (Frame shown in proper state).
Click the Dispose button to close the Frame.
-


- Do the above steps for all the different Frame state combinations available.
- If you observe the proper behavior the test has passed, Press the Pass button.
- Otherwise the test has failed, Press the Fail button. + Do the above steps for all the different Frame state combinations + available.
+ For "Hide, Iconify and Show" case, the frame is hidden then iconified + hence Window2 is not seen on-screen when shown as the frame is still + in the ICONIFIED state. Window2 is visible on-screen when it is restored + to NORMAL state as observed with "Hide, Iconify, Show and Restore" case. +

+ + If you observe the proper behavior for all the combinations, + press PASS else FAIL.

Note: In Frame State Test (Window2) you can also chose the different buttons to see different Frame behavior.
An example of a problem that @@ -106,9 +101,9 @@ After the Frame (Frame State Test (Window2)) comes Button btnDispose = new Button("Dispose Frame"); CheckboxGroup cbgState = new CheckboxGroup(); CheckboxGroup cbgResize = new CheckboxGroup(); - Checkbox cbIconState = new Checkbox("Frame state ICONIFIED", cbgState, true); - Checkbox cbNormState = new Checkbox("Frame state NORMAL", cbgState, false); - Checkbox cbNonResize = new Checkbox("Frame non-resizable", cbgResize, false); + Checkbox cbIconState = new Checkbox("Frame State ICONIFIED", cbgState, true); + Checkbox cbNormState = new Checkbox("Frame State NORMAL", cbgState, false); + Checkbox cbNonResize = new Checkbox("Frame Non-Resizable", cbgResize, false); Checkbox cbResize = new Checkbox("Frame Resizable", cbgResize, true); CreateFrame icontst; @@ -116,12 +111,12 @@ After the Frame (Frame State Test (Window2)) comes public static void main(String[] args) throws Exception { PassFailJFrame .builder() - .title("GetBoundsResizeTest Instructions") + .title("Frame State and Size Test Instructions") .instructions(INSTRUCTIONS) .testTimeOut(10) - .rows(25) + .rows(27) .columns(70) - .logArea(10) + .logArea(6) .splitUIBottom(() -> new FrameStateTest().createPanel()) .build() .awaitAndCheck(); @@ -149,7 +144,7 @@ public void actionPerformed(ActionEvent evt) { if (evt.getSource() == btnCreate) { btnCreate.setEnabled(false); btnDispose.setEnabled(true); - icontst =new CreateFrame(cbIconState.getState(), cbResize.getState()); + icontst = new CreateFrame(cbIconState.getState(), cbResize.getState()); icontst.setVisible(true); } else if (evt.getSource() == btnDispose) { btnCreate.setEnabled(true); @@ -166,7 +161,7 @@ static class CreateFrame extends Frame String name = "Frame State Test"; CreateFrame(boolean iconified, boolean resizable) { - setTitle("Frame State Test (Window 2)"); + setTitle("Test Window (Window 2)"); isResizable = resizable; @@ -175,13 +170,13 @@ static class CreateFrame extends Frame ((isResizable) ? "RESIZABLE" : "NON-RESIZABLE")); setLayout(new FlowLayout()); - add(b1 = new Button("resizable")); - add(b2 = new Button("resize")); - add(b3 = new Button("iconify")); - add(b4 = new Button("iconify and restore")); - add(b5 = new Button("hide and show")); - add(b6 = new Button("hide, iconify and show")); - add(b7 = new Button("hide, iconify, show, and restore")); + add(b1 = new Button("Resizable")); + add(b2 = new Button("Resize")); + add(b3 = new Button("Iconify")); + add(b4 = new Button("Iconify and Restore")); + add(b5 = new Button("Hide and Show")); + add(b6 = new Button("Hide, Iconify and Show")); + add(b7 = new Button("Hide, Iconify, Show and Restore")); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); @@ -191,10 +186,9 @@ static class CreateFrame extends Frame b7.addActionListener(this); addWindowListener(this); - setBounds(100, 2, 200, 200); + setBounds(100, 2, 300, 200); setState(iconified ? Frame.ICONIFIED : Frame.NORMAL); setResizable(isResizable); - pack(); setVisible(true); } @@ -320,11 +314,11 @@ public void windowOpened(WindowEvent e) { public void stateLog(String message) { PassFailJFrame - .log("[State=%d] %s %s".formatted(getState(), name, message)); + .log("[Current State = %d] %s %s".formatted(getState(), name, message)); } public void stateLog() { - PassFailJFrame.log("[State=" + getState() + "]"); + PassFailJFrame.log("[Current State = " + getState() + "]"); } } } From e2c0cfef1468e1081d1e68f74caae71266815cb6 Mon Sep 17 00:00:00 2001 From: Adam Sotona Date: Thu, 2 May 2024 18:07:42 +0000 Subject: [PATCH 060/203] 8331320: ClassFile API OutOfMemoryError with certain class files Reviewed-by: psandoz --- .../classfile/impl/AbstractInstruction.java | 6 ++ test/jdk/jdk/classfile/LimitsTest.java | 55 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java index 1ee9e1136a59d..4e9a55c77ac2c 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java @@ -262,6 +262,9 @@ public static final class BoundLookupSwitchInstruction this.afterPad = pos + 1 + ((4 - ((pos + 1 - code.codeStart) & 3)) & 3); this.npairs = code.classReader.readInt(afterPad + 4); + if (npairs < 0 || npairs > code.codeLength >> 3) { + throw new IllegalArgumentException("Invalid lookupswitch npairs value: " + npairs); + } } static int size(CodeImpl code, int codeStart, int pos) { @@ -314,6 +317,9 @@ static int size(CodeImpl code, int codeStart, int pos) { int pad = ap - (pos + 1); int low = code.classReader.readInt(ap + 4); int high = code.classReader.readInt(ap + 8); + if (high < low || high - low > code.codeLength >> 2) { + throw new IllegalArgumentException("Invalid tableswitch values low: " + low + " high: " + high); + } int cnt = high - low + 1; return 1 + pad + 12 + cnt * 4; } diff --git a/test/jdk/jdk/classfile/LimitsTest.java b/test/jdk/jdk/classfile/LimitsTest.java index 00aaf32385d8d..5b39c0d498521 100644 --- a/test/jdk/jdk/classfile/LimitsTest.java +++ b/test/jdk/jdk/classfile/LimitsTest.java @@ -23,16 +23,22 @@ /* * @test - * @bug 8320360 8330684 + * @bug 8320360 8330684 8331320 * @summary Testing ClassFile limits. * @run junit LimitsTest */ +import java.lang.classfile.Attributes; +import java.lang.classfile.BufWriter; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.MethodTypeDesc; import java.lang.classfile.ClassFile; +import java.lang.classfile.Opcode; +import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.constantpool.ConstantPoolException; +import jdk.internal.classfile.impl.DirectMethodBuilder; import jdk.internal.classfile.impl.LabelContext; +import jdk.internal.classfile.impl.UnboundAttribute; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -99,4 +105,51 @@ void testInvalidClassEntry() { assertThrows(ConstantPoolException.class, () -> ClassFile.of().parse(new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE, 0, 0, 0, 0, 0, 2, ClassFile.TAG_METHODREF, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}).thisClass()); } + + @Test + void testInvalidLookupSwitch() { + assertThrows(IllegalArgumentException.class, () -> + ClassFile.of().parse(ClassFile.of().build(ClassDesc.of("LookupSwitchClass"), cb -> cb.withMethod( + "lookupSwitchMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, mb -> + ((DirectMethodBuilder)mb).writeAttribute(new UnboundAttribute.AdHocAttribute(Attributes.CODE) { + @Override + public void writeBody(BufWriter b) { + b.writeU2(-1);//max stack + b.writeU2(-1);//max locals + b.writeInt(16); + b.writeU1(Opcode.NOP.bytecode()); + b.writeU1(Opcode.NOP.bytecode()); + b.writeU1(Opcode.NOP.bytecode()); + b.writeU1(Opcode.NOP.bytecode()); + b.writeU1(Opcode.LOOKUPSWITCH.bytecode()); + b.writeU1(0); //padding + b.writeU2(0); //padding + b.writeInt(0); //default + b.writeInt(-2); //npairs to jump back and cause OOME if not checked + b.writeU2(0);//exception handlers + b.writeU2(0);//attributes + }})))).methods().get(0).code().get().elementList()); + } + + @Test + void testInvalidTableSwitch() { + assertThrows(IllegalArgumentException.class, () -> + ClassFile.of().parse(ClassFile.of().build(ClassDesc.of("TableSwitchClass"), cb -> cb.withMethod( + "tableSwitchMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, mb -> + ((DirectMethodBuilder)mb).writeAttribute(new UnboundAttribute.AdHocAttribute(Attributes.CODE) { + @Override + public void writeBody(BufWriter b) { + b.writeU2(-1);//max stack + b.writeU2(-1);//max locals + b.writeInt(16); + b.writeU1(Opcode.TABLESWITCH.bytecode()); + b.writeU1(0); //padding + b.writeU2(0); //padding + b.writeInt(0); //default + b.writeInt(0); //low + b.writeInt(-5); //high to jump back and cause OOME if not checked + b.writeU2(0);//exception handlers + b.writeU2(0);//attributes + }})))).methods().get(0).code().get().elementList()); + } } From 73cdc9a070249791f7d228a93fe5b9335c5f72bd Mon Sep 17 00:00:00 2001 From: Swati Sharma Date: Thu, 2 May 2024 18:28:50 +0000 Subject: [PATCH 061/203] 8326421: Add jtreg test for large arrayCopy disjoint case. Co-authored-by: Steve Dohrmann Reviewed-by: kvn, sviswanathan --- .../arraycopy/TestArrayCopyDisjointLarge.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyDisjointLarge.java diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyDisjointLarge.java b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyDisjointLarge.java new file mode 100644 index 0000000000000..70d983e6ccd92 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyDisjointLarge.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.arraycopy; +import java.util.Random; + +/** + * @test + * @bug 8310159 + * @summary Test large arrayCopy. + * + * @run main/timeout=600 compiler.arraycopy.TestArrayCopyDisjointLarge + * + */ + +public class TestArrayCopyDisjointLarge { + + public static final int ARRLEN = 4194304; + public static int fromPos, toPos; + public static byte[] fromByteArr, toByteArr; + + public static void setup() { + fromPos = 0; + toPos = 0; + + fromByteArr = new byte[ARRLEN]; + toByteArr = new byte[ARRLEN]; + for (int i = 0 ; i < ARRLEN ; i++) { + fromByteArr[i] = (byte)i; + } + } + + public static void validate(String msg, byte[] toByteArr, int length, int fromPos, int toPos) { + for(int i = 0 ; i < length; i++) { + if (fromByteArr[i + fromPos] != toByteArr[i + toPos]) { + System.out.println(msg + "[" + toByteArr.getClass() + "] Result mismtach at i = " + i + + " expected = " + fromByteArr[i + fromPos] + + " actual = " + toByteArr[i + toPos] + + " fromPos = " + fromPos + + " toPos = " + toPos); + throw new Error("Fail"); + } + } + } + + public static void testByte(int length, int fromPos, int toPos) { + System.arraycopy(fromByteArr, fromPos, toByteArr, toPos, length); + validate(" Test ByteArr ", toByteArr, length, fromPos, toPos); + } + + public static void main(String [] args) { + int base_size = 2621440; + Random r = new Random(1024); + int [] lengths = {base_size - 1, base_size, base_size + 1, base_size + 63, base_size + 64, + base_size + 65, base_size + 255, base_size + 256, base_size + 257, + base_size + r.nextInt(2048)}; + setup(); + + for (int i = 0 ; i < 20 ; i++ ) { + testByte(lengths[i % lengths.length], 0, 0); + testByte(lengths[i % lengths.length], 0, 9); + testByte(lengths[i % lengths.length], 9, 0); + testByte(lengths[i % lengths.length], 9, 9); + testByte(lengths[i % lengths.length], r.nextInt(2048) , r.nextInt(2048)); + } + } +} From cd3a607576bede17f48c3d5ebde2bf05f3b615ba Mon Sep 17 00:00:00 2001 From: Ben Perez Date: Thu, 2 May 2024 18:50:38 +0000 Subject: [PATCH 062/203] 8328864: NullPointerException in sun.security.jca.ProviderList.getService() Reviewed-by: weijun --- .../sun/security/jca/ProviderList.java | 8 ++-- .../sun/security/jca/NullPreferredList.java | 41 +++++++++++++++++++ .../sun/security/jca/app-security.properties | 1 + 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 test/jdk/sun/security/jca/NullPreferredList.java create mode 100644 test/jdk/sun/security/jca/app-security.properties diff --git a/src/java.base/share/classes/sun/security/jca/ProviderList.java b/src/java.base/share/classes/sun/security/jca/ProviderList.java index c0ed5cc018b8c..033ad2e9210c4 100644 --- a/src/java.base/share/classes/sun/security/jca/ProviderList.java +++ b/src/java.base/share/classes/sun/security/jca/ProviderList.java @@ -369,17 +369,19 @@ public Service getService(String type, String name) { int i; // Preferred provider list - if (preferredPropList != null && - (pList = preferredPropList.getAll(type, name)) != null) { + if (preferredPropList != null) { + pList = preferredPropList.getAll(type, name); for (i = 0; i < pList.size(); i++) { Provider p = getProvider(pList.get(i).provider); + if (p == null) { + continue; + } Service s = p.getService(type, name); if (s != null) { return s; } } } - for (i = 0; i < configs.length; i++) { Provider p = getProvider(i); Service s = p.getService(type, name); diff --git a/test/jdk/sun/security/jca/NullPreferredList.java b/test/jdk/sun/security/jca/NullPreferredList.java new file mode 100644 index 0000000000000..0a8cf73443c29 --- /dev/null +++ b/test/jdk/sun/security/jca/NullPreferredList.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.*; + +/** + * @test + * @bug 8328864 + * @summary Test that ProviderList.getService checks configs when + * ProviderList.getProvider fails for preferred providers. + * @run main/othervm + * -Djava.security.properties=${test.src}/app-security.properties NullPreferredList + */ + +public class NullPreferredList { + + public static void main(final String[] args) throws Exception { + final KeyStore ks = KeyStore.getInstance("PKCS12"); + System.out.println("Got keystore " + ks); + } +} diff --git a/test/jdk/sun/security/jca/app-security.properties b/test/jdk/sun/security/jca/app-security.properties new file mode 100644 index 0000000000000..1f15a7797c294 --- /dev/null +++ b/test/jdk/sun/security/jca/app-security.properties @@ -0,0 +1 @@ +jdk.security.provider.preferred=KeyStore.PKCS12:NonExistingProvider From 99654ec3fb2c2e7c8d5bf5965aaf45aeb4b88c61 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 2 May 2024 20:18:16 +0000 Subject: [PATCH 063/203] 8331516: Tests should not use the "Classpath" exception form of the legal header Reviewed-by: iris, serb --- test/jdk/java/awt/font/GlyphVector/LayoutCompatTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/jdk/java/awt/font/GlyphVector/LayoutCompatTest.java b/test/jdk/java/awt/font/GlyphVector/LayoutCompatTest.java index 35aa90374d504..11d0c2ee3bcc2 100644 --- a/test/jdk/java/awt/font/GlyphVector/LayoutCompatTest.java +++ b/test/jdk/java/awt/font/GlyphVector/LayoutCompatTest.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. + * 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 From f6cdcc6f65f2a436906541bb8266e69ded17e2e3 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 2 May 2024 20:18:25 +0000 Subject: [PATCH 064/203] 8280988: [XWayland] Click on title to request focus test failures Reviewed-by: honkar, serb --- test/jdk/java/awt/Focus/6981400/Test1.java | 57 ++++-- .../ActualFocusedWindowBlockingTest.java | 43 +++- .../Focus/ModalDialogInFocusEventTest.java | 38 ++-- .../HierarchyBoundsListenerMixingTest.java | 192 +++++++++++------- test/lib/jdk/test/lib/Platform.java | 11 +- 5 files changed, 216 insertions(+), 125 deletions(-) diff --git a/test/jdk/java/awt/Focus/6981400/Test1.java b/test/jdk/java/awt/Focus/6981400/Test1.java index 730e10804faa6..ab60129ba94df 100644 --- a/test/jdk/java/awt/Focus/6981400/Test1.java +++ b/test/jdk/java/awt/Focus/6981400/Test1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @bug 6981400 * @summary Tabbing between textfiled do not work properly when ALT+TAB * @author anton.tarasov - * @library ../../regtesthelpers - * @build Util + * @library /java/awt/regtesthelpers /test/lib + * @build Util jdk.test.lib.Platform * @run main Test1 */ @@ -41,12 +41,28 @@ // The FOCUS_LOST/FOCUS_GAINED events order in the original frame is tracked and should be: // b0 -> b1 -> b2 -> b3. -import java.awt.*; -import java.awt.event.*; +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import javax.swing.*; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +import jdk.test.lib.Platform; import test.java.awt.regtesthelpers.Util; public class Test1 { @@ -72,7 +88,7 @@ public class Test1 { static boolean tracking; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { public void eventDispatched(AWTEvent e) { System.out.println(e); @@ -81,6 +97,7 @@ public void eventDispatched(AWTEvent e) { try { robot = new Robot(); + robot.setAutoDelay(50); } catch (AWTException ex) { throw new RuntimeException("Error: can't create Robot"); } @@ -90,13 +107,13 @@ public void eventDispatched(AWTEvent e) { f0.add(f0b2); f0.add(f0b3); f0.setLayout(new FlowLayout()); - f0.setBounds(0, 100, 400, 200); + f0.setBounds(100, 100, 400, 200); f1.add(f1b0); - f1.setBounds(0, 400, 400, 200); + f1.setBounds(100, 400, 400, 200); f2.add(f2b0); - f2.setBounds(0, 400, 400, 200); + f2.setBounds(100, 400, 400, 200); f0b0.addFocusListener(new FocusAdapter() { @Override @@ -115,6 +132,7 @@ public void focusLost(FocusEvent e) { f0.setVisible(true); Util.waitForIdle(robot); + robot.delay(500); if (!f0b0.isFocusOwner()) { Util.clickOnComp(f0b0, robot); @@ -152,28 +170,29 @@ public void focusLost(FocusEvent e) { System.out.println("\nTest passed."); } - public static void test(Component compToClick) { + public static void test(Component compToClick) throws Exception { tracking = true; robot.keyPress(KeyEvent.VK_TAB); - robot.delay(50); robot.keyRelease(KeyEvent.VK_TAB); - robot.delay(50); + robot.waitForIdle(); robot.keyPress(KeyEvent.VK_TAB); - robot.delay(50); robot.keyRelease(KeyEvent.VK_TAB); - robot.delay(50); + robot.waitForIdle(); robot.keyPress(KeyEvent.VK_TAB); - robot.delay(50); robot.keyRelease(KeyEvent.VK_TAB); + robot.waitForIdle(); - robot.delay(50); Util.clickOnComp(compToClick, robot); - robot.delay(50); - Util.clickOnTitle(f0, robot); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(f0::toFront); + + if (!Platform.isOnWayland()) { + Util.clickOnTitle(f0, robot); + } Util.waitForIdle(robot); diff --git a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java index 1e5b27892087c..35c6b5cdee64c 100644 --- a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java +++ b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,27 @@ @key headful @bug 6314575 @summary Tests that previosly focused owned window doesn't steal focus when an owner's component requests focus. - @library ../../regtesthelpers - @build Util + @library /java/awt/regtesthelpers /test/lib + @build Util jdk.test.lib.Platform @run main ActualFocusedWindowBlockingTest */ -import java.awt.*; -import java.awt.event.*; +import java.awt.AWTEvent; +import java.awt.Button; +import java.awt.Color; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusEvent; +import java.awt.event.WindowEvent; + +import jdk.test.lib.Platform; import test.java.awt.regtesthelpers.Util; public class ActualFocusedWindowBlockingTest { @@ -44,7 +58,7 @@ public class ActualFocusedWindowBlockingTest { Button wButton = new Button("window button") {public String toString() {return "Window_Button";}}; Button aButton = new Button("auxiliary button") {public String toString() {return "Auxiliary_Button";}}; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { ActualFocusedWindowBlockingTest app = new ActualFocusedWindowBlockingTest(); app.init(); app.start(); @@ -68,7 +82,7 @@ public void eventDispatched(AWTEvent e) { tuneAndShowWindows(new Window[] {owner, win, frame}); } - public void start() { + public void start() throws Exception { System.out.println("\nTest started:\n"); // Test 1. @@ -99,7 +113,12 @@ public void start() { clickOnCheckFocus(fButton); clickOnCheckFocus(aButton); - Util.clickOnTitle(owner, robot); + EventQueue.invokeAndWait(owner::toFront); + + if (!Platform.isOnWayland()) { + Util.clickOnTitle(owner, robot); + } + if (!testFocused(fButton)) { throw new TestFailedException("The owner's component [" + fButton + "] couldn't be focused as the most recent focus owner"); } @@ -117,11 +136,15 @@ void tuneAndShowWindows(Window[] arr) { y += 200; Util.waitForIdle(robot); } + robot.delay(500); } - void clickOnCheckFocus(Component c) { + void clickOnCheckFocus(Component c) throws Exception { if (c instanceof Frame) { - Util.clickOnTitle((Frame)c, robot); + EventQueue.invokeAndWait(() -> ((Frame) c).toFront()); + if (!Platform.isOnWayland()) { + Util.clickOnTitle((Frame) c, robot); + } } else { Util.clickOnComp(c, robot); } diff --git a/test/jdk/java/awt/Focus/ModalDialogInFocusEventTest.java b/test/jdk/java/awt/Focus/ModalDialogInFocusEventTest.java index d4f0d65f071e0..4c659819c3c25 100644 --- a/test/jdk/java/awt/Focus/ModalDialogInFocusEventTest.java +++ b/test/jdk/java/awt/Focus/ModalDialogInFocusEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,11 +22,11 @@ */ /* - test + @test + @key headful @bug 4531693 4636269 4681908 4688142 4691646 4721470 @summary Showing modal dialog during dispatching SequencedEvent - @key headful - @run main AutomaticAppletTest + @run main ModalDialogInFocusEventTest */ import java.awt.AWTEvent; @@ -68,6 +68,8 @@ public class ModalDialogInFocusEventTest static final int MAX_STAGE_NUM = stages.length; static final Object stageMonitor = new Object(); + static boolean isOnWayland; + Robot robot = null; Frame frame; Frame oppositeFrame; @@ -209,18 +211,21 @@ public void windowLostFocus(WindowEvent e) { void clickOnFrameTitle(Frame frame) throws InterruptedException, InvocationTargetException { - System.out.println("click on title of " + frame.getName()); - int[] point = new int[2]; - EventQueue.invokeAndWait(() -> { - Point location = frame.getLocationOnScreen(); - Insets insets = frame.getInsets(); - int width = frame.getWidth(); - point[0] = location.x + width / 2; - point[1] = location.y + insets.top / 2; - }); - robot.mouseMove(point[0], point[1]); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + EventQueue.invokeAndWait(frame::toFront); + if (!isOnWayland) { + System.out.println("click on title of " + frame.getName()); + int[] point = new int[2]; + EventQueue.invokeAndWait(() -> { + Point location = frame.getLocationOnScreen(); + Insets insets = frame.getInsets(); + int width = frame.getWidth(); + point[0] = location.x + width / 2; + point[1] = location.y + insets.top / 2; + }); + robot.mouseMove(point[0], point[1]); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } EventQueue.invokeAndWait(frame::requestFocusInWindow); } @@ -344,6 +349,7 @@ public void focusLost(FocusEvent e) { public static void main(String[] args) throws InterruptedException, InvocationTargetException { + isOnWayland = System.getenv("WAYLAND_DISPLAY") != null; ModalDialogInFocusEventTest test = new ModalDialogInFocusEventTest(); test.start(); } diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java b/test/jdk/java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java index 108cdc99d1fd7..3dfdfd8b6b84d 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,12 +21,33 @@ * questions. */ - -import java.awt.*; -import java.awt.event.*; +import java.awt.Button; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.List; +import java.awt.Panel; +import java.awt.Robot; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.HierarchyBoundsListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.InputEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import javax.swing.SwingUtilities; -import java.io.*; + +import jdk.test.lib.Platform; /** * AWT Mixing test for HierarchyBoundsListener ancestors. @@ -37,7 +58,8 @@ * @key headful * @bug 6768230 8221823 * @summary Mixing test for HierarchyBoundsListener ancestors - * @build FrameBorderCounter + * @library /test/lib + * @build FrameBorderCounter jdk.test.lib.Platform * @run main HierarchyBoundsListenerMixingTest */ public class HierarchyBoundsListenerMixingTest { @@ -137,9 +159,9 @@ protected boolean performTest() { robot.mouseMove((int) components[0].getLocationOnScreen().x + components[0].getSize().width / 2, (int) components[0].getLocationOnScreen().y + components[0].getSize().height / 2); robot.delay(delay); - robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.delay(delay); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.delay(delay); resetValues(); @@ -177,45 +199,54 @@ public void run() { robot.delay(delay * 5); resetValues(); - int x = (int) frame.getLocationOnScreen().x; - int y = (int) frame.getLocationOnScreen().y; - int w = frame.getSize().width; - int h = frame.getSize().height; - - robot.mouseMove(x + w + BORDER_SHIFT, y + h / 2); - robot.delay(delay); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(delay); - for (int i = 0; i < 20; i++) { - robot.mouseMove(x + w + i + BORDER_SHIFT, y + h / 2); - robot.delay(50); - } - robot.delay(delay); - robot.mouseRelease(InputEvent.BUTTON1_MASK); - if (! resizeTriggered) { - synchronized (resizeLock) { - try { - resizeLock.wait(delay * 10); - } catch (Exception e) { + int x; + int y; + int w; + int h; + + if (!Platform.isOnWayland()) { + x = frame.getLocationOnScreen().x; + y = frame.getLocationOnScreen().y; + w = frame.getSize().width; + h = frame.getSize().height; + + robot.mouseMove(x + w + BORDER_SHIFT, y + h / 2); + robot.delay(delay); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(delay); + for (int i = 0; i < 20; i++) { + robot.mouseMove(x + w + i + BORDER_SHIFT, y + h / 2); + robot.delay(50); + } + robot.delay(delay); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (!resizeTriggered) { + synchronized (resizeLock) { + try { + resizeLock.wait(delay * 10); + } catch (Exception e) { + } } } - } - for (int i = 0; i < components.length; i++) { - if (! ancestorResized[i]) { - System.err.println("FAIL: Frame resized using mouse action. " + - "Ancestor resized event did not occur for " + - components[i].getClass()); + for (int i = 0; i < components.length; i++) { + if (!ancestorResized[i]) { + System.err.println("FAIL: Frame resized using mouse action. " + + "Ancestor resized event did not occur for " + + components[i].getClass()); + passed = false; + } + } + if (moveCount > 0) { + System.err.println("FAIL: Ancestor moved event occurred when Frame resized using mouse"); passed = false; } - } - if (moveCount > 0) { - System.err.println("FAIL: Ancestor moved event occured when Frame resized using mouse"); - passed = false; + + resetValues(); } - resetValues(); try { EventQueue.invokeAndWait(new Runnable() { public void run() { @@ -250,52 +281,55 @@ public void run() { robot.delay(delay * 10); resetValues(); - x = (int) frame.getLocationOnScreen().x; - y = (int) frame.getLocationOnScreen().y; - w = frame.getSize().width; - h = frame.getSize().height; - - //Click on the dummy frame so that the test frame loses focus. This is to workaround - //a bug in Linux AS. - robot.mouseMove((int) dummy.getLocationOnScreen().x + dummy.getSize().width / 2, - (int) dummy.getLocationOnScreen().y + dummy.getSize().height / 2); - robot.delay(delay); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(delay); - robot.mouseRelease(InputEvent.BUTTON1_MASK); - robot.delay(delay); - robot.mouseMove(x + w / 2, y + 10); - robot.delay(delay); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(delay); - for (int i = 1; i <= 20; i++) { - robot.mouseMove(x + w / 2 + i, y + 10); - robot.delay(50); - } - robot.delay(delay); - robot.mouseRelease(InputEvent.BUTTON1_MASK); - - if (! moveTriggered) { - synchronized (moveLock) { - try { - moveLock.wait(delay * 10); - } catch (Exception e) { + if (!Platform.isOnWayland()) { + x = frame.getLocationOnScreen().x; + y = frame.getLocationOnScreen().y; + w = frame.getSize().width; + h = frame.getSize().height; + + //Click on the dummy frame so that the test frame loses focus. This is to workaround + //a bug in Linux AS. + robot.mouseMove((int) dummy.getLocationOnScreen().x + dummy.getSize().width / 2, + (int) dummy.getLocationOnScreen().y + dummy.getSize().height / 2); + robot.delay(delay); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(delay); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(delay); + + robot.mouseMove(x + w / 2, y + 10); + robot.delay(delay); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(delay); + for (int i = 1; i <= 20; i++) { + robot.mouseMove(x + w / 2 + i, y + 10); + robot.delay(50); + } + robot.delay(delay); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (! moveTriggered) { + synchronized (moveLock) { + try { + moveLock.wait(delay * 10); + } catch (Exception e) { + } } } - } - for (int i = 0; i < components.length; i++) { - if (! ancestorMoved[i]) { - System.err.println("FAIL: Frame moved using mouse action. " + - "Ancestor moved event did not occur for " + components[i].getClass()); + for (int i = 0; i < components.length; i++) { + if (! ancestorMoved[i]) { + System.err.println("FAIL: Frame moved using mouse action. " + + "Ancestor moved event did not occur for " + components[i].getClass()); + passed = false; + } + } + if (resizeCount > 0) { + System.err.println("FAIL: Ancestor resized event occured when Frame moved using mouse"); passed = false; } } - if (resizeCount > 0) { - System.err.println("FAIL: Ancestor resized event occured when Frame moved using mouse"); - passed = false; - } return passed; } @@ -450,7 +484,7 @@ private static void init() throws InterruptedException { // instantiated in the same VM. Being static (and using // static vars), it aint gonna work. Not worrying about // it for now. - public static void main(String args[]) throws InterruptedException { + public static void main(String[] args) throws InterruptedException { mainThread = Thread.currentThread(); try { init(); diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 92663c65d0fd5..e2451fc83664e 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -473,4 +473,13 @@ public static boolean isDefaultCDSArchiveSupported() { public static boolean areCustomLoadersSupportedForCDS() { return (is64bit() && (isLinux() || isOSX() || isWindows())); } + + /** + * Checks if the current system is running on Wayland display server on Linux. + * + * @return {@code true} if the system is running on Wayland display server + */ + public static boolean isOnWayland() { + return System.getenv("WAYLAND_DISPLAY") != null; + } } From 04271dfe7a262379944e2a2cf83a98a3a1b78a74 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Thu, 2 May 2024 21:19:16 +0000 Subject: [PATCH 065/203] 8331331: :tier1 target explanation in doc/testing.md is incorrect Reviewed-by: erikj, dholmes, ihse --- doc/testing.html | 5 +++-- doc/testing.md | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/testing.html b/doc/testing.html index 251475808498b..f907ef3a83868 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -179,8 +179,9 @@

Test selection

The test specifications given in TEST is parsed into fully qualified test descriptors, which clearly and unambigously show which tests will be run. As an example, :tier1 will expand -to -jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1 jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1 jtreg:$(TOPDIR)/test/nashorn:tier1 jtreg:$(TOPDIR)/test/jaxp:tier1. +to include all subcomponent test directories that define `tier1`, +for example: +jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1 jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1 .... You can always submit a list of fully qualified test descriptors in the TEST variable if you want to shortcut the parser.

Common Test Groups

diff --git a/doc/testing.md b/doc/testing.md index 63a869bfc1c0d..9a45283a98b23 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -103,11 +103,11 @@ test runs, the `test TEST="x"` solution needs to be used. The test specifications given in `TEST` is parsed into fully qualified test descriptors, which clearly and unambigously show which tests will be run. As an -example, `:tier1` will expand to `jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1 -jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1 -jtreg:$(TOPDIR)/test/nashorn:tier1 jtreg:$(TOPDIR)/test/jaxp:tier1`. You can -always submit a list of fully qualified test descriptors in the `TEST` variable -if you want to shortcut the parser. +example, `:tier1` will expand to include all subcomponent test directories +that define `tier1`, for example: `jtreg:$(TOPDIR)/test/hotspot/jtreg:tier1 +jtreg:$(TOPDIR)/test/jdk:tier1 jtreg:$(TOPDIR)/test/langtools:tier1 ...`. You +can always submit a list of fully qualified test descriptors in the `TEST` +variable if you want to shortcut the parser. ### Common Test Groups From 01125fa21b733199d4fe670ecf38b82cd917e242 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 2 May 2024 21:29:27 +0000 Subject: [PATCH 066/203] 8331605: jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java test failure Reviewed-by: prr --- .../jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java index f8ce856bddd18..e78e200ac248c 100644 --- a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java +++ b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ private static enum MethodGroup { IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild", "isMusl", "isSlowDebugBuild", "hasSA", "isRoot", "isTieredSupported", "areCustomLoadersSupportedForCDS", "isDefaultCDSArchiveSupported", - "isHardenedOSX", "hasOSXPlistEntries", "isOracleLinux7"); + "isHardenedOSX", "hasOSXPlistEntries", "isOracleLinux7", "isOnWayland"); public final List methodNames; From 6bef0474c8b8773d0d20c0f25c36a2ce9cdbd7e8 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Fri, 3 May 2024 00:28:18 +0000 Subject: [PATCH 067/203] 8272364: Parallel GC adaptive size policy may shrink the heap below MinHeapSize Reviewed-by: ayang, rkennke --- src/hotspot/share/gc/shared/genArguments.cpp | 3 + .../gc/arguments/TestParallelGCErgo.java | 97 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java diff --git a/src/hotspot/share/gc/shared/genArguments.cpp b/src/hotspot/share/gc/shared/genArguments.cpp index da9fc3f9a851e..fa0e675cf7343 100644 --- a/src/hotspot/share/gc/shared/genArguments.cpp +++ b/src/hotspot/share/gc/shared/genArguments.cpp @@ -264,6 +264,9 @@ void GenArguments::initialize_size_info() { // size can be too small. initial_young_size = clamp(scale_by_NewRatio_aligned(InitialHeapSize, GenAlignment), NewSize, max_young_size); + + // Derive MinNewSize from MinHeapSize + MinNewSize = MIN2(scale_by_NewRatio_aligned(MinHeapSize, GenAlignment), initial_young_size); } } diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java b/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java new file mode 100644 index 0000000000000..a84ebc5fe5cc6 --- /dev/null +++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCErgo.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 gc.arguments; + +/* + * @test TestParallelGCErgo + * @bug 8272364 + * @requires vm.gc.Parallel + * @summary Verify ParallelGC minimum young and old ergonomics are setup correctly + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @library / + * @run driver gc.arguments.TestParallelGCErgo + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import java.util.ArrayList; +import java.util.Arrays; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Platform; + +public class TestParallelGCErgo { + private static final long HEAPWORD_SIZE = Platform.is64bit() ? 8 : 4; + // Must be a power of 2 + private static final long GEN_ALIGNMENT = 64 * 1024 * HEAPWORD_SIZE; + + private static final long MINIMUM_HEAP_SIZE = 256 * 1024 * 1024; // 256M + private static final long EXPECTED_MIN_YOUNG = alignDown(MINIMUM_HEAP_SIZE / 3, GEN_ALIGNMENT); + private static final long EXPECTED_MIN_OLD = MINIMUM_HEAP_SIZE - EXPECTED_MIN_YOUNG; // heap size = young size + old size + + // s has to be a power of 2 + private static long alignDown(long s, long align) { + return s & (~(align-1)); + } + + public static void main(String[] args) throws Exception { + ArrayList flagList = new ArrayList(); + flagList.add("-XX:+UseParallelGC"); + flagList.add("-Xms256m"); + flagList.add("-Xmx1g"); + flagList.add("-Xlog:gc+heap=trace"); + flagList.add("-version"); + + OutputAnalyzer output = GCArguments.executeTestJava(flagList); + output.shouldHaveExitValue(0); + + String stdout = output.getStdout(); + long minimumHeap = getFlagValue("Minimum heap", stdout); + if (minimumHeap != MINIMUM_HEAP_SIZE) { + throw new RuntimeException("Wrong value for minimum heap. Expected " + MINIMUM_HEAP_SIZE + " but got " + minimumHeap); + } + + long minimumYoung = getFlagValue("Minimum young", stdout); + if (minimumYoung != EXPECTED_MIN_YOUNG) { + throw new RuntimeException("Wrong value for minimum young. Expected " + EXPECTED_MIN_YOUNG + " but got " + minimumYoung); + } + + long minimumOld = getFlagValue("Minimum old", stdout); + if (minimumOld != EXPECTED_MIN_OLD) { + throw new RuntimeException("Wrong value for minimum old. Expected " + EXPECTED_MIN_OLD + " but got " + minimumOld); + } + } + + private static long getFlagValue(String flag, String where) { + Matcher m = Pattern.compile(flag + " \\d+").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + String match = m.group(); + return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length())); + } + +} From 7c1fad4fb6c387bbfb72b3f96b610e7cbc2ef312 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 3 May 2024 05:11:52 +0000 Subject: [PATCH 068/203] 8329559: Test javax/swing/JFrame/bug4419914.java failed because The End and Start buttons are not placed correctly and Tab focus does not move as expected Reviewed-by: abhiscxk, honkar, dnguyen --- test/jdk/javax/swing/JFrame/bug4419914.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/jdk/javax/swing/JFrame/bug4419914.java b/test/jdk/javax/swing/JFrame/bug4419914.java index 5e15d3c8f9167..4574b1ac3d6ff 100644 --- a/test/jdk/javax/swing/JFrame/bug4419914.java +++ b/test/jdk/javax/swing/JFrame/bug4419914.java @@ -53,8 +53,8 @@ public static void main(String[] args) throws Exception { PassFailJFrame.builder() .title("Tab movement Instructions") .instructions(INSTRUCTIONS) - .rows(12) - .columns(42) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(48) .testUI(bug4419914::createTestUI) .build() .awaitAndCheck(); @@ -65,11 +65,12 @@ private static JFrame createTestUI() { frame.setFocusCycleRoot(true); frame.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); frame.setLocale(Locale.ENGLISH); - frame.enableInputMethods(false); - frame.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); - frame.setLocale(Locale.ENGLISH); - frame.setLayout(new BorderLayout()); + + frame.getContentPane().setComponentOrientation( + ComponentOrientation.RIGHT_TO_LEFT); + frame.getContentPane().setLocale(Locale.ENGLISH); + frame.getContentPane().setLayout(new BorderLayout()); frame.add(new JButton("SOUTH"), BorderLayout.SOUTH); frame.add(new JButton("CENTER"), BorderLayout.CENTER); frame.add(new JButton("END"), BorderLayout.LINE_END); From 8bc641ebe75ba4c975a99a8646b89ed10a7029f5 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Fri, 3 May 2024 05:49:39 +0000 Subject: [PATCH 069/203] 8331404: IGV: Show line numbers for callees in properties Reviewed-by: tholenstein, thartmann --- src/hotspot/share/opto/idealGraphPrinter.cpp | 47 +++++++++++++------- src/hotspot/share/opto/idealGraphPrinter.hpp | 8 ++-- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index d5858b4bb3f0e..1f0fec8b58a42 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -609,23 +609,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { } } - if (caller != nullptr) { - stringStream bciStream; - ciMethod* last = nullptr; - int last_bci; - while(caller) { - if (caller->has_method()) { - last = caller->method(); - last_bci = caller->bci(); - } - bciStream.print("%d ", caller->bci()); - caller = caller->caller(); - } - print_prop("bci", bciStream.freeze()); - if (last != nullptr && last->has_linenumber_table() && last_bci >= 0) { - print_prop("line", last->line_number_from_bci(last_bci)); - } - } + print_bci_and_line_number(caller); #ifdef ASSERT if (node->debug_orig() != nullptr) { @@ -654,6 +638,35 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { } } +void IdealGraphPrinter::print_bci_and_line_number(JVMState* caller) { + if (caller != nullptr) { + ResourceMark rm; + stringStream bciStream; + stringStream lineStream; + + // Print line and bci numbers for the callee and all entries in the call stack until we reach the root method. + while (caller) { + const int bci = caller->bci(); + bool appended_line = false; + if (caller->has_method()) { + ciMethod* method = caller->method(); + if (method->has_linenumber_table() && bci >= 0) { + lineStream.print("%d ", method->line_number_from_bci(bci)); + appended_line = true; + } + } + if (!appended_line) { + lineStream.print("%s ", "_"); + } + bciStream.print("%d ", bci); + caller = caller->caller(); + } + + print_prop("bci", bciStream.freeze()); + print_prop("line", lineStream.freeze()); + } +} + void IdealGraphPrinter::print_field(const Node* node) { buffer[0] = 0; stringStream ss(buffer, sizeof(buffer) - 1); diff --git a/src/hotspot/share/opto/idealGraphPrinter.hpp b/src/hotspot/share/opto/idealGraphPrinter.hpp index aff139a82e3fa..11b0b6e5ea169 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.hpp +++ b/src/hotspot/share/opto/idealGraphPrinter.hpp @@ -40,6 +40,7 @@ class Matcher; class Node; class InlineTree; class ciMethod; +class JVMState; class IdealGraphPrinter : public CHeapObj { private: @@ -96,9 +97,10 @@ class IdealGraphPrinter : public CHeapObj { Compile *C; double _max_freq; - void print_method(ciMethod *method, int bci, InlineTree *tree); - void print_inline_tree(InlineTree *tree); - void visit_node(Node *n, bool edges, VectorSet* temp_set); + void print_method(ciMethod* method, int bci, InlineTree* tree); + void print_inline_tree(InlineTree* tree); + void visit_node(Node* n, bool edges, VectorSet* temp_set); + void print_bci_and_line_number(JVMState* caller); void print_field(const Node* node); ciField* get_field(const Node* node); ciField* find_source_field_of_array_access(const Node* node, uint& depth); From a10845b553fc6fe7e06a0f37ce73fe5f704dc7c4 Mon Sep 17 00:00:00 2001 From: Joachim Kern Date: Fri, 3 May 2024 08:31:42 +0000 Subject: [PATCH 070/203] 8330539: Use #include instead of -Dalloca'(size)'=__builtin_alloca'(size)' for AIX Reviewed-by: jwaters, mdoerr, kbarrett, ihse --- make/autoconf/flags-cflags.m4 | 2 +- src/hotspot/share/utilities/globalDefinitions_gcc.hpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index c96b289084cca..97a3ec14ecd5e 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -459,7 +459,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], CFLAGS_OS_DEF_JVM="-D_ALLBSD_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" CFLAGS_OS_DEF_JDK="-D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" elif test "x$OPENJDK_TARGET_OS" = xaix; then - CFLAGS_OS_DEF_JVM="-DAIX -Dalloca'(size)'=__builtin_alloca'(size)' -D_LARGE_FILES" + CFLAGS_OS_DEF_JVM="-DAIX -D_LARGE_FILES" CFLAGS_OS_DEF_JDK="-D_LARGE_FILES" elif test "x$OPENJDK_TARGET_OS" = xbsd; then CFLAGS_OS_DEF_JDK="-D_ALLBSD_SOURCE" diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp index 4267cdb2746cd..e5decbcd53693 100644 --- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp @@ -31,6 +31,7 @@ // globally used constants & types, class (forward) // declarations and a few frequently used utility functions. +#include #include #include #include From f665e07ab223bdabb6cf3f653f799913d874bc55 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Fri, 3 May 2024 10:17:11 +0000 Subject: [PATCH 071/203] 8331540: [BACKOUT] NMT: add/make a mandatory MEMFLAGS argument to family of os::reserve/commit/uncommit memory API Reviewed-by: jwilhelm --- .../cpu/aarch64/compressedKlass_aarch64.cpp | 4 +- src/hotspot/os/aix/os_aix.cpp | 10 +- .../bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp | 4 +- .../bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp | 4 +- src/hotspot/os/bsd/os_bsd.cpp | 16 +-- src/hotspot/os/linux/os_linux.cpp | 26 ++-- src/hotspot/os/posix/os_posix.cpp | 6 +- src/hotspot/os/posix/perfMemory_posix.cpp | 6 +- src/hotspot/os/windows/os_windows.cpp | 70 +++++------ src/hotspot/os/windows/perfMemory_windows.cpp | 6 +- src/hotspot/share/cds/archiveBuilder.cpp | 2 +- src/hotspot/share/cds/filemap.cpp | 27 ++--- src/hotspot/share/cds/metaspaceShared.cpp | 15 ++- .../share/classfile/compactHashtable.cpp | 4 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 2 +- .../share/gc/g1/g1PageBasedVirtualSpace.cpp | 8 +- .../share/gc/g1/g1RegionToSpaceMapper.cpp | 6 +- .../share/gc/parallel/mutableNUMASpace.cpp | 4 +- .../share/gc/parallel/mutableSpace.cpp | 4 +- .../share/gc/parallel/objectStartArray.cpp | 3 +- .../share/gc/parallel/parMarkBitMap.cpp | 6 +- .../share/gc/parallel/psParallelCompact.cpp | 4 +- .../share/gc/parallel/psVirtualspace.cpp | 4 +- .../gc/serial/serialBlockOffsetTable.cpp | 4 +- src/hotspot/share/gc/shared/cardTable.cpp | 9 +- .../gc/shenandoah/shenandoahCollectionSet.cpp | 10 +- .../share/gc/shenandoah/shenandoahHeap.cpp | 40 +++--- .../gc/shenandoah/shenandoahHeapRegion.cpp | 4 +- .../share/gc/x/xMarkStackAllocator.cpp | 6 +- src/hotspot/share/gc/x/xPhysicalMemory.cpp | 6 +- src/hotspot/share/gc/x/xVirtualMemory.cpp | 5 +- .../share/gc/z/zMarkStackAllocator.cpp | 6 +- src/hotspot/share/gc/z/zNMT.cpp | 4 +- .../jfr/recorder/storage/jfrVirtualMemory.cpp | 6 +- .../share/memory/allocation.inline.hpp | 6 +- src/hotspot/share/memory/heap.cpp | 6 +- src/hotspot/share/memory/metaspace.cpp | 9 +- .../share/memory/metaspace/testHelpers.cpp | 4 +- .../memory/metaspace/virtualSpaceNode.cpp | 7 +- src/hotspot/share/memory/virtualspace.cpp | 114 +++++++++--------- src/hotspot/share/memory/virtualspace.hpp | 38 +++--- src/hotspot/share/nmt/memTracker.hpp | 16 +-- .../share/nmt/virtualMemoryTracker.cpp | 12 +- .../share/nmt/virtualMemoryTracker.hpp | 13 +- src/hotspot/share/oops/compressedKlass.cpp | 4 +- src/hotspot/share/prims/jni.cpp | 5 +- src/hotspot/share/prims/whitebox.cpp | 16 ++- src/hotspot/share/runtime/os.cpp | 46 +++---- src/hotspot/share/runtime/os.hpp | 47 ++++---- .../share/runtime/safepointMechanism.cpp | 7 +- src/hotspot/share/utilities/debug.cpp | 5 +- .../gtest/gc/g1/test_freeRegionList.cpp | 2 +- .../gtest/gc/g1/test_stressCommitUncommit.cpp | 4 +- test/hotspot/gtest/gc/z/test_zForwarding.cpp | 8 +- .../gtest/memory/test_virtualspace.cpp | 24 ++-- .../gtest/nmt/test_nmt_locationprinting.cpp | 2 +- .../runtime/test_committed_virtualmemory.cpp | 6 +- test/hotspot/gtest/runtime/test_os.cpp | 36 +++--- test/hotspot/gtest/runtime/test_os_linux.cpp | 16 +-- .../gtest/runtime/test_os_reserve_between.cpp | 8 +- .../hotspot/gtest/runtime/test_os_windows.cpp | 8 +- .../runtime/test_virtualMemoryTracker.cpp | 8 +- 62 files changed, 420 insertions(+), 398 deletions(-) diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp index c918d9bdf0eb5..54af69ffaba6c 100644 --- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp @@ -69,7 +69,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) { const uint64_t immediate = ((uint64_t)immediates[index]) << 32; assert(immediate > 0 && Assembler::operand_valid_for_logical_immediate(/*is32*/false, immediate), "Invalid immediate %d " UINT64_FORMAT, index, immediate); - result = os::attempt_reserve_memory_at((char*)immediate, size, !ExecMem, mtClass); + result = os::attempt_reserve_memory_at((char*)immediate, size, false); if (result == nullptr) { log_trace(metaspace, map)("Failed to attach at " UINT64_FORMAT_X, immediate); } @@ -112,7 +112,7 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size if (result == nullptr) { constexpr size_t alignment = nth_bit(32); log_debug(metaspace, map)("Trying to reserve at a 32-bit-aligned address"); - result = os::reserve_memory_aligned(size, alignment, !ExecMem, mtClass); + result = os::reserve_memory_aligned(size, alignment, false); } return result; diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 862d8e8b0f4e2..f0a984d3d1fe0 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -1805,7 +1805,7 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) { void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { } size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) { @@ -1847,7 +1847,7 @@ bool os::numa_get_group_ids_for_range(const void** addresses, int* lgrp_ids, siz } // Reserves and attaches a shared memory segment. -char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { +char* os::pd_reserve_memory(size_t bytes, bool exec) { // Always round to os::vm_page_size(), which may be larger than 4K. bytes = align_up(bytes, os::vm_page_size()); @@ -1996,7 +1996,7 @@ void os::large_page_init() { return; // Nothing to do. See query_multipage_support and friends. } -char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec, MEMFLAGS flag) { +char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) { fatal("os::reserve_memory_special should not be called on AIX."); return nullptr; } @@ -2015,7 +2015,7 @@ bool os::can_commit_large_page_memory() { return false; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); char* result = nullptr; @@ -2033,7 +2033,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec, MEMFLAGS flag) { +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) { char* addr = nullptr; // Always round to os::vm_page_size(), which may be larger than 4K. diff --git a/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp index ea7a128cd13a0..2c64c3788d34d 100644 --- a/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp +++ b/src/hotspot/os/bsd/gc/x/xPhysicalMemoryBacking_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -78,7 +78,7 @@ XPhysicalMemoryBacking::XPhysicalMemoryBacking(size_t max_capacity) : _initialized(false) { // Reserve address space for backing memory - _base = (uintptr_t)os::reserve_memory(max_capacity, !ExecMem, mtJavaHeap); + _base = (uintptr_t)os::reserve_memory(max_capacity); if (_base == 0) { // Failed log_error_pd(gc)("Failed to reserve address space for backing memory"); diff --git a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp index 5bc901d0c0ba2..bd1d7174c12d1 100644 --- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, 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 @@ -79,7 +79,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) _initialized(false) { // Reserve address space for backing memory - _base = (uintptr_t)os::reserve_memory(max_capacity, !ExecMem, mtJavaHeap); + _base = (uintptr_t)os::reserve_memory(max_capacity); if (_base == 0) { // Failed log_error_pd(gc)("Failed to reserve address space for backing memory"); diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 95f8016e2e990..e5b6c74ce2f1b 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -1668,7 +1668,7 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size, void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { ::madvise(addr, bytes, MADV_DONTNEED); } @@ -1766,13 +1766,13 @@ bool os::pd_uncommit_memory(char* addr, size_t size, bool exec) { } bool os::pd_create_stack_guard_pages(char* addr, size_t size) { - return os::commit_memory(addr, size, !ExecMem, mtThreadStack); + return os::commit_memory(addr, size, !ExecMem); } // If this is a growable mapping, remove the guard pages entirely by // munmap()ping them. If not, just call uncommit_memory(). bool os::remove_stack_guard_pages(char* addr, size_t size) { - return os::uncommit_memory(addr, size, !ExecMem, mtThreadStack); + return os::uncommit_memory(addr, size); } // 'requested_addr' is only treated as a hint, the return value may or @@ -1809,7 +1809,7 @@ static int anon_munmap(char * addr, size_t size) { } } -char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { +char* os::pd_reserve_memory(size_t bytes, bool exec) { return anon_mmap(nullptr /* addr */, bytes, exec); } @@ -1869,7 +1869,7 @@ void os::large_page_init() { } -char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec, MEMFLAGS flag) { +char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) { fatal("os::reserve_memory_special should not be called on BSD."); return nullptr; } @@ -1888,9 +1888,9 @@ bool os::can_commit_large_page_memory() { return false; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); - char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem, flag); + char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem); if (result != nullptr) { if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == nullptr) { vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); @@ -1902,7 +1902,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec, MEMFLAGS flag) { +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) { // Assert only that the size is a multiple of the page size, since // that's all that mmap requires, and since that's all we really know // about at this low abstraction level. If we need higher alignment, diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 3181ad82dab9f..20d3c99cd3eac 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -3023,14 +3023,14 @@ void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { // This method works by doing an mmap over an existing mmaping and effectively discarding // the existing pages. However it won't work for SHM-based large pages that cannot be // uncommitted at all. We don't do anything in this case to avoid creating a segment with // small pages on top of the SHM segment. This method always works for small pages, so we // allow that in any case. if (alignment_hint <= os::vm_page_size() || can_commit_large_page_memory()) { - commit_memory(addr, bytes, alignment_hint, !ExecMem, flag); + commit_memory(addr, bytes, alignment_hint, !ExecMem); } } @@ -3637,7 +3637,7 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) { } } - return os::commit_memory(addr, size, !ExecMem, mtThreadStack); + return os::commit_memory(addr, size, !ExecMem); } // If this is a growable mapping, remove the guard pages entirely by @@ -3653,7 +3653,7 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) { return ::munmap(addr, size) == 0; } - return os::uncommit_memory(addr, size, !ExecMem, mtThreadStack); + return os::uncommit_memory(addr, size); } // 'requested_addr' is only treated as a hint, the return value may or @@ -3757,7 +3757,7 @@ static int anon_munmap(char * addr, size_t size) { return 1; } -char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { +char* os::pd_reserve_memory(size_t bytes, bool exec) { return anon_mmap(nullptr, bytes); } @@ -4214,7 +4214,7 @@ static char* reserve_memory_special_huge_tlbfs(size_t bytes, } char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, - char* req_addr, bool exec, MEMFLAGS flag) { + char* req_addr, bool exec) { assert(UseLargePages, "only for large pages"); char* const addr = reserve_memory_special_huge_tlbfs(bytes, alignment, page_size, req_addr, exec); @@ -4249,9 +4249,9 @@ bool os::can_commit_large_page_memory() { return UseTransparentHugePages; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); - char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem, flag); + char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem); if (result != nullptr) { if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == nullptr) { vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); @@ -4263,7 +4263,7 @@ char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, i // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec, MEMFLAGS flag) { +char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) { // Assert only that the size is a multiple of the page size, since // that's all that mmap requires, and since that's all we really know // about at this low abstraction level. If we need higher alignment, @@ -4655,7 +4655,7 @@ static void workaround_expand_exec_shield_cs_limit() { */ char* hint = (char*)(os::Linux::initial_thread_stack_bottom() - (StackOverflow::stack_guard_zone_size() + page_size)); - char* codebuf = os::attempt_reserve_memory_at(hint, page_size, !ExecMem, mtInternal); + char* codebuf = os::attempt_reserve_memory_at(hint, page_size); if (codebuf == nullptr) { // JDK-8197429: There may be a stack gap of one megabyte between @@ -4663,13 +4663,15 @@ static void workaround_expand_exec_shield_cs_limit() { // Linux kernel workaround for CVE-2017-1000364. If we failed to // map our codebuf, try again at an address one megabyte lower. hint -= 1 * M; - codebuf = os::attempt_reserve_memory_at(hint, page_size, !ExecMem, mtInternal); + codebuf = os::attempt_reserve_memory_at(hint, page_size); } - if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, ExecMem, mtInternal))) { + if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, true))) { return; // No matter, we tried, best effort. } + MemTracker::record_virtual_memory_type((address)codebuf, mtInternal); + log_info(os)("[CS limit NX emulation work-around, exec code at: %p]", codebuf); // Some code to exec: the 'ret' instruction diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index db3aef14543f7..a18a633002c4b 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -395,9 +395,9 @@ static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base, // Multiple threads can race in this code, and can remap over each other with MAP_FIXED, // so on posix, unmap the section at the start and at the end of the chunk that we mapped // rather than unmapping and remapping the whole chunk to get requested alignment. -char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec, MEMFLAGS flag) { +char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) { size_t extra_size = calculate_aligned_extra_size(size, alignment); - char* extra_base = os::reserve_memory(extra_size, exec, flag); + char* extra_base = os::reserve_memory(extra_size, exec); if (extra_base == nullptr) { return nullptr; } @@ -421,7 +421,7 @@ char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int file_des if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == nullptr) { vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory")); } - MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC, flag); + MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC); return aligned_base; } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 2ed33c3fb9c91..4339a21ae4e92 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -65,14 +65,14 @@ static char* backing_store_file_name = nullptr; // name of the backing store static char* create_standard_memory(size_t size) { // allocate an aligned chuck of memory - char* mapAddress = os::reserve_memory(size, !ExecMem, mtInternal); + char* mapAddress = os::reserve_memory(size); if (mapAddress == nullptr) { return nullptr; } // commit memory - if (!os::commit_memory(mapAddress, size, !ExecMem, mtInternal)) { + if (!os::commit_memory(mapAddress, size, !ExecMem)) { if (PrintMiscellaneous && Verbose) { warning("Could not commit PerfData memory\n"); } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index a99e67d417c5b..20422e83cb77c 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2755,7 +2755,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { addr = (address)((uintptr_t)addr & (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); os::commit_memory((char *)addr, thread->stack_base() - addr, - !ExecMem, mtThreadStack); + !ExecMem); return EXCEPTION_CONTINUE_EXECUTION; } #endif @@ -3117,9 +3117,8 @@ static bool numa_interleaving_init() { // Reasons for doing this: // * UseLargePagesIndividualAllocation was set (normally only needed on WS2003 but possible to be set otherwise) // * UseNUMAInterleaving requires a separate node for each piece -static char* allocate_pages_individually(size_t bytes, char* addr, DWORD alloc_type, +static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, DWORD prot, - MEMFLAGS flag, bool should_inject_error = false) { char * p_buf; // note: at setup time we guaranteed that NUMAInterleaveGranularity was aligned up to a page size @@ -3143,7 +3142,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD alloc_t PAGE_READWRITE); // If reservation failed, return null if (p_buf == nullptr) return nullptr; - MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC, flag); + MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC); os::release_memory(p_buf, bytes + chunk_size); // we still need to round up to a page boundary (in case we are using large pages) @@ -3185,13 +3184,13 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD alloc_t if (!UseNUMAInterleaving) { p_new = (char *) virtualAlloc(next_alloc_addr, bytes_to_rq, - alloc_type, + flags, prot); } else { // get the next node to use from the used_node_list assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected"); DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count()); - p_new = (char *)virtualAllocExNuma(hProc, next_alloc_addr, bytes_to_rq, alloc_type, prot, node); + p_new = (char *)virtualAllocExNuma(hProc, next_alloc_addr, bytes_to_rq, flags, prot, node); } } @@ -3204,7 +3203,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD alloc_t // need to create a dummy 'reserve' record to match // the release. MemTracker::record_virtual_memory_reserve((address)p_buf, - bytes_to_release, CALLER_PC, flag); + bytes_to_release, CALLER_PC); os::release_memory(p_buf, bytes_to_release); } #ifdef ASSERT @@ -3221,10 +3220,10 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD alloc_t } // Although the memory is allocated individually, it is returned as one. // NMT records it as one block. - if ((alloc_type & MEM_COMMIT) != 0) { - MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC, flag); + if ((flags & MEM_COMMIT) != 0) { + MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC); } else { - MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC, flag); + MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC); } // made it this far, success @@ -3352,7 +3351,7 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in // Multiple threads can race in this code but it's not possible to unmap small sections of // virtual space to get requested alignment, like posix-like os's. // Windows prevents multiple thread from remapping over each other so this loop is thread-safe. -static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MEMFLAGS flag) { +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MEMFLAGS flag = mtNone) { assert(is_aligned(alignment, os::vm_allocation_granularity()), "Alignment must be a multiple of allocation granularity (page size)"); assert(is_aligned(size, os::vm_allocation_granularity()), @@ -3366,7 +3365,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) { char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc, flag) : - os::reserve_memory(extra_size, !ExecMem, flag); + os::reserve_memory(extra_size, false, flag); if (extra_base == nullptr) { return nullptr; } @@ -3383,7 +3382,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi // Attempt to map, into the just vacated space, the slightly smaller aligned area. // Which may fail, hence the loop. aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, flag) : - os::attempt_reserve_memory_at(aligned_base, size, !ExecMem, flag); + os::attempt_reserve_memory_at(aligned_base, size, false, flag); } assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts?", max_attempts); @@ -3391,22 +3390,22 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi return aligned_base; } -char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec, MEMFLAGS flag) { +char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) { // exec can be ignored - return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */, flag); + return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */); } char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MEMFLAGS flag) { return map_or_reserve_memory_aligned(size, alignment, fd, flag); } -char* os::pd_reserve_memory(size_t bytes, bool exec, MEMFLAGS flag) { - return pd_attempt_reserve_memory_at(nullptr /* addr */, bytes, exec, flag); +char* os::pd_reserve_memory(size_t bytes, bool exec) { + return pd_attempt_reserve_memory_at(nullptr /* addr */, bytes, exec); } // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). -char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec, MEMFLAGS flag) { +char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec) { assert((size_t)addr % os::vm_allocation_granularity() == 0, "reserve alignment"); assert(bytes % os::vm_page_size() == 0, "reserve page size"); @@ -3421,7 +3420,7 @@ char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec, MEMF if (Verbose && PrintMiscellaneous) reserveTimer.start(); // in numa interleaving, we have to allocate pages individually // (well really chunks of NUMAInterleaveGranularity size) - res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE, flag); + res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE); if (res == nullptr) { warning("NUMA page allocation failed"); } @@ -3442,7 +3441,7 @@ size_t os::vm_min_address() { return _vm_min_address_default; } -char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc, MEMFLAGS flag) { +char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) { assert(file_desc >= 0, "file_desc is not valid"); return map_memory_to_file(requested_addr, bytes, file_desc); } @@ -3458,13 +3457,13 @@ bool os::can_commit_large_page_memory() { return false; } -static char* reserve_large_pages_individually(size_t size, char* req_addr, bool exec, MEMFLAGS flag) { +static char* reserve_large_pages_individually(size_t size, char* req_addr, bool exec) { log_debug(pagesize)("Reserving large pages individually."); const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - const DWORD alloc_type = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; + const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; - char * p_buf = allocate_pages_individually(size, req_addr, alloc_type, prot, flag, LargePagesIndividualAllocationInjectError); + char * p_buf = allocate_pages_individually(size, req_addr, flags, prot, LargePagesIndividualAllocationInjectError); if (p_buf == nullptr) { // give an appropriate warning message if (UseNUMAInterleaving) { @@ -3488,12 +3487,12 @@ static char* reserve_large_pages_single_range(size_t size, char* req_addr, bool return (char *) virtualAlloc(req_addr, size, flags, prot); } -static char* reserve_large_pages(size_t size, char* req_addr, bool exec, MEMFLAGS flag) { +static char* reserve_large_pages(size_t size, char* req_addr, bool exec) { // with large pages, there are two cases where we need to use Individual Allocation // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003) // 2) NUMA Interleaving is enabled, in which case we use a different node for each page if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) { - return reserve_large_pages_individually(size, req_addr, exec, flag); + return reserve_large_pages_individually(size, req_addr, exec); } return reserve_large_pages_single_range(size, req_addr, exec); } @@ -3510,7 +3509,7 @@ static char* find_aligned_address(size_t size, size_t alignment) { return aligned_addr; } -static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exec, MEMFLAGS flag) { +static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exec) { log_debug(pagesize)("Reserving large pages at an aligned address, alignment=" SIZE_FORMAT "%s", byte_size_in_exact_unit(alignment), exact_unit_for_byte_size(alignment)); @@ -3523,7 +3522,7 @@ static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exe char* aligned_address = find_aligned_address(size, alignment); // Try to do the large page reservation using the aligned address. - aligned_address = reserve_large_pages(size, aligned_address, exec, flag); + aligned_address = reserve_large_pages(size, aligned_address, exec); if (aligned_address != nullptr) { // Reservation at the aligned address succeeded. guarantee(is_aligned(aligned_address, alignment), "Must be aligned"); @@ -3536,7 +3535,7 @@ static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exe } char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* addr, - bool exec, MEMFLAGS flag) { + bool exec) { assert(UseLargePages, "only for large pages"); assert(page_size == os::large_page_size(), "Currently only support one large page size on Windows"); assert(is_aligned(addr, alignment), "Must be"); @@ -3552,11 +3551,11 @@ char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_ // ensure that the requested alignment is met. When there is a requested address // this solves it self, since it must be properly aligned already. if (addr == nullptr && alignment > page_size) { - return reserve_large_pages_aligned(bytes, alignment, exec, flag); + return reserve_large_pages_aligned(bytes, alignment, exec); } // No additional requirements, just reserve the large pages. - return reserve_large_pages(bytes, addr, exec, flag); + return reserve_large_pages(bytes, addr, exec); } bool os::pd_release_memory_special(char* base, size_t bytes) { @@ -3722,11 +3721,11 @@ bool os::pd_release_memory(char* addr, size_t bytes) { } bool os::pd_create_stack_guard_pages(char* addr, size_t size) { - return os::commit_memory(addr, size, !ExecMem, mtThreadStack); + return os::commit_memory(addr, size, !ExecMem); } bool os::remove_stack_guard_pages(char* addr, size_t size) { - return os::uncommit_memory(addr, size, !ExecMem, mtThreadStack); + return os::uncommit_memory(addr, size); } static bool protect_pages_individually(char* addr, size_t bytes, unsigned int p, DWORD *old_status) { @@ -3777,7 +3776,7 @@ bool os::protect_memory(char* addr, size_t bytes, ProtType prot, // memory, not a big deal anyway, as bytes less or equal than 64K if (!is_committed) { commit_memory_or_exit(addr, bytes, prot == MEM_PROT_RWX, - mtInternal, "cannot commit protection page"); + "cannot commit protection page"); } // One cannot use os::guard_memory() here, as on Win32 guard page // have different (one-shot) semantics, from MSDN on PAGE_GUARD: @@ -3817,7 +3816,7 @@ bool os::unguard_memory(char* addr, size_t bytes) { } void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } -void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { } +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { } size_t os::pd_pretouch_memory(void* first, void* last, size_t page_size) { return page_size; @@ -5105,6 +5104,9 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, return nullptr; } + // Record virtual memory allocation + MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC); + DWORD bytes_read; OVERLAPPED overlapped; overlapped.Offset = (DWORD)file_offset; diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index 0e5b5fedbcd51..a71101731fb98 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,14 +55,14 @@ typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)( static char* create_standard_memory(size_t size) { // allocate an aligned chuck of memory - char* mapAddress = os::reserve_memory(size, !ExecMem, mtInternal); + char* mapAddress = os::reserve_memory(size); if (mapAddress == nullptr) { return nullptr; } // commit memory - if (!os::commit_memory(mapAddress, size, !ExecMem, mtInternal)) { + if (!os::commit_memory(mapAddress, size, !ExecMem)) { if (PrintMiscellaneous && Verbose) { warning("Could not commit PerfData memory\n"); } diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index b8004f741ba63..51399f03434f6 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -326,7 +326,7 @@ size_t ArchiveBuilder::estimate_archive_size() { address ArchiveBuilder::reserve_buffer() { size_t buffer_size = estimate_archive_size(); - ReservedSpace rs(buffer_size, MetaspaceShared::core_region_alignment(), os::vm_page_size(), mtClassShared); + ReservedSpace rs(buffer_size, MetaspaceShared::core_region_alignment(), os::vm_page_size()); if (!rs.is_reserved()) { log_error(cds)("Failed to reserve " SIZE_FORMAT " bytes of output buffer.", buffer_size); MetaspaceShared::unrecoverable_writing_error(); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 22895bd326162..2182865ebaacc 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1710,9 +1710,9 @@ void FileMapInfo::close() { /* * Same as os::map_memory() but also pretouches if AlwaysPreTouch is enabled. */ -static char* map_and_pretouch_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only, - bool allow_exec, MEMFLAGS flags) { +static char* map_memory(int fd, const char* file_name, size_t file_offset, + char *addr, size_t bytes, bool read_only, + bool allow_exec, MEMFLAGS flags = mtNone) { char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes, AlwaysPreTouch ? false : read_only, allow_exec, flags); @@ -1741,7 +1741,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() { // Replace old mapping with new one that is writable. char *base = os::map_memory(_fd, _full_path, r->file_offset(), addr, size, false /* !read_only */, - r->allow_exec(), mtClassShared); + r->allow_exec()); close(); // These have to be errors because the shared region is now unmapped. if (base == nullptr) { @@ -1800,7 +1800,7 @@ bool FileMapInfo::read_region(int i, char* base, size_t size, bool do_commit) { log_info(cds)("Commit %s region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)%s", is_static() ? "static " : "dynamic", i, p2i(base), p2i(base + size), shared_region_name[i], r->allow_exec() ? " exec" : ""); - if (!os::commit_memory(base, size, r->allow_exec(), mtClassShared)) { + if (!os::commit_memory(base, size, r->allow_exec())) { log_error(cds)("Failed to commit %s region #%d (%s)", is_static() ? "static " : "dynamic", i, shared_region_name[i]); return false; @@ -1860,9 +1860,9 @@ MapArchiveResult FileMapInfo::map_region(int i, intx addr_delta, char* mapped_ba // Note that this may either be a "fresh" mapping into unreserved address // space (Windows, first mapping attempt), or a mapping into pre-reserved // space (Posix). See also comment in MetaspaceShared::map_archives(). - char* base = map_and_pretouch_memory(_fd, _full_path, r->file_offset(), - requested_addr, size, r->read_only(), - r->allow_exec(), mtClassShared); + char* base = map_memory(_fd, _full_path, r->file_offset(), + requested_addr, size, r->read_only(), + r->allow_exec(), mtClassShared); if (base != requested_addr) { log_info(cds)("Unable to map %s shared space at " INTPTR_FORMAT, shared_region_name[i], p2i(requested_addr)); @@ -1889,8 +1889,8 @@ char* FileMapInfo::map_bitmap_region() { } bool read_only = true, allow_exec = false; char* requested_addr = nullptr; // allow OS to pick any location - char* bitmap_base = map_and_pretouch_memory(_fd, _full_path, r->file_offset(), - requested_addr, r->used_aligned(), read_only, allow_exec, mtClassShared); + char* bitmap_base = map_memory(_fd, _full_path, r->file_offset(), + requested_addr, r->used_aligned(), read_only, allow_exec, mtClassShared); if (bitmap_base == nullptr) { log_info(cds)("failed to map relocation bitmap"); return nullptr; @@ -2176,11 +2176,10 @@ bool FileMapInfo::map_heap_region_impl() { // Map the archived heap data. No need to call MemTracker::record_virtual_memory_type() // for mapped region as it is part of the reserved java heap, which is already recorded. - // So we pass the mtJavaHeap to tell MemTracker the type of the already tracked memory. char* addr = (char*)_mapped_heap_memregion.start(); - char* base = map_and_pretouch_memory(_fd, _full_path, r->file_offset(), - addr, _mapped_heap_memregion.byte_size(), r->read_only(), - r->allow_exec(), mtJavaHeap); + char* base = map_memory(_fd, _full_path, r->file_offset(), + addr, _mapped_heap_memregion.byte_size(), r->read_only(), + r->allow_exec()); if (base == nullptr || base != addr) { dealloc_heap_region(); log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. " diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 3f5560ca22ae0..c7d14f83d036a 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -269,7 +269,7 @@ void MetaspaceShared::initialize_for_static_dump() { SharedBaseAddress = (size_t)_requested_base_address; size_t symbol_rs_size = LP64_ONLY(3 * G) NOT_LP64(128 * M); - _symbol_rs = ReservedSpace(symbol_rs_size, mtClassShared); + _symbol_rs = ReservedSpace(symbol_rs_size); if (!_symbol_rs.is_reserved()) { log_error(cds)("Unable to reserve memory for symbols: " SIZE_FORMAT " bytes.", symbol_rs_size); MetaspaceShared::unrecoverable_writing_error(); @@ -1270,10 +1270,12 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma // Get the simple case out of the way first: // no compressed class space, simple allocation. archive_space_rs = ReservedSpace(archive_space_size, archive_space_alignment, - os::vm_page_size(), mtClassShared, (char*)base_address); + os::vm_page_size(), (char*)base_address); if (archive_space_rs.is_reserved()) { assert(base_address == nullptr || (address)archive_space_rs.base() == base_address, "Sanity"); + // Register archive space with NMT. + MemTracker::record_virtual_memory_type(archive_space_rs.base(), mtClassShared); return archive_space_rs.base(); } return nullptr; @@ -1317,18 +1319,21 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma // via sequential file IO. address ccs_base = base_address + archive_space_size + gap_size; archive_space_rs = ReservedSpace(archive_space_size, archive_space_alignment, - os::vm_page_size(), mtClassShared, (char*)base_address); + os::vm_page_size(), (char*)base_address); class_space_rs = ReservedSpace(class_space_size, class_space_alignment, - os::vm_page_size(), mtClass, (char*)ccs_base); + os::vm_page_size(), (char*)ccs_base); } if (!archive_space_rs.is_reserved() || !class_space_rs.is_reserved()) { release_reserved_spaces(total_space_rs, archive_space_rs, class_space_rs); return nullptr; } + // NMT: fix up the space tags + MemTracker::record_virtual_memory_type(archive_space_rs.base(), mtClassShared); + MemTracker::record_virtual_memory_type(class_space_rs.base(), mtClass); } else { if (use_archive_base_addr && base_address != nullptr) { total_space_rs = ReservedSpace(total_range_size, archive_space_alignment, - os::vm_page_size(), mtClassShared, (char*) base_address); + os::vm_page_size(), (char*) base_address); } else { // We did not manage to reserve at the preferred address, or were instructed to relocate. In that // case we reserve wherever possible, but the start address needs to be encodable as narrow Klass diff --git a/src/hotspot/share/classfile/compactHashtable.cpp b/src/hotspot/share/classfile/compactHashtable.cpp index 890d0e035f862..d4657e35a84eb 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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 @@ -240,7 +240,7 @@ HashtableTextDump::HashtableTextDump(const char* filename) : _fd(-1) { if (_fd < 0) { quit("Unable to open hashtable dump file", filename); } - _base = os::map_memory(_fd, filename, 0, nullptr, _size, true, false, mtClassShared); + _base = os::map_memory(_fd, filename, 0, nullptr, _size, true, false); if (_base == nullptr) { quit("Unable to map hashtable dump file", filename); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 2b890530c4bdf..1384c30d2be2f 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1213,7 +1213,7 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des size_t translation_factor) { size_t preferred_page_size = os::page_size_for_region_unaligned(size, 1); // Allocate a new reserved space, preferring to use large pages. - ReservedSpace rs(size, preferred_page_size, mtGC); + ReservedSpace rs(size, preferred_page_size); size_t page_size = rs.page_size(); G1RegionToSpaceMapper* result = G1RegionToSpaceMapper::create_mapper(rs, diff --git a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp index c0cf66fb2fdc2..bdb732f6ebb39 100644 --- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp +++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, 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 @@ -135,14 +135,14 @@ void G1PageBasedVirtualSpace::commit_preferred_pages(size_t start, size_t num_pa char* start_addr = page_start(start); size_t size = num_pages * _page_size; - os::commit_memory_or_exit(start_addr, size, _page_size, !ExecMem, mtGC, "G1 virtual space"); + os::commit_memory_or_exit(start_addr, size, _page_size, false, "G1 virtual space"); } void G1PageBasedVirtualSpace::commit_tail() { vmassert(_tail_size > 0, "The size of the tail area must be > 0 when reaching here"); char* const aligned_end_address = align_down(_high_boundary, _page_size); - os::commit_memory_or_exit(aligned_end_address, _tail_size, os::vm_page_size(), !ExecMem, mtGC, "G1 virtual space"); + os::commit_memory_or_exit(aligned_end_address, _tail_size, os::vm_page_size(), false, "G1 virtual space"); } void G1PageBasedVirtualSpace::commit_internal(size_t start_page, size_t end_page) { @@ -201,7 +201,7 @@ void G1PageBasedVirtualSpace::uncommit_internal(size_t start_page, size_t end_pa "Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page); char* start_addr = page_start(start_page); - os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char)), !ExecMem, mtGC); + os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char))); } void G1PageBasedVirtualSpace::uncommit(size_t start_page, size_t size_in_pages) { diff --git a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp index 104b126c01674..5f903960cce8c 100644 --- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp +++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, 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,10 +43,12 @@ G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs, MEMFLAGS type) : _listener(nullptr), _storage(rs, used_size, page_size), - _region_commit_map(rs.size() * commit_factor / region_granularity, type), + _region_commit_map(rs.size() * commit_factor / region_granularity, mtGC), _memory_type(type) { guarantee(is_power_of_2(page_size), "must be"); guarantee(is_power_of_2(region_granularity), "must be"); + + MemTracker::record_virtual_memory_type((address)rs.base(), type); } // Used to manually signal a mapper to handle a set of regions as committed. diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index c94da37741000..2a39ce7b4700d 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2023, 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 @@ -227,7 +227,7 @@ void MutableNUMASpace::bias_region(MemRegion mr, uint lgrp_id) { // Then we uncommit the pages in the range. // The alignment_hint argument must be less than or equal to the small page // size if not using large pages or else this function does nothing. - os::free_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align, mtGC); + os::free_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align); // And make them local/first-touch biased. os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), checked_cast(lgrp_id)); } diff --git a/src/hotspot/share/gc/parallel/mutableSpace.cpp b/src/hotspot/share/gc/parallel/mutableSpace.cpp index 019d457f293df..4641b4ce5c611 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, 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,7 +60,7 @@ void MutableSpace::numa_setup_pages(MemRegion mr, size_t page_size, bool clear_s size_t size = pointer_delta(end, start, sizeof(char)); if (clear_space) { // Prefer page reallocation to migration. - os::free_memory((char*)start, size, page_size, mtJavaHeap); + os::free_memory((char*)start, size, page_size); } os::numa_make_global((char*)start, size); } diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index 2a0f12ec70e72..b1fc956a54a21 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -47,10 +47,11 @@ void ObjectStartArray::initialize(MemRegion reserved_region) { // Do not use large-pages for the backing store. The one large page region // will be used for the heap proper. - ReservedSpace backing_store(bytes_to_reserve, mtGC); + ReservedSpace backing_store(bytes_to_reserve); if (!backing_store.is_reserved()) { vm_exit_during_initialization("Could not reserve space for ObjectStartArray"); } + MemTracker::record_virtual_memory_type(backing_store.base(), mtGC); // We do not commit any memory initially _virtual_space.initialize(backing_store); diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp index fefc915094576..deffcc019c95c 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, 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 @@ -49,11 +49,13 @@ ParMarkBitMap::initialize(MemRegion covered_region) const size_t rs_align = page_sz == os::vm_page_size() ? 0 : MAX2(page_sz, granularity); - ReservedSpace rs(_reserved_byte_size, rs_align, page_sz, mtGC); + ReservedSpace rs(_reserved_byte_size, rs_align, page_sz); const size_t used_page_sz = rs.page_size(); os::trace_page_sizes("Mark Bitmap", raw_bytes, raw_bytes, rs.base(), rs.size(), used_page_sz); + MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); + _virtual_space = new PSVirtualSpace(rs, page_sz); if (_virtual_space != nullptr && _virtual_space->expand_by(_reserved_byte_size)) { _region_start = covered_region.start(); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 165f9d3c05c15..8ac16e059b1ea 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -440,10 +440,12 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) const size_t rs_align = page_sz == os::vm_page_size() ? 0 : MAX2(page_sz, granularity); - ReservedSpace rs(_reserved_byte_size, rs_align, page_sz, mtGC); + ReservedSpace rs(_reserved_byte_size, rs_align, page_sz); os::trace_page_sizes("Parallel Compact Data", raw_bytes, raw_bytes, rs.base(), rs.size(), page_sz); + MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); + PSVirtualSpace* vspace = new PSVirtualSpace(rs, page_sz); if (vspace != 0) { if (vspace->expand_by(_reserved_byte_size)) { diff --git a/src/hotspot/share/gc/parallel/psVirtualspace.cpp b/src/hotspot/share/gc/parallel/psVirtualspace.cpp index 8e441ec806137..a4d686d867042 100644 --- a/src/hotspot/share/gc/parallel/psVirtualspace.cpp +++ b/src/hotspot/share/gc/parallel/psVirtualspace.cpp @@ -78,7 +78,7 @@ bool PSVirtualSpace::expand_by(size_t bytes) { char* const base_addr = committed_high_addr(); bool result = special() || - os::commit_memory(base_addr, bytes, alignment(), !ExecMem, mtGC); + os::commit_memory(base_addr, bytes, alignment(), !ExecMem); if (result) { _committed_high_addr += bytes; } @@ -95,7 +95,7 @@ bool PSVirtualSpace::shrink_by(size_t bytes) { } char* const base_addr = committed_high_addr() - bytes; - bool result = special() || os::uncommit_memory(base_addr, bytes, !ExecMem, mtGC); + bool result = special() || os::uncommit_memory(base_addr, bytes); if (result) { _committed_high_addr -= bytes; } diff --git a/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp b/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp index 7ac0fcc8b53c5..59b7f130df30b 100644 --- a/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp +++ b/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp @@ -37,11 +37,13 @@ SerialBlockOffsetTable::SerialBlockOffsetTable(MemRegion reserved, size_t init_word_size): _reserved(reserved) { size_t size = compute_size(reserved.word_size()); - ReservedSpace rs(size, mtGC); + ReservedSpace rs(size); if (!rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for heap offset array"); } + MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); + if (!_vs.initialize(rs, 0)) { vm_exit_during_initialization("Could not reserve enough space for heap offset array"); } diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 243f47eee239d..95f7058f4e4ee 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -82,7 +82,9 @@ void CardTable::initialize(void* region0_start, void* region1_start) { const size_t rs_align = _page_size == os::vm_page_size() ? 0 : MAX2(_page_size, os::vm_allocation_granularity()); - ReservedSpace heap_rs(_byte_map_size, rs_align, _page_size, mtGC); + ReservedSpace heap_rs(_byte_map_size, rs_align, _page_size); + + MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtGC); os::trace_page_sizes("Card Table", num_bytes, num_bytes, heap_rs.base(), heap_rs.size(), _page_size); @@ -164,7 +166,6 @@ void CardTable::resize_covered_region(MemRegion new_region) { delta.byte_size(), _page_size, !ExecMem, - mtGCCardSet, "card table expansion"); memset(delta.start(), clean_card, delta.byte_size()); @@ -173,9 +174,7 @@ void CardTable::resize_covered_region(MemRegion new_region) { MemRegion delta = MemRegion(new_committed.end(), old_committed.word_size() - new_committed.word_size()); bool res = os::uncommit_memory((char*)delta.start(), - delta.byte_size(), - !ExecMem, - mtGCCardSet); + delta.byte_size()); assert(res, "uncommit should succeed"); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp index 34a66d9f6d963..25062c5317dcb 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp @@ -57,19 +57,21 @@ ShenandoahCollectionSet::ShenandoahCollectionSet(ShenandoahHeap* heap, ReservedS // subsystem for mapping not-yet-written-to pages to a single physical backing page, // but this is not guaranteed, and would confuse NMT and other memory accounting tools. + MemTracker::record_virtual_memory_type(_map_space.base(), mtGC); + size_t page_size = os::vm_page_size(); if (!_map_space.special()) { // Commit entire pages that cover the heap cset map. char* bot_addr = align_down(_cset_map, page_size); char* top_addr = align_up(_cset_map + _map_size, page_size); - os::commit_memory_or_exit(bot_addr, pointer_delta(top_addr, bot_addr, 1), !ExecMem, - mtGC, "Unable to commit collection set bitmap: heap"); + os::commit_memory_or_exit(bot_addr, pointer_delta(top_addr, bot_addr, 1), false, + "Unable to commit collection set bitmap: heap"); // Commit the zero page, if not yet covered by heap cset map. if (bot_addr != _biased_cset_map) { - os::commit_memory_or_exit(_biased_cset_map, page_size, !ExecMem, - mtGC, "Unable to commit collection set bitmap: zero page"); + os::commit_memory_or_exit(_biased_cset_map, page_size, false, + "Unable to commit collection set bitmap: zero page"); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 09737d68352c5..c9d3d1d93647f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -213,8 +213,8 @@ jint ShenandoahHeap::initialize() { ReservedSpace sh_rs = heap_rs.first_part(max_byte_size); if (!_heap_region_special) { - os::commit_memory_or_exit(sh_rs.base(), _initial_size, heap_alignment, !ExecMem, - mtGC, "Cannot commit heap memory"); + os::commit_memory_or_exit(sh_rs.base(), _initial_size, heap_alignment, false, + "Cannot commit heap memory"); } // @@ -247,11 +247,12 @@ jint ShenandoahHeap::initialize() { "Bitmap slices should be page-granular: bps = " SIZE_FORMAT ", page size = " SIZE_FORMAT, _bitmap_bytes_per_slice, bitmap_page_size); - ReservedSpace bitmap(_bitmap_size, bitmap_page_size, mtGC); + ReservedSpace bitmap(_bitmap_size, bitmap_page_size); os::trace_page_sizes_for_requested_size("Mark Bitmap", bitmap_size_orig, bitmap_page_size, bitmap.base(), bitmap.size(), bitmap.page_size()); + MemTracker::record_virtual_memory_type(bitmap.base(), mtGC); _bitmap_region = MemRegion((HeapWord*) bitmap.base(), bitmap.size() / HeapWordSize); _bitmap_region_special = bitmap.special(); @@ -259,22 +260,23 @@ jint ShenandoahHeap::initialize() { align_up(num_committed_regions, _bitmap_regions_per_slice) / _bitmap_regions_per_slice; bitmap_init_commit = MIN2(_bitmap_size, bitmap_init_commit); if (!_bitmap_region_special) { - os::commit_memory_or_exit((char *) _bitmap_region.start(), bitmap_init_commit, bitmap_page_size, !ExecMem, - mtGC, "Cannot commit bitmap memory"); + os::commit_memory_or_exit((char *) _bitmap_region.start(), bitmap_init_commit, bitmap_page_size, false, + "Cannot commit bitmap memory"); } _marking_context = new ShenandoahMarkingContext(_heap_region, _bitmap_region, _num_regions, _max_workers); if (ShenandoahVerify) { - ReservedSpace verify_bitmap(_bitmap_size, bitmap_page_size, mtGC); + ReservedSpace verify_bitmap(_bitmap_size, bitmap_page_size); os::trace_page_sizes_for_requested_size("Verify Bitmap", bitmap_size_orig, bitmap_page_size, verify_bitmap.base(), verify_bitmap.size(), verify_bitmap.page_size()); if (!verify_bitmap.special()) { - os::commit_memory_or_exit(verify_bitmap.base(), verify_bitmap.size(), bitmap_page_size, !ExecMem, - mtGC, "Cannot commit verification bitmap memory"); + os::commit_memory_or_exit(verify_bitmap.base(), verify_bitmap.size(), bitmap_page_size, false, + "Cannot commit verification bitmap memory"); } + MemTracker::record_virtual_memory_type(verify_bitmap.base(), mtGC); MemRegion verify_bitmap_region = MemRegion((HeapWord *) verify_bitmap.base(), verify_bitmap.size() / HeapWordSize); _verification_bit_map.initialize(_heap_region, verify_bitmap_region); _verifier = new ShenandoahVerifier(this, &_verification_bit_map); @@ -290,11 +292,12 @@ jint ShenandoahHeap::initialize() { aux_bitmap_page_size = os::vm_page_size(); } #endif - ReservedSpace aux_bitmap(_bitmap_size, aux_bitmap_page_size, mtGC); + ReservedSpace aux_bitmap(_bitmap_size, aux_bitmap_page_size); os::trace_page_sizes_for_requested_size("Aux Bitmap", bitmap_size_orig, aux_bitmap_page_size, aux_bitmap.base(), aux_bitmap.size(), aux_bitmap.page_size()); + MemTracker::record_virtual_memory_type(aux_bitmap.base(), mtGC); _aux_bitmap_region = MemRegion((HeapWord*) aux_bitmap.base(), aux_bitmap.size() / HeapWordSize); _aux_bitmap_region_special = aux_bitmap.special(); _aux_bit_map.initialize(_heap_region, _aux_bitmap_region); @@ -307,14 +310,15 @@ jint ShenandoahHeap::initialize() { size_t region_storage_size = align_up(region_storage_size_orig, MAX2(region_page_size, os::vm_allocation_granularity())); - ReservedSpace region_storage(region_storage_size, region_page_size, mtGC); + ReservedSpace region_storage(region_storage_size, region_page_size); os::trace_page_sizes_for_requested_size("Region Storage", region_storage_size_orig, region_page_size, region_storage.base(), region_storage.size(), region_storage.page_size()); + MemTracker::record_virtual_memory_type(region_storage.base(), mtGC); if (!region_storage.special()) { - os::commit_memory_or_exit(region_storage.base(), region_storage_size, region_page_size, !ExecMem, - mtGC, "Cannot commit region memory"); + os::commit_memory_or_exit(region_storage.base(), region_storage_size, region_page_size, false, + "Cannot commit region memory"); } // Try to fit the collection set bitmap at lower addresses. This optimizes code generation for cset checks. @@ -332,7 +336,7 @@ jint ShenandoahHeap::initialize() { for (uintptr_t addr = min; addr <= max; addr <<= 1u) { char* req_addr = (char*)addr; assert(is_aligned(req_addr, cset_align), "Should be aligned"); - cset_rs = ReservedSpace(cset_size, cset_align, cset_page_size, mtGC, req_addr); + cset_rs = ReservedSpace(cset_size, cset_align, cset_page_size, req_addr); if (cset_rs.is_reserved()) { assert(cset_rs.base() == req_addr, "Allocated where requested: " PTR_FORMAT ", " PTR_FORMAT, p2i(cset_rs.base()), addr); _collection_set = new ShenandoahCollectionSet(this, cset_rs, sh_rs.base()); @@ -341,7 +345,7 @@ jint ShenandoahHeap::initialize() { } if (_collection_set == nullptr) { - cset_rs = ReservedSpace(cset_size, cset_align, os::vm_page_size(), mtGC); + cset_rs = ReservedSpace(cset_size, cset_align, os::vm_page_size()); _collection_set = new ShenandoahCollectionSet(this, cset_rs, sh_rs.base()); } os::trace_page_sizes_for_requested_size("Collection Set", @@ -1410,7 +1414,7 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) { bool ShenandoahHeap::prepare_aux_bitmap_for_iteration() { assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints"); - if (!_aux_bitmap_region_special && !os::commit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), !ExecMem, mtGC)) { + if (!_aux_bitmap_region_special && !os::commit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), false)) { log_warning(gc)("Could not commit native memory for auxiliary marking bitmap for heap iteration"); return false; } @@ -1430,7 +1434,7 @@ void ShenandoahHeap::scan_roots_for_iteration(ShenandoahScanObjectStack* oop_sta } void ShenandoahHeap::reclaim_aux_bitmap_for_iteration() { - if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), !ExecMem, mtGC)) { + if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size())) { log_warning(gc)("Could not uncommit native memory for auxiliary marking bitmap for heap iteration"); } } @@ -2260,7 +2264,7 @@ bool ShenandoahHeap::commit_bitmap_slice(ShenandoahHeapRegion* r) { size_t len = _bitmap_bytes_per_slice; char* start = (char*) _bitmap_region.start() + off; - if (!os::commit_memory(start, len, !ExecMem, mtGC)) { + if (!os::commit_memory(start, len, false)) { return false; } @@ -2289,7 +2293,7 @@ bool ShenandoahHeap::uncommit_bitmap_slice(ShenandoahHeapRegion *r) { size_t slice = r->index() / _bitmap_regions_per_slice; size_t off = _bitmap_bytes_per_slice * slice; size_t len = _bitmap_bytes_per_slice; - if (!os::uncommit_memory((char*)_bitmap_region.start() + off, len, !ExecMem, mtGC)) { + if (!os::uncommit_memory((char*)_bitmap_region.start() + off, len)) { return false; } return true; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index a8386a36c3f9a..8a94b20670a9f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -620,7 +620,7 @@ size_t ShenandoahHeapRegion::setup_sizes(size_t max_heap_size) { void ShenandoahHeapRegion::do_commit() { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->is_heap_region_special() && !os::commit_memory((char *) bottom(), RegionSizeBytes, !ExecMem, mtJavaHeap)) { + if (!heap->is_heap_region_special() && !os::commit_memory((char *) bottom(), RegionSizeBytes, false)) { report_java_out_of_memory("Unable to commit region"); } if (!heap->commit_bitmap_slice(this)) { @@ -634,7 +634,7 @@ void ShenandoahHeapRegion::do_commit() { void ShenandoahHeapRegion::do_uncommit() { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->is_heap_region_special() && !os::uncommit_memory((char *) bottom(), RegionSizeBytes, !ExecMem, mtJavaHeap)) { + if (!heap->is_heap_region_special() && !os::uncommit_memory((char *) bottom(), RegionSizeBytes)) { report_java_out_of_memory("Unable to uncommit region"); } if (!heap->uncommit_bitmap_slice(this)) { diff --git a/src/hotspot/share/gc/x/xMarkStackAllocator.cpp b/src/hotspot/share/gc/x/xMarkStackAllocator.cpp index 70892879d2b8f..b5cc3ad641aff 100644 --- a/src/hotspot/share/gc/x/xMarkStackAllocator.cpp +++ b/src/hotspot/share/gc/x/xMarkStackAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -88,7 +88,7 @@ size_t XMarkStackSpace::expand_space() { old_size / M, new_size / M); // Expand - os::commit_memory_or_exit((char*)_end, expand_size, !ExecMem, mtGC, "Mark stack space"); + os::commit_memory_or_exit((char*)_end, expand_size, false /* executable */, "Mark stack space"); return expand_size; } @@ -105,7 +105,7 @@ size_t XMarkStackSpace::shrink_space() { old_size / M, new_size / M); const uintptr_t shrink_start = _end - shrink_size; - os::uncommit_memory((char*)shrink_start, shrink_size, !ExecMem, mtGC); + os::uncommit_memory((char*)shrink_start, shrink_size, false /* executable */); } return shrink_size; diff --git a/src/hotspot/share/gc/x/xPhysicalMemory.cpp b/src/hotspot/share/gc/x/xPhysicalMemory.cpp index 619e41cab9c9e..0269c64f0f1aa 100644 --- a/src/hotspot/share/gc/x/xPhysicalMemory.cpp +++ b/src/hotspot/share/gc/x/xPhysicalMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, 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 @@ -279,13 +279,13 @@ void XPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max void XPhysicalMemoryManager::nmt_commit(uintptr_t offset, size_t size) const { // From an NMT point of view we treat the first heap view (marked0) as committed const uintptr_t addr = XAddress::marked0(offset); - MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC, mtGC); + MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC); } void XPhysicalMemoryManager::nmt_uncommit(uintptr_t offset, size_t size) const { const uintptr_t addr = XAddress::marked0(offset); ThreadCritical tc; - MemTracker::record_virtual_memory_uncommit((address)addr, size, mtGC); + MemTracker::record_virtual_memory_uncommit((address)addr, size); } void XPhysicalMemoryManager::alloc(XPhysicalMemory& pmem, size_t size) { diff --git a/src/hotspot/share/gc/x/xVirtualMemory.cpp b/src/hotspot/share/gc/x/xVirtualMemory.cpp index 496dcdc2464e3..1d66cdd069ef7 100644 --- a/src/hotspot/share/gc/x/xVirtualMemory.cpp +++ b/src/hotspot/share/gc/x/xVirtualMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -181,7 +181,8 @@ bool XVirtualMemoryManager::reserve(size_t max_capacity) { } void XVirtualMemoryManager::nmt_reserve(uintptr_t start, size_t size) { - MemTracker::record_virtual_memory_reserve((void*)start, size, CALLER_PC, mtJavaHeap); + MemTracker::record_virtual_memory_reserve((void*)start, size, CALLER_PC); + MemTracker::record_virtual_memory_type((void*)start, mtJavaHeap); } bool XVirtualMemoryManager::is_initialized() const { diff --git a/src/hotspot/share/gc/z/zMarkStackAllocator.cpp b/src/hotspot/share/gc/z/zMarkStackAllocator.cpp index 866121ce0d330..a9e404a0f55c1 100644 --- a/src/hotspot/share/gc/z/zMarkStackAllocator.cpp +++ b/src/hotspot/share/gc/z/zMarkStackAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -87,7 +87,7 @@ size_t ZMarkStackSpace::expand_space() { old_size / M, new_size / M); // Expand - os::commit_memory_or_exit((char*)_end, expand_size, !ExecMem, mtGC, "Mark stack space"); + os::commit_memory_or_exit((char*)_end, expand_size, false /* executable */, "Mark stack space"); return expand_size; } @@ -104,7 +104,7 @@ size_t ZMarkStackSpace::shrink_space() { old_size / M, new_size / M); const uintptr_t shrink_start = _end - shrink_size; - os::uncommit_memory((char*)shrink_start, shrink_size, !ExecMem, mtGC); + os::uncommit_memory((char*)shrink_start, shrink_size, false /* executable */); } return shrink_size; diff --git a/src/hotspot/share/gc/z/zNMT.cpp b/src/hotspot/share/gc/z/zNMT.cpp index 9778ac0c975d1..9a54c0f596343 100644 --- a/src/hotspot/share/gc/z/zNMT.cpp +++ b/src/hotspot/share/gc/z/zNMT.cpp @@ -71,10 +71,10 @@ void ZNMT::process_fake_mapping(zoffset offset, size_t size, bool commit) { // commit / uncommit memory if (commit) { - MemTracker::record_virtual_memory_commit((void*)sub_range_addr, sub_range_size, CALLER_PC, mtGC); + MemTracker::record_virtual_memory_commit((void*)sub_range_addr, sub_range_size, CALLER_PC); } else { ThreadCritical tc; - MemTracker::record_virtual_memory_uncommit((address)sub_range_addr, sub_range_size, mtGC); + MemTracker::record_virtual_memory_uncommit((address)sub_range_addr, sub_range_size); } left_to_process -= sub_range_size; diff --git a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp index 31855ee1eb627..78309f00913cc 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, 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 @@ -104,8 +104,7 @@ bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes) assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant"); _rs = ReservedSpace(reservation_size_request_bytes, os::vm_allocation_granularity(), - os::vm_page_size(), - mtTracing); + os::vm_page_size()); if (!_rs.is_reserved()) { return false; } @@ -118,6 +117,7 @@ bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes) _rs.base(), _rs.size(), os::vm_page_size()); + MemTracker::record_virtual_memory_type((address)_rs.base(), mtTracing); assert(is_aligned(_rs.base(), os::vm_page_size()), "invariant"); assert(is_aligned(_rs.size(), os::vm_page_size()), "invariant"); diff --git a/src/hotspot/share/memory/allocation.inline.hpp b/src/hotspot/share/memory/allocation.inline.hpp index 3b4f163a51d73..4a1b0b0c5971b 100644 --- a/src/hotspot/share/memory/allocation.inline.hpp +++ b/src/hotspot/share/memory/allocation.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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 @@ -63,7 +63,7 @@ E* MmapArrayAllocator::allocate_or_null(size_t length, MEMFLAGS flags) { return nullptr; } - if (os::commit_memory(addr, size, !ExecMem, flags)) { + if (os::commit_memory(addr, size, !ExecMem)) { return (E*)addr; } else { os::release_memory(addr, size); @@ -80,7 +80,7 @@ E* MmapArrayAllocator::allocate(size_t length, MEMFLAGS flags) { vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)"); } - os::commit_memory_or_exit(addr, size, !ExecMem, flags, "Allocator (commit)"); + os::commit_memory_or_exit(addr, size, !ExecMem, "Allocator (commit)"); return (E*)addr; } diff --git a/src/hotspot/share/memory/heap.cpp b/src/hotspot/share/memory/heap.cpp index 92a376defa5a5..98e59f5818432 100644 --- a/src/hotspot/share/memory/heap.cpp +++ b/src/hotspot/share/memory/heap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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 @@ -227,11 +227,13 @@ bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_s const size_t committed_segments_size = align_to_page_size(_number_of_committed_segments); // reserve space for _segmap - ReservedSpace seg_rs(reserved_segments_size, mtCode); + ReservedSpace seg_rs(reserved_segments_size); if (!_segmap.initialize(seg_rs, committed_segments_size)) { return false; } + MemTracker::record_virtual_memory_type((address)_segmap.low_boundary(), mtCode); + assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "could not commit enough space for segment map"); assert(_segmap.reserved_size() >= (size_t) _number_of_reserved_segments , "could not reserve enough space for segment map"); assert(_segmap.reserved_size() >= _segmap.committed_size() , "just checking"); diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 65eeaefe74cd7..22ec4d942a6b1 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -589,7 +589,7 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz if (result == nullptr) { // Fallback: reserve anywhere log_debug(metaspace, map)("Trying anywhere..."); - result = os::reserve_memory_aligned(size, Metaspace::reserve_alignment(), !ExecMem, mtClass); + result = os::reserve_memory_aligned(size, Metaspace::reserve_alignment(), false); } // Wrap resulting range in ReservedSpace @@ -598,7 +598,7 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz log_debug(metaspace, map)("Mapped at " PTR_FORMAT, p2i(result)); assert(is_aligned(result, Metaspace::reserve_alignment()), "Alignment too small for metaspace"); rs = ReservedSpace::space_for_range(result, size, Metaspace::reserve_alignment(), - os::vm_page_size(), false, false, mtClass); + os::vm_page_size(), false, false); } else { log_debug(metaspace, map)("Failed to map."); rs = ReservedSpace(); @@ -739,7 +739,7 @@ void Metaspace::global_initialize() { CompressedClassSpaceBaseAddress, Metaspace::reserve_alignment())); } rs = ReservedSpace(size, Metaspace::reserve_alignment(), - os::vm_page_size() /* large */, mtClass, (char*)base); + os::vm_page_size() /* large */, (char*)base); if (rs.is_reserved()) { log_info(metaspace)("Successfully forced class space address to " PTR_FORMAT, p2i(base)); } else { @@ -767,6 +767,9 @@ void Metaspace::global_initialize() { CompressedClassSpaceSize)); } + // Mark class space as such + MemTracker::record_virtual_memory_type((address)rs.base(), mtClass); + // Initialize space Metaspace::initialize_class_space(rs); diff --git a/src/hotspot/share/memory/metaspace/testHelpers.cpp b/src/hotspot/share/memory/metaspace/testHelpers.cpp index ecc8af2f7dc63..2d1071d77dd6a 100644 --- a/src/hotspot/share/memory/metaspace/testHelpers.cpp +++ b/src/hotspot/share/memory/metaspace/testHelpers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -78,7 +78,7 @@ MetaspaceTestContext::MetaspaceTestContext(const char* name, size_t commit_limit reserve_limit, Metaspace::reserve_alignment_words()); if (reserve_limit > 0) { // have reserve limit -> non-expandable context - _rs = ReservedSpace(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size(), mtMetaspace); + _rs = ReservedSpace(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size()); _context = MetaspaceContext::create_nonexpandable_context(name, _rs, &_commit_limiter); } else { // no reserve limit -> expandable vslist diff --git a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp index 52553b889dfa5..a8afbc130c968 100644 --- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp +++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp @@ -109,7 +109,7 @@ bool VirtualSpaceNode::commit_range(MetaWord* p, size_t word_size) { } // Commit... - if (os::commit_memory((char*)p, word_size * BytesPerWord, !ExecMem, _rs.nmt_flag()) == false) { + if (os::commit_memory((char*)p, word_size * BytesPerWord, false) == false) { vm_exit_out_of_memory(word_size * BytesPerWord, OOM_MMAP_ERROR, "Failed to commit metaspace."); } @@ -188,7 +188,7 @@ void VirtualSpaceNode::uncommit_range(MetaWord* p, size_t word_size) { } // Uncommit... - if (os::uncommit_memory((char*)p, word_size * BytesPerWord, !ExecMem, _rs.nmt_flag()) == false) { + if (os::uncommit_memory((char*)p, word_size * BytesPerWord) == false) { // Note: this can actually happen, since uncommit may increase the number of mappings. fatal("Failed to uncommit metaspace."); } @@ -255,10 +255,11 @@ VirtualSpaceNode* VirtualSpaceNode::create_node(size_t word_size, DEBUG_ONLY(assert_is_aligned(word_size, chunklevel::MAX_CHUNK_WORD_SIZE);) ReservedSpace rs(word_size * BytesPerWord, Settings::virtual_space_node_reserve_alignment_words() * BytesPerWord, - os::vm_page_size(), mtMetaspace); + os::vm_page_size()); if (!rs.is_reserved()) { vm_exit_out_of_memory(word_size * BytesPerWord, OOM_MMAP_ERROR, "Failed to reserve memory for metaspace"); } + MemTracker::record_virtual_memory_type(rs.base(), mtMetaspace); assert_is_aligned(rs.base(), chunklevel::MAX_CHUNK_BYTE_SIZE); InternalStats::inc_num_vsnodes_births(); return new VirtualSpaceNode(rs, true, limiter, reserve_words_counter, commit_words_counter); diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index 6811d6be8463d..06775f9803252 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -42,19 +42,19 @@ // Dummy constructor ReservedSpace::ReservedSpace() : _base(nullptr), _size(0), _noaccess_prefix(0), - _alignment(0), _fd_for_heap(-1), _special(false), _executable(false), _flag(mtNone) { + _alignment(0), _special(false), _fd_for_heap(-1), _executable(false) { } -ReservedSpace::ReservedSpace(size_t size, MEMFLAGS flag) : _fd_for_heap(-1), _flag(flag) { +ReservedSpace::ReservedSpace(size_t size) : _fd_for_heap(-1) { // Want to use large pages where possible. If the size is // not large page aligned the mapping will be a mix of // large and normal pages. size_t page_size = os::page_size_for_region_unaligned(size, 1); size_t alignment = os::vm_allocation_granularity(); - initialize(size, alignment, page_size, nullptr, false, flag); + initialize(size, alignment, page_size, nullptr, false); } -ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size, MEMFLAGS flag) : _fd_for_heap(-1), _flag(flag) { +ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) : _fd_for_heap(-1) { // When a page size is given we don't want to mix large // and normal pages. If the size is not a multiple of the // page size it will be aligned up to achieve this. @@ -63,46 +63,45 @@ ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size, MEMFLAGS f alignment = MAX2(preferred_page_size, alignment); size = align_up(size, alignment); } - initialize(size, alignment, preferred_page_size, nullptr, false, flag); + initialize(size, alignment, preferred_page_size, nullptr, false); } ReservedSpace::ReservedSpace(size_t size, size_t alignment, size_t page_size, - MEMFLAGS flag, - char* requested_address) : _fd_for_heap(-1), _flag(flag) { - initialize(size, alignment, page_size, requested_address, false, flag); + char* requested_address) : _fd_for_heap(-1) { + initialize(size, alignment, page_size, requested_address, false); } ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment, size_t page_size, - bool special, bool executable, MEMFLAGS flag) : _fd_for_heap(-1), _flag(flag) { + bool special, bool executable) : _fd_for_heap(-1) { assert((size % os::vm_allocation_granularity()) == 0, "size not allocation aligned"); - initialize_members(base, size, alignment, page_size, special, executable, flag); + initialize_members(base, size, alignment, page_size, special, executable); } // Helper method -static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd, bool executable, MEMFLAGS flag) { +static char* attempt_map_or_reserve_memory_at(char* base, size_t size, int fd, bool executable) { if (fd != -1) { - return os::attempt_map_memory_to_file_at(base, size, fd, flag); + return os::attempt_map_memory_to_file_at(base, size, fd); } - return os::attempt_reserve_memory_at(base, size, executable, flag); + return os::attempt_reserve_memory_at(base, size, executable); } // Helper method -static char* map_or_reserve_memory(size_t size, int fd, bool executable, MEMFLAGS flag) { +static char* map_or_reserve_memory(size_t size, int fd, bool executable) { if (fd != -1) { - return os::map_memory_to_file(size, fd, flag); + return os::map_memory_to_file(size, fd); } - return os::reserve_memory(size, executable, flag); + return os::reserve_memory(size, executable); } // Helper method -static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd, bool executable, MEMFLAGS flag) { +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fd, bool executable) { if (fd != -1) { - return os::map_memory_to_file_aligned(size, alignment, fd, flag); + return os::map_memory_to_file_aligned(size, alignment, fd); } - return os::reserve_memory_aligned(size, alignment, executable, flag); + return os::reserve_memory_aligned(size, alignment, executable); } // Helper method @@ -155,7 +154,7 @@ static void log_on_large_pages_failure(char* req_addr, size_t bytes) { } static char* reserve_memory(char* requested_address, const size_t size, - const size_t alignment, int fd, bool exec, MEMFLAGS flag) { + const size_t alignment, int fd, bool exec) { char* base; // If the memory was requested at a particular address, use // os::attempt_reserve_memory_at() to avoid mapping over something @@ -164,19 +163,19 @@ static char* reserve_memory(char* requested_address, const size_t size, assert(is_aligned(requested_address, alignment), "Requested address " PTR_FORMAT " must be aligned to " SIZE_FORMAT, p2i(requested_address), alignment); - base = attempt_map_or_reserve_memory_at(requested_address, size, fd, exec, flag); + base = attempt_map_or_reserve_memory_at(requested_address, size, fd, exec); } else { // Optimistically assume that the OS returns an aligned base pointer. // When reserving a large address range, most OSes seem to align to at // least 64K. - base = map_or_reserve_memory(size, fd, exec, flag); + base = map_or_reserve_memory(size, fd, exec); // Check alignment constraints. This is only needed when there is // no requested address. if (!is_aligned(base, alignment)) { // Base not aligned, retry. unmap_or_release_memory(base, size, fd != -1 /*is_file_mapped*/); // Map using the requested alignment. - base = map_or_reserve_memory_aligned(size, alignment, fd, exec, flag); + base = map_or_reserve_memory_aligned(size, alignment, fd, exec); } } @@ -184,14 +183,14 @@ static char* reserve_memory(char* requested_address, const size_t size, } static char* reserve_memory_special(char* requested_address, const size_t size, - const size_t alignment, const size_t page_size, bool exec, MEMFLAGS flag) { + const size_t alignment, const size_t page_size, bool exec) { log_trace(pagesize)("Attempt special mapping: size: " SIZE_FORMAT "%s, " "alignment: " SIZE_FORMAT "%s", byte_size_in_exact_unit(size), exact_unit_for_byte_size(size), byte_size_in_exact_unit(alignment), exact_unit_for_byte_size(alignment)); - char* base = os::reserve_memory_special(size, alignment, page_size, requested_address, exec, flag); + char* base = os::reserve_memory_special(size, alignment, page_size, requested_address, exec); if (base != nullptr) { // Check alignment constraints. assert(is_aligned(base, alignment), @@ -203,19 +202,18 @@ static char* reserve_memory_special(char* requested_address, const size_t size, } void ReservedSpace::clear_members() { - initialize_members(nullptr, 0, 0, 0, false, false, mtNone); + initialize_members(nullptr, 0, 0, 0, false, false); } void ReservedSpace::initialize_members(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable, MEMFLAGS flag) { + size_t page_size, bool special, bool executable) { _base = base; _size = size; - _noaccess_prefix = 0; _alignment = alignment; _page_size = page_size; _special = special; _executable = executable; - _flag = flag; + _noaccess_prefix = 0; } void ReservedSpace::reserve(size_t size, @@ -237,9 +235,9 @@ void ReservedSpace::reserve(size_t size, // When there is a backing file directory for this space then whether // large pages are allocated is up to the filesystem of the backing file. // So UseLargePages is not taken into account for this reservation. - char* base = reserve_memory(requested_address, size, alignment, _fd_for_heap, executable, _flag); + char* base = reserve_memory(requested_address, size, alignment, _fd_for_heap, executable); if (base != nullptr) { - initialize_members(base, size, alignment, os::vm_page_size(), true, executable, _flag); + initialize_members(base, size, alignment, os::vm_page_size(), true, executable); } // Always return, not possible to fall back to reservation not using a file. return; @@ -252,10 +250,10 @@ void ReservedSpace::reserve(size_t size, // explicit large pages and these have to be committed up front to ensure // no reservations are lost. do { - char* base = reserve_memory_special(requested_address, size, alignment, page_size, executable, _flag); + char* base = reserve_memory_special(requested_address, size, alignment, page_size, executable); if (base != nullptr) { // Successful reservation using large pages. - initialize_members(base, size, alignment, page_size, true, executable, _flag); + initialize_members(base, size, alignment, page_size, true, executable); return; } page_size = os::page_sizes().next_smaller(page_size); @@ -268,10 +266,10 @@ void ReservedSpace::reserve(size_t size, } // == Case 3 == - char* base = reserve_memory(requested_address, size, alignment, -1, executable, _flag); + char* base = reserve_memory(requested_address, size, alignment, -1, executable); if (base != nullptr) { // Successful mapping. - initialize_members(base, size, alignment, page_size, false, executable, _flag); + initialize_members(base, size, alignment, page_size, false, executable); } } @@ -279,8 +277,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, size_t page_size, char* requested_address, - bool executable, - MEMFLAGS flag) { + bool executable) { const size_t granularity = os::vm_allocation_granularity(); assert((size & (granularity - 1)) == 0, "size not aligned to os::vm_allocation_granularity()"); @@ -293,9 +290,6 @@ void ReservedSpace::initialize(size_t size, clear_members(); - // _flag is cleared in clear_members in above call - _flag = flag; - if (size == 0) { return; } @@ -316,14 +310,14 @@ void ReservedSpace::initialize(size_t size, ReservedSpace ReservedSpace::first_part(size_t partition_size, size_t alignment) { assert(partition_size <= size(), "partition failed"); - ReservedSpace result(base(), partition_size, alignment, page_size(), special(), executable(), nmt_flag()); + ReservedSpace result(base(), partition_size, alignment, page_size(), special(), executable()); return result; } ReservedSpace ReservedSpace::last_part(size_t partition_size, size_t alignment) { assert(partition_size <= size(), "partition failed"); ReservedSpace result(base() + partition_size, size() - partition_size, - alignment, page_size(), special(), executable(), nmt_flag()); + alignment, page_size(), special(), executable()); return result; } @@ -366,12 +360,12 @@ void ReservedSpace::release() { // Put a ReservedSpace over an existing range ReservedSpace ReservedSpace::space_for_range(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable, MEMFLAGS flag) { + size_t page_size, bool special, bool executable) { assert(is_aligned(base, os::vm_allocation_granularity()), "Unaligned base"); assert(is_aligned(size, os::vm_page_size()), "Unaligned size"); assert(os::page_sizes().contains(page_size), "Invalid pagesize"); ReservedSpace space; - space.initialize_members(base, size, alignment, page_size, special, executable, flag); + space.initialize_members(base, size, alignment, page_size, special, executable); return space; } @@ -613,17 +607,16 @@ void ReservedHeapSpace::initialize_compressed_heap(const size_t size, size_t ali // Last, desperate try without any placement. if (_base == nullptr) { log_trace(gc, heap, coops)("Trying to allocate at address null heap of size " SIZE_FORMAT_X, size + noaccess_prefix); - initialize(size + noaccess_prefix, alignment, page_size, nullptr, !ExecMem, nmt_flag()); + initialize(size + noaccess_prefix, alignment, page_size, nullptr, false); } } } ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, size_t page_size, const char* heap_allocation_directory) : ReservedSpace() { + if (size == 0) { return; } - // _flag is used internally by initialize_compressed_heap - _flag = mtJavaHeap; if (heap_allocation_directory != nullptr) { _fd_for_heap = os::create_file_for_heap(heap_allocation_directory); @@ -651,7 +644,7 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, size_t page_ establish_noaccess_prefix(); } } else { - initialize(size, alignment, page_size, nullptr, false, nmt_flag()); + initialize(size, alignment, page_size, nullptr, false); } assert(markWord::encode_pointer_as_mark(_base).decode_pointer() == _base, @@ -659,6 +652,9 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, size_t page_ assert(markWord::encode_pointer_as_mark(&_base[size]).decode_pointer() == &_base[size], "area must be distinguishable from marks for mark-sweep"); + if (base() != nullptr) { + MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap); + } if (_fd_for_heap != -1) { ::close(_fd_for_heap); @@ -674,7 +670,8 @@ MemRegion ReservedHeapSpace::region() const { ReservedCodeSpace::ReservedCodeSpace(size_t r_size, size_t rs_align, size_t rs_page_size) : ReservedSpace() { - initialize(r_size, rs_align, rs_page_size, /*requested address*/ nullptr, /*executable*/ true, mtCode); + initialize(r_size, rs_align, rs_page_size, /*requested address*/ nullptr, /*executable*/ true); + MemTracker::record_virtual_memory_type((address)base(), mtCode); } // VirtualSpace @@ -695,7 +692,6 @@ VirtualSpace::VirtualSpace() { _upper_alignment = 0; _special = false; _executable = false; - _flag = mtNone; } @@ -717,7 +713,6 @@ bool VirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t committe _special = rs.special(); _executable = rs.executable(); - _flag = rs.nmt_flag(); // When a VirtualSpace begins life at a large size, make all future expansion // and shrinking occur aligned to a granularity of large pages. This avoids @@ -776,7 +771,6 @@ void VirtualSpace::release() { _upper_alignment = 0; _special = false; _executable = false; - _flag = mtNone; } @@ -842,8 +836,8 @@ static void pretouch_expanded_memory(void* start, void* end) { os::pretouch_memory(start, end); } -static bool commit_expanded(char* start, size_t size, size_t alignment, bool pre_touch, bool executable, MEMFLAGS flag) { - if (os::commit_memory(start, size, alignment, executable, flag)) { +static bool commit_expanded(char* start, size_t size, size_t alignment, bool pre_touch, bool executable) { + if (os::commit_memory(start, size, alignment, executable)) { if (pre_touch || AlwaysPreTouch) { pretouch_expanded_memory(start, start + size); } @@ -932,7 +926,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { // Commit regions if (lower_needs > 0) { assert(lower_high() + lower_needs <= lower_high_boundary(), "must not expand beyond region"); - if (!commit_expanded(lower_high(), lower_needs, _lower_alignment, pre_touch, _executable, _flag)) { + if (!commit_expanded(lower_high(), lower_needs, _lower_alignment, pre_touch, _executable)) { return false; } _lower_high += lower_needs; @@ -940,7 +934,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { if (middle_needs > 0) { assert(middle_high() + middle_needs <= middle_high_boundary(), "must not expand beyond region"); - if (!commit_expanded(middle_high(), middle_needs, _middle_alignment, pre_touch, _executable, _flag)) { + if (!commit_expanded(middle_high(), middle_needs, _middle_alignment, pre_touch, _executable)) { return false; } _middle_high += middle_needs; @@ -948,7 +942,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { if (upper_needs > 0) { assert(upper_high() + upper_needs <= upper_high_boundary(), "must not expand beyond region"); - if (!commit_expanded(upper_high(), upper_needs, _upper_alignment, pre_touch, _executable, _flag)) { + if (!commit_expanded(upper_high(), upper_needs, _upper_alignment, pre_touch, _executable)) { return false; } _upper_high += upper_needs; @@ -1020,7 +1014,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(middle_high_boundary() <= aligned_upper_new_high && aligned_upper_new_high + upper_needs <= upper_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable, _flag)) { + if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable)) { debug_only(warning("os::uncommit_memory failed")); return; } else { @@ -1031,7 +1025,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(lower_high_boundary() <= aligned_middle_new_high && aligned_middle_new_high + middle_needs <= middle_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable, _flag)) { + if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable)) { debug_only(warning("os::uncommit_memory failed")); return; } else { @@ -1042,7 +1036,7 @@ void VirtualSpace::shrink_by(size_t size) { assert(low_boundary() <= aligned_lower_new_high && aligned_lower_new_high + lower_needs <= lower_high_boundary(), "must not shrink beyond region"); - if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable, _flag)) { + if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable)) { debug_only(warning("os::uncommit_memory failed")); return; } else { diff --git a/src/hotspot/share/memory/virtualspace.hpp b/src/hotspot/share/memory/virtualspace.hpp index 357c4952c3456..046ad0cf7a420 100644 --- a/src/hotspot/share/memory/virtualspace.hpp +++ b/src/hotspot/share/memory/virtualspace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, 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,20 +35,19 @@ class outputStream; class ReservedSpace { friend class VMStructs; protected: - char* _base; - size_t _size; - size_t _noaccess_prefix; - size_t _alignment; - size_t _page_size; - int _fd_for_heap; - bool _special; - bool _executable; - MEMFLAGS _flag; + char* _base; + size_t _size; + size_t _noaccess_prefix; + size_t _alignment; + size_t _page_size; + bool _special; + int _fd_for_heap; private: + bool _executable; // ReservedSpace ReservedSpace(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable, MEMFLAGS flag); + size_t page_size, bool special, bool executable); protected: // Helpers to clear and set members during initialization. Two members // require special treatment: @@ -59,28 +58,25 @@ class ReservedSpace { // 0 during initialization. void clear_members(); void initialize_members(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable, MEMFLAGS flag); + size_t page_size, bool special, bool executable); void initialize(size_t size, size_t alignment, size_t page_size, - char* requested_address, bool executable, MEMFLAGS flag); + char* requested_address, bool executable); void reserve(size_t size, size_t alignment, size_t page_size, char* requested_address, bool executable); public: - - MEMFLAGS nmt_flag() const { return _flag; } - // Constructor ReservedSpace(); // Initialize the reserved space with the given size. Depending on the size // a suitable page size and alignment will be used. - explicit ReservedSpace(size_t size, MEMFLAGS flag); + explicit ReservedSpace(size_t size); // Initialize the reserved space with the given size. The preferred_page_size // is used as the minimum page size/alignment. This may waste some space if // the given size is not aligned to that value, as the reservation will be // aligned up to the final alignment in this case. - ReservedSpace(size_t size, size_t preferred_page_size, MEMFLAGS flag); - ReservedSpace(size_t size, size_t alignment, size_t page_size, MEMFLAGS flag, + ReservedSpace(size_t size, size_t preferred_page_size); + ReservedSpace(size_t size, size_t alignment, size_t page_size, char* requested_address = nullptr); // Accessors @@ -116,7 +112,7 @@ class ReservedSpace { // Put a ReservedSpace over an existing range static ReservedSpace space_for_range(char* base, size_t size, size_t alignment, - size_t page_size, bool special, bool executable, MEMFLAGS flag); + size_t page_size, bool special, bool executable); }; ReservedSpace ReservedSpace::first_part(size_t partition_size) @@ -183,8 +179,6 @@ class VirtualSpace { // Need to know if commit should be executable. bool _executable; - MEMFLAGS _flag; - // MPSS Support // Each virtualspace region has a lower, middle, and upper region. // Each region has an end boundary and a high pointer which is the diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp index 83880fc6dcc61..41a8f72b52760 100644 --- a/src/hotspot/share/nmt/memTracker.hpp +++ b/src/hotspot/share/nmt/memTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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 @@ -120,7 +120,7 @@ class MemTracker : AllStatic { // (we do not do any reservations before that). static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, - MEMFLAGS flag) { + MEMFLAGS flag = mtNone) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { @@ -137,32 +137,32 @@ class MemTracker : AllStatic { } } - static inline void record_virtual_memory_uncommit(address addr, size_t size, MEMFLAGS flag) { + static inline void record_virtual_memory_uncommit(address addr, size_t size) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { - VirtualMemoryTracker::remove_uncommitted_region((address)addr, size, flag); + VirtualMemoryTracker::remove_uncommitted_region((address)addr, size); } } static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, - const NativeCallStack& stack, MEMFLAGS flag) { + const NativeCallStack& stack, MEMFLAGS flag = mtNone) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { ThreadCritical tc; VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag); - VirtualMemoryTracker::add_committed_region((address)addr, size, stack, flag); + VirtualMemoryTracker::add_committed_region((address)addr, size, stack); } } static inline void record_virtual_memory_commit(void* addr, size_t size, - const NativeCallStack& stack, MEMFLAGS flag) { + const NativeCallStack& stack) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { ThreadCritical tc; - VirtualMemoryTracker::add_committed_region((address)addr, size, stack, flag); + VirtualMemoryTracker::add_committed_region((address)addr, size, stack); } } diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.cpp b/src/hotspot/share/nmt/virtualMemoryTracker.cpp index a96718f59ff13..06f9469f25e14 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.cpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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 @@ -424,20 +424,20 @@ void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) if (reserved_rgn != nullptr) { assert(reserved_rgn->contain_address(addr), "Containment"); if (reserved_rgn->flag() != flag) { - assert(reserved_rgn->flag() == mtNone, "Overwrite memory type (should be mtNone, is: \"%s\") wants to change to \"%s\"", - NMTUtil::flag_to_name(reserved_rgn->flag()), NMTUtil::flag_to_name(flag)); + assert(reserved_rgn->flag() == mtNone, "Overwrite memory type (should be mtNone, is: \"%s\")", + NMTUtil::flag_to_name(reserved_rgn->flag())); reserved_rgn->set_flag(flag); } } } bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, - const NativeCallStack& stack, MEMFLAGS flag) { + const NativeCallStack& stack) { assert(addr != nullptr, "Invalid address"); assert(size > 0, "Invalid size"); assert(_reserved_regions != nullptr, "Sanity check"); - ReservedMemoryRegion rgn(addr, size, stack, flag); + ReservedMemoryRegion rgn(addr, size); ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); if (reserved_rgn == nullptr) { @@ -452,7 +452,7 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, return result; } -bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size, MEMFLAGS flag) { +bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { assert(addr != nullptr, "Invalid address"); assert(size > 0, "Invalid size"); assert(_reserved_regions != nullptr, "Sanity check"); diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.hpp b/src/hotspot/share/nmt/virtualMemoryTracker.hpp index 6404f3fac4b2e..db49f108c84b9 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.hpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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 @@ -296,16 +296,13 @@ class ReservedMemoryRegion : public VirtualMemoryRegion { public: ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack, - MEMFLAGS flag) : + MEMFLAGS flag = mtNone) : VirtualMemoryRegion(base, size), _stack(stack), _flag(flag) { } ReservedMemoryRegion(address base, size_t size) : VirtualMemoryRegion(base, size), _stack(NativeCallStack::empty_stack()), _flag(mtNone) { } - ReservedMemoryRegion(address base, size_t size, MEMFLAGS flag) : - VirtualMemoryRegion(base, size), _stack(NativeCallStack::empty_stack()), _flag(flag) { } - // Copy constructor ReservedMemoryRegion(const ReservedMemoryRegion& rr) : VirtualMemoryRegion(rr.base(), rr.size()) { @@ -382,10 +379,10 @@ class VirtualMemoryTracker : AllStatic { public: static bool initialize(NMT_TrackingLevel level); - static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag); + static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone); - static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag); - static bool remove_uncommitted_region (address base_addr, size_t size, MEMFLAGS flag); + static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack); + static bool remove_uncommitted_region (address base_addr, size_t size); static bool remove_released_region (address base_addr, size_t size); static bool remove_released_region (ReservedMemoryRegion* rgn); static void set_reserved_region_type (address addr, MEMFLAGS flag); diff --git a/src/hotspot/share/oops/compressedKlass.cpp b/src/hotspot/share/oops/compressedKlass.cpp index 98be5dc978141..4a94eb9bde02d 100644 --- a/src/hotspot/share/oops/compressedKlass.cpp +++ b/src/hotspot/share/oops/compressedKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ void CompressedKlassPointers::initialize_for_given_encoding(address addr, size_t char* CompressedKlassPointers::reserve_address_space_X(uintptr_t from, uintptr_t to, size_t size, size_t alignment, bool aslr) { alignment = MAX2(Metaspace::reserve_alignment(), alignment); - return os::attempt_reserve_memory_between((char*)from, (char*)to, size, alignment, aslr, mtMetaspace); + return os::attempt_reserve_memory_between((char*)from, (char*)to, size, alignment, aslr); } char* CompressedKlassPointers::reserve_address_space_for_unscaled_encoding(size_t size, bool aslr) { diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index e66daa1db9ccf..b6a4443a8c763 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -2396,10 +2396,11 @@ static char* get_bad_address() { static char* bad_address = nullptr; if (bad_address == nullptr) { size_t size = os::vm_allocation_granularity(); - bad_address = os::reserve_memory(size, !ExecMem, mtInternal); + bad_address = os::reserve_memory(size); if (bad_address != nullptr) { os::protect_memory(bad_address, size, os::MEM_PROT_READ, /*is_committed*/false); + MemTracker::record_virtual_memory_type((void*)bad_address, mtInternal); } } return bad_address; diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 2a99e33eaf83a..54fb62180bf17 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -697,21 +697,27 @@ WB_END WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) jlong addr = 0; - addr = (jlong)(uintptr_t)os::reserve_memory(size, !ExecMem, mtTest); + + addr = (jlong)(uintptr_t)os::reserve_memory(size); + MemTracker::record_virtual_memory_type((address)addr, mtTest); + return addr; WB_END WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size)) - addr = (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, !ExecMem, mtTest); + addr = (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size); + MemTracker::record_virtual_memory_type((address)addr, mtTest); + return addr; WB_END WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) - os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem, mtTest); + os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem); + MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest); WB_END WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) - os::uncommit_memory((char *)(uintptr_t)addr, size, !ExecMem, mtTest); + os::uncommit_memory((char *)(uintptr_t)addr, size); WB_END WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) @@ -1480,7 +1486,7 @@ WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o)) static char c; static volatile char* p; - p = os::reserve_memory(os::vm_allocation_granularity(), !ExecMem, mtTest); + p = os::reserve_memory(os::vm_allocation_granularity()); if (p == nullptr) { THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory"); } diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 5197abf5b541a..53c438cd20895 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1821,7 +1821,7 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) { } char* os::reserve_memory(size_t bytes, bool executable, MEMFLAGS flags) { - char* result = pd_reserve_memory(bytes, executable, flags); + char* result = pd_reserve_memory(bytes, executable); if (result != nullptr) { MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC, flags); log_debug(os, map)("Reserved " RANGEFMT, RANGEFMTARGS(result, bytes)); @@ -1832,7 +1832,7 @@ char* os::reserve_memory(size_t bytes, bool executable, MEMFLAGS flags) { } char* os::attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MEMFLAGS flag) { - char* result = SimulateFullAddressSpace ? nullptr : pd_attempt_reserve_memory_at(addr, bytes, executable, flag); + char* result = SimulateFullAddressSpace ? nullptr : pd_attempt_reserve_memory_at(addr, bytes, executable); if (result != nullptr) { MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, flag); log_debug(os, map)("Reserved " RANGEFMT, RANGEFMTARGS(result, bytes)); @@ -1879,7 +1879,7 @@ static void hemi_split(T* arr, unsigned num) { // Given an address range [min, max), attempts to reserve memory within this area, with the given alignment. // If randomize is true, the location will be randomized. -char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize, MEMFLAGS flag) { +char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize) { // Please keep the following constants in sync with the companion gtests: @@ -2017,7 +2017,7 @@ char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, siz const unsigned candidate_offset = points[i]; char* const candidate = lo_att + candidate_offset * alignment_adjusted; assert(candidate <= hi_att, "Invalid offset %u (" ARGSFMT ")", candidate_offset, ARGSFMTARGS); - result = SimulateFullAddressSpace ? nullptr : os::pd_attempt_reserve_memory_at(candidate, bytes, !ExecMem, flag); + result = SimulateFullAddressSpace ? nullptr : os::pd_attempt_reserve_memory_at(candidate, bytes, false); if (!result) { log_trace(os, map)("Failed to attach at " PTR_FORMAT, p2i(candidate)); } @@ -2034,7 +2034,7 @@ char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, siz assert(is_aligned(result, alignment), "alignment invalid (" ERRFMT ")", ERRFMTARGS); log_trace(os, map)(ERRFMT, ERRFMTARGS); log_debug(os, map)("successfully attached at " PTR_FORMAT, p2i(result)); - MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, flag); + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); } else { log_debug(os, map)("failed to attach anywhere in [" PTR_FORMAT "-" PTR_FORMAT ")", p2i(min), p2i(max)); } @@ -2050,11 +2050,11 @@ static void assert_nonempty_range(const char* addr, size_t bytes) { p2i(addr), p2i(addr) + bytes); } -bool os::commit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag) { +bool os::commit_memory(char* addr, size_t bytes, bool executable) { assert_nonempty_range(addr, bytes); bool res = pd_commit_memory(addr, bytes, executable); if (res) { - MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC, flag); + MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC); log_debug(os, map)("Committed " RANGEFMT, RANGEFMTARGS(addr, bytes)); } else { log_info(os, map)("Failed to commit " RANGEFMT, RANGEFMTARGS(addr, bytes)); @@ -2063,11 +2063,11 @@ bool os::commit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag) } bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, - bool executable, MEMFLAGS flag) { + bool executable) { assert_nonempty_range(addr, size); bool res = os::pd_commit_memory(addr, size, alignment_hint, executable); if (res) { - MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC, flag); + MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); log_debug(os, map)("Committed " RANGEFMT, RANGEFMTARGS(addr, size)); } else { log_info(os, map)("Failed to commit " RANGEFMT, RANGEFMTARGS(addr, size)); @@ -2076,27 +2076,27 @@ bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, } void os::commit_memory_or_exit(char* addr, size_t bytes, bool executable, - MEMFLAGS flag, const char* mesg) { + const char* mesg) { assert_nonempty_range(addr, bytes); pd_commit_memory_or_exit(addr, bytes, executable, mesg); - MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC, flag); + MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC); } void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, - bool executable, MEMFLAGS flag, const char* mesg) { + bool executable, const char* mesg) { assert_nonempty_range(addr, size); os::pd_commit_memory_or_exit(addr, size, alignment_hint, executable, mesg); - MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC, flag); + MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); } -bool os::uncommit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag) { +bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { assert_nonempty_range(addr, bytes); bool res; if (MemTracker::enabled()) { ThreadCritical tc; res = pd_uncommit_memory(addr, bytes, executable); if (res) { - MemTracker::record_virtual_memory_uncommit((address)addr, bytes, flag); + MemTracker::record_virtual_memory_uncommit((address)addr, bytes); } } else { res = pd_uncommit_memory(addr, bytes, executable); @@ -2180,7 +2180,7 @@ char* os::map_memory_to_file(size_t bytes, int file_desc, MEMFLAGS flag) { } char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc, MEMFLAGS flag) { - char* result = pd_attempt_map_memory_to_file_at(addr, bytes, file_desc, flag); + char* result = pd_attempt_map_memory_to_file_at(addr, bytes, file_desc); if (result != nullptr) { MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC, flag); } @@ -2188,8 +2188,8 @@ char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc, } char* os::map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only, - bool allow_exec, MEMFLAGS flags) { + char *addr, size_t bytes, bool read_only, + bool allow_exec, MEMFLAGS flags) { char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec); if (result != nullptr) { MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC, flags); @@ -2211,8 +2211,8 @@ bool os::unmap_memory(char *addr, size_t bytes) { return result; } -void os::free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag) { - pd_free_memory(addr, bytes, alignment_hint, flag); +void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) { + pd_free_memory(addr, bytes, alignment_hint); } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { @@ -2220,14 +2220,14 @@ void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size, - char* addr, bool executable, MEMFLAGS flag) { + char* addr, bool executable) { assert(is_aligned(addr, alignment), "Unaligned request address"); - char* result = pd_reserve_memory_special(size, alignment, page_size, addr, executable, flag); + char* result = pd_reserve_memory_special(size, alignment, page_size, addr, executable); if (result != nullptr) { // The memory is committed - MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC, flag); + MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC); log_debug(os, map)("Reserved and committed " RANGEFMT, RANGEFMTARGS(result, size)); } else { log_info(os, map)("Reserve and commit failed (%zu bytes)", size); diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 29ef6d5d29d23..4bfcd9c2da563 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -208,9 +208,9 @@ class os: AllStatic { // low enough to leave most of the valuable low-4gb address space open. static constexpr size_t _vm_min_address_default = 16 * M; - static char* pd_reserve_memory(size_t bytes, bool executable, MEMFLAGS flag); + static char* pd_reserve_memory(size_t bytes, bool executable); - static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MEMFLAGS flag); + static char* pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool executable); static bool pd_commit_memory(char* addr, size_t bytes, bool executable); static bool pd_commit_memory(char* addr, size_t size, size_t alignment_hint, @@ -225,13 +225,13 @@ class os: AllStatic { static bool pd_uncommit_memory(char* addr, size_t bytes, bool executable); static bool pd_release_memory(char* addr, size_t bytes); - static char* pd_attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc, MEMFLAGS flag); + static char* pd_attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc); static char* pd_map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only = false, - bool allow_exec = false); + char *addr, size_t bytes, bool read_only = false, + bool allow_exec = false); static bool pd_unmap_memory(char *addr, size_t bytes); - static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag); + static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint); static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint); // Returns 0 if pretouch is done via platform dependent method, or otherwise @@ -239,7 +239,8 @@ class os: AllStatic { static size_t pd_pretouch_memory(void* first, void* last, size_t page_size); static char* pd_reserve_memory_special(size_t size, size_t alignment, size_t page_size, - char* addr, bool executable, MEMFLAGS flag); + + char* addr, bool executable); static bool pd_release_memory_special(char* addr, size_t bytes); static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); @@ -447,30 +448,30 @@ class os: AllStatic { inline static size_t cds_core_region_alignment(); // Reserves virtual memory. - static char* reserve_memory(size_t bytes, bool executable, MEMFLAGS flags); + static char* reserve_memory(size_t bytes, bool executable = false, MEMFLAGS flags = mtNone); // Reserves virtual memory that starts at an address that is aligned to 'alignment'. - static char* reserve_memory_aligned(size_t size, size_t alignment, bool executable, MEMFLAGS flag); + static char* reserve_memory_aligned(size_t size, size_t alignment, bool executable = false); // Attempts to reserve the virtual memory at [addr, addr + bytes). // Does not overwrite existing mappings. - static char* attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MEMFLAGS flag); + static char* attempt_reserve_memory_at(char* addr, size_t bytes, bool executable = false, MEMFLAGS flag = mtNone); // Given an address range [min, max), attempts to reserve memory within this area, with the given alignment. // If randomize is true, the location will be randomized. - static char* attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize, MEMFLAGS flag); + static char* attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomize); - static bool commit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag); + static bool commit_memory(char* addr, size_t bytes, bool executable); static bool commit_memory(char* addr, size_t size, size_t alignment_hint, - bool executable, MEMFLAGS flag); + bool executable); // Same as commit_memory() that either succeeds or calls // vm_exit_out_of_memory() with the specified mesg. static void commit_memory_or_exit(char* addr, size_t bytes, - bool executable, MEMFLAGS flag, const char* mesg); + bool executable, const char* mesg); static void commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, - bool executable, MEMFLAGS flag, const char* mesg); - static bool uncommit_memory(char* addr, size_t bytes, bool executable, MEMFLAGS flag); + bool executable, const char* mesg); + static bool uncommit_memory(char* addr, size_t bytes, bool executable = false); static bool release_memory(char* addr, size_t bytes); // Does the platform support trimming the native heap? @@ -506,18 +507,18 @@ class os: AllStatic { static int create_file_for_heap(const char* dir); // Map memory to the file referred by fd. This function is slightly different from map_memory() // and is added to be used for implementation of -XX:AllocateHeapAt - static char* map_memory_to_file(size_t size, int fd, MEMFLAGS flag); - static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MEMFLAGS flag); + static char* map_memory_to_file(size_t size, int fd, MEMFLAGS flag = mtNone); + static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MEMFLAGS flag = mtNone); static char* map_memory_to_file(char* base, size_t size, int fd); - static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MEMFLAGS flag); + static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MEMFLAGS flag = mtNone); // Replace existing reserved memory with file mapping static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd); static char* map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, bool read_only, - bool allow_exec, MEMFLAGS flag); + char *addr, size_t bytes, bool read_only = false, + bool allow_exec = false, MEMFLAGS flags = mtNone); static bool unmap_memory(char *addr, size_t bytes); - static void free_memory(char *addr, size_t bytes, size_t alignment_hint, MEMFLAGS flag); + static void free_memory(char *addr, size_t bytes, size_t alignment_hint); static void realign_memory(char *addr, size_t bytes, size_t alignment_hint); // NUMA-specific interface @@ -539,7 +540,7 @@ class os: AllStatic { static char* non_memory_address_word(); // reserve, commit and pin the entire memory region static char* reserve_memory_special(size_t size, size_t alignment, size_t page_size, - char* addr, bool executable, MEMFLAGS flag); + char* addr, bool executable); static bool release_memory_special(char* addr, size_t bytes); static void large_page_init(); static size_t large_page_size(); diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index dcad8acb215a0..624583db3d130 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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,8 +58,9 @@ void SafepointMechanism::default_initialize() { // Polling page const size_t page_size = os::vm_page_size(); const size_t allocation_size = 2 * page_size; - char* polling_page = os::reserve_memory(allocation_size, !ExecMem, mtSafepoint); - os::commit_memory_or_exit(polling_page, allocation_size, !ExecMem, mtSafepoint, "Unable to commit Safepoint polling page"); + char* polling_page = os::reserve_memory(allocation_size); + os::commit_memory_or_exit(polling_page, allocation_size, false, "Unable to commit Safepoint polling page"); + MemTracker::record_virtual_memory_type((address)polling_page, mtSafepoint); char* bad_page = polling_page; char* good_page = polling_page + page_size; diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index e12e55e49845d..9f839fc1a136b 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -709,9 +709,10 @@ struct TestMultipleStaticAssertFormsInClassScope { static ucontext_t g_stored_assertion_context; void initialize_assert_poison() { - char* page = os::reserve_memory(os::vm_page_size(), !ExecMem, mtInternal); + char* page = os::reserve_memory(os::vm_page_size()); if (page) { - if (os::commit_memory(page, os::vm_page_size(), !ExecMem, mtInternal) && + MemTracker::record_virtual_memory_type(page, mtInternal); + if (os::commit_memory(page, os::vm_page_size(), false) && os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) { g_assert_poison = page; } diff --git a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp index 6dfde68678a29..4639f1c969430 100644 --- a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp +++ b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp @@ -50,7 +50,7 @@ TEST_OTHER_VM(FreeRegionList, length) { // the BOT. size_t bot_size = G1BlockOffsetTable::compute_size(heap.word_size()); HeapWord* bot_data = NEW_C_HEAP_ARRAY(HeapWord, bot_size, mtGC); - ReservedSpace bot_rs(G1BlockOffsetTable::compute_size(heap.word_size()), mtTest); + ReservedSpace bot_rs(G1BlockOffsetTable::compute_size(heap.word_size())); G1RegionToSpaceMapper* bot_storage = G1RegionToSpaceMapper::create_mapper(bot_rs, bot_rs.size(), diff --git a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp index 2285f58d55c7f..8ce98827ab2e0 100644 --- a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp +++ b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp @@ -81,7 +81,7 @@ TEST_VM(G1RegionToSpaceMapper, smallStressAdjacent) { size_t size = G1BlockOffsetTable::compute_size(num_regions * region_size / HeapWordSize); size_t page_size = os::vm_page_size(); - ReservedSpace rs(size, os::vm_page_size(), mtTest); + ReservedSpace rs(size, os::vm_page_size()); G1RegionToSpaceMapper* small_mapper = G1RegionToSpaceMapper::create_mapper(rs, @@ -105,7 +105,7 @@ TEST_VM(G1RegionToSpaceMapper, largeStressAdjacent) { size_t size = G1BlockOffsetTable::compute_size(num_regions * region_size / HeapWordSize); size_t page_size = os::vm_page_size(); - ReservedSpace rs(size, page_size, mtTest); + ReservedSpace rs(size, page_size); G1RegionToSpaceMapper* large_mapper = G1RegionToSpaceMapper::create_mapper(rs, diff --git a/test/hotspot/gtest/gc/z/test_zForwarding.cpp b/test/hotspot/gtest/gc/z/test_zForwarding.cpp index 570e402ccd796..622c6d9d8f4a0 100644 --- a/test/hotspot/gtest/gc/z/test_zForwarding.cpp +++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ class ZForwardingTest : public Test { const size_t increment = MAX2(align_up(unused / 100, ZGranuleSize), ZGranuleSize); for (uintptr_t start = 0; start + ZGranuleSize <= ZAddressOffsetMax; start += increment) { - char* const reserved = os::attempt_reserve_memory_at((char*)ZAddressHeapBase + start, ZGranuleSize, !ExecMem /* executable */, mtTest); + char* const reserved = os::attempt_reserve_memory_at((char*)ZAddressHeapBase + start, ZGranuleSize, false /* executable */); if (reserved != nullptr) { // Success return reserved; @@ -100,7 +100,7 @@ class ZForwardingTest : public Test { _reserved = reserved; - os::commit_memory((char*)_reserved, ZGranuleSize, !ExecMem /* executable */, mtTest); + os::commit_memory((char*)_reserved, ZGranuleSize, false /* executable */); _page_offset = uintptr_t(_reserved) - ZAddressHeapBase; } @@ -111,7 +111,7 @@ class ZForwardingTest : public Test { ZGeneration::_old = _old_old; ZGeneration::_young = _old_young; if (_reserved != nullptr) { - os::uncommit_memory((char*)_reserved, ZGranuleSize, !ExecMem, mtTest); + os::uncommit_memory((char*)_reserved, ZGranuleSize, false /* executable */); os::release_memory((char*)_reserved, ZGranuleSize); } } diff --git a/test/hotspot/gtest/memory/test_virtualspace.cpp b/test/hotspot/gtest/memory/test_virtualspace.cpp index a20f85ba6c5c2..2240f0f4cb37d 100644 --- a/test/hotspot/gtest/memory/test_virtualspace.cpp +++ b/test/hotspot/gtest/memory/test_virtualspace.cpp @@ -64,7 +64,7 @@ namespace { static void test_reserved_size(size_t size) { ASSERT_PRED2(is_size_aligned, size, os::vm_allocation_granularity()); - ReservedSpace rs(size, mtTest); + ReservedSpace rs(size); MemoryReleaser releaser(&rs); EXPECT_TRUE(rs.base() != nullptr) << "rs.special: " << rs.special(); @@ -78,7 +78,7 @@ namespace { static void test_reserved_size_alignment(size_t size, size_t alignment) { ASSERT_PRED2(is_size_aligned, size, alignment) << "Incorrect input parameters"; size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); - ReservedSpace rs(size, alignment, page_size, mtTest, (char *) nullptr); + ReservedSpace rs(size, alignment, page_size, (char *) nullptr); ASSERT_TRUE(rs.base() != nullptr) << "rs.special = " << rs.special(); ASSERT_EQ(size, rs.size()) << "rs.special = " << rs.special(); @@ -106,7 +106,7 @@ namespace { bool large = maybe_large && UseLargePages && size >= os::large_page_size(); size_t page_size = large ? os::large_page_size() : os::vm_page_size(); - ReservedSpace rs(size, alignment, page_size, mtTest); + ReservedSpace rs(size, alignment, page_size); MemoryReleaser releaser(&rs); EXPECT_TRUE(rs.base() != nullptr) << "rs.special: " << rs.special(); @@ -215,13 +215,12 @@ namespace { default: case Default: case Reserve: - return ReservedSpace(reserve_size_aligned, mtTest); + return ReservedSpace(reserve_size_aligned); case Disable: case Commit: return ReservedSpace(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size(), - mtTest); + os::vm_page_size()); } } @@ -300,7 +299,7 @@ TEST_VM(VirtualSpace, actual_committed_space_one_large_page) { size_t large_page_size = os::large_page_size(); - ReservedSpace reserved(large_page_size, large_page_size, large_page_size, mtTest); + ReservedSpace reserved(large_page_size, large_page_size, large_page_size); ReservedSpaceReleaser releaser(&reserved); ASSERT_TRUE(reserved.is_reserved()); @@ -370,7 +369,6 @@ class TestReservedSpace : AllStatic { ReservedSpace rs(size, // size alignment, // alignment page_size, // page size - mtTest, // NMT MEM Flag (char *)nullptr); // requested_address EXPECT_TRUE(rs.base() != nullptr); @@ -389,7 +387,7 @@ class TestReservedSpace : AllStatic { static void test_reserved_space2(size_t size) { ASSERT_TRUE(is_aligned(size, os::vm_allocation_granularity())) << "Must be at least AG aligned"; - ReservedSpace rs(size, mtTest); + ReservedSpace rs(size); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -414,7 +412,7 @@ class TestReservedSpace : AllStatic { bool large = maybe_large && UseLargePages && size >= os::large_page_size(); size_t page_size = large ? os::large_page_size() : os::vm_page_size(); - ReservedSpace rs(size, alignment, page_size, mtTest); + ReservedSpace rs(size, alignment, page_size); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -518,12 +516,12 @@ class TestVirtualSpace : AllStatic { default: case Default: case Reserve: - return ReservedSpace(reserve_size_aligned, mtTest); + return ReservedSpace(reserve_size_aligned); case Disable: case Commit: return ReservedSpace(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size(), mtTest); + os::vm_page_size()); } } @@ -578,7 +576,7 @@ class TestVirtualSpace : AllStatic { size_t large_page_size = os::large_page_size(); - ReservedSpace reserved(large_page_size, large_page_size, large_page_size, mtTest); + ReservedSpace reserved(large_page_size, large_page_size, large_page_size); EXPECT_TRUE(reserved.is_reserved()); diff --git a/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp b/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp index 359c492bb6a0e..87ad2a798e004 100644 --- a/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp @@ -114,7 +114,7 @@ TEST_VM(NMT, DISABLED_location_printing_cheap_dead_7) { test_for_dead_c_heap_blo #endif static void test_for_mmap(size_t sz, ssize_t offset) { - char* addr = os::reserve_memory(sz, !ExecMem, mtTest); + char* addr = os::reserve_memory(sz, false, mtTest); if (MemTracker::enabled()) { test_pointer(addr + offset, true, "in mmap'd memory region"); } else { diff --git a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp index 4036c798079ef..d4959cfa00854 100644 --- a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp +++ b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp @@ -93,7 +93,7 @@ class CommittedVirtualMemoryTest { const size_t page_sz = os::vm_page_size(); const size_t size = num_pages * page_sz; char* base = os::reserve_memory(size, !ExecMem, mtThreadStack); - bool result = os::commit_memory(base, size, !ExecMem, mtThreadStack); + bool result = os::commit_memory(base, size, !ExecMem); size_t index; ASSERT_NE(base, (char*)nullptr); for (index = 0; index < touch_pages; index ++) { @@ -132,7 +132,7 @@ class CommittedVirtualMemoryTest { } // Cleanup - os::free_memory(base, size, page_sz, mtThreadStack); + os::free_memory(base, size, page_sz); VirtualMemoryTracker::remove_released_region((address)base, size); rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion((address)base, size)); @@ -162,7 +162,7 @@ class CommittedVirtualMemoryTest { const size_t size = num_pages * page_sz; char* base = os::reserve_memory(size, !ExecMem, mtTest); ASSERT_NE(base, (char*)nullptr); - result = os::commit_memory(base, size, !ExecMem, mtTest); + result = os::commit_memory(base, size, !ExecMem); ASSERT_TRUE(result); // touch all pages diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index 3b7267b5790d8..55d30349ee5a9 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -367,7 +367,7 @@ TEST_VM(os, jio_snprintf) { static inline bool can_reserve_executable_memory(void) { bool executable = true; size_t len = 128; - char* p = os::reserve_memory(len, executable, mtTest); + char* p = os::reserve_memory(len, executable); bool exec_supported = (p != nullptr); if (exec_supported) { os::release_memory(p, len); @@ -405,7 +405,7 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) { for (int tries = 0; tries < 256 && p == nullptr; tries ++) { size_t total_range_len = num_stripes * stripe_len; // Reserve a large contiguous area to get the address space... - p = (address)os::reserve_memory(total_range_len, !ExecMem, mtTest); + p = (address)os::reserve_memory(total_range_len); EXPECT_NE(p, (address)nullptr); // .. release it... EXPECT_TRUE(os::release_memory((char*)p, total_range_len)); @@ -419,14 +419,14 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) { #else const bool executable = stripe % 2 == 0; #endif - q = (address)os::attempt_reserve_memory_at((char*)q, stripe_len, executable, mtTest); + q = (address)os::attempt_reserve_memory_at((char*)q, stripe_len, executable); if (q == nullptr) { // Someone grabbed that area concurrently. Cleanup, then retry. tty->print_cr("reserve_multiple: retry (%d)...", stripe); carefully_release_multiple(p, stripe, stripe_len); p = nullptr; } else { - EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, executable, mtTest)); + EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, executable)); } } } @@ -439,12 +439,12 @@ static address reserve_multiple(int num_stripes, size_t stripe_len) { static address reserve_one_commit_multiple(int num_stripes, size_t stripe_len) { assert(is_aligned(stripe_len, os::vm_allocation_granularity()), "Sanity"); size_t total_range_len = num_stripes * stripe_len; - address p = (address)os::reserve_memory(total_range_len, !ExecMem, mtTest); + address p = (address)os::reserve_memory(total_range_len); EXPECT_NE(p, (address)nullptr); for (int stripe = 0; stripe < num_stripes; stripe++) { address q = p + (stripe * stripe_len); if (stripe % 2 == 0) { - EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, !ExecMem, mtTest)); + EXPECT_TRUE(os::commit_memory((char*)q, stripe_len, false)); } } return p; @@ -506,7 +506,7 @@ TEST_VM(os, release_multi_mappings) { PRINT_MAPPINGS("B"); // ...re-reserve the middle stripes. This should work unless release silently failed. - address p2 = (address)os::attempt_reserve_memory_at((char*)p_middle_stripes, middle_stripe_len, !ExecMem, mtTest); + address p2 = (address)os::attempt_reserve_memory_at((char*)p_middle_stripes, middle_stripe_len); ASSERT_EQ(p2, p_middle_stripes); @@ -529,7 +529,7 @@ TEST_VM_ASSERT_MSG(os, release_bad_ranges, ".*bad release") { #else TEST_VM(os, release_bad_ranges) { #endif - char* p = os::reserve_memory(4 * M, !ExecMem, mtTest); + char* p = os::reserve_memory(4 * M); ASSERT_NE(p, (char*)nullptr); // Release part of range ASSERT_FALSE(os::release_memory(p, M)); @@ -564,7 +564,7 @@ TEST_VM(os, release_one_mapping_multi_commits) { // // make things even more difficult by trying to reserve at the border of the region address border = p + num_stripes * stripe_len; - address p2 = (address)os::attempt_reserve_memory_at((char*)border, stripe_len, !ExecMem, mtTest); + address p2 = (address)os::attempt_reserve_memory_at((char*)border, stripe_len); PRINT_MAPPINGS("B"); ASSERT_TRUE(p2 == nullptr || p2 == border); @@ -605,9 +605,9 @@ TEST_VM(os, show_mappings_small_range) { TEST_VM(os, show_mappings_full_range) { // Reserve a small range and fill it with a marker string, should show up // on implementations displaying range snippets - char* p = os::reserve_memory(1 * M, !ExecMem, mtInternal); + char* p = os::reserve_memory(1 * M, false, mtInternal); if (p != nullptr) { - if (os::commit_memory(p, 1 * M, !ExecMem, mtTest)) { + if (os::commit_memory(p, 1 * M, false)) { strcpy(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); } } @@ -629,7 +629,7 @@ TEST_VM(os, find_mapping_simple) { // A simple allocation { - address p = (address)os::reserve_memory(total_range_len, !ExecMem, mtTest); + address p = (address)os::reserve_memory(total_range_len); ASSERT_NE(p, (address)nullptr); PRINT_MAPPINGS("A"); for (size_t offset = 0; offset < total_range_len; offset += 4711) { @@ -934,9 +934,9 @@ TEST_VM(os, open_O_CLOEXEC) { } TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_smallpages) { - char* p1 = os::reserve_memory(M, !ExecMem, mtTest); + char* p1 = os::reserve_memory(M, false, mtTest); ASSERT_NE(p1, nullptr); - char* p2 = os::attempt_reserve_memory_at(p1, M, !ExecMem, mtTest); + char* p2 = os::attempt_reserve_memory_at(p1, M); ASSERT_EQ(p2, nullptr); // should have failed os::release_memory(p1, M); } @@ -944,9 +944,9 @@ TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_smallpages) { TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_largepages) { if (UseLargePages && !os::can_commit_large_page_memory()) { // aka special const size_t lpsz = os::large_page_size(); - char* p1 = os::reserve_memory_aligned(lpsz, lpsz, !ExecMem, mtTest); + char* p1 = os::reserve_memory_aligned(lpsz, lpsz, false); ASSERT_NE(p1, nullptr); - char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, !ExecMem, mtTest); + char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, false); ASSERT_EQ(p2, nullptr); // should have failed os::release_memory(p1, M); } else { @@ -958,9 +958,9 @@ TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_largepages) { // On Aix, we should fail attach attempts not aligned to segment boundaries (256m) TEST_VM(os, aix_reserve_at_non_shmlba_aligned_address) { if (Use64KPages) { - char* p = os::attempt_reserve_memory_at((char*)0x1f00000, M, !ExecMem, mtTest); + char* p = os::attempt_reserve_memory_at((char*)0x1f00000, M); ASSERT_EQ(p, nullptr); // should have failed - p = os::attempt_reserve_memory_at((char*)((64 * G) + M), M, !ExecMem, mtTest); + p = os::attempt_reserve_memory_at((char*)((64 * G) + M), M); ASSERT_EQ(p, nullptr); // should have failed } } diff --git a/test/hotspot/gtest/runtime/test_os_linux.cpp b/test/hotspot/gtest/runtime/test_os_linux.cpp index 582a516465cf4..69c3d991b2a4f 100644 --- a/test/hotspot/gtest/runtime/test_os_linux.cpp +++ b/test/hotspot/gtest/runtime/test_os_linux.cpp @@ -54,7 +54,7 @@ namespace { const size_t _size; public: static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) { - return os::reserve_memory_special(bytes, alignment, page_size, req_addr, exec, mtTest); + return os::reserve_memory_special(bytes, alignment, page_size, req_addr, exec); } HugeTlbfsMemory(char* const ptr, size_t size) : _ptr(ptr), _size(size) { } ~HugeTlbfsMemory() { @@ -224,7 +224,7 @@ class TestReserveMemorySpecial : AllStatic { if (!using_explicit_hugepages()) { return; } - char* addr = os::reserve_memory_special(size, alignment, page_size, nullptr, !ExecMem, mtTest); + char* addr = os::reserve_memory_special(size, alignment, page_size, nullptr, false); if (addr != nullptr) { small_page_write(addr, size); os::release_memory_special(addr, size); @@ -281,7 +281,7 @@ class TestReserveMemorySpecial : AllStatic { for (int i = 0; i < num_sizes; i++) { const size_t size = sizes[i]; for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { - char* p = os::reserve_memory_special(size, alignment, lp, nullptr, !ExecMem, mtTest); + char* p = os::reserve_memory_special(size, alignment, lp, nullptr, false); if (p != nullptr) { EXPECT_TRUE(is_aligned(p, alignment)); small_page_write(p, size); @@ -296,7 +296,7 @@ class TestReserveMemorySpecial : AllStatic { for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { // req_addr must be at least large page aligned. char* const req_addr = align_up(mapping1, MAX2(alignment, lp)); - char* p = os::reserve_memory_special(size, alignment, lp, req_addr, !ExecMem, mtTest); + char* p = os::reserve_memory_special(size, alignment, lp, req_addr, false); if (p != nullptr) { EXPECT_EQ(p, req_addr); small_page_write(p, size); @@ -311,7 +311,7 @@ class TestReserveMemorySpecial : AllStatic { for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) { // req_addr must be at least large page aligned. char* const req_addr = align_up(mapping2, MAX2(alignment, lp)); - char* p = os::reserve_memory_special(size, alignment, lp, req_addr, !ExecMem, mtTest); + char* p = os::reserve_memory_special(size, alignment, lp, req_addr, false); // as the area around req_addr contains already existing mappings, the API should always // return nullptr (as per contract, it cannot return another address) EXPECT_TRUE(p == nullptr); @@ -355,9 +355,9 @@ TEST_VM(os_linux, pretouch_thp_and_use_concurrent) { const size_t size = 1 * G; const bool useThp = UseTransparentHugePages; UseTransparentHugePages = true; - char* const heap = os::reserve_memory(size, !ExecMem, mtInternal); + char* const heap = os::reserve_memory(size, false, mtInternal); EXPECT_NE(heap, nullptr); - EXPECT_TRUE(os::commit_memory(heap, size, !ExecMem, mtInternal)); + EXPECT_TRUE(os::commit_memory(heap, size, false)); { auto pretouch = [heap, size](Thread*, int) { @@ -379,7 +379,7 @@ TEST_VM(os_linux, pretouch_thp_and_use_concurrent) { for (int i = 0; i < 1000; i++) EXPECT_EQ(*iptr++, i); - EXPECT_TRUE(os::uncommit_memory(heap, size, !ExecMem, mtInternal)); + EXPECT_TRUE(os::uncommit_memory(heap, size, false)); EXPECT_TRUE(os::release_memory(heap, size)); UseTransparentHugePages = useThp; } diff --git a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp index 1e052ddf65ede..aad6acc095a1e 100644 --- a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp +++ b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp @@ -66,7 +66,7 @@ static size_t allocation_granularity() { << " bytes: " << bytes << " alignment: " << alignment << " randomized: " << randomized static char* call_attempt_reserve_memory_between(char* min, char* max, size_t bytes, size_t alignment, bool randomized) { - char* const addr = os::attempt_reserve_memory_between(min, max, bytes, alignment, randomized, mtTest); + char* const addr = os::attempt_reserve_memory_between(min, max, bytes, alignment, randomized); if (addr != nullptr) { EXPECT_TRUE(is_aligned(addr, alignment)) << ERRINFO; EXPECT_TRUE(is_aligned(addr, allocation_granularity())) << ERRINFO; @@ -158,7 +158,7 @@ struct SpaceWithHole { // the hole. const uintptr_t candidate = nth_bit(i); if ((candidate + _len) <= ARMB_constants::absolute_max) { - _base = os::attempt_reserve_memory_at((char*)candidate, _len, !ExecMem, mtTest); + _base = os::attempt_reserve_memory_at((char*)candidate, _len); } } if (_base == nullptr) { @@ -166,8 +166,8 @@ struct SpaceWithHole { } // Release total mapping, remap the individual non-holy parts os::release_memory(_base, _len); - _p1 = os::attempt_reserve_memory_at(_base + _p1_offset, _p1_size, !ExecMem, mtTest); - _p2 = os::attempt_reserve_memory_at(_base + _p2_offset, _p2_size, !ExecMem, mtTest); + _p1 = os::attempt_reserve_memory_at(_base + _p1_offset, _p1_size); + _p2 = os::attempt_reserve_memory_at(_base + _p2_offset, _p2_size); if (_p1 == nullptr || _p2 == nullptr) { return false; } diff --git a/test/hotspot/gtest/runtime/test_os_windows.cpp b/test/hotspot/gtest/runtime/test_os_windows.cpp index 87ae501a08be7..8c6f003de6f26 100644 --- a/test/hotspot/gtest/runtime/test_os_windows.cpp +++ b/test/hotspot/gtest/runtime/test_os_windows.cpp @@ -67,7 +67,7 @@ void TestReserveMemorySpecial_test() { FLAG_SET_CMDLINE(UseNUMAInterleaving, false); const size_t large_allocation_size = os::large_page_size() * 4; - char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), os::large_page_size(), nullptr, !ExecMem, mtTest); + char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), os::large_page_size(), nullptr, false); if (result == nullptr) { // failed to allocate memory, skipping the test return; @@ -77,12 +77,12 @@ void TestReserveMemorySpecial_test() { // Reserve another page within the recently allocated memory area. This should fail const size_t expected_allocation_size = os::large_page_size(); char* expected_location = result + os::large_page_size(); - char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, !ExecMem, mtTest); + char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false); EXPECT_TRUE(actual_location == nullptr) << "Should not be allowed to reserve within present reservation"; // Instead try reserving after the first reservation. expected_location = result + large_allocation_size; - actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, !ExecMem, mtTest); + actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false); EXPECT_TRUE(actual_location != nullptr) << "Unexpected reservation failure, can’t verify correct location"; EXPECT_TRUE(actual_location == expected_location) << "Reservation must be at requested location"; MemoryReleaser m2(actual_location, os::large_page_size()); @@ -90,7 +90,7 @@ void TestReserveMemorySpecial_test() { // Now try to do a reservation with a larger alignment. const size_t alignment = os::large_page_size() * 2; const size_t new_large_size = alignment * 4; - char* aligned_request = os::reserve_memory_special(new_large_size, alignment, os::large_page_size(), nullptr, !ExecMem, mtTest); + char* aligned_request = os::reserve_memory_special(new_large_size, alignment, os::large_page_size(), nullptr, false); EXPECT_TRUE(aligned_request != nullptr) << "Unexpected reservation failure, can’t verify correct alignment"; EXPECT_TRUE(is_aligned(aligned_request, alignment)) << "Returned address must be aligned"; MemoryReleaser m3(aligned_request, new_large_size); diff --git a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp index f2b3b843c2313..b098416456d6c 100644 --- a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp +++ b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp @@ -93,7 +93,7 @@ class VirtualMemoryTrackerTest { static void test_add_committed_region_adjacent() { size_t size = 0x01000000; - ReservedSpace rs(size, mtTest); + ReservedSpace rs(size); address addr = (address)rs.base(); address frame1 = (address)0x1234; @@ -167,7 +167,7 @@ class VirtualMemoryTrackerTest { static void test_add_committed_region_adjacent_overlapping() { size_t size = 0x01000000; - ReservedSpace rs(size, mtTest); + ReservedSpace rs(size); address addr = (address)rs.base(); address frame1 = (address)0x1234; @@ -254,7 +254,7 @@ class VirtualMemoryTrackerTest { static void test_add_committed_region_overlapping() { size_t size = 0x01000000; - ReservedSpace rs(size, mtTest); + ReservedSpace rs(size); address addr = (address)rs.base(); address frame1 = (address)0x1234; @@ -425,7 +425,7 @@ class VirtualMemoryTrackerTest { static void test_remove_uncommitted_region() { size_t size = 0x01000000; - ReservedSpace rs(size, mtTest); + ReservedSpace rs(size); address addr = (address)rs.base(); address frame1 = (address)0x1234; From f78fa0556d93d8ec98f403694e067611e4501fd4 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Fri, 3 May 2024 10:17:23 +0000 Subject: [PATCH 072/203] 8331636: [BACKOUT] Build failure after 8330076 Reviewed-by: jwilhelm --- src/hotspot/share/memory/virtualspace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index 06775f9803252..a75d9f076ad22 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -323,7 +323,7 @@ ReservedSpace ReservedSpace::last_part(size_t partition_size, size_t alignment) ReservedSpace ReservedSpace::partition(size_t offset, size_t partition_size, size_t alignment) { assert(offset + partition_size <= size(), "partition failed"); - ReservedSpace result(base() + offset, partition_size, alignment, page_size(), special(), executable(), nmt_flag()); + ReservedSpace result(base() + offset, partition_size, alignment, page_size(), special(), executable()); return result; } From c60474b1229b67265acbd709f6ba081303329be4 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Fri, 3 May 2024 11:08:33 +0000 Subject: [PATCH 073/203] 8323707: Adjust Classfile API's type arg model to better represent the embodied type Reviewed-by: asotona --- .../java/lang/classfile/Signature.java | 95 +++++++++++-------- .../classfile/impl/ClassRemapperImpl.java | 10 +- .../classfile/impl/SignaturesImpl.java | 27 +++--- .../com/sun/tools/javap/ClassWriter.java | 24 +++-- test/jdk/jdk/classfile/SignaturesTest.java | 7 +- .../javap/classfile/6888367/T6888367.java | 25 ++--- 6 files changed, 105 insertions(+), 83 deletions(-) diff --git a/src/java.base/share/classes/java/lang/classfile/Signature.java b/src/java.base/share/classes/java/lang/classfile/Signature.java index ad2528fd7138a..22ca477f4e6a2 100644 --- a/src/java.base/share/classes/java/lang/classfile/Signature.java +++ b/src/java.base/share/classes/java/lang/classfile/Signature.java @@ -185,88 +185,107 @@ public static ClassTypeSig of(ClassTypeSig outerType, String className, TypeArg. /** * Models the type argument. * + * @sealedGraph * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - public sealed interface TypeArg - permits SignaturesImpl.TypeArgImpl { + public sealed interface TypeArg { /** - * Indicator for whether a wildcard has default bound, no bound, - * an upper bound, or a lower bound - * - * @since 22 + * Models an unbounded type argument {@code *}. + * @since 23 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - public enum WildcardIndicator { - - /** - * default bound wildcard (empty) - */ - DEFAULT, - - /** - * unbounded indicator {@code *} - */ - UNBOUNDED, + public sealed interface Unbounded extends TypeArg permits SignaturesImpl.UnboundedTypeArgImpl { + } - /** - * upper-bounded indicator {@code +} - */ - EXTENDS, + /** + * Models a type argument with an explicit bound type. + * @since 23 + */ + @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) + public sealed interface Bounded extends TypeArg permits SignaturesImpl.TypeArgImpl { /** - * lower-bounded indicator {@code -} + * Models a type argument's wildcard indicator. + * @since 23 */ - SUPER; + @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) + public enum WildcardIndicator { + + /** + * No wildcard (empty), an exact type. Also known as + * {@index invariant}. + */ + NONE, + + /** + * Upper-bound indicator {@code +}. Also known as + * {@index covariant}. + */ + EXTENDS, + + /** + * Lower-bound indicator {@code -}. Also known as + * {@index contravariant}. + */ + SUPER; + } + + /** {@return the kind of wildcard} */ + WildcardIndicator wildcardIndicator(); + + /** {@return the signature of the type bound} */ + RefTypeSig boundType(); } - /** {@return the wildcard indicator} */ - WildcardIndicator wildcardIndicator(); - - /** {@return the signature of the type bound, if any} */ - Optional boundType(); - /** * {@return a bounded type arg} * @param boundType the bound + * @since 23 */ - public static TypeArg of(RefTypeSig boundType) { + public static TypeArg.Bounded of(RefTypeSig boundType) { requireNonNull(boundType); - return of(WildcardIndicator.DEFAULT, Optional.of(boundType)); + return bounded(Bounded.WildcardIndicator.NONE, boundType); } /** * {@return an unbounded type arg} + * @since 23 */ - public static TypeArg unbounded() { - return of(WildcardIndicator.UNBOUNDED, Optional.empty()); + public static TypeArg.Unbounded unbounded() { + return SignaturesImpl.UnboundedTypeArgImpl.INSTANCE; } /** * {@return an upper-bounded type arg} * @param boundType the upper bound + * @since 23 */ - public static TypeArg extendsOf(RefTypeSig boundType) { + public static TypeArg.Bounded extendsOf(RefTypeSig boundType) { requireNonNull(boundType); - return of(WildcardIndicator.EXTENDS, Optional.of(boundType)); + return bounded(Bounded.WildcardIndicator.EXTENDS, boundType); } /** * {@return a lower-bounded type arg} * @param boundType the lower bound + * @since 23 */ - public static TypeArg superOf(RefTypeSig boundType) { + public static TypeArg.Bounded superOf(RefTypeSig boundType) { requireNonNull(boundType); - return of(WildcardIndicator.SUPER, Optional.of(boundType)); + return bounded(Bounded.WildcardIndicator.SUPER, boundType); } /** * {@return a bounded type arg} * @param wildcard the wild card * @param boundType optional bound type + * @since 23 */ - public static TypeArg of(WildcardIndicator wildcard, Optional boundType) { + public static TypeArg.Bounded bounded(Bounded.WildcardIndicator wildcard, RefTypeSig boundType) { + requireNonNull(wildcard); + requireNonNull(boundType); return new SignaturesImpl.TypeArgImpl(wildcard, boundType); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java index 6e80e289064ac..de6128a9f7f9e 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassRemapperImpl.java @@ -369,11 +369,11 @@ S mapSignature(S signature) { Signature.ClassTypeSig.of( cts.outerType().map(this::mapSignature).orElse(null), map(cts.classDesc()), - cts.typeArgs().stream() - .map(ta -> Signature.TypeArg.of( - ta.wildcardIndicator(), - ta.boundType().map(this::mapSignature))) - .toArray(Signature.TypeArg[]::new)); + cts.typeArgs().stream().map(ta -> switch (ta) { + case Signature.TypeArg.Unbounded u -> u; + case Signature.TypeArg.Bounded bta -> Signature.TypeArg.bounded( + bta.wildcardIndicator(), mapSignature(bta.boundType())); + }).toArray(Signature.TypeArg[]::new)); default -> signature; }; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java index 3447e40b25807..77f6933a0c214 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java @@ -280,24 +280,29 @@ public String signatureString() { if (!typeArgs.isEmpty()) { var sb = new StringBuilder(); sb.append('<'); - for (var ta : typeArgs) - sb.append(((TypeArgImpl)ta).signatureString()); + for (var ta : typeArgs) { + switch (ta) { + case TypeArg.Bounded b -> { + switch (b.wildcardIndicator()) { + case SUPER -> sb.append('-'); + case EXTENDS -> sb.append('+'); + } + sb.append(b.boundType().signatureString()); + } + case TypeArg.Unbounded _ -> sb.append('*'); + } + } suffix = sb.append(">;").toString(); } return prefix + className + suffix; } } - public static record TypeArgImpl(WildcardIndicator wildcardIndicator, Optional boundType) implements Signature.TypeArg { + public static enum UnboundedTypeArgImpl implements TypeArg.Unbounded { + INSTANCE; + } - public String signatureString() { - return switch (wildcardIndicator) { - case DEFAULT -> boundType.get().signatureString(); - case EXTENDS -> "+" + boundType.get().signatureString(); - case SUPER -> "-" + boundType.get().signatureString(); - case UNBOUNDED -> "*"; - }; - } + public static record TypeArgImpl(WildcardIndicator wildcardIndicator, RefTypeSig boundType) implements Signature.TypeArg.Bounded { } public static record TypeParamImpl(String identifier, Optional classBound, List interfaceBounds) diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java index 028fc480f58aa..c5ac15ee7dab9 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java @@ -366,16 +366,20 @@ private void print(StringBuilder sb, Signature sig) { } private void print(StringBuilder sb, Signature.TypeArg ta) { - switch (ta.wildcardIndicator()) { - case DEFAULT -> print(sb, ta.boundType().get()); - case UNBOUNDED -> sb.append('?'); - case EXTENDS -> { - sb.append("? extends "); - print(sb, ta.boundType().get()); - } - case SUPER -> { - sb.append("? super "); - print(sb, ta.boundType().get()); + switch (ta) { + case Signature.TypeArg.Unbounded _ -> sb.append('?'); + case Signature.TypeArg.Bounded bta -> { + switch (bta.wildcardIndicator()) { + case NONE -> print(sb, bta.boundType()); + case EXTENDS -> { + sb.append("? extends "); + print(sb, bta.boundType()); + } + case SUPER -> { + sb.append("? super "); + print(sb, bta.boundType()); + } + } } } } diff --git a/test/jdk/jdk/classfile/SignaturesTest.java b/test/jdk/jdk/classfile/SignaturesTest.java index cfd3201c95a4a..f4da2405dcd9f 100644 --- a/test/jdk/jdk/classfile/SignaturesTest.java +++ b/test/jdk/jdk/classfile/SignaturesTest.java @@ -183,9 +183,10 @@ static class Observer extends ArrayList.Inner>{} void testClassSignatureClassDesc() throws IOException { var observerCf = ClassFile.of().parse(Path.of(System.getProperty("test.classes"), "SignaturesTest$Observer.class")); var sig = observerCf.findAttribute(Attributes.SIGNATURE).orElseThrow().asClassSignature(); - var innerSig = (ClassTypeSig) sig.superclassSignature() // ArrayList - .typeArgs().getFirst() // Outer.Inner - .boundType().orElseThrow(); // assert it's exact bound + var arrayListSig = sig.superclassSignature(); // ArrayList + var arrayListTypeArg = (TypeArg.Bounded) arrayListSig.typeArgs().getFirst(); // Outer.Inner + assertEquals(TypeArg.Bounded.WildcardIndicator.NONE, arrayListTypeArg.wildcardIndicator()); + var innerSig = (ClassTypeSig) arrayListTypeArg.boundType(); assertEquals("Inner", innerSig.className(), "simple name in signature"); assertEquals(Outer.Inner.class.describeConstable().orElseThrow(), innerSig.classDesc(), "ClassDesc derived from signature"); diff --git a/test/langtools/tools/javap/classfile/6888367/T6888367.java b/test/langtools/tools/javap/classfile/6888367/T6888367.java index 05df08b5948d7..16bc06321cab3 100644 --- a/test/langtools/tools/javap/classfile/6888367/T6888367.java +++ b/test/langtools/tools/javap/classfile/6888367/T6888367.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -312,21 +312,14 @@ public String visitTypeParamType(Signature.TypeParam type) { } public String visitWildcardType(Signature.TypeArg type) { - switch (type.wildcardIndicator()) { - case UNBOUNDED -> { - return "W{?}"; - } - case EXTENDS -> { - return "W{e," + print(type.boundType().get()) + "}"; - } - case SUPER -> { - return "W{s," + print(type.boundType().get()) + "}"; - } - default -> { - if (type.boundType().isPresent()) return print(type.boundType().get()); - else throw new AssertionError(); - } - } + return switch (type) { + case Signature.TypeArg.Unbounded _ -> "W{?}"; + case Signature.TypeArg.Bounded b -> switch (b.wildcardIndicator()) { + case EXTENDS -> "W{e," + print(b.boundType()) + "}"; + case SUPER -> "W{s," + print(b.boundType()) + "}"; + case NONE -> print(b.boundType()); + }; + }; } }; From 1f6d38f7a63c6cb429953c5e9bb0b9f365bfcabe Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Fri, 3 May 2024 11:57:10 +0000 Subject: [PATCH 074/203] 8294978: Convert 5 test/jdk/jdk/jfr tests from ASM library to Classfile API Reviewed-by: asotona --- .../event/compiler/TestCompilerInlining.java | 128 +++++++------- .../jdk/jfr/event/io/TestInstrumentation.java | 157 ++++++++---------- .../javaagent/TestEventInstrumentation.java | 96 ++++------- .../jdk/jfr/jvm/TestLargeJavaEvent512k.java | 3 +- .../jdk/jfr/jvm/TestLargeJavaEvent64k.java | 3 +- 5 files changed, 176 insertions(+), 211 deletions(-) diff --git a/test/jdk/jdk/jfr/event/compiler/TestCompilerInlining.java b/test/jdk/jdk/jfr/event/compiler/TestCompilerInlining.java index cea86e6e99701..79b3fe11cb972 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCompilerInlining.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCompilerInlining.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ package jdk.jfr.event.compiler; -import jdk.internal.org.objectweb.asm.*; import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordedMethod; @@ -35,13 +34,24 @@ import jdk.test.whitebox.WhiteBox; import java.io.IOException; +import java.lang.classfile.ClassModel; +import java.lang.classfile.ClassFile; +import java.lang.classfile.Instruction; +import java.lang.classfile.instruction.InvokeInstruction; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.util.*; import java.util.stream.IntStream; +import java.util.stream.Stream; -/** +import static java.lang.constant.ConstantDescs.CD_Object; +import static java.lang.constant.ConstantDescs.CD_void; +import static java.lang.constant.ConstantDescs.INIT_NAME; + +/* * @test CompilerInliningTest * @bug 8073607 * @key jfr @@ -50,8 +60,8 @@ * * @requires vm.opt.Inline == true | vm.opt.Inline == null * @library /test/lib - * @modules java.base/jdk.internal.org.objectweb.asm - * jdk.jfr + * @modules jdk.jfr + * @enablePreview * * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox @@ -64,7 +74,7 @@ public class TestCompilerInlining { private static final int LEVEL_SIMPLE = 1; private static final int LEVEL_FULL_OPTIMIZATION = 4; private static final Executable ENTRY_POINT = getConstructor(TestCase.class); - private static final String TEST_CASE_CLASS_NAME = TestCase.class.getName().replace('.', '/'); + private static final ClassDesc CD_TestCase = TestCase.class.describeConstable().orElseThrow(); public static void main(String[] args) throws Exception { InlineCalls inlineCalls = new InlineCalls(TestCase.class); @@ -100,8 +110,8 @@ private static void testLevel(Map expectedResult, int level) thro MethodDesc caller = methodToMethodDesc(callerObject); MethodDesc callee = ciMethodToMethodDesc(calleeObject); // only TestCase.* -> TestCase.* OR TestCase.* -> Object. are tested/filtered - if (caller.className.equals(TEST_CASE_CLASS_NAME) && (callee.className.equals(TEST_CASE_CLASS_NAME) - || (callee.className.equals("java/lang/Object") && callee.methodName.equals("")))) { + if (caller.className.equals(CD_TestCase) && (callee.className.equals(CD_TestCase) + || (callee.className.equals(CD_Object) && callee.methodName.equals(INIT_NAME)))) { System.out.println(event); boolean succeeded = (boolean) event.getValue("succeeded"); int bci = Events.assertField(event, "bci").atLeast(0).getValue(); @@ -132,17 +142,17 @@ private static int[] determineAvailableLevels() { } private static MethodDesc methodToMethodDesc(RecordedMethod method) { - String internalClassName = method.getType().getName().replace('.', '/'); + ClassDesc classDesc = ClassDesc.of(method.getType().getName()); String methodName = method.getValue("name"); - String methodDescriptor = method.getValue("descriptor"); - return new MethodDesc(internalClassName, methodName, methodDescriptor); + MethodTypeDesc methodDescriptor = MethodTypeDesc.ofDescriptor(method.getValue("descriptor")); + return new MethodDesc(classDesc, methodName, methodDescriptor); } private static MethodDesc ciMethodToMethodDesc(RecordedObject ciMethod) { - String internalClassName = ciMethod.getValue("type"); + ClassDesc classDesc = ClassDesc.ofInternalName(ciMethod.getValue("type")); String methodName = ciMethod.getValue("name"); - String methodDescriptor = ciMethod.getValue("descriptor"); - return new MethodDesc(internalClassName, methodName, methodDescriptor); + MethodTypeDesc methodDescriptor = MethodTypeDesc.ofDescriptor(ciMethod.getValue("descriptor")); + return new MethodDesc(classDesc, methodName, methodDescriptor); } private static Method getMethod(Class aClass, String name, Class... params) { @@ -246,35 +256,33 @@ public String toString() { * data structure for method description */ class MethodDesc { - public final String className; + public final ClassDesc className; public final String methodName; - public final String descriptor; - - public MethodDesc(Class aClass, String methodName, String descriptor) { - this(aClass.getName().replace('.', '/'), methodName, descriptor); - } + public final MethodTypeDesc descriptor; - public MethodDesc(String className, String methodName, String descriptor) { + public MethodDesc(ClassDesc className, String methodName, MethodTypeDesc descriptor) { Objects.requireNonNull(className); Objects.requireNonNull(methodName); Objects.requireNonNull(descriptor); - this.className = className.replace('.', '/'); + this.className = className; this.methodName = methodName; this.descriptor = descriptor; } public MethodDesc(Executable executable) { - Class aClass = executable.getDeclaringClass(); - className = Type.getInternalName(aClass).replace('.', '/'); + className = executable.getDeclaringClass().describeConstable().orElseThrow(); + ClassDesc retType; - if (executable instanceof Constructor) { - methodName = ""; - descriptor = Type.getConstructorDescriptor((Constructor) executable); - } else { + if (executable instanceof Method method) { methodName = executable.getName(); - descriptor = Type.getMethodDescriptor((Method) executable); + retType = method.getReturnType().describeConstable().orElseThrow(); + } else { + methodName = INIT_NAME; + retType = CD_void; } + descriptor = MethodTypeDesc.of(retType, Stream.of(executable.getParameterTypes()) + .map(c -> c.describeConstable().orElseThrow()).toArray(ClassDesc[]::new)); } @Override @@ -361,43 +369,41 @@ public void forceInline(Executable executable) { private static Collection getCalls(Class aClass) { List calls = new ArrayList<>(); - ClassWriter cw; - ClassReader cr; + ClassModel clm; try { - cr = new ClassReader(aClass.getName()); + var stream = ClassLoader.getSystemResourceAsStream(aClass.getName() + .replace('.', '/') + ".class"); + if (stream == null) { + throw new IOException("Cannot find class file for " + aClass.getName()); + } + clm = ClassFile.of().parse(stream.readAllBytes()); } catch (IOException e) { throw new Error("TESTBUG : unexpected IOE during class reading", e); } - cw = new ClassWriter(cr, 0); - ClassVisitor cv = new ClassVisitor(Opcodes.ASM7, cw) { - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String descriptor, String[] exceptions) { - System.out.println("Method: " +name); - MethodVisitor mv = super.visitMethod(access, name, desc, descriptor, exceptions); - return new CallTracer(aClass, name, desc, mv, calls); - } - }; - cr.accept(cv, 0); + clm.methods().forEach(mm -> { + System.out.println("Method: " + mm.methodName().stringValue()); + mm.code().ifPresent(com -> { + MethodDesc caller = new MethodDesc( + clm.thisClass().asSymbol(), + mm.methodName().stringValue(), + mm.methodTypeSymbol() + ); + int offset = 0; + for (var ce : com.elements()) { + if (ce instanceof Instruction ins) { + if (ins instanceof InvokeInstruction inv) { + calls.add(new Call(caller, new MethodDesc( + inv.owner().asSymbol(), + inv.name().stringValue(), + inv.typeSymbol() + ), offset)); + } + offset += ins.sizeInBytes(); + } + } + }); + }); return calls; } - - private static class CallTracer extends MethodVisitor { - private final MethodDesc caller; - private Collection calls; - - public CallTracer(Class aClass, String name, String desc, MethodVisitor mv, Collection calls) { - super(Opcodes.ASM7, mv); - caller = new MethodDesc(aClass.getName(), name, desc); - this.calls = calls; - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - Label label = new Label(); - visitLabel(label); - super.visitMethodInsn(opcode, owner, name, desc, itf); - calls.add(new Call(caller, new MethodDesc(owner, name, desc), label.getOffset())); - } - } } diff --git a/test/jdk/jdk/jfr/event/io/TestInstrumentation.java b/test/jdk/jdk/jfr/event/io/TestInstrumentation.java index ddbc120649762..5f3885f31bf49 100644 --- a/test/jdk/jdk/jfr/event/io/TestInstrumentation.java +++ b/test/jdk/jdk/jfr/event/io/TestInstrumentation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,14 @@ package jdk.jfr.event.io; +import java.lang.classfile.ClassFile; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.CodeElement; +import java.lang.classfile.CodeTransform; +import java.lang.classfile.MethodModel; +import java.lang.classfile.MethodTransform; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; import java.util.Arrays; import java.util.Set; import java.util.HashSet; @@ -31,16 +39,15 @@ import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; import java.lang.instrument.IllegalClassFormatException; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import static java.lang.constant.ConstantDescs.CD_String; +import static java.lang.constant.ConstantDescs.CD_void; + /* * @test * @summary Test that will instrument the same classes that JFR will also instrument. @@ -48,10 +55,11 @@ * @requires vm.hasJFR * * @library /test/lib /test/jdk - * @modules java.base/jdk.internal.org.objectweb.asm - * java.instrument + * @modules java.instrument * jdk.jartool/sun.tools.jar * jdk.jfr + * @enablePreview + * @comment update --enable-preview in launchTest() too * * @run main/othervm jdk.jfr.event.io.TestInstrumentation */ @@ -90,7 +98,7 @@ public class TestInstrumentation implements ClassFileTransformer { private static TestInstrumentation testTransformer = null; // All methods that will be instrumented. - private static final String[] instrMethodKeys = { + private static final Set instrMethodKeys = Stream.of( "java/io/RandomAccessFile::seek::(J)V", "java/io/RandomAccessFile::read::()I", "java/io/RandomAccessFile::read::([B)I", @@ -116,31 +124,24 @@ public class TestInstrumentation implements ClassFileTransformer { "java/nio/channels/SocketChannel::read::([Ljava/nio/ByteBuffer;)J", "java/nio/channels/SocketChannel::write::([Ljava/nio/ByteBuffer;)J", "sun/nio/ch/FileChannelImpl::read::(Ljava/nio/ByteBuffer;)I", - "sun/nio/ch/FileChannelImpl::write::(Ljava/nio/ByteBuffer;)I", - }; - - private static String getInstrMethodKey(String className, String methodName, String signature) { - // This key is used to identify a class and method. It is sent to callback(key) - return className + "::" + methodName + "::" + signature; - } - - private static String getClassFromMethodKey(String methodKey) { - return methodKey.split("::")[0]; - } + "sun/nio/ch/FileChannelImpl::write::(Ljava/nio/ByteBuffer;)I" + ).map(s -> { + String[] a = s.split("::"); + return new MethodKey(a[0], a[1], a[2]); + }).collect(Collectors.toUnmodifiableSet()); // Set of all classes targeted for instrumentation. - private static Set instrClassesTarget = null; + private static Set instrClassesTarget = null; // Set of all classes where instrumentation has been completed. - private static Set instrClassesDone = null; + private static Set instrClassesDone = null; static { // Split class names from InstrMethodKeys. - instrClassesTarget = new HashSet(); - instrClassesDone = new HashSet(); - for (String s : instrMethodKeys) { - String className = getClassFromMethodKey(s); - instrClassesTarget.add(className); + instrClassesTarget = new HashSet<>(); + instrClassesDone = new HashSet<>(); + for (MethodKey key : instrMethodKeys) { + instrClassesTarget.add(key.owner()); } } @@ -164,9 +165,10 @@ public static void main(String[] args) throws Throwable { runAllTests(TransformStatus.Transformed); // Retransform all classes and then repeat tests - Set> classes = new HashSet>(); - for (String className : instrClassesTarget) { - Class clazz = Class.forName(className.replaceAll("/", ".")); + Set> classes = new HashSet<>(); + for (ClassDesc className : instrClassesTarget) { + var desc = className.descriptorString(); + Class clazz = Class.forName(desc.substring(1, desc.length() - 1).replace('/', '.')); classes.add(clazz); log("Will retransform " + clazz.getName()); } @@ -197,10 +199,10 @@ public static void runAllTests(TransformStatus status) throws Throwable { // Verify that all expected callbacks have been called. Set callbackKeys = InstrumentationCallback.getKeysCopy(); - for (String key : instrMethodKeys) { - boolean gotCallback = callbackKeys.contains(key); + for (MethodKey key : instrMethodKeys) { + boolean gotCallback = callbackKeys.contains(key.toString()); boolean expectsCallback = isClassInstrumented(status, key); - String msg = String.format("key:%s, expects:%b", key, expectsCallback); + String msg = String.format("status:%s, key:%s, expects:%b", status, key, expectsCallback); if (gotCallback != expectsCallback) { throw new Exception("Wrong callback() for " + msg); } else { @@ -214,14 +216,14 @@ public static void runAllTests(TransformStatus status) throws Throwable { } } - private static boolean isClassInstrumented(TransformStatus status, String key) throws Throwable { + private static boolean isClassInstrumented(TransformStatus status, MethodKey key) throws Throwable { switch (status) { case Retransformed: return true; case Removed: return false; case Transformed: - String className = getClassFromMethodKey(key); + var className = key.owner(); return instrClassesDone.contains(className); } throw new Exception("Test error: Unknown TransformStatus: " + status); @@ -279,7 +281,7 @@ private static void launchTest() throws Throwable { String[] args = { "-Xbootclasspath/a:" + testClassDir + "InstrumentationCallback.jar", - "--add-exports", "java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED", + "--enable-preview", "-classpath", classpath, "-javaagent:" + testClassDir + "TestInstrumentation.jar", "jdk.jfr.event.io.TestInstrumentation$TestMain" }; @@ -305,67 +307,52 @@ public byte[] transform( ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain pd, byte[] bytes) throws IllegalClassFormatException { // Check if this class should be instrumented. - if (!instrClassesTarget.contains(className)) { + ClassDesc target = ClassDesc.ofInternalName(className); + if (!instrClassesTarget.contains(target)) { return null; } boolean isRedefinition = classBeingRedefined != null; log("instrument class(" + className + ") " + (isRedefinition ? "redef" : "load")); - ClassReader reader = new ClassReader(bytes); - ClassWriter writer = new ClassWriter( - reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); - CallbackClassVisitor classVisitor = new CallbackClassVisitor(writer); - reader.accept(classVisitor, 0); - instrClassesDone.add(className); - return writer.toByteArray(); - } - - private static class CallbackClassVisitor extends ClassVisitor { - private String className; - - public CallbackClassVisitor(ClassVisitor cv) { - super(Opcodes.ASM7, cv); - } - - @Override - public void visit( - int version, int access, String name, String signature, - String superName, String[] interfaces) { - cv.visit(version, access, name, signature, superName, interfaces); - className = name; - } + instrClassesDone.add(target); + var cf = ClassFile.of(); + return cf.transform(cf.parse(bytes), (clb, ce) -> { + MethodKey key; + if (ce instanceof MethodModel mm && instrMethodKeys.contains(key = new MethodKey( + target, mm.methodName().stringValue(), mm.methodTypeSymbol()))) { + clb.transformMethod(mm, MethodTransform.transformingCode(new CodeTransform() { + private static final MethodTypeDesc MTD_callback = MethodTypeDesc.of(CD_void, CD_String); + private static final ClassDesc CD_InstrumentationCallback = InstrumentationCallback.class + .describeConstable().orElseThrow(); + + @Override + public void atStart(CodeBuilder cb) { + cb.loadConstant(key.toString()); + cb.invokestatic(CD_InstrumentationCallback, "callback", MTD_callback); + log("instrumented " + key); + } - @Override - public MethodVisitor visitMethod( - int access, String methodName, String desc, String signature, String[] exceptions) { - String methodKey = getInstrMethodKey(className, methodName, desc); - boolean isInstrumentedMethod = Arrays.asList(instrMethodKeys).contains(methodKey); - MethodVisitor mv = cv.visitMethod(access, methodName, desc, signature, exceptions); - if (isInstrumentedMethod && mv != null) { - mv = new CallbackMethodVisitor(mv, methodKey); - log("instrumented " + methodKey); + @Override + public void accept(CodeBuilder cb, CodeElement ce) { + cb.with(ce); + } + })); + } else { + clb.with(ce); } - return mv; - } + }); } - public static class CallbackMethodVisitor extends MethodVisitor { - private String logMessage; - - public CallbackMethodVisitor(MethodVisitor mv, String logMessage) { - super(Opcodes.ASM7, mv); - this.logMessage = logMessage; + public record MethodKey(ClassDesc owner, String name, MethodTypeDesc desc) { + public MethodKey(String className, String methodName, String signature) { + this(ClassDesc.ofInternalName(className), methodName, MethodTypeDesc.ofDescriptor(signature)); } @Override - public void visitCode() { - mv.visitCode(); - String methodDescr = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)); - String className = InstrumentationCallback.class.getName().replace('.', '/'); - mv.visitLdcInsn(logMessage); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, "callback", methodDescr); + public String toString() { + var ownerDesc = owner.descriptorString(); + return ownerDesc.substring(1, ownerDesc.length() - 1) + "::" + name + "::" + desc.descriptorString(); } } - } diff --git a/test/jdk/jdk/jfr/javaagent/TestEventInstrumentation.java b/test/jdk/jdk/jfr/javaagent/TestEventInstrumentation.java index 6dae08044c3b8..8a8415dc524c0 100644 --- a/test/jdk/jdk/jfr/javaagent/TestEventInstrumentation.java +++ b/test/jdk/jdk/jfr/javaagent/TestEventInstrumentation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,13 @@ */ package jdk.jfr.javaagent; +import java.lang.classfile.ClassFile; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.CodeElement; +import java.lang.classfile.CodeTransform; +import java.lang.classfile.MethodModel; +import java.lang.classfile.MethodTransform; +import java.lang.constant.ClassDesc; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; @@ -29,18 +36,14 @@ import java.nio.file.Paths; import java.security.ProtectionDomain; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; - import jdk.jfr.Event; import jdk.jfr.Recording; import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.Asserts; +import static java.lang.constant.ConstantDescs.INIT_NAME; +import static java.lang.constant.ConstantDescs.MTD_void; + /* * @test * @summary Verify that a subclass of the JFR Event class @@ -48,8 +51,8 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib - * @modules java.base/jdk.internal.org.objectweb.asm - * jdk.jartool/sun.tools.jar + * @modules jdk.jartool/sun.tools.jar + * @enablePreview * @build jdk.jfr.javaagent.InstrumentationEventCallback * jdk.jfr.javaagent.TestEventInstrumentation * @run driver jdk.test.lib.util.JavaAgentBuilder @@ -99,6 +102,9 @@ public static void premain(String args, Instrumentation inst) throws Exception { } static class Transformer implements ClassFileTransformer { + private static final ClassDesc CD_InstrumentationEventCallback = InstrumentationEventCallback.class + .describeConstable().orElseThrow(); + public byte[] transform(ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain pd, byte[] bytes) throws IllegalClassFormatException { @@ -109,13 +115,25 @@ public byte[] transform(ClassLoader classLoader, String className, return null; } - ClassReader reader = new ClassReader(bytes); - ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); - CallbackClassVisitor classVisitor = new CallbackClassVisitor(writer); - - // visit the reader's class by the classVisitor - reader.accept(classVisitor, 0); - result = writer.toByteArray(); + var cf = ClassFile.of(); + result = cf.transform(cf.parse(bytes), (clb, ce) -> { + if (ce instanceof MethodModel mm && mm.methodName().equalsString(INIT_NAME)) { + clb.transformMethod(mm, MethodTransform.transformingCode(new CodeTransform() { + @Override + public void atStart(CodeBuilder cb) { + cb.invokestatic(CD_InstrumentationEventCallback, "callback", MTD_void); + log("instrumented in class " + className); + } + + @Override + public void accept(CodeBuilder cb, CodeElement ce) { + cb.accept(ce); + } + })); + } else { + clb.with(ce); + } + }); } catch (Exception e) { log("Exception occured in transform(): " + e.getMessage()); e.printStackTrace(System.out); @@ -123,49 +141,5 @@ public byte[] transform(ClassLoader classLoader, String className, } return result; } - - private static class CallbackClassVisitor extends ClassVisitor { - private String className; - - public CallbackClassVisitor(ClassVisitor cv) { - super(Opcodes.ASM7, cv); - } - - @Override - public void visit(int version, int access, String name, String signature, - String superName, String[] interfaces) { - // visit the header of the class - called per class header visit - cv.visit(version, access, name, signature, superName, interfaces); - className = name; - } - - @Override - public MethodVisitor visitMethod( - int access, String methodName, String desc, - String signature, String[] exceptions) { - // called for each method in a class - boolean isInstrumentedMethod = methodName.contains(""); - MethodVisitor mv = cv.visitMethod(access, methodName, desc, signature, exceptions); - if (isInstrumentedMethod) { - mv = new CallbackMethodVisitor(mv); - log("instrumented in class " + className); - } - return mv; - } - } - - public static class CallbackMethodVisitor extends MethodVisitor { - public CallbackMethodVisitor(MethodVisitor mv) { - super(Opcodes.ASM7, mv); - } - - @Override - public void visitCode() { - mv.visitCode(); - String methodDescr = Type.getMethodDescriptor(Type.VOID_TYPE, Type.VOID_TYPE); - String className = InstrumentationEventCallback.class.getName().replace('.', '/'); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, "callback", "()V", false); - } - } } } diff --git a/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent512k.java b/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent512k.java index 93ef8f937d4db..eacffb7a13b29 100644 --- a/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent512k.java +++ b/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent512k.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,6 @@ * @requires vm.hasJFR * @library /test/lib * @modules jdk.jfr/jdk.jfr.internal - * java.base/jdk.internal.org.objectweb.asm * @run main/othervm jdk.jfr.jvm.TestLargeJavaEvent512k */ public class TestLargeJavaEvent512k { diff --git a/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent64k.java b/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent64k.java index d3b535117e54a..0de03efb35c59 100644 --- a/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent64k.java +++ b/test/jdk/jdk/jfr/jvm/TestLargeJavaEvent64k.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,6 @@ * @requires vm.hasJFR * @library /test/lib * @modules jdk.jfr/jdk.jfr.internal - * java.base/jdk.internal.org.objectweb.asm * @run main/othervm jdk.jfr.jvm.TestLargeJavaEvent64k */ public class TestLargeJavaEvent64k { From 8ed319023e921a980ea197fbffe417f35fc59b94 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 3 May 2024 12:03:28 +0000 Subject: [PATCH 075/203] 8331401: G1: Make G1HRPrinter AllStatic Reviewed-by: iwalulya, ayang, gli --- src/hotspot/share/gc/g1/g1Allocator.cpp | 3 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 25 ++++++------- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 5 --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 3 +- src/hotspot/share/gc/g1/g1HRPrinter.hpp | 35 ++++++++++--------- .../share/gc/g1/g1HeapRegionManager.cpp | 12 +++---- .../share/gc/g1/g1ParScanThreadState.cpp | 3 +- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 14 ++------ src/hotspot/share/gc/g1/g1YoungCollector.hpp | 2 -- .../gc/g1/g1YoungGCPostEvacuateTasks.cpp | 5 +-- 10 files changed, 46 insertions(+), 61 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index 3964ad8c8af3b..758d16a89f5f1 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -31,6 +31,7 @@ #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionSet.inline.hpp" #include "gc/g1/g1HeapRegionType.hpp" +#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1NUMA.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/shared/tlab_globals.hpp" @@ -118,7 +119,7 @@ void G1Allocator::reuse_retained_old_region(G1EvacInfo* evacuation_info, // it's retired again. _g1h->old_set_remove(retained_region); old->set(retained_region); - _g1h->hr_printer()->reuse(retained_region); + G1HRPrinter::reuse(retained_region); evacuation_info->set_alloc_regions_used_before(retained_region->used()); } } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 1384c30d2be2f..45f570dcd2bae 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -52,6 +52,7 @@ #include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" +#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1InitLogger.hpp" #include "gc/g1/g1MemoryPool.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" @@ -325,7 +326,7 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(HeapRegion* first_hr, for (uint i = first; i <= last; ++i) { HeapRegion *hr = region_at(i); _humongous_set.add(hr); - _hr_printer.alloc(hr); + G1HRPrinter::alloc(hr); } return new_obj; @@ -524,7 +525,7 @@ HeapWord* G1CollectedHeap::alloc_archive_region(size_t word_size, HeapWord* pref r->set_top(top); r->set_old(); - _hr_printer.alloc(r); + G1HRPrinter::alloc(r); _old_set.add(r); }; @@ -710,17 +711,12 @@ HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size, } class PostCompactionPrinterClosure: public HeapRegionClosure { -private: - G1HRPrinter* _hr_printer; public: bool do_heap_region(HeapRegion* hr) { assert(!hr->is_young(), "not expecting to find young regions"); - _hr_printer->post_compaction(hr); + G1HRPrinter::post_compaction(hr); return false; } - - PostCompactionPrinterClosure(G1HRPrinter* hr_printer) - : _hr_printer(hr_printer) { } }; void G1CollectedHeap::print_heap_after_full_collection() { @@ -728,8 +724,8 @@ void G1CollectedHeap::print_heap_after_full_collection() { // We should do this after we potentially resize the heap so // that all the COMMIT / UNCOMMIT events are generated before // the compaction events. - if (_hr_printer.is_active()) { - PostCompactionPrinterClosure cl(hr_printer()); + if (G1HRPrinter::is_active()) { + PostCompactionPrinterClosure cl; heap_region_iterate(&cl); } } @@ -1152,7 +1148,6 @@ G1CollectedHeap::G1CollectedHeap() : _monitoring_support(nullptr), _num_humongous_objects(0), _num_humongous_reclaim_candidates(0), - _hr_printer(), _collector_state(), _old_marking_cycles_started(0), _old_marking_cycles_completed(0), @@ -2862,7 +2857,7 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, node_index); if (new_alloc_region != nullptr) { set_region_short_lived_locked(new_alloc_region); - _hr_printer.alloc(new_alloc_region, !should_allocate); + G1HRPrinter::alloc(new_alloc_region, !should_allocate); _policy->remset_tracker()->update_at_allocate(new_alloc_region); return new_alloc_region; } @@ -2878,7 +2873,7 @@ void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region, collection_set()->add_eden_region(alloc_region); increase_used(allocated_bytes); _eden.add_used_bytes(allocated_bytes); - _hr_printer.retire(alloc_region); + G1HRPrinter::retire(alloc_region); // We update the eden sizes here, when the region is retired, // instead of when it's allocated, since this is the point that its @@ -2925,7 +2920,7 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, G1HeapRegionA } _policy->remset_tracker()->update_at_allocate(new_alloc_region); register_region_with_region_attr(new_alloc_region); - _hr_printer.alloc(new_alloc_region); + G1HRPrinter::alloc(new_alloc_region); return new_alloc_region; } return nullptr; @@ -2946,7 +2941,7 @@ void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region, if (during_im && allocated_bytes > 0) { _cm->add_root_region(alloc_region); } - _hr_printer.retire(alloc_region); + G1HRPrinter::retire(alloc_region); } HeapRegion* G1CollectedHeap::alloc_highest_free_region() { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 3ee77786621c3..6f31122014ff2 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -40,7 +40,6 @@ #include "gc/g1/g1HeapRegionSet.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" -#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" #include "gc/g1/g1MonotonicArenaFreePool.hpp" @@ -265,8 +264,6 @@ class G1CollectedHeap : public CollectedHeap { void update_parallel_gc_threads_cpu_time(); private: - G1HRPrinter _hr_printer; - // Return true if an explicit GC should start a concurrent cycle instead // of doing a STW full GC. A concurrent cycle should be started if: // (a) cause == _g1_humongous_allocation, @@ -669,8 +666,6 @@ class G1CollectedHeap : public CollectedHeap { return _old_marking_cycles_completed; } - G1HRPrinter* hr_printer() { return &_hr_printer; } - // Allocates a new heap region instance. HeapRegion* new_heap_region(uint hrs_index, MemRegion mr); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index fdb380ae99f28..68b5050ff600a 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -40,6 +40,7 @@ #include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "gc/g1/g1HeapRegionSet.inline.hpp" #include "gc/g1/g1HeapVerifier.hpp" +#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RegionMarkStatsCache.inline.hpp" @@ -1317,7 +1318,7 @@ class G1UpdateRegionLivenessAndSelectForRebuildTask : public WorkerTask { if (!_cleanup_list.is_empty()) { log_debug(gc)("Reclaimed %u empty regions", _cleanup_list.length()); // Now print the empty regions list. - _g1h->hr_printer()->mark_reclaim(&_cleanup_list); + G1HRPrinter::mark_reclaim(&_cleanup_list); // And actually make them available. _g1h->prepend_to_freelist(&_cleanup_list); } diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.hpp b/src/hotspot/share/gc/g1/g1HRPrinter.hpp index 5c1736b13ab56..05d087932df65 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.hpp +++ b/src/hotspot/share/gc/g1/g1HRPrinter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,11 @@ #include "gc/g1/g1HeapRegion.hpp" #include "logging/log.hpp" +#include "memory/allStatic.hpp" class FreeRegionList; -class G1HRPrinter { +class G1HRPrinter : public AllStatic { private: @@ -40,7 +41,7 @@ class G1HRPrinter { action, hr->get_type_str(), p2i(hr->bottom()), p2i(hr->top()), p2i(hr->end())); } - void mark_reclaim(HeapRegion* hr) { + static void mark_reclaim(HeapRegion* hr) { print("MARK-RECLAIM", hr); } @@ -48,79 +49,79 @@ class G1HRPrinter { // In some places we iterate over a list in order to generate output // for the list's elements. By exposing this we can avoid this // iteration if the printer is not active. - bool is_active() { return log_is_enabled(Trace, gc, region); } + static bool is_active() { return log_is_enabled(Trace, gc, region); } // The methods below are convenient wrappers for the print() method. - void alloc(HeapRegion* hr, bool force = false) { + static void alloc(HeapRegion* hr, bool force = false) { if (is_active()) { print((force) ? "ALLOC-FORCE" : "ALLOC", hr); } } - void retire(HeapRegion* hr) { + static void retire(HeapRegion* hr) { if (is_active()) { print("RETIRE", hr); } } - void reuse(HeapRegion* hr) { + static void reuse(HeapRegion* hr) { if (is_active()) { print("REUSE", hr); } } - void cset(HeapRegion* hr) { + static void cset(HeapRegion* hr) { if (is_active()) { print("CSET", hr); } } - void evac_failure(HeapRegion* hr) { + static void evac_failure(HeapRegion* hr) { if (is_active()) { print("EVAC-FAILURE", hr); } } - void mark_reclaim(FreeRegionList* free_list); + static void mark_reclaim(FreeRegionList* free_list); - void eager_reclaim(HeapRegion* hr) { + static void eager_reclaim(HeapRegion* hr) { if (is_active()) { print("EAGER-RECLAIM", hr); } } - void evac_reclaim(HeapRegion* hr) { + static void evac_reclaim(HeapRegion* hr) { if (is_active()) { print("EVAC-RECLAIM", hr); } } - void post_compaction(HeapRegion* hr) { + static void post_compaction(HeapRegion* hr) { if (is_active()) { print("POST-COMPACTION", hr); } } - void commit(HeapRegion* hr) { + static void commit(HeapRegion* hr) { if (is_active()) { print("COMMIT", hr); } } - void active(HeapRegion* hr) { + static void active(HeapRegion* hr) { if (is_active()) { print("ACTIVE", hr); } } - void inactive(HeapRegion* hr) { + static void inactive(HeapRegion* hr) { if (is_active()) { print("INACTIVE", hr); } } - void uncommit(HeapRegion* hr) { + static void uncommit(HeapRegion* hr) { if (is_active()) { print("UNCOMMIT", hr); } diff --git a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp index 0fb8e7499d68f..0d0f8b6b2883e 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp @@ -30,6 +30,7 @@ #include "gc/g1/g1HeapRegion.hpp" #include "gc/g1/g1HeapRegionManager.inline.hpp" #include "gc/g1/g1HeapRegionSet.inline.hpp" +#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1NUMAStats.hpp" #include "jfr/jfrEvents.hpp" #include "logging/logStream.hpp" @@ -170,7 +171,7 @@ void HeapRegionManager::expand(uint start, uint num_regions, WorkerThreads* pret _regions.set_by_index(i, hr); _allocated_heapregions_length = MAX2(_allocated_heapregions_length, i + 1); } - G1CollectedHeap::heap()->hr_printer()->commit(hr); + G1HRPrinter::commit(hr); } activate_regions(start, num_regions); } @@ -193,13 +194,12 @@ void HeapRegionManager::uncommit_regions(uint start, uint num_regions) { guarantee(num_regions > 0, "No point in calling this for zero regions"); uint end = start + num_regions; - G1HRPrinter* printer = G1CollectedHeap::heap()->hr_printer(); - if (printer->is_active()) { + if (G1HRPrinter::is_active()) { for (uint i = start; i < end; i++) { // Can't use at() here since region is no longer marked available. HeapRegion* hr = _regions.get_by_index(i); assert(hr != nullptr, "Region should still be present"); - printer->uncommit(hr); + G1HRPrinter::uncommit(hr); } } @@ -223,7 +223,7 @@ void HeapRegionManager::initialize_regions(uint start, uint num_regions) { hr->initialize(); hr->set_node_index(G1NUMA::numa()->index_for_region(hr)); insert_into_free_list(hr); - G1CollectedHeap::heap()->hr_printer()->active(hr); + G1HRPrinter::active(hr); } } @@ -250,7 +250,7 @@ void HeapRegionManager::deactivate_regions(uint start, uint num_regions) { for (uint i = start; i < end; i++) { HeapRegion* hr = at(i); hr->set_node_index(G1NUMA::UnknownNodeIndex); - G1CollectedHeap::heap()->hr_printer()->inactive(hr); + G1HRPrinter::inactive(hr); } _committed_map.deactivate(start, end); diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index c495889faade6..da9a7d9a575e5 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -27,6 +27,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1EvacFailureRegions.inline.hpp" +#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1RootClosures.hpp" @@ -642,7 +643,7 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m, siz HeapRegion* r = _g1h->heap_region_containing(old); if (_evac_failure_regions->record(_worker_id, r->hrm_index(), cause_pinned)) { - _g1h->hr_printer()->evac_failure(r); + G1HRPrinter::evac_failure(r); } // Mark the failing object in the marking bitmap and later use the bitmap to handle diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index 906d9854d8d59..f08d6543efd4e 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -216,10 +216,6 @@ G1GCPhaseTimes* G1YoungCollector::phase_times() const { return _g1h->phase_times(); } -G1HRPrinter* G1YoungCollector::hr_printer() const { - return _g1h->hr_printer(); -} - G1MonitoringSupport* G1YoungCollector::monitoring_support() const { return _g1h->monitoring_support(); } @@ -264,13 +260,9 @@ void G1YoungCollector::wait_for_root_region_scanning() { } class G1PrintCollectionSetClosure : public HeapRegionClosure { -private: - G1HRPrinter* _hr_printer; public: - G1PrintCollectionSetClosure(G1HRPrinter* hr_printer) : HeapRegionClosure(), _hr_printer(hr_printer) { } - virtual bool do_heap_region(HeapRegion* r) { - _hr_printer->cset(r); + G1HRPrinter::cset(r); return false; } }; @@ -286,8 +278,8 @@ void G1YoungCollector::calculate_collection_set(G1EvacInfo* evacuation_info, dou concurrent_mark()->verify_no_collection_set_oops(); - if (hr_printer()->is_active()) { - G1PrintCollectionSetClosure cl(hr_printer()); + if (G1HRPrinter::is_active()) { + G1PrintCollectionSetClosure cl; collection_set()->iterate(&cl); collection_set()->iterate_optional(&cl); } diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.hpp b/src/hotspot/share/gc/g1/g1YoungCollector.hpp index e7f3c51b65ca0..260880e2d8cb0 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.hpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.hpp @@ -40,7 +40,6 @@ class G1ConcurrentMark; class G1EvacFailureRegions; class G1EvacInfo; class G1GCPhaseTimes; -class G1HRPrinter; class G1MonitoringSupport; class G1MonotonicArenaMemoryStats; class G1NewTracer; @@ -69,7 +68,6 @@ class G1YoungCollector { STWGCTimer* gc_timer_stw() const; G1NewTracer* gc_tracer_stw() const; - G1HRPrinter* hr_printer() const; G1MonitoringSupport* monitoring_support() const; G1GCPhaseTimes* phase_times() const; G1Policy* policy() const; diff --git a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp index 98f4c43d27553..16c617323c89d 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp @@ -36,6 +36,7 @@ #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" +#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.hpp" #include "gc/g1/g1RemSet.hpp" @@ -412,7 +413,7 @@ class G1FreeHumongousRegionClosure : public HeapRegionIndexClosure { r->set_containing_set(nullptr); _humongous_regions_reclaimed++; _g1h->free_humongous_region(r, nullptr); - _g1h->hr_printer()->eager_reclaim(r); + G1HRPrinter::eager_reclaim(r); }; _g1h->humongous_obj_regions_iterate(r, free_humongous_region); @@ -760,7 +761,7 @@ class FreeCSetClosure : public HeapRegionClosure { // Free the region and its remembered set. _g1h->free_region(r, nullptr); - _g1h->hr_printer()->evac_reclaim(r); + G1HRPrinter::evac_reclaim(r); } void handle_failed_region(HeapRegion* r) { From 3c77dad007df2329eb653264cb8e0273f09fabfe Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 3 May 2024 12:06:11 +0000 Subject: [PATCH 076/203] 8331507: JFR: Improve example usage in -XX:StartFlightRecording:help Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/internal/dcmd/DCmdStart.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 0dbd70801d2ba..d115b9f5b62dc 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -321,6 +321,7 @@ private boolean hasJDKEvents(Map settings) { public String[] getStartupHelp() { Map parameters = Map.of( "$SYNTAX", "-XX:StartFlightRecording:[options]", + "$SOURCE_NO_ARGUMENTS", "-XX:StartFlightRecording", "$SOURCE", "-XX:StartFlightRecording:", "$DELIMITER", ",", "$DELIMITER_NAME", "comma", @@ -334,6 +335,7 @@ public String[] getStartupHelp() { public String[] getHelp() { Map parameters = Map.of( "$SYNTAX", "JFR.start [options]", + "$SOURCE_NO_ARGUMENTS", "$ jcmd JFR.start", "$SOURCE", "$ jcmd JFR.start ", "$DELIMITER", " ", "$DELIMITER_NAME", "whitespace", @@ -440,7 +442,7 @@ Virtual Machine (JVM) shuts down. If set to 'true' and no value Example usage: - $SOURCE + $SOURCE_NO_ARGUMENTS $SOURCEfilename=dump.jfr $SOURCEfilename=$DIRECTORY $SOURCEdumponexit=true From 58ef9e4805c0cc78935eb5a1c82ae10411d52e85 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 3 May 2024 12:33:41 +0000 Subject: [PATCH 077/203] 8331402: G1: Remove is_active() calls in G1HRPrinter logging Reviewed-by: iwalulya, ayang, gli --- src/hotspot/share/gc/g1/g1HRPrinter.hpp | 74 ++++--------------------- 1 file changed, 12 insertions(+), 62 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.hpp b/src/hotspot/share/gc/g1/g1HRPrinter.hpp index 05d087932df65..035e92fefacbe 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.hpp +++ b/src/hotspot/share/gc/g1/g1HRPrinter.hpp @@ -33,8 +33,6 @@ class FreeRegionList; class G1HRPrinter : public AllStatic { -private: - // Print an action event. static void print(const char* action, HeapRegion* hr) { log_trace(gc, region)("G1HR %s(%s) [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]", @@ -53,79 +51,31 @@ class G1HRPrinter : public AllStatic { // The methods below are convenient wrappers for the print() method. - static void alloc(HeapRegion* hr, bool force = false) { - if (is_active()) { - print((force) ? "ALLOC-FORCE" : "ALLOC", hr); - } - } + static void alloc(HeapRegion* hr, bool force = false) { print(force ? "ALLOC-FORCE" : "ALLOC", hr); } - static void retire(HeapRegion* hr) { - if (is_active()) { - print("RETIRE", hr); - } - } + static void retire(HeapRegion* hr) { print("RETIRE", hr); } - static void reuse(HeapRegion* hr) { - if (is_active()) { - print("REUSE", hr); - } - } + static void reuse(HeapRegion* hr) { print("REUSE", hr); } - static void cset(HeapRegion* hr) { - if (is_active()) { - print("CSET", hr); - } - } + static void cset(HeapRegion* hr) { print("CSET", hr); } - static void evac_failure(HeapRegion* hr) { - if (is_active()) { - print("EVAC-FAILURE", hr); - } - } + static void evac_failure(HeapRegion* hr) { print("EVAC-FAILURE", hr); } static void mark_reclaim(FreeRegionList* free_list); - static void eager_reclaim(HeapRegion* hr) { - if (is_active()) { - print("EAGER-RECLAIM", hr); - } - } + static void eager_reclaim(HeapRegion* hr) { print("EAGER-RECLAIM", hr); } - static void evac_reclaim(HeapRegion* hr) { - if (is_active()) { - print("EVAC-RECLAIM", hr); - } - } + static void evac_reclaim(HeapRegion* hr) { print("EVAC-RECLAIM", hr); } - static void post_compaction(HeapRegion* hr) { - if (is_active()) { - print("POST-COMPACTION", hr); - } - } + static void post_compaction(HeapRegion* hr) { print("POST-COMPACTION", hr); } - static void commit(HeapRegion* hr) { - if (is_active()) { - print("COMMIT", hr); - } - } + static void commit(HeapRegion* hr) { print("COMMIT", hr); } - static void active(HeapRegion* hr) { - if (is_active()) { - print("ACTIVE", hr); - } - } + static void active(HeapRegion* hr) { print("ACTIVE", hr); } - static void inactive(HeapRegion* hr) { - if (is_active()) { - print("INACTIVE", hr); - } - } + static void inactive(HeapRegion* hr) { print("INACTIVE", hr); } - static void uncommit(HeapRegion* hr) { - if (is_active()) { - print("UNCOMMIT", hr); - } - } + static void uncommit(HeapRegion* hr) { print("UNCOMMIT", hr); } }; #endif // SHARE_GC_G1_G1HRPRINTER_HPP From ce73fec882357d749619576a3219516b7391fb3f Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Fri, 3 May 2024 12:35:58 +0000 Subject: [PATCH 078/203] 8331048: G1: Prune rebuild candidates based on G1HeapWastePercent early Reviewed-by: ayang, tschatzl --- .../share/gc/g1/g1CollectionSetCandidates.cpp | 40 +++++++++++++++---- .../share/gc/g1/g1CollectionSetCandidates.hpp | 6 ++- .../share/gc/g1/g1CollectionSetChooser.cpp | 11 +++-- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 7 ++++ src/hotspot/share/gc/g1/g1Policy.cpp | 2 +- src/hotspot/share/gc/g1/g1Policy.hpp | 3 +- 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp index b4649414b10e6..36a194bdfb0ec 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "gc/g1/g1CollectionSetCandidates.hpp" +#include "gc/g1/g1CollectionSetCandidates.inline.hpp" #include "gc/g1/g1CollectionSetChooser.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "utilities/bitMap.inline.hpp" @@ -44,7 +44,7 @@ void G1CollectionCandidateList::append_unsorted(HeapRegion* r) { } void G1CollectionCandidateList::sort_by_efficiency() { - _candidates.sort(compare); + _candidates.sort(compare_gc_efficiency); } void G1CollectionCandidateList::remove(G1CollectionCandidateRegionList* other) { @@ -94,7 +94,22 @@ void G1CollectionCandidateList::verify() { } #endif -int G1CollectionCandidateList::compare(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2) { +int G1CollectionCandidateList::compare_gc_efficiency(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2) { + assert(ci1->_r != nullptr && ci2->_r != nullptr, "Should not be!"); + + double gc_eff1 = ci1->_gc_efficiency; + double gc_eff2 = ci2->_gc_efficiency; + + if (gc_eff1 > gc_eff2) { + return -1; + } else if (gc_eff1 < gc_eff2) { + return 1; + } else { + return 0; + } +} + +int G1CollectionCandidateList::compare_reclaimble_bytes(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2) { // Make sure that null entries are moved to the end. if (ci1->_r == nullptr) { if (ci2->_r == nullptr) { @@ -106,12 +121,12 @@ int G1CollectionCandidateList::compare(G1CollectionSetCandidateInfo* ci1, G1Coll return -1; } - double gc_eff1 = ci1->_gc_efficiency; - double gc_eff2 = ci2->_gc_efficiency; + size_t reclaimable1 = ci1->_r->reclaimable_bytes(); + size_t reclaimable2 = ci2->_r->reclaimable_bytes(); - if (gc_eff1 > gc_eff2) { + if (reclaimable1 > reclaimable2) { return -1; - } if (gc_eff1 < gc_eff2) { + } else if (reclaimable1 < reclaimable2) { return 1; } else { return 0; @@ -182,6 +197,17 @@ void G1CollectionSetCandidates::clear() { _last_marking_candidates_length = 0; } +void G1CollectionSetCandidates::sort_marking_by_efficiency() { + G1CollectionCandidateListIterator iter = _marking_regions.begin(); + for (; iter != _marking_regions.end(); ++iter) { + HeapRegion* hr = (*iter)->_r; + (*iter)->_gc_efficiency = hr->calc_gc_efficiency(); + } + _marking_regions.sort_by_efficiency(); + + _marking_regions.verify(); +} + void G1CollectionSetCandidates::set_candidates_from_marking(G1CollectionSetCandidateInfo* candidate_infos, uint num_infos) { assert(_marking_regions.length() == 0, "must be empty before adding new ones"); diff --git a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp index 4eb5523d0399e..dd38d33b5d39e 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp @@ -129,7 +129,9 @@ class G1CollectionCandidateList : public CHeapObj { // Comparison function to order regions in decreasing GC efficiency order. This // will cause regions with a lot of live objects and large remembered sets to end // up at the end of the list. - static int compare(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2); + static int compare_gc_efficiency(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2); + + static int compare_reclaimble_bytes(G1CollectionSetCandidateInfo* ci1, G1CollectionSetCandidateInfo* ci2); G1CollectionCandidateListIterator begin() { return G1CollectionCandidateListIterator(this, 0); @@ -213,6 +215,8 @@ class G1CollectionSetCandidates : public CHeapObj { void sort_by_efficiency(); + void sort_marking_by_efficiency(); + // Add the given region to the set of retained regions without regards to the // gc efficiency sorting. The retained regions must be re-sorted manually later. void add_retained_region_unsorted(HeapRegion* r); diff --git a/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp b/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp index 92a342ec7579d..df3e72cb22f37 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp @@ -94,17 +94,17 @@ class G1BuildCandidateRegionsTask : public WorkerTask { void set(uint idx, HeapRegion* hr) { assert(idx < _max_size, "Index %u out of bounds %u", idx, _max_size); assert(_data[idx]._r == nullptr, "Value must not have been set."); - _data[idx] = CandidateInfo(hr, hr->calc_gc_efficiency()); + _data[idx] = CandidateInfo(hr, 0.0); } - void sort_by_efficiency() { + void sort_by_reclaimable_bytes() { if (_cur_claim_idx == 0) { return; } for (uint i = _cur_claim_idx; i < _max_size; i++) { assert(_data[i]._r == nullptr, "must be"); } - qsort(_data, _cur_claim_idx, sizeof(_data[0]), (_sort_Fn)G1CollectionCandidateList::compare); + qsort(_data, _cur_claim_idx, sizeof(_data[0]), (_sort_Fn)G1CollectionCandidateList::compare_reclaimble_bytes); for (uint i = _cur_claim_idx; i < _max_size; i++) { assert(_data[i]._r == nullptr, "must be"); } @@ -152,8 +152,7 @@ class G1BuildCandidateRegionsTask : public WorkerTask { } // Can not add a region without a remembered set to the candidates. - assert(!r->rem_set()->is_updating(), "must be"); - if (!r->rem_set()->is_complete()) { + if (!r->rem_set()->is_tracked()) { return false; } @@ -249,7 +248,7 @@ class G1BuildCandidateRegionsTask : public WorkerTask { } void sort_and_prune_into(G1CollectionSetCandidates* candidates) { - _result.sort_by_efficiency(); + _result.sort_by_reclaimable_bytes(); prune(_result.array()); candidates->set_candidates_from_marking(_result.array(), _num_regions_added); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 68b5050ff600a..f2af91d241e1c 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1438,7 +1438,14 @@ void G1ConcurrentMark::remark() { log_debug(gc, remset, tracking)("Remembered Set Tracking update regions total %u, selected %u", _g1h->num_regions(), cl.total_selected_for_rebuild()); + _needs_remembered_set_rebuild = (cl.total_selected_for_rebuild() > 0); + + if (_needs_remembered_set_rebuild) { + // Prune rebuild candidates based on G1HeapWastePercent. + // Improves rebuild time in addition to remembered set memory usage. + G1CollectionSetChooser::build(_g1h->workers(), _g1h->num_regions(), _g1h->policy()->candidates()); + } } if (log_is_enabled(Trace, gc, liveness)) { diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index dd9d937ad77b5..b27ddd0a9bb0e 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -1310,7 +1310,7 @@ void G1Policy::decide_on_concurrent_start_pause() { void G1Policy::record_concurrent_mark_cleanup_end(bool has_rebuilt_remembered_sets) { bool mixed_gc_pending = false; if (has_rebuilt_remembered_sets) { - G1CollectionSetChooser::build(_g1h->workers(), _g1h->num_regions(), candidates()); + candidates()->sort_marking_by_efficiency(); mixed_gc_pending = next_gc_should_be_mixed(); } diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index c951909788c2e..43759dc476778 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -184,9 +184,10 @@ class G1Policy: public CHeapObj { return _mmu_tracker->max_gc_time() * 1000.0; } + G1CollectionSetCandidates* candidates() const; + private: G1CollectionSet* _collection_set; - G1CollectionSetCandidates* candidates() const; double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const; double other_time_ms(double pause_time_ms) const; From 9697bc38586059d9bb020d3ca44a1c6cd7de315c Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 3 May 2024 13:02:37 +0000 Subject: [PATCH 079/203] 8331428: ubsan: JVM flag checking complains about MaxTenuringThresholdConstraintFunc, InitialTenuringThresholdConstraintFunc and AllocatePrefetchStepSizeConstraintFunc Reviewed-by: stefank, aboldtch, tschatzl --- src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp | 6 +++--- src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp | 6 +++--- .../share/runtime/flags/jvmFlagConstraintsCompiler.cpp | 6 +++--- .../share/runtime/flags/jvmFlagConstraintsCompiler.hpp | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp index 6c6f83177d204..cb36962e61e58 100644 --- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp +++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -174,7 +174,7 @@ JVMFlag::Error MaxMetaspaceFreeRatioConstraintFunc(uint value, bool verbose) { } } -JVMFlag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) { +JVMFlag::Error InitialTenuringThresholdConstraintFunc(uint value, bool verbose) { #if INCLUDE_PARALLELGC JVMFlag::Error status = InitialTenuringThresholdConstraintFuncParallel(value, verbose); if (status != JVMFlag::SUCCESS) { @@ -185,7 +185,7 @@ JVMFlag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) return JVMFlag::SUCCESS; } -JVMFlag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose) { +JVMFlag::Error MaxTenuringThresholdConstraintFunc(uint value, bool verbose) { #if INCLUDE_PARALLELGC JVMFlag::Error status = MaxTenuringThresholdConstraintFuncParallel(value, verbose); if (status != JVMFlag::SUCCESS) { diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp index 591838c071753..a89f42959e1b6 100644 --- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp +++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,8 +49,8 @@ f(size_t, MarkStackSizeConstraintFunc) \ f(uint, MinMetaspaceFreeRatioConstraintFunc) \ f(uint, MaxMetaspaceFreeRatioConstraintFunc) \ - f(uintx, InitialTenuringThresholdConstraintFunc) \ - f(uintx, MaxTenuringThresholdConstraintFunc) \ + f(uint, InitialTenuringThresholdConstraintFunc) \ + f(uint, MaxTenuringThresholdConstraintFunc) \ \ f(uintx, MaxGCPauseMillisConstraintFunc) \ f(uintx, GCPauseIntervalMillisConstraintFunc) \ diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index c32177224a59e..2cd7371909d1e 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,11 +67,11 @@ JVMFlag::Error CICompilerCountConstraintFunc(intx value, bool verbose) { } } -JVMFlag::Error AllocatePrefetchStepSizeConstraintFunc(intx value, bool verbose) { +JVMFlag::Error AllocatePrefetchStepSizeConstraintFunc(int value, bool verbose) { if (AllocatePrefetchStyle == 3) { if (value % wordSize != 0) { JVMFlag::printError(verbose, - "AllocatePrefetchStepSize (" INTX_FORMAT ") must be multiple of %d\n", + "AllocatePrefetchStepSize (%d) must be multiple of %d\n", value, wordSize); return JVMFlag::VIOLATES_CONSTRAINT; } diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp index 8538c836ca937..60adf4903a328 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ #define COMPILER_CONSTRAINTS(f) \ f(intx, CICompilerCountConstraintFunc) \ f(intx, AllocatePrefetchInstrConstraintFunc) \ - f(intx, AllocatePrefetchStepSizeConstraintFunc) \ + f(int, AllocatePrefetchStepSizeConstraintFunc) \ f(intx, CompileThresholdConstraintFunc) \ f(intx, OnStackReplacePercentageConstraintFunc) \ f(uintx, CodeCacheSegmentSizeConstraintFunc) \ From 1d083eb15a653dbfbd262de76c1312207192bda7 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 3 May 2024 13:10:00 +0000 Subject: [PATCH 080/203] 8331562: G1: Remove API to force allocation of new regions Reviewed-by: iwalulya, ayang, gli --- src/hotspot/share/gc/g1/g1AllocRegion.cpp | 14 +++++--------- src/hotspot/share/gc/g1/g1AllocRegion.hpp | 18 +++++------------- .../share/gc/g1/g1AllocRegion.inline.hpp | 15 +-------------- src/hotspot/share/gc/g1/g1Allocator.hpp | 2 -- src/hotspot/share/gc/g1/g1Allocator.inline.hpp | 5 ----- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 5 ++--- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 2 +- src/hotspot/share/gc/g1/g1HRPrinter.hpp | 2 +- 8 files changed, 15 insertions(+), 48 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.cpp b/src/hotspot/share/gc/g1/g1AllocRegion.cpp index f20f24bcde42b..b86fe1099ac0e 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.cpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.cpp @@ -130,13 +130,12 @@ size_t G1AllocRegion::retire(bool fill_up) { return waste; } -HeapWord* G1AllocRegion::new_alloc_region_and_allocate(size_t word_size, - bool force) { +HeapWord* G1AllocRegion::new_alloc_region_and_allocate(size_t word_size) { assert_alloc_region(_alloc_region == _dummy_region, "pre-condition"); assert_alloc_region(_used_bytes_before == 0, "pre-condition"); trace("attempting region allocation"); - HeapRegion* new_alloc_region = allocate_new_region(word_size, force); + HeapRegion* new_alloc_region = allocate_new_region(word_size); if (new_alloc_region != nullptr) { new_alloc_region->reset_pre_dummy_top(); // Need to do this before the allocation @@ -258,9 +257,8 @@ G1AllocRegion::G1AllocRegion(const char* name, _node_index(node_index) { } -HeapRegion* MutatorAllocRegion::allocate_new_region(size_t word_size, - bool force) { - return _g1h->new_mutator_alloc_region(word_size, force, _node_index); +HeapRegion* MutatorAllocRegion::allocate_new_region(size_t word_size) { + return _g1h->new_mutator_alloc_region(word_size, _node_index); } void MutatorAllocRegion::retire_region(HeapRegion* alloc_region, @@ -344,9 +342,7 @@ HeapRegion* MutatorAllocRegion::release() { return ret; } -HeapRegion* G1GCAllocRegion::allocate_new_region(size_t word_size, - bool force) { - assert(!force, "not supported for GC alloc regions"); +HeapRegion* G1GCAllocRegion::allocate_new_region(size_t word_size) { return _g1h->new_gc_alloc_region(word_size, _purpose, _node_index); } diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.hpp b/src/hotspot/share/gc/g1/g1AllocRegion.hpp index b39a717d3b708..9ea20c676f4d7 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.hpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.hpp @@ -83,10 +83,8 @@ class G1AllocRegion : public CHeapObj { void update_alloc_region(HeapRegion* alloc_region); // Allocate a new active region and use it to perform a word_size - // allocation. The force parameter will be passed on to - // G1CollectedHeap::allocate_new_alloc_region() and tells it to try - // to allocate a new region even if the max has been reached. - HeapWord* new_alloc_region_and_allocate(size_t word_size, bool force); + // allocation. + HeapWord* new_alloc_region_and_allocate(size_t word_size); // Perform an allocation out of a new allocation region, retiring the current one. inline HeapWord* attempt_allocation_using_new_region(size_t min_word_size, @@ -132,7 +130,7 @@ class G1AllocRegion : public CHeapObj { // For convenience as subclasses use it. static G1CollectedHeap* _g1h; - virtual HeapRegion* allocate_new_region(size_t word_size, bool force) = 0; + virtual HeapRegion* allocate_new_region(size_t word_size) = 0; virtual void retire_region(HeapRegion* alloc_region, size_t allocated_bytes) = 0; @@ -172,12 +170,6 @@ class G1AllocRegion : public CHeapObj { size_t desired_word_size, size_t* actual_word_size); - // Should be called to allocate a new region even if the max of this - // type of regions has been reached. Should only be called if other - // allocation attempts have failed and we are not holding a valid - // active region. - inline HeapWord* attempt_allocation_force(size_t word_size); - // Should be called before we start using this object. virtual void init(); @@ -213,7 +205,7 @@ class MutatorAllocRegion : public G1AllocRegion { // in it and the free size in the currently retained region, if any. bool should_retain(HeapRegion* region); protected: - virtual HeapRegion* allocate_new_region(size_t word_size, bool force); + virtual HeapRegion* allocate_new_region(size_t word_size); virtual void retire_region(HeapRegion* alloc_region, size_t allocated_bytes); virtual size_t retire(bool fill_up); public: @@ -249,7 +241,7 @@ class G1GCAllocRegion : public G1AllocRegion { G1EvacStats* _stats; G1HeapRegionAttr::region_type_t _purpose; - virtual HeapRegion* allocate_new_region(size_t word_size, bool force); + virtual HeapRegion* allocate_new_region(size_t word_size); virtual void retire_region(HeapRegion* alloc_region, size_t allocated_bytes); virtual size_t retire(bool fill_up); diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp b/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp index 00ef254e84c37..9e702a4f8c909 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp @@ -98,7 +98,7 @@ inline HeapWord* G1AllocRegion::attempt_allocation_using_new_region(size_t min_w size_t desired_word_size, size_t* actual_word_size) { retire(true /* fill_up */); - HeapWord* result = new_alloc_region_and_allocate(desired_word_size, false /* force */); + HeapWord* result = new_alloc_region_and_allocate(desired_word_size); if (result != nullptr) { *actual_word_size = desired_word_size; trace("alloc locked (second attempt)", min_word_size, desired_word_size, *actual_word_size, result); @@ -108,19 +108,6 @@ inline HeapWord* G1AllocRegion::attempt_allocation_using_new_region(size_t min_w return nullptr; } -inline HeapWord* G1AllocRegion::attempt_allocation_force(size_t word_size) { - assert_alloc_region(_alloc_region != nullptr, "not initialized properly"); - - trace("forcing alloc", word_size, word_size); - HeapWord* result = new_alloc_region_and_allocate(word_size, true /* force */); - if (result != nullptr) { - trace("alloc forced", word_size, word_size, word_size, result); - return result; - } - trace("alloc forced failed", word_size, word_size); - return nullptr; -} - inline HeapWord* MutatorAllocRegion::attempt_retained_allocation(size_t min_word_size, size_t desired_word_size, size_t* actual_word_size) { diff --git a/src/hotspot/share/gc/g1/g1Allocator.hpp b/src/hotspot/share/gc/g1/g1Allocator.hpp index 32f37778a18ad..e273365b12fea 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.hpp @@ -121,8 +121,6 @@ class G1Allocator : public CHeapObj { // current allocation region, and then attempts an allocation using a new region. inline HeapWord* attempt_allocation_locked(size_t word_size); - inline HeapWord* attempt_allocation_force(size_t word_size); - size_t unsafe_max_tlab_alloc(); size_t used_in_alloc_regions(); diff --git a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp index 13ae9b9bbbdea..ff84306e74f95 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp @@ -71,11 +71,6 @@ inline HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size) { return result; } -inline HeapWord* G1Allocator::attempt_allocation_force(size_t word_size) { - uint node_index = current_node_index(); - return mutator_alloc_region(node_index)->attempt_allocation_force(word_size); -} - inline PLAB* G1PLABAllocator::alloc_buffer(G1HeapRegionAttr dest, uint node_index) const { assert(dest.is_valid(), "Allocation buffer index out of bounds: %s", dest.get_type_str()); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 45f570dcd2bae..c411b7a75346a 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2846,18 +2846,17 @@ void G1CollectedHeap::rebuild_region_sets(bool free_list_only) { // Methods for the mutator alloc region HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, - bool force, uint node_index) { assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); bool should_allocate = policy()->should_allocate_mutator_region(); - if (force || should_allocate) { + if (should_allocate) { HeapRegion* new_alloc_region = new_region(word_size, HeapRegionType::Eden, false /* do_expand */, node_index); if (new_alloc_region != nullptr) { set_region_short_lived_locked(new_alloc_region); - G1HRPrinter::alloc(new_alloc_region, !should_allocate); + G1HRPrinter::alloc(new_alloc_region); _policy->remset_tracker()->update_at_allocate(new_alloc_region); return new_alloc_region; } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 6f31122014ff2..3aaa6d8b72342 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -465,7 +465,7 @@ class G1CollectedHeap : public CollectedHeap { // These methods are the "callbacks" from the G1AllocRegion class. // For mutator alloc regions. - HeapRegion* new_mutator_alloc_region(size_t word_size, bool force, uint node_index); + HeapRegion* new_mutator_alloc_region(size_t word_size, uint node_index); void retire_mutator_alloc_region(HeapRegion* alloc_region, size_t allocated_bytes); diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.hpp b/src/hotspot/share/gc/g1/g1HRPrinter.hpp index 035e92fefacbe..57e451bbb612b 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.hpp +++ b/src/hotspot/share/gc/g1/g1HRPrinter.hpp @@ -51,7 +51,7 @@ class G1HRPrinter : public AllStatic { // The methods below are convenient wrappers for the print() method. - static void alloc(HeapRegion* hr, bool force = false) { print(force ? "ALLOC-FORCE" : "ALLOC", hr); } + static void alloc(HeapRegion* hr) { print("ALLOC", hr); } static void retire(HeapRegion* hr) { print("RETIRE", hr); } From 37c24695390e409aae6df9f7d2ecc86724dd051d Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 3 May 2024 13:27:58 +0000 Subject: [PATCH 081/203] 8331633: Use MIN2 in bound_minus_alignment Reviewed-by: zgu --- src/hotspot/share/gc/shared/genArguments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shared/genArguments.cpp b/src/hotspot/share/gc/shared/genArguments.cpp index fa0e675cf7343..3c1d1ac6ec1cd 100644 --- a/src/hotspot/share/gc/shared/genArguments.cpp +++ b/src/hotspot/share/gc/shared/genArguments.cpp @@ -58,7 +58,7 @@ static size_t bound_minus_alignment(size_t desired_size, size_t maximum_size, size_t alignment) { size_t max_minus = maximum_size - alignment; - return desired_size < max_minus ? desired_size : max_minus; + return MIN2(desired_size, max_minus); } void GenArguments::initialize_alignments() { From 87bb66cea1b6b70fc4929e7a6e3788883f87e02d Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 3 May 2024 13:39:48 +0000 Subject: [PATCH 082/203] 8331569: G1: Rename G1HRPrinter to G1HeapRegionPrinter Reviewed-by: gli, ayang --- src/hotspot/share/gc/g1/g1Allocator.cpp | 4 ++-- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 18 +++++++++--------- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 4 ++-- .../share/gc/g1/g1HeapRegionManager.cpp | 12 ++++++------ ...g1HRPrinter.cpp => g1HeapRegionPrinter.cpp} | 6 +++--- ...g1HRPrinter.hpp => g1HeapRegionPrinter.hpp} | 8 ++++---- .../share/gc/g1/g1ParScanThreadState.cpp | 4 ++-- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 6 +++--- .../share/gc/g1/g1YoungGCPostEvacuateTasks.cpp | 6 +++--- 9 files changed, 34 insertions(+), 34 deletions(-) rename src/hotspot/share/gc/g1/{g1HRPrinter.cpp => g1HeapRegionPrinter.cpp} (86%) rename src/hotspot/share/gc/g1/{g1HRPrinter.hpp => g1HeapRegionPrinter.hpp} (94%) diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index 758d16a89f5f1..2a028f480c0b8 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -29,9 +29,9 @@ #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1HeapRegionSet.inline.hpp" #include "gc/g1/g1HeapRegionType.hpp" -#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1NUMA.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/shared/tlab_globals.hpp" @@ -119,7 +119,7 @@ void G1Allocator::reuse_retained_old_region(G1EvacInfo* evacuation_info, // it's retired again. _g1h->old_set_remove(retained_region); old->set(retained_region); - G1HRPrinter::reuse(retained_region); + G1HeapRegionPrinter::reuse(retained_region); evacuation_info->set_alloc_regions_used_before(retained_region->used()); } } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index c411b7a75346a..f8031c35b9a3a 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -47,12 +47,12 @@ #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1GCPauseType.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "gc/g1/g1HeapRegionSet.inline.hpp" #include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" -#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1InitLogger.hpp" #include "gc/g1/g1MemoryPool.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" @@ -326,7 +326,7 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(HeapRegion* first_hr, for (uint i = first; i <= last; ++i) { HeapRegion *hr = region_at(i); _humongous_set.add(hr); - G1HRPrinter::alloc(hr); + G1HeapRegionPrinter::alloc(hr); } return new_obj; @@ -525,7 +525,7 @@ HeapWord* G1CollectedHeap::alloc_archive_region(size_t word_size, HeapWord* pref r->set_top(top); r->set_old(); - G1HRPrinter::alloc(r); + G1HeapRegionPrinter::alloc(r); _old_set.add(r); }; @@ -714,7 +714,7 @@ class PostCompactionPrinterClosure: public HeapRegionClosure { public: bool do_heap_region(HeapRegion* hr) { assert(!hr->is_young(), "not expecting to find young regions"); - G1HRPrinter::post_compaction(hr); + G1HeapRegionPrinter::post_compaction(hr); return false; } }; @@ -724,7 +724,7 @@ void G1CollectedHeap::print_heap_after_full_collection() { // We should do this after we potentially resize the heap so // that all the COMMIT / UNCOMMIT events are generated before // the compaction events. - if (G1HRPrinter::is_active()) { + if (G1HeapRegionPrinter::is_active()) { PostCompactionPrinterClosure cl; heap_region_iterate(&cl); } @@ -2856,7 +2856,7 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, node_index); if (new_alloc_region != nullptr) { set_region_short_lived_locked(new_alloc_region); - G1HRPrinter::alloc(new_alloc_region); + G1HeapRegionPrinter::alloc(new_alloc_region); _policy->remset_tracker()->update_at_allocate(new_alloc_region); return new_alloc_region; } @@ -2872,7 +2872,7 @@ void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region, collection_set()->add_eden_region(alloc_region); increase_used(allocated_bytes); _eden.add_used_bytes(allocated_bytes); - G1HRPrinter::retire(alloc_region); + G1HeapRegionPrinter::retire(alloc_region); // We update the eden sizes here, when the region is retired, // instead of when it's allocated, since this is the point that its @@ -2919,7 +2919,7 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, G1HeapRegionA } _policy->remset_tracker()->update_at_allocate(new_alloc_region); register_region_with_region_attr(new_alloc_region); - G1HRPrinter::alloc(new_alloc_region); + G1HeapRegionPrinter::alloc(new_alloc_region); return new_alloc_region; } return nullptr; @@ -2940,7 +2940,7 @@ void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region, if (during_im && allocated_bytes > 0) { _cm->add_root_region(alloc_region); } - G1HRPrinter::retire(alloc_region); + G1HeapRegionPrinter::retire(alloc_region); } HeapRegion* G1CollectedHeap::alloc_highest_free_region() { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index f2af91d241e1c..804f255217fdb 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -37,10 +37,10 @@ #include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionManager.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "gc/g1/g1HeapRegionSet.inline.hpp" #include "gc/g1/g1HeapVerifier.hpp" -#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RegionMarkStatsCache.inline.hpp" @@ -1318,7 +1318,7 @@ class G1UpdateRegionLivenessAndSelectForRebuildTask : public WorkerTask { if (!_cleanup_list.is_empty()) { log_debug(gc)("Reclaimed %u empty regions", _cleanup_list.length()); // Now print the empty regions list. - G1HRPrinter::mark_reclaim(&_cleanup_list); + G1HeapRegionPrinter::mark_reclaim(&_cleanup_list); // And actually make them available. _g1h->prepend_to_freelist(&_cleanup_list); } diff --git a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp index 0d0f8b6b2883e..81cba2329c89e 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp @@ -29,8 +29,8 @@ #include "gc/g1/g1CommittedRegionMap.inline.hpp" #include "gc/g1/g1HeapRegion.hpp" #include "gc/g1/g1HeapRegionManager.inline.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1HeapRegionSet.inline.hpp" -#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1NUMAStats.hpp" #include "jfr/jfrEvents.hpp" #include "logging/logStream.hpp" @@ -171,7 +171,7 @@ void HeapRegionManager::expand(uint start, uint num_regions, WorkerThreads* pret _regions.set_by_index(i, hr); _allocated_heapregions_length = MAX2(_allocated_heapregions_length, i + 1); } - G1HRPrinter::commit(hr); + G1HeapRegionPrinter::commit(hr); } activate_regions(start, num_regions); } @@ -194,12 +194,12 @@ void HeapRegionManager::uncommit_regions(uint start, uint num_regions) { guarantee(num_regions > 0, "No point in calling this for zero regions"); uint end = start + num_regions; - if (G1HRPrinter::is_active()) { + if (G1HeapRegionPrinter::is_active()) { for (uint i = start; i < end; i++) { // Can't use at() here since region is no longer marked available. HeapRegion* hr = _regions.get_by_index(i); assert(hr != nullptr, "Region should still be present"); - G1HRPrinter::uncommit(hr); + G1HeapRegionPrinter::uncommit(hr); } } @@ -223,7 +223,7 @@ void HeapRegionManager::initialize_regions(uint start, uint num_regions) { hr->initialize(); hr->set_node_index(G1NUMA::numa()->index_for_region(hr)); insert_into_free_list(hr); - G1HRPrinter::active(hr); + G1HeapRegionPrinter::active(hr); } } @@ -250,7 +250,7 @@ void HeapRegionManager::deactivate_regions(uint start, uint num_regions) { for (uint i = start; i < end; i++) { HeapRegion* hr = at(i); hr->set_node_index(G1NUMA::UnknownNodeIndex); - G1HRPrinter::inactive(hr); + G1HeapRegionPrinter::inactive(hr); } _committed_map.deactivate(start, end); diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.cpp b/src/hotspot/share/gc/g1/g1HeapRegionPrinter.cpp similarity index 86% rename from src/hotspot/share/gc/g1/g1HRPrinter.cpp rename to src/hotspot/share/gc/g1/g1HeapRegionPrinter.cpp index 99769f85390fe..1c87b800601f9 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,10 @@ #include "precompiled.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1HeapRegionSet.hpp" -#include "gc/g1/g1HRPrinter.hpp" -void G1HRPrinter::mark_reclaim(FreeRegionList* cleanup_list) { +void G1HeapRegionPrinter::mark_reclaim(FreeRegionList* cleanup_list) { if (is_active()) { FreeRegionListIterator iter(cleanup_list); while (iter.more_available()) { diff --git a/src/hotspot/share/gc/g1/g1HRPrinter.hpp b/src/hotspot/share/gc/g1/g1HeapRegionPrinter.hpp similarity index 94% rename from src/hotspot/share/gc/g1/g1HRPrinter.hpp rename to src/hotspot/share/gc/g1/g1HeapRegionPrinter.hpp index 57e451bbb612b..20a6e795da0cd 100644 --- a/src/hotspot/share/gc/g1/g1HRPrinter.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionPrinter.hpp @@ -22,8 +22,8 @@ * */ -#ifndef SHARE_GC_G1_G1HRPRINTER_HPP -#define SHARE_GC_G1_G1HRPRINTER_HPP +#ifndef SHARE_GC_G1_G1HEAPREGIONPRINTER_HPP +#define SHARE_GC_G1_G1HEAPREGIONPRINTER_HPP #include "gc/g1/g1HeapRegion.hpp" #include "logging/log.hpp" @@ -31,7 +31,7 @@ class FreeRegionList; -class G1HRPrinter : public AllStatic { +class G1HeapRegionPrinter : public AllStatic { // Print an action event. static void print(const char* action, HeapRegion* hr) { @@ -78,4 +78,4 @@ class G1HRPrinter : public AllStatic { static void uncommit(HeapRegion* hr) { print("UNCOMMIT", hr); } }; -#endif // SHARE_GC_G1_G1HRPRINTER_HPP +#endif // SHARE_GC_G1_G1HEAPREGIONPRINTER_HPP diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index da9a7d9a575e5..bc09a6607301b 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -27,7 +27,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1EvacFailureRegions.inline.hpp" -#include "gc/g1/g1HRPrinter.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1RootClosures.hpp" @@ -643,7 +643,7 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m, siz HeapRegion* r = _g1h->heap_region_containing(old); if (_evac_failure_regions->record(_worker_id, r->hrm_index(), cause_pinned)) { - G1HRPrinter::evac_failure(r); + G1HeapRegionPrinter::evac_failure(r); } // Mark the failing object in the marking bitmap and later use the bitmap to handle diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index f08d6543efd4e..bf1c8b738f8a0 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -36,7 +36,7 @@ #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1EvacFailureRegions.inline.hpp" #include "gc/g1/g1EvacInfo.hpp" -#include "gc/g1/g1HRPrinter.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1Policy.hpp" @@ -262,7 +262,7 @@ void G1YoungCollector::wait_for_root_region_scanning() { class G1PrintCollectionSetClosure : public HeapRegionClosure { public: virtual bool do_heap_region(HeapRegion* r) { - G1HRPrinter::cset(r); + G1HeapRegionPrinter::cset(r); return false; } }; @@ -278,7 +278,7 @@ void G1YoungCollector::calculate_collection_set(G1EvacInfo* evacuation_info, dou concurrent_mark()->verify_no_collection_set_oops(); - if (G1HRPrinter::is_active()) { + if (G1HeapRegionPrinter::is_active()) { G1PrintCollectionSetClosure cl; collection_set()->iterate(&cl); collection_set()->iterate_optional(&cl); diff --git a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp index 16c617323c89d..288abc87be985 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp @@ -35,8 +35,8 @@ #include "gc/g1/g1EvacInfo.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" +#include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" -#include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.hpp" #include "gc/g1/g1RemSet.hpp" @@ -413,7 +413,7 @@ class G1FreeHumongousRegionClosure : public HeapRegionIndexClosure { r->set_containing_set(nullptr); _humongous_regions_reclaimed++; _g1h->free_humongous_region(r, nullptr); - G1HRPrinter::eager_reclaim(r); + G1HeapRegionPrinter::eager_reclaim(r); }; _g1h->humongous_obj_regions_iterate(r, free_humongous_region); @@ -761,7 +761,7 @@ class FreeCSetClosure : public HeapRegionClosure { // Free the region and its remembered set. _g1h->free_region(r, nullptr); - G1HRPrinter::evac_reclaim(r); + G1HeapRegionPrinter::evac_reclaim(r); } void handle_failed_region(HeapRegion* r) { From 77b71222a05a5ef3875a71eda26e31b25548cba2 Mon Sep 17 00:00:00 2001 From: Sean Coffey Date: Fri, 3 May 2024 15:18:38 +0000 Subject: [PATCH 083/203] 8312104: Update java man pages to include new security category in -XshowSettings Reviewed-by: lancea --- src/java.base/share/man/java.1 | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 3754408fbde9d..990fdccf8d547 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -1103,8 +1103,7 @@ following: .RS .TP \f[V]all\f[R] -Shows all categories of settings. -This is the default value. +Shows all categories of settings in \f[B]verbose\f[R] detail. .TP \f[V]locale\f[R] Shows settings related to locale. @@ -1112,6 +1111,21 @@ Shows settings related to locale. \f[V]properties\f[R] Shows settings related to system properties. .TP +\f[V]security\f[R] +Shows all settings related to security. +.RS +.PP +sub-category arguments for \f[V]security\f[R] include the following: +.IP \[bu] 2 +\f[V]security:all\f[R] : shows all security settings +.IP \[bu] 2 +\f[V]security:properties\f[R] : shows security properties +.IP \[bu] 2 +\f[V]security:providers\f[R] : shows static security provider settings +.IP \[bu] 2 +\f[V]security:tls\f[R] : shows TLS related security settings +.RE +.TP \f[V]vm\f[R] Shows the settings of the JVM. .TP From cf2c80e4fcd74b9d1d60e2358e7883bdd8a4ac80 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Fri, 3 May 2024 16:14:24 +0000 Subject: [PATCH 084/203] 8331582: Incorrect default Console provider comment Reviewed-by: joehw, jlahoda, jlu, prappo --- src/java.base/share/classes/java/io/Console.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index a944e8c77fbff..bbf2e39eb488b 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -406,7 +406,8 @@ private static Console instantiateConsole(boolean istty) { /* * The JdkConsole provider used for Console instantiation can be specified * with the system property "jdk.console", whose value designates the module - * name of the implementation, and which defaults to "java.base". If no + * name of the implementation, and which defaults to the value of + * {@code JdkConsoleProvider.DEFAULT_PROVIDER_MODULE_NAME}. If no * providers are available, or instantiation failed, java.base built-in * Console implementation is used. */ From b33096f887108c3d7e1f4e62689c2b10401234fa Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Fri, 3 May 2024 16:58:59 +0000 Subject: [PATCH 085/203] 8295153: java/util/Base64/TestEncodingDecodingLength.java ran out of memory Reviewed-by: lancea, naoto --- .../Base64/TestEncodingDecodingLength.java | 114 ++++++++++++------ 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/test/jdk/java/util/Base64/TestEncodingDecodingLength.java b/test/jdk/java/util/Base64/TestEncodingDecodingLength.java index 3a91cd88b1f00..ce6d0db4adc5e 100644 --- a/test/jdk/java/util/Base64/TestEncodingDecodingLength.java +++ b/test/jdk/java/util/Base64/TestEncodingDecodingLength.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,55 +21,95 @@ * questions. */ -import java.nio.ByteBuffer; -import java.util.Arrays; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Base64; -/** +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +/* * @test - * @bug 8210583 8217969 8218265 - * @summary Tests Base64.Encoder.encode and Base64.Decoder.decode - * with the large size of input array/buffer - * @requires (sun.arch.data.model == "64" & os.maxMemory >= 10g) - * @run main/othervm -Xms6g -Xmx8g TestEncodingDecodingLength - * + * @bug 8210583 8217969 8218265 8295153 + * @summary White-box test that effectively checks Base64.Encoder.encode and + * Base64.Decoder.decode behavior with large, (Integer.MAX_VALUE) sized + * input array/buffer. Tests the private methods "encodedOutLength" and + * "decodedOutLength". + * @run junit/othervm --add-opens java.base/java.util=ALL-UNNAMED TestEncodingDecodingLength */ +// We perform a white-box test due to the heavy memory usage that testing +// the public API would require which has shown to cause intermittent issues public class TestEncodingDecodingLength { - public static void main(String[] args) { - int size = Integer.MAX_VALUE - 8; - byte[] inputBytes = new byte[size]; - byte[] outputBytes = new byte[size]; + // A value large enough to test the desired memory conditions in encode and decode + private static final int LARGE_MEM_SIZE = Integer.MAX_VALUE - 8; + private static final Base64.Decoder DECODER = Base64.getDecoder(); + private static final Base64.Encoder ENCODER = Base64.getEncoder(); - // Check encoder with large array length - Base64.Encoder encoder = Base64.getEncoder(); - checkOOM("encode(byte[])", () -> encoder.encode(inputBytes)); - checkIAE("encode(byte[] byte[])", () -> encoder.encode(inputBytes, outputBytes)); - checkOOM("encodeToString(byte[])", () -> encoder.encodeToString(inputBytes)); - checkOOM("encode(ByteBuffer)", () -> encoder.encode(ByteBuffer.wrap(inputBytes))); - - // Check decoder with large array length, - // should not throw any exception - Arrays.fill(inputBytes, (byte) 86); - Base64.Decoder decoder = Base64.getDecoder(); - decoder.decode(inputBytes); - decoder.decode(inputBytes, outputBytes); - decoder.decode(ByteBuffer.wrap(inputBytes)); + // Effectively tests that encode(byte[] src, byte[] dst) throws an + // IllegalArgumentException with array sized near Integer.MAX_VALUE. All the + // encode() methods call encodedOutLength(), which is where the OOME is expected + @Test + public void largeEncodeIAETest() throws IllegalAccessException, + InvocationTargetException, NoSuchMethodException { + Method m = getMethod(ENCODER, + "encodedOutLength", int.class, boolean.class); + // When throwOOME param is false, encodedOutLength should return -1 in + // this situation, which encode() uses to throw IAE + assertEquals(-1, m.invoke(ENCODER, LARGE_MEM_SIZE, false)); } - private static final void checkOOM(String methodName, Runnable r) { + // Effectively tests that the overloaded encode() and encodeToString() methods + // throw OutOfMemoryError with array/buffer sized near Integer.MAX_VALUE + @Test + public void largeEncodeOOMETest() throws IllegalAccessException, NoSuchMethodException { + Method m = getMethod(ENCODER, + "encodedOutLength", int.class, boolean.class); try { - r.run(); - throw new RuntimeException("OutOfMemoryError should have been thrown by: " + methodName); - } catch (OutOfMemoryError er) {} + m.invoke(ENCODER, LARGE_MEM_SIZE, true); + } catch (InvocationTargetException ex) { + Throwable rootEx = ex.getCause(); + assertEquals(OutOfMemoryError.class, rootEx.getClass(), + "OOME should be thrown with Integer.MAX_VALUE input"); + assertEquals("Encoded size is too large", rootEx.getMessage()); + } } - private static final void checkIAE(String methodName, Runnable r) { + // Effectively tests that the overloaded decode() methods do not throw + // OOME nor NASE with array/buffer sized near Integer.MAX_VALUE All the decode + // methods call decodedOutLength(), which is where the previously thrown + // OOME or NASE would occur at. + @Test + public void largeDecodeTest() throws IllegalAccessException, NoSuchMethodException { + Method m = getMethod(DECODER, + "decodedOutLength", byte[].class, int.class, int.class); + byte[] src = {1}; try { - r.run(); - throw new RuntimeException("IllegalArgumentException should have been thrown by: " + methodName); - } catch (IllegalArgumentException iae) {} + /* + decodedOutLength() takes the src array, position, and limit as params. + The src array will be indexed at limit-1 to search for padding. + To avoid passing an array with Integer.MAX_VALUE memory allocated, we + set position param to be -size. Since the initial length + is calculated as limit - position. This mocks the potential overflow + calculation and still allows the array to be indexed without an AIOBE. + */ + m.invoke(DECODER, src, -LARGE_MEM_SIZE + 1, 1); + } catch (InvocationTargetException ex) { + // 8210583 - decode no longer throws NASE + // 8217969 - decode no longer throws OOME + fail("Decode threw an unexpected exception with " + + "Integer.MAX_VALUE sized input: " + ex.getCause()); + } } -} + // Utility to get the private visibility method + private static Method getMethod(Object obj, String methodName, Class... params) + throws NoSuchMethodException { + Method m = obj.getClass().getDeclaredMethod(methodName, params); + m.setAccessible(true); + return m; + } +} From 36c9607f66f91a0c46342543b30b57ac1cf106ec Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 3 May 2024 19:06:13 +0000 Subject: [PATCH 086/203] 8331591: sun.font.CharSequenceCodePointIterator is buggy and unused Reviewed-by: angorya, honkar --- .../classes/sun/font/CodePointIterator.java | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/src/java.desktop/share/classes/sun/font/CodePointIterator.java b/src/java.desktop/share/classes/sun/font/CodePointIterator.java index 179e049db6045..31c4bc5c1d423 100644 --- a/src/java.desktop/share/classes/sun/font/CodePointIterator.java +++ b/src/java.desktop/share/classes/sun/font/CodePointIterator.java @@ -56,10 +56,6 @@ public static CodePointIterator create(char[] text, int start, int limit) { return new CharArrayCodePointIterator(text, start, limit); } - public static CodePointIterator create(CharSequence text) { - return new CharSequenceCodePointIterator(text); - } - public static CodePointIterator create(CharacterIterator iter) { return new CharacterIteratorCodePointIterator(iter); } @@ -129,57 +125,6 @@ public int charIndex() { } } -final class CharSequenceCodePointIterator extends CodePointIterator { - private CharSequence text; - private int index; - - public CharSequenceCodePointIterator(CharSequence text) { - this.text = text; - } - - public void setToStart() { - index = 0; - } - - public void setToLimit() { - index = text.length(); - } - - public int next() { - if (index < text.length()) { - char cp1 = text.charAt(index++); - if (Character.isHighSurrogate(cp1) && index < text.length()) { - char cp2 = text.charAt(index+1); - if (Character.isLowSurrogate(cp2)) { - ++index; - return Character.toCodePoint(cp1, cp2); - } - } - return cp1; - } - return DONE; - } - - public int prev() { - if (index > 0) { - char cp2 = text.charAt(--index); - if (Character.isLowSurrogate(cp2) && index > 0) { - char cp1 = text.charAt(index - 1); - if (Character.isHighSurrogate(cp1)) { - --index; - return Character.toCodePoint(cp1, cp2); - } - } - return cp2; - } - return DONE; - } - - public int charIndex() { - return index; - } -} - // note this has different iteration semantics than CharacterIterator final class CharacterIteratorCodePointIterator extends CodePointIterator { private CharacterIterator iter; From c1a164528a538d5de78f99c4c92291b1906703f5 Mon Sep 17 00:00:00 2001 From: Adam Sotona Date: Fri, 3 May 2024 19:15:12 +0000 Subject: [PATCH 087/203] 8331655: ClassFile API ClassCastException with verbose output of certain class files Reviewed-by: psandoz --- .../classfile/impl/ClassReaderImpl.java | 17 +++-------------- test/jdk/jdk/classfile/LimitsTest.java | 11 ++++++++++- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java index 2022f8f01547d..4878ad56ae8b8 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java @@ -391,21 +391,10 @@ private PoolEntry entryByIndex(int index, int lowerBoundTag, int upperBoundTag) @Override public AbstractPoolEntry.Utf8EntryImpl utf8EntryByIndex(int index) { - if (index <= 0 || index >= constantPoolCount) { - throw new ConstantPoolException("Bad CP UTF8 index: " + index); - } - PoolEntry info = cp[index]; - if (info == null) { - int offset = cpOffset[index]; - int tag = readU1(offset); - final int q = offset + 1; - if (tag != TAG_UTF8) throw new ConstantPoolException("Not a UTF8 - index: " + index); - AbstractPoolEntry.Utf8EntryImpl uinfo - = new AbstractPoolEntry.Utf8EntryImpl(this, index, buffer, q + 2, readU2(q)); - cp[index] = uinfo; - return uinfo; + if (entryByIndex(index, TAG_UTF8, TAG_UTF8) instanceof AbstractPoolEntry.Utf8EntryImpl utf8) { + return utf8; } - return (AbstractPoolEntry.Utf8EntryImpl) info; + throw new ConstantPoolException("Not a UTF8 - index: " + index); } @Override diff --git a/test/jdk/jdk/classfile/LimitsTest.java b/test/jdk/jdk/classfile/LimitsTest.java index 5b39c0d498521..8a8d8bddc3580 100644 --- a/test/jdk/jdk/classfile/LimitsTest.java +++ b/test/jdk/jdk/classfile/LimitsTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8320360 8330684 8331320 + * @bug 8320360 8330684 8331320 8331655 * @summary Testing ClassFile limits. * @run junit LimitsTest */ @@ -36,6 +36,7 @@ import java.lang.classfile.Opcode; import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.constantpool.ConstantPoolException; +import java.lang.classfile.constantpool.IntegerEntry; import jdk.internal.classfile.impl.DirectMethodBuilder; import jdk.internal.classfile.impl.LabelContext; import jdk.internal.classfile.impl.UnboundAttribute; @@ -106,6 +107,14 @@ void testInvalidClassEntry() { 0, 0, 0, 0, 0, 2, ClassFile.TAG_METHODREF, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}).thisClass()); } + @Test + void testInvalidUtf8Entry() { + var cp = ClassFile.of().parse(new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE, + 0, 0, 0, 0, 0, 3, ClassFile.TAG_INTEGER, 0, 0, 0, 0, ClassFile.TAG_NAMEANDTYPE, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}).constantPool(); + assertTrue(cp.entryByIndex(1) instanceof IntegerEntry); //parse valid int entry first + assertThrows(ConstantPoolException.class, () -> cp.entryByIndex(2)); + } + @Test void testInvalidLookupSwitch() { assertThrows(IllegalArgumentException.class, () -> From b20fa7b48b0f0a64c0760f26188d4c11c3233b61 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Fri, 3 May 2024 19:51:37 +0000 Subject: [PATCH 088/203] 8329982: compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java failed assert(oopDesc::is_oop_or_null(val)) failed: bad oop found Reviewed-by: never --- .../share/gc/shared/barrierSetNMethod.cpp | 8 +- .../share/jvmci/jvmciCodeInstaller.cpp | 19 +- src/hotspot/share/jvmci/jvmciRuntime.cpp | 1 + src/hotspot/share/jvmci/jvmciRuntime.hpp | 11 +- .../InvalidateInstalledCodeTest.java | 108 ----------- .../events/JvmciNotifyInstallEventTest.config | 2 - .../events/JvmciNotifyInstallEventTest.java | 179 ------------------ .../vm/ci/code/test/CodeInstallationTest.java | 7 +- .../code/test/RuntimeStubAllocFailTest.java | 86 +++++++++ .../code/test/SimpleCodeInstallationTest.java | 23 ++- .../jdk/vm/ci/code/test/TestAssembler.java | 77 ++++++++ .../vm/ci/code/test/TestHotSpotVMConfig.java | 28 +++ .../test/aarch64/AArch64TestAssembler.java | 107 ++++++++++- .../code/test/amd64/AMD64TestAssembler.java | 93 ++++++++- 14 files changed, 422 insertions(+), 327 deletions(-) delete mode 100644 test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java delete mode 100644 test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.config delete mode 100644 test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java create mode 100644 test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp index adf0527681b5e..548e6b671eff0 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp @@ -65,16 +65,10 @@ bool BarrierSetNMethod::supports_entry_barrier(nmethod* nm) { return false; } - if (nm->is_native_method() || nm->is_compiled_by_c2() || nm->is_compiled_by_c1()) { + if (nm->is_native_method() || nm->is_compiled_by_c2() || nm->is_compiled_by_c1() || nm->is_compiled_by_jvmci()) { return true; } -#if INCLUDE_JVMCI - if (nm->is_compiled_by_jvmci() && nm->jvmci_nmethod_data()->has_entry_barrier()) { - return true; - } -#endif - return false; } diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 7dd2840656dc7..52a060427d5d4 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -771,11 +771,8 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, JVMCI_THROW_MSG_(IllegalArgumentException, "InstalledCode object must be a HotSpotNmethod when installing a HotSpotCompiledNmethod", JVMCI::ok); } - // We would like to be strict about the nmethod entry barrier but there are various test - // configurations which generate assembly without being a full compiler. So for now we enforce - // that JIT compiled methods must have an nmethod barrier. - bool install_default = JVMCIENV->get_HotSpotNmethod_isDefault(installed_code) != 0; - if (_nmethod_entry_patch_offset == -1 && install_default) { + // Enforce that compiled methods have an nmethod barrier. + if (_nmethod_entry_patch_offset == -1) { JVMCI_THROW_MSG_(IllegalArgumentException, "nmethod entry barrier is missing", JVMCI::ok); } @@ -816,14 +813,12 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, DirectivesStack::release(directive); } - if (_nmethod_entry_patch_offset != -1) { - BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); - // an empty error buffer for use by the verify_barrier code - err_msg msg(""); - if (!bs_nm->verify_barrier(nm, msg)) { - JVMCI_THROW_MSG_(IllegalArgumentException, err_msg("nmethod entry barrier is malformed: %s", msg.buffer()), JVMCI::ok); - } + // an empty error buffer for use by the verify_barrier code + err_msg msg(""); + if (!bs_nm->verify_barrier(nm, msg)) { + JVMCI_THROW_MSG_(IllegalArgumentException, err_msg("nmethod entry barrier is malformed: %s", msg.buffer()), JVMCI::ok); } } } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 2e588373cdf1d..3a8a040db4616 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -787,6 +787,7 @@ void JVMCINMethodData::initialize(int nmethod_mirror_index, { _failed_speculations = failed_speculations; _nmethod_mirror_index = nmethod_mirror_index; + guarantee(nmethod_entry_patch_offset != -1, "missing entry barrier"); _nmethod_entry_patch_offset = nmethod_entry_patch_offset; if (nmethod_mirror_name != nullptr) { _has_name = true; diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index c12c18abd7836..6a920eb8c7018 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -54,10 +54,8 @@ class JVMCINMethodData : public ResourceObj { // This is -1 if there is no mirror in the oops table. int _nmethod_mirror_index; - // This is the offset of the patchable part of the nmethod entry barrier sequence. The meaning is - // somewhat platform dependent as the way patching is done varies by architecture. Older JVMCI - // based compilers didn't emit the entry barrier so having a positive value for this offset - // confirms that the installed code supports the entry barrier. + // This is the offset of the patchable part of the nmethod entry barrier sequence. The meaning is + // somewhat platform dependent as the way patching is done varies by architecture. int _nmethod_entry_patch_offset; // Address of the failed speculations list to which a speculation @@ -129,12 +127,7 @@ class JVMCINMethodData : public ResourceObj { // Sets the mirror in nm's oops table. void set_nmethod_mirror(nmethod* nm, oop mirror); - bool has_entry_barrier() { - return _nmethod_entry_patch_offset != -1; - } - int nmethod_entry_patch_offset() { - guarantee(_nmethod_entry_patch_offset != -1, "missing entry barrier"); return _nmethod_entry_patch_offset; } }; diff --git a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java deleted file mode 100644 index 9307ab8250a35..0000000000000 --- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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 - * 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 8136421 - * @requires vm.jvmci - * @library /test/lib / - * @library ../common/patches - * @modules java.base/jdk.internal.misc - * @modules java.base/jdk.internal.org.objectweb.asm - * java.base/jdk.internal.org.objectweb.asm.tree - * jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.code - * jdk.internal.vm.ci/jdk.vm.ci.code.site - * jdk.internal.vm.ci/jdk.vm.ci.meta - * jdk.internal.vm.ci/jdk.vm.ci.runtime - * - * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper - * jdk.test.whitebox.WhiteBox jdk.test.whitebox.parser.DiagnosticCommand - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * jdk.test.whitebox.parser.DiagnosticCommand - * @run junit/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI - * compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest - */ - -package compiler.jvmci.compilerToVM; - -import compiler.jvmci.common.CodeInstallerTest; -import compiler.jvmci.common.CTVMUtilities; -import jdk.test.lib.Asserts; -import jdk.test.lib.Utils; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.site.Site; -import jdk.vm.ci.code.site.DataPatch; -import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment; -import jdk.vm.ci.hotspot.HotSpotNmethod; -import jdk.vm.ci.meta.Assumptions.Assumption; - -import java.util.List; -import org.junit.Test; - -public class InvalidateInstalledCodeTest extends CodeInstallerTest { - - @Test - public void testInvalidation() { - List testCases - = CompileCodeTestCase.generate(/* bci = */ 0); - testCases.addAll(CompileCodeTestCase.generate(/* bci = */ -1)); - testCases.forEach(t -> check(t)); - checkNull(); - } - - private void checkNull() { - Utils.runAndCheckException( - () -> CompilerToVMHelper.invalidateHotSpotNmethod(null, true), - NullPointerException.class); - } - - private void check(CompileCodeTestCase testCase) { - HotSpotResolvedJavaMethod javaMethod = CTVMUtilities.getResolvedMethod(testCase.executable); - HotSpotNmethod nmethod = (HotSpotNmethod) installEmptyCode(new Site[0], new Assumption[0], - new Comment[0], 8, new DataPatch[0], null); - - Asserts.assertTrue(nmethod.isValid(), testCase + " : code is invalid even before invalidation"); - - Asserts.assertTrue(nmethod.isValid(), testCase + " : code is not valid, i = " + nmethod); - Asserts.assertTrue(nmethod.isAlive(), testCase + " : code is not alive, i = " + nmethod); - Asserts.assertNotEquals(nmethod.getStart(), 0L); - - // Make nmethod non-entrant but still alive - CompilerToVMHelper.invalidateHotSpotNmethod(nmethod, false); - Asserts.assertFalse(nmethod.isValid(), testCase + " : code is valid, i = " + nmethod); - Asserts.assertTrue(nmethod.isAlive(), testCase + " : code is not alive, i = " + nmethod); - Asserts.assertEquals(nmethod.getStart(), 0L); - - // Deoptimize the nmethod and cut the link to it from the HotSpotNmethod - CompilerToVMHelper.invalidateHotSpotNmethod(nmethod, true); - Asserts.assertFalse(nmethod.isValid(), testCase + " : code is valid, i = " + nmethod); - Asserts.assertFalse(nmethod.isAlive(), testCase + " : code is alive, i = " + nmethod); - Asserts.assertEquals(nmethod.getStart(), 0L); - } -} diff --git a/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.config b/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.config deleted file mode 100644 index 9e2866167c1f7..0000000000000 --- a/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.config +++ /dev/null @@ -1,2 +0,0 @@ -compiler.jvmci.events.JvmciNotifyInstallEventTest -compiler.jvmci.common.JVMCIHelpers diff --git a/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java b/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java deleted file mode 100644 index c5d1b99235a07..0000000000000 --- a/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2015, 2019, 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 8136421 - * @requires vm.jvmci & !vm.graal.enabled & vm.compMode == "Xmixed" - * @library / /test/lib - * @library ../common/patches - * @modules java.base/jdk.internal.misc - * @modules java.base/jdk.internal.org.objectweb.asm - * java.base/jdk.internal.org.objectweb.asm.tree - * jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.code - * jdk.internal.vm.ci/jdk.vm.ci.code.site - * jdk.internal.vm.ci/jdk.vm.ci.meta - * jdk.internal.vm.ci/jdk.vm.ci.runtime - * jdk.internal.vm.ci/jdk.vm.ci.services - * - * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper - * @build compiler.jvmci.common.JVMCIHelpers - * @run driver jdk.test.lib.FileInstaller ./JvmciNotifyInstallEventTest.config - * ./META-INF/services/jdk.vm.ci.services.JVMCIServiceLocator - * @run driver jdk.test.lib.helpers.ClassFileInstaller - * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler - * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory - * compiler.jvmci.common.JVMCIHelpers$EmptyCompilationRequestResult - * compiler.jvmci.common.JVMCIHelpers$EmptyVMEventListener - * @run main/othervm -XX:+UnlockExperimentalVMOptions - * -Djvmci.Compiler=EmptyCompiler -Xbootclasspath/a:. - * -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI - * -XX:-UseJVMCINativeLibrary -XX:JVMCITraceLevel=1 - * -Dtest.jvmci.forceRuntimeStubAllocFail=test_stub_that_fails_to_be_allocated - * compiler.jvmci.events.JvmciNotifyInstallEventTest - * @run main/othervm -XX:+UnlockExperimentalVMOptions - * -Djvmci.Compiler=EmptyCompiler -Xbootclasspath/a:. - * -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI -XX:JVMCINMethodSizeLimit=0 - * -XX:-UseJVMCINativeLibrary - * compiler.jvmci.events.JvmciNotifyInstallEventTest - */ - -package compiler.jvmci.events; - -import compiler.jvmci.common.CTVMUtilities; -import compiler.jvmci.common.testcases.SimpleClass; -import jdk.test.lib.Asserts; -import jdk.test.lib.Platform; -import jdk.test.lib.Utils; -import jdk.vm.ci.services.JVMCIServiceLocator; -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.code.CompiledCode; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.site.DataPatch; -import jdk.vm.ci.code.site.Site; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import jdk.vm.ci.hotspot.HotSpotCompiledCode; -import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment; -import jdk.vm.ci.hotspot.HotSpotCompiledNmethod; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotVMEventListener; -import jdk.vm.ci.meta.Assumptions.Assumption; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import java.lang.reflect.Method; - -public class JvmciNotifyInstallEventTest extends JVMCIServiceLocator implements HotSpotVMEventListener { - private static final String METHOD_NAME = "testMethod"; - private static volatile int gotInstallNotification = 0; - - public static void main(String args[]) { - new JvmciNotifyInstallEventTest().runTest(); - } - - @Override - public S getProvider(Class service) { - if (service == HotSpotVMEventListener.class) { - return service.cast(this); - } - return null; - } - - private void runTest() { - if (gotInstallNotification != 0) { - throw new Error("Got install notification before test actions"); - } - HotSpotCodeCacheProvider codeCache; - try { - codeCache = (HotSpotCodeCacheProvider) HotSpotJVMCIRuntime.runtime() - .getHostJVMCIBackend().getCodeCache(); - } catch (InternalError ie) { - // passed - return; - } - Method testMethod; - try { - testMethod = SimpleClass.class.getDeclaredMethod(METHOD_NAME); - } catch (NoSuchMethodException e) { - throw new Error("TEST BUG: Can't find " + METHOD_NAME, e); - } - HotSpotResolvedJavaMethod method = CTVMUtilities - .getResolvedMethod(SimpleClass.class, testMethod); - int dataSectionAlignment = 8; // CodeBuffer::SECT_CONSTS code section alignment - HotSpotCompiledCode compiledCode = new HotSpotCompiledNmethod(METHOD_NAME, - new byte[0], 0, new Site[0], new Assumption[0], - new ResolvedJavaMethod[]{method}, new Comment[0], new byte[0], - dataSectionAlignment, new DataPatch[0], false, 0, null, - method, 0, 1, 0L, false); - codeCache.installCode(method, compiledCode, /* installedCode = */ null, - /* speculationLog = */ null, /* isDefault = */ false); - Asserts.assertEQ(gotInstallNotification, 1, - "Got unexpected event count after 1st install attempt"); - // since "empty" compilation result is ok, a second attempt should be ok - codeCache.installCode(method, compiledCode, /* installedCode = */ null, - /* speculationLog = */ null, /* isDefault = */ false); - Asserts.assertEQ(gotInstallNotification, 2, - "Got unexpected event count after 2nd install attempt"); - // and an incorrect cases - Utils.runAndCheckException(() -> { - codeCache.installCode(method, null, null, null, true); - }, NullPointerException.class); - Asserts.assertEQ(gotInstallNotification, 2, - "Got unexpected event count after 3rd install attempt"); - Utils.runAndCheckException(() -> { - codeCache.installCode(null, null, null, null, true); - }, NullPointerException.class); - Asserts.assertEQ(gotInstallNotification, 2, - "Got unexpected event count after 4th install attempt"); - - String stubToFail = System.getProperty("test.jvmci.forceRuntimeStubAllocFail"); - if (Platform.isDebugBuild() && stubToFail != null) { - HotSpotCompiledCode stub = new HotSpotCompiledCode(stubToFail, - /* targetCode */ new byte[0], - /* targetCodeSize */ 0, - /* sites */ new Site[0], - /* assumptions */ new Assumption[0], - /* methods */ new ResolvedJavaMethod[0], - /* comments */ new Comment[0], - /* dataSection */ new byte[0], - dataSectionAlignment, - /* dataSectionPatches */ new DataPatch[0], - /* isImmutablePIC */ false, - /* totalFrameSize */ 0, - /* deoptRescueSlot */ null); - try { - codeCache.installCode(null, stub, null, null, true); - throw new AssertionError("Didn't get expected " + BailoutException.class.getName()); - } catch (BailoutException e) { - Asserts.assertEQ(e.getMessage(), "Error installing " + stubToFail + ": code cache is full"); - } - } - } - - @Override - public void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, - InstalledCode installedCode, CompiledCode compiledCode) { - gotInstallNotification++; - } -} diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java index 7483c45a654f0..97583b45458d8 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java @@ -35,6 +35,7 @@ import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotNmethod; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -95,7 +96,7 @@ protected Method getMethod(String name, Class... args) { } } - protected void test(TestCompiler compiler, Method method, Object... args) { + protected HotSpotNmethod test(TestCompiler compiler, Method method, Object... args) { try { HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method); TestAssembler asm = createAssembler(); @@ -115,9 +116,9 @@ protected void test(TestCompiler compiler, Method method, Object... args) { Object expected = method.invoke(null, args); Object actual = installed.executeVarargs(args); Assert.assertEquals(expected, actual); + return (HotSpotNmethod) installed; } catch (Exception e) { - e.printStackTrace(); - Assert.fail(e.toString()); + throw new AssertionError(e); } } } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java new file mode 100644 index 0000000000000..dea523af1668e --- /dev/null +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/RuntimeStubAllocFailTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 + * @requires vm.jvmci & !vm.graal.enabled & vm.compMode == "Xmixed" + * @library / /test/lib + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.code + * jdk.internal.vm.ci/jdk.vm.ci.code.site + * jdk.internal.vm.ci/jdk.vm.ci.meta + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * + * @run main/othervm -XX:+UnlockExperimentalVMOptions + * -Xbootclasspath/a:. + * -XX:+EnableJVMCI -XX:JVMCITraceLevel=1 + * -Dtest.jvmci.forceRuntimeStubAllocFail=test_stub_that_fails_to_be_allocated + * jdk.vm.ci.code.test.RuntimeStubAllocFailTest + */ + +package jdk.vm.ci.code.test; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.code.site.DataPatch; +import jdk.vm.ci.code.site.Site; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotCompiledCode; +import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment; +import jdk.vm.ci.meta.Assumptions.Assumption; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.runtime.JVMCI; +import jdk.vm.ci.runtime.JVMCIRuntime; +import jdk.vm.ci.runtime.JVMCIBackend; + +public class RuntimeStubAllocFailTest { + + public static void main(String args[]) { + JVMCIBackend backend = JVMCI.getRuntime().getHostJVMCIBackend(); + HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) backend.getCodeCache(); + int dataSectionAlignment = 8; // CodeBuffer::SECT_CONSTS code section alignment + String stubToFail = System.getProperty("test.jvmci.forceRuntimeStubAllocFail"); + if (Platform.isDebugBuild() && stubToFail != null) { + HotSpotCompiledCode stub = new HotSpotCompiledCode(stubToFail, + /* targetCode */ new byte[0], + /* targetCodeSize */ 0, + /* sites */ new Site[0], + /* assumptions */ new Assumption[0], + /* methods */ new ResolvedJavaMethod[0], + /* comments */ new Comment[0], + /* dataSection */ new byte[0], + dataSectionAlignment, + /* dataSectionPatches */ new DataPatch[0], + /* isImmutablePIC */ false, + /* totalFrameSize */ 0, + /* deoptRescueSlot */ null); + try { + codeCache.installCode(null, stub, null, null, true); + throw new AssertionError("Didn't get expected " + BailoutException.class.getName()); + } catch (BailoutException e) { + Asserts.assertEQ(e.getMessage(), "Error installing " + stubToFail + ": code cache is full"); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java index 80c63392b6e39..82058ec02cf30 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java @@ -25,7 +25,7 @@ * @test * @requires vm.jvmci * @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" - * @library / + * @library /test/lib / * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot * jdk.internal.vm.ci/jdk.vm.ci.meta * jdk.internal.vm.ci/jdk.vm.ci.code @@ -39,8 +39,10 @@ */ package jdk.vm.ci.code.test; +import jdk.test.lib.Asserts; import jdk.vm.ci.code.Register; +import jdk.vm.ci.hotspot.HotSpotNmethod; import org.junit.Test; /** @@ -61,6 +63,23 @@ private static void compileAdd(TestAssembler asm) { @Test public void test() { - test(SimpleCodeInstallationTest::compileAdd, getMethod("add", int.class, int.class), 5, 7); + HotSpotNmethod nmethod = test(SimpleCodeInstallationTest::compileAdd, getMethod("add", int.class, int.class), 5, 7); + + // Test code invalidation + Asserts.assertTrue(nmethod.isValid(), "code is not valid, i = " + nmethod); + Asserts.assertTrue(nmethod.isAlive(), "code is not alive, i = " + nmethod); + Asserts.assertNotEquals(nmethod.getStart(), 0L); + + // Make nmethod non-entrant but still alive + nmethod.invalidate(false); + Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod); + Asserts.assertTrue(nmethod.isAlive(), "code is not alive, i = " + nmethod); + Asserts.assertEquals(nmethod.getStart(), 0L); + + // Deoptimize the nmethod and cut the link to it from the HotSpotNmethod + nmethod.invalidate(true); + Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod); + Asserts.assertFalse(nmethod.isAlive(), "code is alive, i = " + nmethod); + Asserts.assertEquals(nmethod.getStart(), 0L); } } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestAssembler.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestAssembler.java index f1afef3bae2d0..6a4f6addd0d07 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestAssembler.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestAssembler.java @@ -243,6 +243,27 @@ protected TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config, this.curStackSlot = initialFrameSize; } + public class Bookmark implements AutoCloseable { + private final int registerMark = nextRegister; + private final int codePos = code.position(); + private final int dataPos = data.position(); + + @Override + public void close() { + nextRegister = registerMark; + code.data.position(codePos); + data.data.position(dataPos); + } + } + + /** + * Enters a scope in which the current register, code and data emitting state + * is restored upon leaving the scope. + */ + public Bookmark bookmark() { + return new Bookmark(); + } + public ValueKind getValueKind(JavaKind kind) { return new TestValueKind(codeCache.getTarget().arch.getPlatformKind(kind)); } @@ -296,6 +317,18 @@ protected void recordDataPatchInData(Reference ref) { dataPatches.add(new DataPatch(data.position(), ref)); } + /** + * Emits the 32 bit constant `c` into the data section. + */ + public DataSectionReference emitDataItem(int c) { + DataSectionReference ref = new DataSectionReference(); + ref.setOffset(data.position()); + + recordDataPatchInCode(ref); + data.emitInt(c); + return ref; + } + public DataSectionReference emitDataItem(HotSpotConstant c) { DataSectionReference ref = new DataSectionReference(); ref.setOffset(data.position()); @@ -321,6 +354,50 @@ public HotSpotCompiledCode finish(HotSpotResolvedJavaMethod method) { finishedDataPatches, false, frameSize, deoptRescue, method, -1, id, 0L, false); } + /** + * @param n Number of bits that should be set to 1. Must be between 0 and 32 (inclusive). + * @return A number with n bits set to 1. + */ + public static int getNbitNumberInt(int n) { + assert n >= 0 && n <= 32 : "0 <= n <= 32; instead: " + n; + if (n < 32) { + return (1 << n) - 1; + } else { + return 0xFFFFFFFF; + } + } + + public static boolean isSignedNbit(int n, int value) { + assert n > 0 && n < 32 : n; + int min = -(1 << (n - 1)); + int max = (1 << (n - 1)) - 1; + return value >= min && value <= max; + } + + public static boolean isUnsignedNbit(int n, int value) { + assert n > 0 && n < 32 : n; + return 32 - Integer.numberOfLeadingZeros(value) <= n; + } + + /** + * Determines if `x` is in the range of signed byte values. + */ + public static boolean isByte(int x) { + return (byte) x == x; + } + + /** + * Determines if `l` is in the range of signed int values. + */ + public static boolean isInt(long l) { + return (int) l == l; + } + + public static void check(boolean condition, String errorMessage, Object... args) { + if (!condition) { + throw new AssertionError(errorMessage.formatted(args)); + } + } protected static class Buffer { private ByteBuffer data = ByteBuffer.allocate(32).order(ByteOrder.nativeOrder()); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java index 9468027bc85b0..12664bd433f3d 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java @@ -32,6 +32,7 @@ public class TestHotSpotVMConfig extends HotSpotVMConfigAccess { public TestHotSpotVMConfig(HotSpotVMConfigStore config, Architecture arch) { super(config); ropProtection = (arch instanceof AArch64) ? getFieldValue("VM_Version::_rop_protection", Boolean.class) : false; + nmethodEntryBarrierConcurrentPatch = initNmethodEntryBarrierConcurrentPatch(arch); } public final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); @@ -47,10 +48,37 @@ public TestHotSpotVMConfig(HotSpotVMConfigStore config, Architecture arch) { // Checkstyle: stop public final int MARKID_DEOPT_HANDLER_ENTRY = getConstant("CodeInstaller::DEOPT_HANDLER_ENTRY", Integer.class); + public final int MARKID_FRAME_COMPLETE = getConstant("CodeInstaller::FRAME_COMPLETE", Integer.class); + public final int MARKID_ENTRY_BARRIER_PATCH = getConstant("CodeInstaller::ENTRY_BARRIER_PATCH", Integer.class); public final long handleDeoptStub = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", Long.class, "address"); public final int maxOopMapStackOffset = getFieldValue("CompilerToVM::Data::_max_oop_map_stack_offset", Integer.class, "int"); public final int heapWordSize = getConstant("HeapWordSize", Integer.class); public final boolean ropProtection; + + private Boolean initNmethodEntryBarrierConcurrentPatch(Architecture arch) { + Boolean patchConcurrent = null; + if (arch instanceof AArch64 && nmethodEntryBarrier != 0) { + Integer patchingType = getFieldValue("CompilerToVM::Data::BarrierSetAssembler_nmethod_patching_type", Integer.class, "int"); + if (patchingType != null) { + // There currently only 2 variants in use that differ only by the presence of a + // dmb instruction + int stw = getConstant("NMethodPatchingType::stw_instruction_and_data_patch", Integer.class); + int conc = getConstant("NMethodPatchingType::conc_data_patch", Integer.class); + if (patchingType == stw) { + patchConcurrent = false; + } else if (patchingType == conc) { + patchConcurrent = true; + } else { + throw new IllegalArgumentException("unsupported barrier sequence " + patchingType); + } + } + } + return patchConcurrent; + } + + public final int threadDisarmedOffset = getFieldValue("CompilerToVM::Data::thread_disarmed_guard_value_offset", Integer.class, "int"); + public final long nmethodEntryBarrier = getFieldValue("CompilerToVM::Data::nmethod_entry_barrier", Long.class, "address"); + public final Boolean nmethodEntryBarrierConcurrentPatch; } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/aarch64/AArch64TestAssembler.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/aarch64/AArch64TestAssembler.java index e87944f3ca9ec..8d6814c543548 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/aarch64/AArch64TestAssembler.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/aarch64/AArch64TestAssembler.java @@ -46,8 +46,69 @@ public class AArch64TestAssembler extends TestAssembler { private static final Register scratchRegister = AArch64.rscratch1; + private static final Register scratchRegister2 = AArch64.rscratch2; private static final Register doubleScratch = AArch64.v9; + /** + * Condition Flags for branches. See C1.2.4 + */ + public enum ConditionFlag { + // Integer | Floating-point meanings + /** Equal | Equal. */ + EQ(0x0), + + /** Not Equal | Not equal or unordered. */ + NE(0x1), + + /** Unsigned Higher or Same | Greater than, equal or unordered. */ + HS(0x2), + + /** Unsigned lower | less than. */ + LO(0x3), + + /** Minus (negative) | less than. */ + MI(0x4), + + /** Plus (positive or zero) | greater than, equal or unordered. */ + PL(0x5), + + /** Overflow set | unordered. */ + VS(0x6), + + /** Overflow clear | ordered. */ + VC(0x7), + + /** Unsigned higher | greater than or unordered. */ + HI(0x8), + + /** Unsigned lower or same | less than or equal. */ + LS(0x9), + + /** Signed greater than or equal | greater than or equal. */ + GE(0xA), + + /** Signed less than | less than or unordered. */ + LT(0xB), + + /** Signed greater than | greater than. */ + GT(0xC), + + /** Signed less than or equal | less than, equal or unordered. */ + LE(0xD), + + /** Always | always. */ + AL(0xE), + + /** Always | always (identical to AL, just to have valid 0b1111 encoding). */ + NV(0xF); + + public final int encoding; + + ConditionFlag(int encoding) { + this.encoding = encoding; + } + } + public AArch64TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) { super(codeCache, config, 16 /* initialFrameSize */, 16 /* stackAlignment */, @@ -215,6 +276,22 @@ private void emitBlr(Register Rn) { | f(0, 4, 0)); } + /** + * C6.2.25 Branch conditionally. + * + * @param condition may not be null. + * @param imm21 Signed 21-bit offset, has to be 4-byte aligned. + */ + protected void emitBranch(ConditionFlag condition, int imm21) { + // B.cond + check(isSignedNbit(21, imm21) && (imm21 & 0b11) == 0, + "0x%x must be a 21-bit signed number and 4-byte aligned", imm21); + int imm19 = (imm21 & getNbitNumberInt(21)) >> 2; + code.emitInt(f(0b001010100, 31, 24) + | f(imm19, 23, 4) + | f(condition.encoding, 3, 0)); + } + private void emitFmov(Register Rd, AArch64Kind kind, Register Rn) { // FMOV (general) int ftype = 0, sf = 0; @@ -261,9 +338,25 @@ public void emitPrologue() { code.emitInt(0xa9bf7bfd); // stp x29, x30, [sp, #-16]! code.emitInt(0x910003fd); // mov x29, sp + emitNMethodEntryBarrier(); + setDeoptRescueSlot(newStackSlot(AArch64Kind.QWORD)); } + private void emitNMethodEntryBarrier() { + recordMark(config.MARKID_ENTRY_BARRIER_PATCH); + DataSectionReference ref = emitDataItem(0); + emitLoadPointer(scratchRegister, AArch64Kind.DWORD, ref); + if (config.nmethodEntryBarrierConcurrentPatch) { + code.emitInt(0xd50339bf); // dmb ishld + } + Register thread = AArch64.r28; + emitLoadPointer(scratchRegister2, AArch64Kind.DWORD, thread, config.threadDisarmedOffset); + code.emitInt(0x6b09011f); // cmp w8, w9 + emitBranch(ConditionFlag.EQ, 8); // jump over slow path, runtime call + emitCall(config.nmethodEntryBarrier); + } + @Override public void emitEpilogue() { recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); @@ -361,8 +454,11 @@ public Register emitLoadPointer(HotSpotConstant c) { @Override public Register emitLoadPointer(Register b, int offset) { - Register ret = newRegister(); - emitLoadRegister(ret, AArch64Kind.QWORD, b, offset); + return emitLoadPointer(newRegister(), AArch64Kind.QWORD, b, offset); + } + + public Register emitLoadPointer(Register ret, AArch64Kind kind, Register b, int offset) { + emitLoadRegister(ret, kind, b, offset); return ret; } @@ -377,10 +473,13 @@ public Register emitLoadNarrowPointer(DataSectionReference ref) { @Override public Register emitLoadPointer(DataSectionReference ref) { + return emitLoadPointer(newRegister(), AArch64Kind.QWORD, ref); + } + + public Register emitLoadPointer(Register ret, AArch64Kind kind, DataSectionReference ref) { recordDataPatchInCode(ref); - Register ret = newRegister(); - emitLoadRegister(ret, AArch64Kind.QWORD, 0xdead); + emitLoadRegister(ret, kind, 0xdead); return ret; } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java index a0fcdd2b0a988..32b0e66df33d7 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java @@ -49,6 +49,40 @@ public class AMD64TestAssembler extends TestAssembler { private static final Register scratchRegister = AMD64.r12; private static final Register doubleScratch = AMD64.xmm15; + /** + * The x86 condition codes used for conditional jumps/moves. + */ + public enum ConditionFlag { + Zero(0x4, "|zero|"), + NotZero(0x5, "|nzero|"), + Equal(0x4, "="), + NotEqual(0x5, "!="), + Less(0xc, "<"), + LessEqual(0xe, "<="), + Greater(0xf, ">"), + GreaterEqual(0xd, ">="), + Below(0x2, "|<|"), + BelowEqual(0x6, "|<=|"), + Above(0x7, "|>|"), + AboveEqual(0x3, "|>=|"), + Overflow(0x0, "|of|"), + NoOverflow(0x1, "|nof|"), + CarrySet(0x2, "|carry|"), + CarryClear(0x3, "|ncarry|"), + Negative(0x8, "|neg|"), + Positive(0x9, "|pos|"), + Parity(0xa, "|par|"), + NoParity(0xb, "|npar|"); + + public final int value; + public final String operator; + + ConditionFlag(int value, String operator) { + this.value = value; + this.operator = operator; + } + } + public AMD64TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) { super(codeCache, config, 16, 16, AMD64Kind.DWORD, AMD64.rax, AMD64.rcx, AMD64.rdi, AMD64.r8, AMD64.r9, AMD64.r10); } @@ -63,6 +97,62 @@ private void emitFatNop() { code.emitByte(0x00); } + /** + * Emit the expected patchable code sequence for the nmethod entry barrier. The int sized + * payload must be naturally aligned so it can be patched atomically. + */ + private void emitNMethodEntryCompare(int displacement) { + // cmp dword ptr [r15 + ], 0x00000000 + // 41 81 7f 00 00 00 00 + code.emitByte(0x41); + code.emitByte(0x81); + code.emitByte(0x7f); + check(isByte(displacement), "expected byte sized displacement: 0x%x", displacement); + code.emitByte(displacement & 0xff); + check(code.position() % 4 == 0, "must be aligned"); + code.emitInt(0); + } + + /** + * Emits a long (i.e. 6 byte) format conditional branch. + * + * @param offset the offset of the branch target wrt the start of the branch instruction + */ + private void emitBranch(ConditionFlag condition, int offset) { + final int longSize = 6; + int disp32 = offset - longSize; + + // 0000 1111 1000 tttn #32-bit disp + check(isInt(disp32), "must be 32bit disp: %d", disp32); + code.emitByte(0x0F); + code.emitByte(0x80 | condition.value); + code.emitInt(disp32); + } + + public void emitAlign(int modulus) { + while (code.position() % modulus != 0) { + code.emitByte(0x90); + } + } + + private void emitNMethodEntryBarrier() { + // The following code sequence must be emitted in exactly this fashion as HotSpot + // will check that the barrier is the expected code sequence. + emitAlign(4); + recordMark(config.MARKID_FRAME_COMPLETE); + recordMark(config.MARKID_ENTRY_BARRIER_PATCH); + emitNMethodEntryCompare(config.threadDisarmedOffset); + int branchOffset; + try (Bookmark bm = bookmark()) { + int pos = code.position(); + emitBranch(ConditionFlag.Equal, 0); + emitCall(config.nmethodEntryBarrier); + branchOffset = code.position() - pos; + } + emitBranch(ConditionFlag.Equal, branchOffset); + emitCall(config.nmethodEntryBarrier); + } + @Override public void emitPrologue() { // WARNING: Initial instruction MUST be 5 bytes or longer so that @@ -71,6 +161,7 @@ public void emitPrologue() { emitFatNop(); code.emitByte(0x50 | AMD64.rbp.encoding); // PUSH rbp emitMove(true, AMD64.rbp, AMD64.rsp); // MOV rbp, rsp + emitNMethodEntryBarrier(); setDeoptRescueSlot(newStackSlot(AMD64Kind.QWORD)); } @@ -414,7 +505,7 @@ public void emitCallPrologue(CallingConvention cc, Object... prim) { @Override public void emitCall(long addr) { - Register target = emitLoadLong(addr); + Register target = emitLoadLong(AMD64.rax, addr); code.emitByte(0xFF); // CALL r/m64 int enc = target.encoding; if (enc >= 8) { From 9347bb7df845ee465c378c6f511ef8a6caea18ea Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Fri, 3 May 2024 23:41:12 +0000 Subject: [PATCH 089/203] 8330247: C2: CTW fail with assert(adr_t->is_known_instance_field()) failed: instance required Reviewed-by: kvn --- src/hotspot/share/opto/macro.cpp | 3 + ...stReduceAllocationAndNonExactAllocate.java | 73 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndNonExactAllocate.java diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 1f6473616dcd1..38b82e6af93b7 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -573,6 +573,9 @@ bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode if (res_type == nullptr) { NOT_PRODUCT(fail_eliminate = "Neither instance or array allocation";) can_eliminate = false; + } else if (!res_type->klass_is_exact()) { + NOT_PRODUCT(fail_eliminate = "Not an exact type.";) + can_eliminate = false; } else if (res_type->isa_aryptr()) { int length = alloc->in(AllocateNode::ALength)->find_int_con(-1); if (length < 0) { diff --git a/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndNonExactAllocate.java b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndNonExactAllocate.java new file mode 100644 index 0000000000000..19b641036bd6b --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndNonExactAllocate.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8330247 + * @summary Check that Reduce Allocation Merges doesn't try to reduce non-exact allocations. + * @library /test/lib / + * @modules java.base/jdk.internal.misc + * @requires vm.debug & vm.flagless & vm.compiler2.enabled & vm.opt.final.EliminateAllocations + * @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationAndNonExactAllocate*::test + * -XX:CompileCommand=compileonly,*::allocateInstance + * -XX:CompileCommand=dontinline,*TestReduceAllocationAndNonExactAllocate*::* + * -XX:+UnlockDiagnosticVMOptions + * -XX:+TraceReduceAllocationMerges + * -XX:-TieredCompilation + * -Xbatch + * -Xcomp + * -server + * compiler.c2.TestReduceAllocationAndNonExactAllocate + */ + +package compiler.c2; + +import jdk.internal.misc.Unsafe; + +public class TestReduceAllocationAndNonExactAllocate { + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + public static void main(String[] args) { + try { + if (test(20, Integer.class) != 2032) { + throw new RuntimeException("Expected the value to be 2032."); + } + } + catch (InstantiationException e) { + e.printStackTrace(); + } + } + + public static int test(int val, Class c) throws InstantiationException { + Object p = null; + + if (val == 20) { + p = UNSAFE.allocateInstance(c); + } + + dummy(); + return p != null ? 2032 : 3242; + } + + static int dummy() { return 42; } +} From f2c4a41304d4fe984b79792cb3be460d7026e812 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 6 May 2024 05:49:28 +0000 Subject: [PATCH 090/203] 8328481: Implement JEP 476: Module Import Declarations (Preview) Co-authored-by: Jim Laskey Reviewed-by: mcimadamore, vromero --- .../jdk/internal/javac/PreviewFeature.java | 2 + .../com/sun/source/tree/ImportTree.java | 10 +- .../com/sun/tools/javac/code/Preview.java | 3 +- .../com/sun/tools/javac/code/Source.java | 1 + .../com/sun/tools/javac/comp/Check.java | 9 +- .../com/sun/tools/javac/comp/TreeDiffer.java | 9 +- .../com/sun/tools/javac/comp/TypeEnter.java | 75 +- .../sun/tools/javac/parser/JavacParser.java | 7 + .../tools/javac/resources/compiler.properties | 15 + .../com/sun/tools/javac/tree/JCTree.java | 60 +- .../com/sun/tools/javac/tree/Pretty.java | 19 +- .../com/sun/tools/javac/tree/TreeCopier.java | 11 +- .../com/sun/tools/javac/tree/TreeMaker.java | 11 +- .../jdk/internal/jshell/tool/JShellTool.java | 21 +- .../jdk/internal/jshell/tool/Startup.java | 39 +- .../share/classes/jdk/jshell/Eval.java | 25 +- .../share/classes/jdk/jshell/Snippet.java | 12 +- .../jshell/tool/resources/PREVIEW_DEFAULT.jsh | 1 + test/langtools/jdk/jshell/ImportTest.java | 22 +- test/langtools/jdk/jshell/KullaTesting.java | 3 +- .../langtools/jdk/jshell/StartOptionTest.java | 20 +- .../jdk/jshell/ToolProviderTest.java | 8 + test/langtools/tools/javac/ImportModule.java | 722 ++++++++++++++++++ .../javac/diags/examples/ImportModule.java | 31 + .../ImportModuleDoesNotRead/module-info.java | 28 + .../ImportModuleDoesNotRead/test/Test.java | 26 + .../ImportModuleDoesNotReadUnnamed.java | 32 + .../diags/examples/ImportModuleNotFound.java | 32 + test/langtools/tools/javac/tree/Imports.java | 137 ++++ .../tools/jdeps/listdeps/ListModuleDeps.java | 1 + test/langtools/tools/lib/toolbox/ToolBox.java | 29 +- 31 files changed, 1349 insertions(+), 72 deletions(-) create mode 100644 src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh create mode 100644 test/langtools/tools/javac/ImportModule.java create mode 100644 test/langtools/tools/javac/diags/examples/ImportModule.java create mode 100644 test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java create mode 100644 test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/test/Test.java create mode 100644 test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java create mode 100644 test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java create mode 100644 test/langtools/tools/javac/tree/Imports.java diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java index cfccff7dd9302..43dcf25c263bf 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -81,6 +81,8 @@ public enum Feature { CLASSFILE_API, @JEP(number=473, title="Stream Gatherers", status="Second Preview") STREAM_GATHERERS, + @JEP(number=476, title="Module Import Declarations", status="Preview") + MODULE_IMPORTS, LANGUAGE_MODEL, /** * A key for testing. diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java index de8e895e68daa..83a6c3eb87b66 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.source.tree; +import jdk.internal.javac.PreviewFeature; + /** * A tree node for an import declaration. * @@ -47,6 +49,12 @@ public interface ImportTree extends Tree { * @return true if this is a static import */ boolean isStatic(); + /** + * {@return true if this is an module import declaration.} + * @since 23 + */ + @PreviewFeature(feature=PreviewFeature.Feature.MODULE_IMPORTS, reflective=true) + boolean isModule(); /** * Returns the qualified identifier for the declaration(s) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index 1572973179b26..6af766effa524 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -210,6 +210,7 @@ public boolean isPreview(Feature feature) { case IMPLICIT_CLASSES -> true; case SUPER_INIT -> true; case PRIMITIVE_PATTERNS -> true; + case MODULE_IMPORTS -> true; //Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing). //When real preview features will be added, this method can be implemented to return 'true' //for those selected features, and 'false' for all the others. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java index 479e6891d8f69..f1cc1e89272b6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java @@ -255,6 +255,7 @@ public enum Feature { UNNAMED_VARIABLES(JDK22, Fragments.FeatureUnnamedVariables, DiagKind.PLURAL), PRIMITIVE_PATTERNS(JDK23, Fragments.FeaturePrimitivePatterns, DiagKind.PLURAL), SUPER_INIT(JDK22, Fragments.FeatureSuperInit, DiagKind.NORMAL), + MODULE_IMPORTS(JDK23, Fragments.FeatureModuleImports, DiagKind.PLURAL), ; enum DiagKind { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index e909afc0bdffd..d98aad1e9d892 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -4396,7 +4396,9 @@ public void checkFunctionalInterface(JCClassDecl tree, ClassSymbol cs) { } public void checkImportsResolvable(final JCCompilationUnit toplevel) { - for (final JCImport imp : toplevel.getImports()) { + for (final JCImportBase impBase : toplevel.getImports()) { + if (!(impBase instanceof JCImport imp)) + continue; if (!imp.staticImport || !imp.qualid.hasTag(SELECT)) continue; final JCFieldAccess select = imp.qualid; @@ -4420,8 +4422,9 @@ public void checkImportsResolvable(final JCCompilationUnit toplevel) { // Check that packages imported are in scope (JLS 7.4.3, 6.3, 6.5.3.1, 6.5.3.2) public void checkImportedPackagesObservable(final JCCompilationUnit toplevel) { - OUTER: for (JCImport imp : toplevel.getImports()) { - if (!imp.staticImport && TreeInfo.name(imp.qualid) == names.asterisk) { + OUTER: for (JCImportBase impBase : toplevel.getImports()) { + if (impBase instanceof JCImport imp && !imp.staticImport && + TreeInfo.name(imp.qualid) == names.asterisk) { TypeSymbol tsym = imp.qualid.selected.type.tsym; if (tsym.kind == PCK && tsym.members().isEmpty() && !(Feature.IMPORT_ON_DEMAND_OBSERVABLE_PACKAGES.allowedInSource(source) && tsym.exists())) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java index 4bcc7937aa9b0..df14b1859e342 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2018, Google LLC. All rights reserved. - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,7 @@ import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCModuleDecl; +import com.sun.tools.javac.tree.JCTree.JCModuleImport; import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCOpens; @@ -410,6 +411,12 @@ public void visitImport(JCImport tree) { result = tree.staticImport == that.staticImport && scan(tree.qualid, that.qualid); } + @Override + public void visitModuleImport(JCModuleImport tree) { + JCModuleImport that = (JCModuleImport) parameter; + result = scan(tree.module, that.module); + } + @Override public void visitIndexed(JCArrayAccess tree) { JCArrayAccess that = (JCArrayAccess) parameter; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java index 9366e802b1668..f36f425283a1a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java @@ -32,16 +32,15 @@ import javax.tools.JavaFileObject; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Directive.ExportsDirective; +import com.sun.tools.javac.code.Directive.RequiresDirective; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Scope.ImportFilter; -import com.sun.tools.javac.code.Scope.ImportScope; import com.sun.tools.javac.code.Scope.NamedImportScope; import com.sun.tools.javac.code.Scope.StarImportScope; import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; -import com.sun.tools.javac.parser.Parser; -import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.DefinedBy.Api; @@ -57,7 +56,6 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.code.TypeTag.ERROR; -import com.sun.tools.javac.resources.CompilerProperties.Fragments; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.tree.JCTree.Tag.*; @@ -114,8 +112,6 @@ public class TypeEnter implements Completer { private final Lint lint; private final TypeEnvs typeEnvs; private final Dependencies dependencies; - private final ParserFactory parserFactory; - private final Preview preview; public static TypeEnter instance(Context context) { TypeEnter instance = context.get(typeEnterKey); @@ -143,8 +139,6 @@ protected TypeEnter(Context context) { lint = Lint.instance(context); typeEnvs = TypeEnvs.instance(context); dependencies = Dependencies.instance(context); - parserFactory = ParserFactory.instance(context); - preview = Preview.instance(context); Source source = Source.instance(context); allowDeprecationOnImport = Feature.DEPRECATION_ON_IMPORT.allowedInSource(source); } @@ -370,9 +364,7 @@ private void resolveImports(JCCompilationUnit tree, Env env) { if (tree.getPackage() != null && decl == null) checkClassPackageClash(tree.getPackage()); - for (JCImport imp : tree.getImports()) { - doImport(imp); - } + handleImports(tree.getImports()); if (decl != null) { DiagnosticPosition prevCheckDeprecatedLintPos = deferredLintHandler.setPos(decl.pos()); @@ -394,6 +386,16 @@ private void resolveImports(JCCompilationUnit tree, Env env) { } } + private void handleImports(List imports) { + for (JCImportBase imp : imports) { + if (imp instanceof JCModuleImport mimp) { + doModuleImport(mimp); + } else { + doImport((JCImport) imp); + } + } + } + private void checkClassPackageClash(JCPackageDecl tree) { // check that no class exists with same fully qualified name as // toplevel package @@ -445,6 +447,57 @@ private void doImport(JCImport tree) { } } + private void doModuleImport(JCModuleImport tree) { + Name moduleName = TreeInfo.fullName(tree.module); + ModuleSymbol module = syms.getModule(moduleName); + + if (module != null) { + if (!env.toplevel.modle.readModules.contains(module)) { + if (env.toplevel.modle.isUnnamed()) { + log.error(tree.pos, Errors.ImportModuleDoesNotReadUnnamed(module)); + } else { + log.error(tree.pos, Errors.ImportModuleDoesNotRead(env.toplevel.modle, + module)); + } + //error recovery, make sure the module is completed: + module.getDirectives(); + } + + List todo = List.of(module); + Set seenModules = new HashSet<>(); + + while (!todo.isEmpty()) { + ModuleSymbol currentModule = todo.head; + + todo = todo.tail; + + if (!seenModules.add(currentModule)) { + continue; + } + + for (ExportsDirective export : currentModule.exports) { + if (export.modules != null && !export.modules.contains(env.toplevel.packge.modle)) { + continue; + } + + PackageSymbol pkg = export.getPackage(); + JCImport nestedImport = make.at(tree.pos) + .Import(make.Select(make.QualIdent(pkg), names.asterisk), false); + + doImport(nestedImport); + } + + for (RequiresDirective requires : currentModule.requires) { + if (requires.isTransitive()) { + todo = todo.prepend(requires.module); + } + } + } + } else { + log.error(tree.pos, Errors.ImportModuleNotFound(moduleName)); + } + } + Type attribImportType(JCTree tree, Env env) { Assert.check(completionEnabled); Lint prevLint = chk.setLint(allowDeprecationOnImport ? diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 4eb7aa7c17d9c..4278b902fb31b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -4252,6 +4252,13 @@ protected JCTree importDeclaration() { if (token.kind == STATIC) { importStatic = true; nextToken(); + } else if (token.kind == IDENTIFIER && token.name() == names.module && + peekToken(TokenKind.IDENTIFIER)) { + checkSourceLevel(Feature.MODULE_IMPORTS); + nextToken(); + JCExpression moduleName = qualident(false); + accept(SEMI); + return toP(F.at(pos).ModuleImport(moduleName)); } JCExpression pid = toP(F.at(token.pos).Ident(ident())); do { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 26c16ebdc2c82..a37d9041f4354 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -3218,6 +3218,9 @@ compiler.misc.feature.implicit.classes=\ compiler.misc.feature.super.init=\ statements before super() +compiler.misc.feature.module.imports=\ + module imports + compiler.warn.underscore.as.identifier=\ as of release 9, ''_'' is a keyword, and may not be used as an identifier @@ -3528,6 +3531,18 @@ compiler.err.module.not.found=\ compiler.warn.module.not.found=\ module not found: {0} +# 0: name +compiler.err.import.module.not.found=\ + imported module not found: {0} + +# 0: symbol +compiler.err.import.module.does.not.read.unnamed=\ + unnamed module does not read: {0} + +# 0: symbol, 1: symbol +compiler.err.import.module.does.not.read=\ + module {0} does not read: {1} + compiler.err.too.many.modules=\ too many module declarations found diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java index 56daece2b2f55..5af482516b4e6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -105,6 +105,10 @@ public enum Tag { */ IMPORT, + /** Module import clauses. + */ + MODULEIMPORT, + /** Class definitions, of type ClassDef. */ CLASSDEF, @@ -585,11 +589,11 @@ public ExpressionTree getPackageName() { } @DefinedBy(Api.COMPILER_TREE) - public List getImports() { - ListBuffer imports = new ListBuffer<>(); + public List getImports() { + ListBuffer imports = new ListBuffer<>(); for (JCTree tree : defs) { - if (tree.hasTag(IMPORT)) - imports.append((JCImport)tree); + if (tree instanceof JCImportBase imp) + imports.append(imp); else if (!tree.hasTag(PACKAGEDEF) && !tree.hasTag(SKIP)) break; } @@ -608,7 +612,9 @@ public List getTypeDecls() { List typeDefs; for (typeDefs = defs; !typeDefs.isEmpty(); typeDefs = typeDefs.tail) { if (!typeDefs.head.hasTag(MODULEDEF) - && !typeDefs.head.hasTag(PACKAGEDEF) && !typeDefs.head.hasTag(IMPORT)) { + && !typeDefs.head.hasTag(PACKAGEDEF) + && !typeDefs.head.hasTag(IMPORT) + && !typeDefs.head.hasTag(MODULEIMPORT)) { break; } } @@ -661,10 +667,22 @@ public Tag getTag() { } } + public static abstract class JCImportBase extends JCTree implements ImportTree { + + @DefinedBy(Api.COMPILER_TREE) + public Kind getKind() { return Kind.IMPORT; } + @Override @DefinedBy(Api.COMPILER_TREE) + public R accept(TreeVisitor v, D d) { + return v.visitImport(this, d); + } + + public abstract JCTree getQualifiedIdentifier(); + } + /** * An import clause. */ - public static class JCImport extends JCTree implements ImportTree { + public static class JCImport extends JCImportBase { public boolean staticImport; /** The imported class(es). */ public JCFieldAccess qualid; @@ -679,8 +697,35 @@ protected JCImport(JCFieldAccess qualid, boolean importStatic) { @DefinedBy(Api.COMPILER_TREE) public boolean isStatic() { return staticImport; } @DefinedBy(Api.COMPILER_TREE) + public boolean isModule() { return false; } + @DefinedBy(Api.COMPILER_TREE) public JCFieldAccess getQualifiedIdentifier() { return qualid; } + @Override + public Tag getTag() { + return IMPORT; + } + } + + /** + * A module import clause. + */ + public static class JCModuleImport extends JCImportBase { + /** The module name. */ + public JCExpression module; + protected JCModuleImport(JCExpression module) { + this.module = module; + } + @Override + public void accept(Visitor v) { v.visitModuleImport(this); } + + @DefinedBy(Api.COMPILER_TREE) + public boolean isStatic() { return false; } + @DefinedBy(Api.COMPILER_TREE) + public boolean isModule() { return true; } + @DefinedBy(Api.COMPILER_TREE) + public JCExpression getQualifiedIdentifier() { return module; } + @DefinedBy(Api.COMPILER_TREE) public Kind getKind() { return Kind.IMPORT; } @Override @DefinedBy(Api.COMPILER_TREE) @@ -690,7 +735,7 @@ public R accept(TreeVisitor v, D d) { @Override public Tag getTag() { - return IMPORT; + return MODULEIMPORT; } } @@ -3480,6 +3525,7 @@ public abstract static class Visitor { public void visitTopLevel(JCCompilationUnit that) { visitTree(that); } public void visitPackageDef(JCPackageDecl that) { visitTree(that); } public void visitImport(JCImport that) { visitTree(that); } + public void visitModuleImport(JCModuleImport that) { visitTree(that); } public void visitClassDef(JCClassDecl that) { visitTree(that); } public void visitMethodDef(JCMethodDecl that) { visitTree(that); } public void visitVarDef(JCVariableDecl that) { visitTree(that); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java index 9cc0f6e3b6dbb..e97d07b1d2bfa 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -380,12 +380,12 @@ public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOExcepti (cdef == null || l.head.hasTag(IMPORT) || l.head.hasTag(PACKAGEDEF)); l = l.tail) { - if (l.head.hasTag(IMPORT)) { - JCImport imp = (JCImport)l.head; - Name name = TreeInfo.name(imp.qualid); + if (l.head instanceof JCImportBase imp) { + Name name = TreeInfo.name(imp.getQualifiedIdentifier()); if (name == name.table.names.asterisk || cdef == null || - isUsed(TreeInfo.symbol(imp.qualid), cdef)) { + imp instanceof JCModuleImport || + isUsed(TreeInfo.symbol(imp.getQualifiedIdentifier()), cdef)) { if (firstImport) { firstImport = false; println(); @@ -547,6 +547,17 @@ public void visitImport(JCImport tree) { } } + public void visitModuleImport(JCModuleImport tree) { + try { + print("import module "); + printExpr(tree.module); + print(';'); + println(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitClassDef(JCClassDecl tree) { try { println(); align(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java index 7c2ef075ccbea..9c3ed3bbcd26b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -257,9 +257,14 @@ public JCTree visitIf(IfTree node, P p) { @DefinedBy(Api.COMPILER_TREE) public JCTree visitImport(ImportTree node, P p) { - JCImport t = (JCImport) node; - JCFieldAccess qualid = copy(t.qualid, p); - return M.at(t.pos).Import(qualid, t.staticImport); + if (node instanceof JCModuleImport mimp) { + JCExpression module = copy(mimp.module, p); + return M.at(mimp.pos).ModuleImport(module); + } else { + JCImport t = (JCImport) node; + JCFieldAccess qualid = copy(t.qualid, p); + return M.at(t.pos).Import(qualid, t.staticImport); + } } @DefinedBy(Api.COMPILER_TREE) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java index fe6ca849f3151..b4c6f804a2f40 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -129,6 +129,7 @@ public JCCompilationUnit TopLevel(List defs) { Assert.check(node instanceof JCClassDecl || node instanceof JCPackageDecl || node instanceof JCImport + || node instanceof JCModuleImport || node instanceof JCModuleDecl || node instanceof JCSkip || node instanceof JCErroneous @@ -151,8 +152,14 @@ public JCPackageDecl PackageDecl(List annotations, return tree; } - public JCImport Import(JCFieldAccess qualid, boolean importStatic) { - JCImport tree = new JCImport(qualid, importStatic); + public JCImport Import(JCFieldAccess qualid, boolean staticImport) { + JCImport tree = new JCImport(qualid, staticImport); + tree.pos = pos; + return tree; + } + + public JCModuleImport ModuleImport(JCExpression moduleName) { + JCModuleImport tree = new JCModuleImport(moduleName); tree.pos = pos; return tree; } 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 0ff0c75efd460..0e9b3bf8bfb00 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -338,6 +338,10 @@ String[] shownOptions() { return selectOptions(e -> e.getKey().showOption); } + boolean hasOption(OptionKind kind) { + return optMap.containsKey(kind); + } + void addAll(OptionKind kind, Collection vals) { optMap.computeIfAbsent(kind, k -> new ArrayList<>()) .addAll(vals); @@ -470,7 +474,7 @@ Options parse(OptionSet options) { .map(mp -> mp.contains("=") ? mp : mp + "=ALL-UNNAMED") .toList() ); - if (options.has(argEnablePreview)) { + if (previewEnabled(options)) { opts.addAll(OptionKind.ENABLE_PREVIEW, List.of( OptionKind.ENABLE_PREVIEW.optionFlag)); opts.addAll(OptionKind.SOURCE_RELEASE, List.of( @@ -490,6 +494,10 @@ Options parse(OptionSet options) { } } + boolean previewEnabled(OptionSet options) { + return options.has(argEnablePreview); + } + void addOptions(OptionKind kind, Collection vals) { if (!vals.isEmpty()) { if (kind.onlyOne && vals.size() > 1) { @@ -627,7 +635,8 @@ Options parse(OptionSet options) { initialStartup = Startup.noStartup(); } else { String packedStartup = prefs.get(STARTUP_KEY); - initialStartup = Startup.unpack(packedStartup, new InitMessageHandler()); + boolean preview = previewEnabled(options); + initialStartup = Startup.unpack(packedStartup, preview, new InitMessageHandler()); } if (options.has(argExecution)) { executionControlSpec = options.valueOf(argExecution); @@ -2285,7 +2294,8 @@ boolean setStart(ArgTokenizer at) { return false; } } else if (defaultOption) { - startup = Startup.defaultStartup(this); + boolean preview = options.hasOption(OptionKind.ENABLE_PREVIEW); + startup = Startup.defaultStartup(preview, this); } else if (noneOption) { startup = Startup.noStartup(); } @@ -2302,7 +2312,8 @@ void showSetStart() { StringBuilder sb = new StringBuilder(); String retained = prefs.get(STARTUP_KEY); if (retained != null) { - Startup retainedStart = Startup.unpack(retained, this); + boolean preview = options.hasOption(OptionKind.ENABLE_PREVIEW); + Startup retainedStart = Startup.unpack(retained, preview, this); boolean currentDifferent = !startup.equals(retainedStart); sb.append(retainedStart.show(true)); if (currentDifferent) { diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java index 372faf9f08a52..53c31c3568dab 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,9 +118,13 @@ public boolean equals(Object o) { } private static final String DEFAULT_STARTUP_NAME = "DEFAULT"; + private static final String PREVIEW_DEFAULT_STARTUP_NAME = "PREVIEW_DEFAULT"; // cached DEFAULT start-up - private static Startup defaultStartup = null; + private static Startup[] defaultStartup = new Startup[] { + null, //standard startup + null //preview startup + }; // the list of entries private List entries; @@ -166,7 +170,8 @@ boolean isEmpty() { boolean isDefault() { if (entries.size() == 1) { StartupEntry sue = entries.get(0); - if (sue.isBuiltIn && sue.name.equals(DEFAULT_STARTUP_NAME)) { + if (sue.isBuiltIn && (sue.name.equals(DEFAULT_STARTUP_NAME) || + sue.name.equals(PREVIEW_DEFAULT_STARTUP_NAME))) { return true; } } @@ -217,7 +222,7 @@ String showDetail() { * @param mh handler for error messages * @return Startup, or default startup when error (message has been printed) */ - static Startup unpack(String storedForm, MessageHandler mh) { + static Startup unpack(String storedForm, boolean preview, MessageHandler mh) { if (storedForm != null) { if (storedForm.isEmpty()) { return noStartup(); @@ -255,7 +260,7 @@ static Startup unpack(String storedForm, MessageHandler mh) { mh.errormsg("jshell.err.corrupted.stored.startup", ex.getMessage()); } } - return defaultStartup(mh); + return defaultStartup(preview, mh); } /** @@ -324,22 +329,26 @@ static Startup noStartup() { * @param mh handler for error messages * @return The default Startup, or empty startup when error (message has been printed) */ - static Startup defaultStartup(MessageHandler mh) { - if (defaultStartup != null) { - return defaultStartup; + static Startup defaultStartup(boolean preview, MessageHandler mh) { + int idx = preview ? 1 : 0; + + if (defaultStartup[idx] != null) { + return defaultStartup[idx]; } + String resourceName = preview ? PREVIEW_DEFAULT_STARTUP_NAME + : DEFAULT_STARTUP_NAME; try { - String content = readResource(DEFAULT_STARTUP_NAME); - return defaultStartup = new Startup( - new StartupEntry(true, DEFAULT_STARTUP_NAME, content)); + String content = readResource(resourceName); + return defaultStartup[idx] = new Startup( + new StartupEntry(true, resourceName, content)); } catch (AccessDeniedException e) { - mh.errormsg("jshell.err.file.not.accessible", "jshell", DEFAULT_STARTUP_NAME, e.getMessage()); + mh.errormsg("jshell.err.file.not.accessible", "jshell", resourceName, e.getMessage()); } catch (NoSuchFileException e) { - mh.errormsg("jshell.err.file.not.found", "jshell", DEFAULT_STARTUP_NAME); + mh.errormsg("jshell.err.file.not.found", "jshell", resourceName); } catch (Exception e) { - mh.errormsg("jshell.err.file.exception", "jshell", DEFAULT_STARTUP_NAME, e); + mh.errormsg("jshell.err.file.exception", "jshell", resourceName, e); } - return defaultStartup = noStartup(); + return defaultStartup[idx] = noStartup(); } } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index 3c45fbdbd1426..0ee6a926b41ca 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,6 +83,7 @@ import static jdk.jshell.Util.DOIT_METHOD_NAME; import static jdk.jshell.Util.PREFIX_PATTERN; import static jdk.jshell.Util.expunge; +import static jdk.jshell.Snippet.SubKind.MODULE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_TYPE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_STATIC_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.TYPE_IMPORT_ON_DEMAND_SUBKIND; @@ -96,7 +97,7 @@ */ class Eval { - private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\p{javaWhitespace}+(?static\\p{javaWhitespace}+)?(?[\\p{L}\\p{N}_\\$\\.]+\\.(?[\\p{L}\\p{N}_\\$]+|\\*))"); + private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\p{javaWhitespace}+(?module\\p{javaWhitespace}+)?(?static\\p{javaWhitespace}+)?(?[\\p{L}\\p{N}_\\$\\.]+\\.(?[\\p{L}\\p{N}_\\$]+|\\*))"); private static final Pattern DEFAULT_PREFIX = Pattern.compile("\\p{javaWhitespace}*(default)\\p{javaWhitespace}+"); // for uses that should not change state -- non-evaluations @@ -244,13 +245,20 @@ private List processImport(String userSource, String compileSource) { Matcher mat = IMPORT_PATTERN.matcher(compileSource); String fullname; String name; + boolean isModule; boolean isStatic; if (mat.find()) { + isModule = mat.group("module") != null; isStatic = mat.group("static") != null; - name = mat.group("name"); fullname = mat.group("fullname"); + if (isModule) { + name = fullname; + } else { + name = mat.group("name"); + } } else { // bad import -- fake it + isModule = compileSource.contains(" module "); isStatic = compileSource.contains("static"); name = fullname = compileSource; } @@ -259,9 +267,14 @@ private List processImport(String userSource, String compileSource) { String keyName = isStar ? fullname : name; - SubKind snippetKind = isStar - ? (isStatic ? STATIC_IMPORT_ON_DEMAND_SUBKIND : TYPE_IMPORT_ON_DEMAND_SUBKIND) - : (isStatic ? SINGLE_STATIC_IMPORT_SUBKIND : SINGLE_TYPE_IMPORT_SUBKIND); + SubKind snippetKind; + if (isModule) { + snippetKind = MODULE_IMPORT_SUBKIND; + } else if (isStar) { + snippetKind = isStatic ? STATIC_IMPORT_ON_DEMAND_SUBKIND : TYPE_IMPORT_ON_DEMAND_SUBKIND; + } else { + snippetKind = isStatic ? SINGLE_STATIC_IMPORT_SUBKIND : SINGLE_TYPE_IMPORT_SUBKIND; + } Snippet snip = new ImportSnippet(state.keyMap.keyForImport(keyName, snippetKind), userSource, guts, fullname, name, snippetKind, fullkey, isStatic, isStar); return singletonList(snip); diff --git a/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java b/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java index 2b4d817a588b6..a86ea2a863d43 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import jdk.internal.javac.PreviewFeature; /** * A Snippet represents a snippet of Java source code as passed to @@ -214,6 +215,15 @@ public enum SubKind { */ STATIC_IMPORT_ON_DEMAND_SUBKIND(Kind.IMPORT), + /** + * Import Module Declaration. + * An import declaration of a module. + * @jls 7.5.5 Import Module Declarations + * @since 23 + */ + @PreviewFeature(feature=PreviewFeature.Feature.MODULE_IMPORTS, reflective=true) + MODULE_IMPORT_SUBKIND(Kind.IMPORT), + /** * A class declaration. * A {@code SubKind} of {@link Kind#TYPE_DECL}. diff --git a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh new file mode 100644 index 0000000000000..4644ac8638657 --- /dev/null +++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/PREVIEW_DEFAULT.jsh @@ -0,0 +1 @@ +import module java.base; diff --git a/test/langtools/jdk/jshell/ImportTest.java b/test/langtools/jdk/jshell/ImportTest.java index e09490052cff5..b8f3f1ee5d09a 100644 --- a/test/langtools/jdk/jshell/ImportTest.java +++ b/test/langtools/jdk/jshell/ImportTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,16 +33,20 @@ * @run testng ImportTest */ +import java.lang.reflect.Method; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.function.Consumer; import javax.tools.Diagnostic; +import jdk.jshell.JShell; import jdk.jshell.Snippet; import org.testng.annotations.Test; import static jdk.jshell.Snippet.Status.VALID; import static jdk.jshell.Snippet.Status.OVERWRITTEN; +import static jdk.jshell.Snippet.SubKind.MODULE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_TYPE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_STATIC_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.TYPE_IMPORT_ON_DEMAND_SUBKIND; @@ -168,4 +172,20 @@ public void testImportWithComment() { assertImportKeyMatch("import java.util.List;//comment", "List", SINGLE_TYPE_IMPORT_SUBKIND, added(VALID)); assertEval("List l = null;"); } + + public void testImportModule() { + assertImportKeyMatch("import module java.base;", "java.base", MODULE_IMPORT_SUBKIND, added(VALID)); + assertEval("MethodHandle m;"); + } + + @org.testng.annotations.BeforeMethod + public void setUp(Method m) { + switch (m.getName()) { + case "testImportModule" -> + super.setUp(bc -> bc.compilerOptions("--source", System.getProperty("java.specification.version"), "--enable-preview").remoteVMOptions("--enable-preview")); + default -> + super.setUp(bc -> {}); + } + } + } diff --git a/test/langtools/jdk/jshell/KullaTesting.java b/test/langtools/jdk/jshell/KullaTesting.java index d74f3484f4bd8..e3eb6ef2823c6 100644 --- a/test/langtools/jdk/jshell/KullaTesting.java +++ b/test/langtools/jdk/jshell/KullaTesting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -268,6 +268,7 @@ private Kind getKind(Snippet key) { SubKind expectedSubKind = key.subKind(); Kind expectedKind; switch (expectedSubKind) { + case MODULE_IMPORT_SUBKIND: case SINGLE_TYPE_IMPORT_SUBKIND: case SINGLE_STATIC_IMPORT_SUBKIND: case TYPE_IMPORT_ON_DEMAND_SUBKIND: diff --git a/test/langtools/jdk/jshell/StartOptionTest.java b/test/langtools/jdk/jshell/StartOptionTest.java index aa8d9be03a9ef..60926e69843a7 100644 --- a/test/langtools/jdk/jshell/StartOptionTest.java +++ b/test/langtools/jdk/jshell/StartOptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,6 +126,13 @@ protected void startExCoUoCeCn(Consumer checkExitCode, check(usererr, null, "usererr"); } + protected void startCheckUserOutput(Consumer checkUserOutput, + String... args) { + runShell(args); + check(userout, checkUserOutput, "userout"); + check(usererr, null, "usererr"); + } + // Start with an exit code and command error check protected void startExCe(int eec, Consumer checkError, String... args) { StartOptionTest.this.startExCoUoCeCn( @@ -358,6 +365,17 @@ public void testShowVersion() { "--show-version"); } + public void testPreviewEnabled() { + String fn = writeToFile("System.out.println(\"prefix\");\n" + + "System.out.println(MethodHandle.class.getName());\n" + + "System.out.println(\"suffix\");\n" + + "/exit\n"); + startCheckUserOutput(s -> assertEquals(s, "prefix\nsuffix\n"), + fn); + startCheckUserOutput(s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), + "--enable-preview", fn); + } + @AfterMethod public void tearDown() { cmdout = null; diff --git a/test/langtools/jdk/jshell/ToolProviderTest.java b/test/langtools/jdk/jshell/ToolProviderTest.java index be8ba23f7c487..e27ed410d52c5 100644 --- a/test/langtools/jdk/jshell/ToolProviderTest.java +++ b/test/langtools/jdk/jshell/ToolProviderTest.java @@ -22,6 +22,7 @@ */ import java.util.ServiceLoader; +import java.util.function.Consumer; import javax.tools.Tool; import org.testng.annotations.Test; import static org.testng.Assert.assertTrue; @@ -58,6 +59,13 @@ protected void startExCoUoCeCn(int expectedExitCode, null, expectedError, null, args); } + @Override + protected void startCheckUserOutput(Consumer checkUserOutput, String... args) { + runShell(args); + check(cmdout, checkUserOutput, "userout"); + check(usererr, null, "usererr"); + } + @Override protected int runShell(String... args) { ServiceLoader sl = ServiceLoader.load(Tool.class); diff --git a/test/langtools/tools/javac/ImportModule.java b/test/langtools/tools/javac/ImportModule.java new file mode 100644 index 0000000000000..767288d4d2f0a --- /dev/null +++ b/test/langtools/tools/javac/ImportModule.java @@ -0,0 +1,722 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8328481 + * @summary Check behavior of module imports. + * @library /tools/lib + * @modules java.logging + * java.sql + * 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 ImportModule +*/ + +import com.sun.source.tree.Tree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskEvent.Kind; +import com.sun.source.util.TaskListener; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.JavaTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class ImportModule extends TestRunner { + + private static final String SOURCE_VERSION = System.getProperty("java.specification.version"); + private ToolBox tb; + + public static void main(String... args) throws Exception { + new ImportModule().runTests(); + } + + ImportModule() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testImportJavaBase(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + import module java.base; + public class Test { + public static void main(String... args) { + List l = new ArrayList<>(); + System.out.println(l.getClass().getName()); + } + } + """); + + Files.createDirectories(classes); + + {//with --release: + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + + var out = new JavaTask(tb) + .classpath(classes.toString()) + .className("test.Test") + .vmOptions("--enable-preview") + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + + var expectedOut = List.of("java.util.ArrayList"); + + if (!Objects.equals(expectedOut, out)) { + throw new AssertionError("Incorrect Output, expected: " + expectedOut + + ", actual: " + out); + + } + } + + {//with --source: + new JavacTask(tb) + .options("--enable-preview", "--source", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + + var out = new JavaTask(tb) + .classpath(classes.toString()) + .className("test.Test") + .vmOptions("--enable-preview") + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + + var expectedOut = List.of("java.util.ArrayList"); + + if (!Objects.equals(expectedOut, out)) { + throw new AssertionError("Incorrect Output, expected: " + expectedOut + + ", actual: " + out); + + } + } + } + + @Test + public void testVerifySourceLevelCheck(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + import module java.base; + public class Test { + } + """); + + Files.createDirectories(classes); + + List actualErrors; + List expectedErrors; + + actualErrors = + new JavacTask(tb) + .options("--release", "21", "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)", + "1 error" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + actualErrors = + new JavacTask(tb) + .options("-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)", + "1 error" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + } + + @Test + public void testConflicts(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + import module java.logging; + import java.lang.System.*; + public class Test { + Logger l; + } + """); + + Files.createDirectories(classes); + + List actualErrors; + List expectedErrors; + + actualErrors = + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test.java:5:5: compiler.err.ref.ambiguous: Logger, kindname.interface, java.lang.System.Logger, java.lang.System, kindname.class, java.util.logging.Logger, java.util.logging", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + + tb.writeJavaFiles(src, + """ + package test; + import module java.logging; + import java.lang.System.*; + import java.lang.System.Logger; + public class Test { + Logger l; + } + """); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + tb.writeJavaFiles(src, + """ + package test; + import module java.logging; + import java.lang.System.*; + import java.util.logging.Logger; + public class Test { + Logger l; + } + """); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + tb.writeJavaFiles(src, + """ + package test; + import module java.logging; + import java.lang.System.*; + public class Test { + } + """); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + tb.writeJavaFiles(src, + """ + package test; + import module java.base; + import module java.sql; + public class Test { + Date d; + } + """); + + actualErrors = + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test.java:5:5: compiler.err.ref.ambiguous: Date, kindname.class, java.sql.Date, java.sql, kindname.class, java.util.Date, java.util", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + + tb.writeJavaFiles(src, + """ + package test; + import module java.base; + import module java.sql; + import java.util.Date; + public class Test { + Date d; + } + """); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testNoQualifiedExports(Path base) throws Exception { + Path current = base.resolve("."); + + Path lib = current.resolve("lib"); + Path libSrc = lib.resolve("src"); + Path libClasses = lib.resolve("classes"); + tb.writeJavaFiles(libSrc, + """ + module lib { + exports api; + exports impl to use; + } + """, + """ + package api; + public class Api { + } + """, + """ + package impl; + public class Impl { + } + """); + + Files.createDirectories(libClasses); + + new JavacTask(tb) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run() + .writeAll(); + + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + + tb.writeJavaFiles(src, + """ + package test; + import module lib; + public class Test { + public static void main(String... args) { + Api a; + Impl i; + } + } + """); + + Files.createDirectories(classes); + + List actualErrors; + List expectedErrors; + + actualErrors = + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "-p", libClasses.toString(), + "--add-modules", "lib", + "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test.java:6:9: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.class, test.Test, null)", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "1 error" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + + actualErrors = + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "-p", libClasses.toString(), + "-XDdev", + "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test.java:2:1: compiler.err.import.module.does.not.read.unnamed: lib", + "Test.java:6:9: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.class, test.Test, null)", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "2 errors" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + + tb.writeJavaFiles(src, + """ + module test.module { + } + """); + + actualErrors = + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "-p", libClasses.toString(), + "-XDdev", + "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test.java:2:1: compiler.err.import.module.does.not.read: test.module, lib", + "Test.java:6:9: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.class, test.Test, null)", + "- compiler.note.preview.filename: Test.java, DEFAULT", + "- compiler.note.preview.recompile", + "2 errors" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + } + + @Test + public void testTransitiveDependencies(Path base) throws Exception { + Path current = base.resolve("."); + Path lib = current.resolve("lib"); + Path libSrc = lib.resolve("src"); + Path libM1 = libSrc.resolve("m1"); + tb.writeJavaFiles(libM1, + """ + module m1 { + requires transitive m2; + exports api1; + exports api2 to test; + exports api3 to m3; + } + """, + """ + package api1; + public class Api1 { + } + """, + """ + package api2; + public class Api2 { + } + """, + """ + package api3; + public class Api3 { + } + """, + """ + package impl1; + public class Impl1 { + } + """); + + Path libM2 = libSrc.resolve("m2"); + tb.writeJavaFiles(libM2, + """ + module m2 { + exports api4; + exports api5 to test; + exports api6 to m3; + } + """, + """ + package api4; + public class Api4 { + } + """, + """ + package api5; + public class Api5 { + } + """, + """ + package api6; + public class Api6 { + } + """, + """ + package impl2; + public class Impl2 { + } + """); + + Path libClasses = lib.resolve("classes"); + Files.createDirectories(libClasses); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "--module-source-path", libSrc.toString(), + "-XDrawDiagnostics") + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run() + .writeAll(); + + Path src = current.resolve("src"); + tb.writeJavaFiles(src, + """ + module test { + requires m1; + } + """, + """ + package test; + import module m1; + public class Test1 { + Api1 a1; + Api2 a2; + Api3 a3; + Impl1 i1; + Api4 a4; + Api5 a5; + Api6 a6; + Impl2 i2; + } + """, + """ + package test; + import module m2; + public class Test2 { + Api1 a1; + Api2 a2; + Api3 a3; + Impl1 i1; + Api4 a4; + Api5 a5; + Api6 a6; + Impl2 i2; + } + """); + + Path classes = current.resolve("classes"); + Files.createDirectories(classes); + + List actualErrors; + List expectedErrors; + + actualErrors = + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION, + "--module-path", libClasses.toString(), + "-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expectedErrors = List.of( + "Test1.java:6:5: compiler.err.cant.resolve.location: kindname.class, Api3, , , (compiler.misc.location: kindname.class, test.Test1, null)", + "Test1.java:7:5: compiler.err.cant.resolve.location: kindname.class, Impl1, , , (compiler.misc.location: kindname.class, test.Test1, null)", + "Test1.java:10:5: compiler.err.cant.resolve.location: kindname.class, Api6, , , (compiler.misc.location: kindname.class, test.Test1, null)", + "Test1.java:11:5: compiler.err.cant.resolve.location: kindname.class, Impl2, , , (compiler.misc.location: kindname.class, test.Test1, null)", + "Test2.java:4:5: compiler.err.cant.resolve.location: kindname.class, Api1, , , (compiler.misc.location: kindname.class, test.Test2, null)", + "Test2.java:5:5: compiler.err.cant.resolve.location: kindname.class, Api2, , , (compiler.misc.location: kindname.class, test.Test2, null)", + "Test2.java:6:5: compiler.err.cant.resolve.location: kindname.class, Api3, , , (compiler.misc.location: kindname.class, test.Test2, null)", + "Test2.java:7:5: compiler.err.cant.resolve.location: kindname.class, Impl1, , , (compiler.misc.location: kindname.class, test.Test2, null)", + "Test2.java:10:5: compiler.err.cant.resolve.location: kindname.class, Api6, , , (compiler.misc.location: kindname.class, test.Test2, null)", + "Test2.java:11:5: compiler.err.cant.resolve.location: kindname.class, Impl2, , , (compiler.misc.location: kindname.class, test.Test2, null)", + "- compiler.note.preview.plural: DEFAULT", + "- compiler.note.preview.recompile", + "10 errors" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + out); + + } + } + + @Test + public void testModel(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + import module java.base; + public class Test { + } + """); + + Files.createDirectories(classes); + List kinds = new ArrayList<>(); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void finished(TaskEvent e) { + if (e.getKind() == Kind.ANALYZE) { + for (Tree t : e.getCompilationUnit().getTypeDecls()) { + kinds.add(t.getKind().name()); + } + } + } + }); + }) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + + List expectedKinds = List.of( + "CLASS" + ); + + if (!Objects.equals(expectedKinds, kinds)) { + throw new AssertionError("Incorrect Output, expected: " + expectedKinds + + ", actual: " + kinds); + + } + } + + @Test + public void testModelDisambiguation(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + import module.*; + import module.ModuleClass; + import module.module.*; + import module.module.ModuleModuleClass; + public class Test { + } + """, + """ + package module; + public class ModuleClass{ + } + """, + """ + package module.module; + public class ModuleModuleClass { + } + """); + + Files.createDirectories(classes); + List kinds = new ArrayList<>(); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + } + +} diff --git a/test/langtools/tools/javac/diags/examples/ImportModule.java b/test/langtools/tools/javac/diags/examples/ImportModule.java new file mode 100644 index 0000000000000..2a0a39f5faddb --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/ImportModule.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + + // key: compiler.misc.feature.module.imports + // key: compiler.warn.preview.feature.use.plural + // options: --release ${jdk.version} --enable-preview -Xlint:preview + +import module java.base; + +public class ImportModule { +} diff --git a/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java new file mode 100644 index 0000000000000..e8f9c952fbc19 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +// key: compiler.err.import.module.does.not.read +// key: compiler.note.preview.filename +// key: compiler.note.preview.recompile +// options: --release ${jdk.version} --enable-preview +module m {} diff --git a/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/test/Test.java b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/test/Test.java new file mode 100644 index 0000000000000..a23fe67040120 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/test/Test.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 module java.compiler; + +public class Test {} diff --git a/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java new file mode 100644 index 0000000000000..37ae9673cc8ef --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +// key: compiler.err.import.module.does.not.read.unnamed +// key: compiler.note.preview.filename +// key: compiler.note.preview.recompile +// options: --release ${jdk.version} --enable-preview --limit-modules java.base + +import module java.compiler; + +public class ImportModuleDoesNotReadUnnamed { +} diff --git a/test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java b/test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java new file mode 100644 index 0000000000000..8a12fc0bd034c --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + + // key: compiler.err.import.module.not.found + // key: compiler.note.preview.filename + // key: compiler.note.preview.recompile + // options: --release ${jdk.version} --enable-preview + +import module unknown; + +public class ImportModuleNotFound { +} diff --git a/test/langtools/tools/javac/tree/Imports.java b/test/langtools/tools/javac/tree/Imports.java new file mode 100644 index 0000000000000..8ab59d280f683 --- /dev/null +++ b/test/langtools/tools/javac/tree/Imports.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8328481 + * @summary Verify the Trees model for module imports + * @library /tools/lib + * @modules java.logging + * java.sql + * 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 Imports +*/ + +import com.sun.source.tree.ImportTree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskEvent.Kind; +import com.sun.source.util.TaskListener; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.atomic.AtomicInteger; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class Imports extends TestRunner { + + private static final String SOURCE_VERSION = System.getProperty("java.specification.version"); + private ToolBox tb; + + public static void main(String... args) throws Exception { + new Imports().runTests(); + } + + Imports() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testModuleImport(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + import module java.base; + public class Test { + } + """); + + Files.createDirectories(classes); + + AtomicInteger seenImports = new AtomicInteger(-1); + + new JavacTask(tb) + .options("--enable-preview", "--release", SOURCE_VERSION) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void finished(TaskEvent e) { + if (e.getKind() != Kind.PARSE) { + return ; + } + + var imports = e.getCompilationUnit().getImports(); + + seenImports.set(imports.size()); + + if (imports.size() != 1) { + throw new AssertionError("Exception 1 import, " + + "but got: " + imports.size()); + } + + ImportTree it = imports.get(0); + + if (!it.isModule()) { + throw new AssertionError("Expected module import, but got ordinary one."); + } + + if (!"java.base".equals(it.getQualifiedIdentifier().toString())) { + throw new AssertionError("Expected module import for java.base, " + + "but got: " + it.getQualifiedIdentifier()); + } + + String expectedImportToString = "import module java.base;\n"; + String actualImportToString = it.toString() + .replaceAll("\\R", "\n"); + + if (!expectedImportToString.equals(actualImportToString)) { + throw new AssertionError("Expected '" + expectedImportToString + "', " + + "but got: '" + it + "'"); + } + } + }); + }) + .run(Task.Expect.SUCCESS); + + if (seenImports.get() == (-1)) { + throw new AssertionError("Did not verify any imports!"); + } + } + +} diff --git a/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java b/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java index aa30682e1bceb..63814220c039c 100644 --- a/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java +++ b/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java @@ -92,6 +92,7 @@ public void compileAll() throws Exception { public Object[][] jdkModules() { return new Object[][]{ {"jdk.compiler", new String[]{ + "java.base/jdk.internal.javac", "java.base/jdk.internal.jmod", "java.base/jdk.internal.misc", "java.base/jdk.internal.module", diff --git a/test/langtools/tools/lib/toolbox/ToolBox.java b/test/langtools/tools/lib/toolbox/ToolBox.java index 89dd7229016ce..8f1f8d3ce4a0b 100644 --- a/test/langtools/tools/lib/toolbox/ToolBox.java +++ b/test/langtools/tools/lib/toolbox/ToolBox.java @@ -747,6 +747,8 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) { private final static Pattern commentPattern = Pattern.compile("(?s)(\\s+//.*?\n|/\\*.*?\\*/)"); + private final static Pattern importModulePattern = + Pattern.compile("import\\s+module\\s+(((?:\\w+\\.)*)\\w+);"); private final static Pattern modulePattern = Pattern.compile("module\\s+((?:\\w+\\.)*)"); private final static Pattern packagePattern = @@ -761,15 +763,10 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) { * declarations from which the name is derived. */ static String getJavaFileNameFromSource(String source) { - StringBuilder sb = new StringBuilder(); - Matcher matcher = commentPattern.matcher(source); - int start = 0; - while (matcher.find()) { - sb.append(source, start, matcher.start()); - start = matcher.end(); - } - sb.append(source.substring(start)); - source = sb.toString(); + source = removeMatchingSpans(source, commentPattern); + source = removeMatchingSpans(source, importModulePattern); + + Matcher matcher; String packageName = null; @@ -795,6 +792,20 @@ static String getJavaFileNameFromSource(String source) { "name from the provided source"); } } + + static String removeMatchingSpans(String source, Pattern toRemove) { + StringBuilder sb = new StringBuilder(); + Matcher matcher = toRemove.matcher(source); + int start = 0; + + while (matcher.find()) { + sb.append(source, start, matcher.start()); + start = matcher.end(); + } + + sb.append(source.substring(start)); + return sb.toString(); + } } /** From f1509e007d1538acfb1749f7fafc56be2affd2e6 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 6 May 2024 06:01:42 +0000 Subject: [PATCH 091/203] 8330998: System.console() writes to stderr when stdout is redirected Reviewed-by: naoto --- .../org/jline/JdkConsoleProviderImpl.java | 7 +- .../org/jline/terminal/TerminalBuilder.java | 3 +- .../jdk/internal/jline/RedirectedStdOut.java | 176 ++++++++++++++++++ 3 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 test/jdk/jdk/internal/jline/RedirectedStdOut.java diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java index 3621a9efea835..d876cffb377d9 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import jdk.internal.org.jline.reader.LineReaderBuilder; import jdk.internal.org.jline.terminal.Terminal; import jdk.internal.org.jline.terminal.TerminalBuilder; +import jdk.internal.org.jline.terminal.TerminalBuilder.SystemOutput; /** * JdkConsole/Provider implementations for jline @@ -51,7 +52,9 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider { public JdkConsole console(boolean isTTY, Charset charset) { try { Terminal terminal = TerminalBuilder.builder().encoding(charset) - .exec(false).build(); + .exec(false) + .systemOutput(SystemOutput.SysOut) + .build(); return new JdkConsoleImpl(terminal); } catch (IllegalStateException ise) { //cannot create a non-dumb, non-exec terminal, diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java index 8c047e373422e..014ad78b794d7 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java @@ -506,7 +506,8 @@ private Terminal doBuild() throws IOException { } terminal = new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB, new FileInputStream(FileDescriptor.in), - new FileOutputStream(console == TerminalProvider.Stream.Output ? FileDescriptor.out : FileDescriptor.err), + //JDK change: always write into stdout: + new FileOutputStream(FileDescriptor.out), encoding, signalHandler); } } else { diff --git a/test/jdk/jdk/internal/jline/RedirectedStdOut.java b/test/jdk/jdk/internal/jline/RedirectedStdOut.java new file mode 100644 index 0000000000000..7cbf913219a7d --- /dev/null +++ b/test/jdk/jdk/internal/jline/RedirectedStdOut.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8330998 + * @summary Verify that even if the stdout is redirected java.io.Console will + * use it for writing. + * @modules jdk.internal.le + * @library /test/lib + * @run main RedirectedStdOut runRedirectAllTest + * @run main/othervm RedirectedStdOut runRedirectOutOnly + */ + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Objects; +import java.util.Optional; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class RedirectedStdOut { + private static final String OUTPUT = "Hello!"; + + public static void main(String... args) throws Throwable { + RedirectedStdOut.class.getDeclaredMethod(args[0]) + .invoke(new RedirectedStdOut()); + } + + //verify the case where neither stdin/out/err is attached to a terminal, + //this test is weaker, but more reliable: + void runRedirectAllTest() throws Exception { + if (true) return ; + ProcessBuilder builder = + ProcessTools.createTestJavaProcessBuilder(ConsoleTest.class.getName()); + OutputAnalyzer output = ProcessTools.executeProcess(builder); + + output.waitFor(); + + if (output.getExitValue() != 0) { + throw new AssertionError("Unexpected return value: " + output.getExitValue() + + ", actualOut: " + output.getStdout() + + ", actualErr: " + output.getStderr()); + } + + String expectedOut = OUTPUT; + String actualOut = output.getStdout(); + + if (!Objects.equals(expectedOut, actualOut)) { + throw new AssertionError("Unexpected stdout content. " + + "Expected: '" + expectedOut + "'" + + ", got: '" + actualOut + "'"); + } + + String expectedErr = ""; + String actualErr = output.getStderr(); + + if (!Objects.equals(expectedErr, actualErr)) { + throw new AssertionError("Unexpected stderr content. " + + "Expected: '" + expectedErr + "'" + + ", got: '" + actualErr + "'"); + } + } + + //verify the case where stdin is attached to a terminal, + //this test allocates pty, and it might be skipped, if the appropriate + //native functions cannot be found + //it also leaves the VM in a broken state (with a pty attached), and so + //should run in a separate VM instance + void runRedirectOutOnly() throws Throwable { + Path stdout = Path.of(".", "stdout.txt").toAbsolutePath(); + + Files.deleteIfExists(stdout); + + Linker linker = Linker.nativeLinker(); + SymbolLookup stdlib = linker.defaultLookup(); + MemorySegment parent = Arena.global().allocate(ValueLayout.ADDRESS); + MemorySegment child = Arena.global().allocate(ValueLayout.ADDRESS); + Optional openptyAddress = stdlib.find("openpty"); + + if (openptyAddress.isEmpty()) { + System.out.println("Cannot lookup openpty."); + //does not have forkpty, ignore + return ; + } + + Optional loginttyAddress = stdlib.find("login_tty"); + + if (loginttyAddress.isEmpty()) { + System.out.println("Cannot lookup login_tty."); + //does not have forkpty, ignore + return ; + } + + FunctionDescriptor openttyDescriptor = + FunctionDescriptor.of(ValueLayout.JAVA_INT, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS); + MethodHandle forkpty = linker.downcallHandle(openptyAddress.get(), + openttyDescriptor); + int res = (int) forkpty.invoke(parent, + child, + MemorySegment.NULL, + MemorySegment.NULL, + MemorySegment.NULL); + + if (res != 0) { + throw new AssertionError(); + } + + //set the current VM's in/out to the terminal: + FunctionDescriptor loginttyDescriptor = + FunctionDescriptor.of(ValueLayout.JAVA_INT, + ValueLayout.JAVA_INT); + MethodHandle logintty = linker.downcallHandle(loginttyAddress.get(), + loginttyDescriptor); + logintty.invoke(child.get(ValueLayout.JAVA_INT, 0)); + + ProcessBuilder builder = + ProcessTools.createTestJavaProcessBuilder(ConsoleTest.class.getName()); + + builder.inheritIO(); + builder.redirectOutput(stdout.toFile()); + + OutputAnalyzer output = ProcessTools.executeProcess(builder); + + output.waitFor(); + + String expectedOut = OUTPUT; + String actualOut = Files.readString(stdout); + + if (!Objects.equals(expectedOut, actualOut)) { + throw new AssertionError("Unexpected stdout content. " + + "Expected: '" + expectedOut + "'" + + ", got: '" + actualOut + "'"); + } + } + + public static class ConsoleTest { + public static void main(String... args) { + System.console().printf(OUTPUT); + System.exit(0); + } + } +} From 4bbd972cbb114b99e856aa7904c0240049052b6a Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 6 May 2024 07:48:22 +0000 Subject: [PATCH 092/203] 8305638: Renaming and small clean-ups around predicates Reviewed-by: roland, epeter --- src/hotspot/share/opto/cfgnode.hpp | 5 + src/hotspot/share/opto/loopPredicate.cpp | 115 ++++++++++++----------- src/hotspot/share/opto/loopTransform.cpp | 2 +- src/hotspot/share/opto/loopnode.cpp | 4 +- src/hotspot/share/opto/loopnode.hpp | 4 +- 5 files changed, 70 insertions(+), 60 deletions(-) diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 869ac68bd9e56..de37f4cdd65ca 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -493,6 +493,11 @@ class ParsePredicateNode : public IfNode { _useless = false; } + // Return the uncommon trap If projection of this Parse Predicate. + ParsePredicateUncommonProj* uncommon_proj() const { + return proj_out(0)->as_IfFalse(); + } + Node* uncommon_trap() const; Node* Ideal(PhaseGVN* phase, bool can_reshape) { diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 278f636d9c712..9fcfbaf5e646d 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -99,40 +99,38 @@ void PhaseIdealLoop::register_control(Node* n, IdealLoopTree *loop, Node* pred, // We will create a region to guard the uct call if there is no one there. // The continuation projection (if_cont) of the new_iff is returned which // is an IfTrue projection. This code is also used to clone predicates to cloned loops. -IfProjNode* PhaseIdealLoop::create_new_if_for_predicate(ParsePredicateSuccessProj* parse_predicate_proj, Node* new_entry, - Deoptimization::DeoptReason reason, +IfTrueNode* PhaseIdealLoop::create_new_if_for_predicate(ParsePredicateSuccessProj* parse_predicate_success_proj, + Node* new_entry, const Deoptimization::DeoptReason reason, const int opcode, const bool rewire_uncommon_proj_phi_inputs) { - assert(parse_predicate_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!"); - ParsePredicateNode* parse_predicate = parse_predicate_proj->in(0)->as_ParsePredicate(); - - ProjNode* uncommon_proj = parse_predicate->proj_out(false); - Node* uct_region = uncommon_proj->unique_ctrl_out(); - assert(uct_region->is_Region() || uct_region->is_Call(), "must be a region or call uct"); + assert(parse_predicate_success_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!"); + ParsePredicateNode* parse_predicate = parse_predicate_success_proj->in(0)->as_ParsePredicate(); + ParsePredicateUncommonProj* uncommon_proj = parse_predicate->uncommon_proj(); + Node* uncommon_trap = parse_predicate->uncommon_trap(); uint proj_index = 1; // region's edge corresponding to uncommon_proj - if (!uct_region->is_Region()) { // create a region to guard the call - assert(uct_region->is_Call(), "must be call uct"); - CallNode* call = uct_region->as_Call(); + if (!uncommon_trap->is_Region()) { // create a region to guard the call + assert(uncommon_trap->is_Call(), "must be call uct"); + CallNode* call = uncommon_trap->as_Call(); IdealLoopTree* loop = get_loop(call); - uct_region = new RegionNode(1); + uncommon_trap = new RegionNode(1); Node* uncommon_proj_orig = uncommon_proj; - uncommon_proj = uncommon_proj->clone()->as_Proj(); + uncommon_proj = uncommon_proj->clone()->as_IfFalse(); register_control(uncommon_proj, loop, parse_predicate); - uct_region->add_req(uncommon_proj); - register_control(uct_region, loop, uncommon_proj); - _igvn.replace_input_of(call, 0, uct_region); + uncommon_trap->add_req(uncommon_proj); + register_control(uncommon_trap, loop, uncommon_proj); + _igvn.replace_input_of(call, 0, uncommon_trap); // When called from beautify_loops() idom is not constructed yet. if (_idom != nullptr) { - set_idom(call, uct_region, dom_depth(uct_region)); + set_idom(call, uncommon_trap, dom_depth(uncommon_trap)); } // Move nodes pinned on the projection or whose control is set to // the projection to the region. - lazy_replace(uncommon_proj_orig, uct_region); + lazy_replace(uncommon_proj_orig, uncommon_trap); } else { // Find region's edge corresponding to uncommon_proj - for (; proj_index < uct_region->req(); proj_index++) - if (uct_region->in(proj_index) == uncommon_proj) break; - assert(proj_index < uct_region->req(), "sanity"); + for (; proj_index < uncommon_trap->req(); proj_index++) + if (uncommon_trap->in(proj_index) == uncommon_proj) break; + assert(proj_index < uncommon_trap->req(), "sanity"); } Node* entry = parse_predicate->in(0); @@ -157,22 +155,23 @@ IfProjNode* PhaseIdealLoop::create_new_if_for_predicate(ParsePredicateSuccessPro fatal("no other If variant here"); } register_control(new_iff, lp, entry); - IfProjNode* if_cont = new IfTrueNode(new_iff); - IfProjNode* if_uct = new IfFalseNode(new_iff); + + IfTrueNode* if_cont = new IfTrueNode(new_iff); + IfFalseNode* if_uct = new IfFalseNode(new_iff); register_control(if_cont, lp, new_iff); - register_control(if_uct, get_loop(uct_region), new_iff); + register_control(if_uct, get_loop(uncommon_trap), new_iff); - _igvn.add_input_to(uct_region, if_uct); + _igvn.add_input_to(uncommon_trap, if_uct); // If rgn has phis add new edges which has the same // value as on original uncommon_proj pass. - assert(uct_region->in(uct_region->req() - 1) == if_uct, "new edge should be last"); + assert(uncommon_trap->in(uncommon_trap->req() - 1) == if_uct, "new edge should be last"); bool has_phi = false; - for (DUIterator_Fast imax, i = uct_region->fast_outs(imax); i < imax; i++) { - Node* use = uct_region->fast_out(i); + for (DUIterator_Fast imax, i = uncommon_trap->fast_outs(imax); i < imax; i++) { + Node* use = uncommon_trap->fast_out(i); if (use->is_Phi() && use->outcnt() > 0) { - assert(use->in(0) == uct_region, ""); + assert(use->in(0) == uncommon_trap, ""); _igvn.rehash_node_delayed(use); Node* phi_input = use->in(proj_index); @@ -193,7 +192,7 @@ IfProjNode* PhaseIdealLoop::create_new_if_for_predicate(ParsePredicateSuccessPro has_phi = true; } } - assert(!has_phi || uct_region->req() > 3, "no phis when region is created"); + assert(!has_phi || uncommon_trap->req() > 3, "no phis when region is created"); if (new_entry == nullptr) { // Attach if_cont to iff @@ -205,12 +204,12 @@ IfProjNode* PhaseIdealLoop::create_new_if_for_predicate(ParsePredicateSuccessPro // When called from beautify_loops() idom is not constructed yet. if (_idom != nullptr) { - Node* ridom = idom(uct_region); + Node* ridom = idom(uncommon_trap); Node* nrdom = dom_lca_internal(ridom, new_iff); - set_idom(uct_region, nrdom, dom_depth(uct_region)); + set_idom(uncommon_trap, nrdom, dom_depth(uncommon_trap)); } - return if_cont->as_IfProj(); + return if_cont; } // Update ctrl and control inputs of all data nodes starting from 'node' to 'new_ctrl' which have 'old_ctrl' as @@ -757,8 +756,8 @@ bool IdealLoopTree::is_range_check_if(IfProjNode* if_success_proj, PhaseIdealLoo // max(scale*i + offset) = scale*(limit-stride) + offset // (2) stride*scale < 0 // max(scale*i + offset) = scale*init + offset -BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree* loop, Node* ctrl, int scale, Node* offset, Node* init, - Node* limit, jint stride, Node* range, bool upper, bool& overflow) { +BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, const int scale, Node* offset, Node* init, Node* limit, + const jint stride, Node* range, const bool upper, bool& overflow) { jint con_limit = (limit != nullptr && limit->is_Con()) ? limit->get_int() : 0; jint con_init = init->is_Con() ? init->get_int() : 0; jint con_offset = offset->is_Con() ? offset->get_int() : 0; @@ -1165,18 +1164,19 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod reason, iff->Opcode()); Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0); - BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); + BoolNode* hoisted_check_predicate_bool = invar.clone(bol, ctrl)->as_Bool(); // Negate test if necessary (Parse Predicates always have IfTrue as success projection and IfFalse as uncommon trap) bool negated = false; if (if_success_proj->is_IfFalse()) { - new_predicate_bol = new BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); - register_new_node(new_predicate_bol, ctrl); + hoisted_check_predicate_bool = new BoolNode(hoisted_check_predicate_bool->in(1), + hoisted_check_predicate_bool->_test.negate()); + register_new_node(hoisted_check_predicate_bool, ctrl); negated = true; } IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If(); _igvn.hash_delete(new_predicate_iff); - new_predicate_iff->set_req(1, new_predicate_bol); + new_predicate_iff->set_req(1, hoisted_check_predicate_bool); C->print_method(PHASE_AFTER_LOOP_PREDICATION_IC, 4, new_predicate_proj->in(0)); @@ -1220,7 +1220,8 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod // Perform cloning to keep Invariance state correct since the // late schedule will place invariant things in the loop. - Node* ctrl = parse_predicate_proj->in(0)->as_If()->in(0); + ParsePredicateNode* parse_predicate = parse_predicate_proj->in(0)->as_ParsePredicate(); + Node* ctrl = parse_predicate->in(0); rng = invar.clone(rng, ctrl); if (offset && offset != zero) { assert(invar.is_invariant(offset), "offset must be loop invariant"); @@ -1229,25 +1230,28 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod // If predicate expressions may overflow in the integer range, longs are used. bool overflow = false; // Test the lower bound - BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow); + BoolNode* lower_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, rng, false, overflow); const int if_opcode = iff->Opcode(); IfProjNode* lower_bound_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : if_opcode); IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If(); _igvn.hash_delete(lower_bound_iff); lower_bound_iff->set_req(1, lower_bound_bol); - if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); + if (TraceLoopPredicate) { + tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); + } // Test the upper bound - BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, - overflow); + BoolNode* upper_bound_bol = rc_predicate(lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow); IfProjNode* upper_bound_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : if_opcode); assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); _igvn.hash_delete(upper_bound_iff); upper_bound_iff->set_req(1, upper_bound_bol); - if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", upper_bound_iff->_idx); + if (TraceLoopPredicate) { + tty->print_cr("upper bound check if: %d", upper_bound_iff->_idx); + } // Fall through into rest of the cleanup code which will move any dependent nodes to the skeleton predicates of the // upper bound test. We always need to create skeleton predicates in order to properly remove dead loops when later @@ -1294,7 +1298,7 @@ IfProjNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL Node* opaque_init = new OpaqueLoopInitNode(C, init); register_new_node(opaque_init, upper_bound_proj); bool negate = (if_proj->_con != parse_predicate_proj->_con); - BoolNode* bol = rc_predicate(loop, upper_bound_proj, scale, offset, opaque_init, limit, stride, rng, + BoolNode* bol = rc_predicate(upper_bound_proj, scale, offset, opaque_init, limit, stride, rng, (stride > 0) != (scale > 0), overflow); Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1)); // This will go away once loop opts are over C->add_template_assertion_predicate_opaq(opaque_bol); @@ -1317,7 +1321,7 @@ IfProjNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL max_value = new CastIINode(max_value, loop->_head->as_CountedLoop()->phi()->bottom_type()); register_new_node(max_value, parse_predicate_proj); - bol = rc_predicate(loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0) != (scale > 0), + bol = rc_predicate(new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0) != (scale > 0), overflow); opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1)); C->add_template_assertion_predicate_opaq(opaque_bol); @@ -1340,10 +1344,6 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree* loop) { return false; } - if (head->is_OuterStripMinedLoop()) { - return false; - } - CountedLoopNode *cl = nullptr; if (head->is_valid_counted_loop(T_INT)) { cl = head->as_CountedLoop(); @@ -1514,19 +1514,20 @@ bool PhaseIdealLoop::can_create_loop_predicates(const PredicateBlock* profiled_l //------------------------------loop_predication-------------------------------- // driver routine for loop predication optimization -bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) { +bool IdealLoopTree::loop_predication(PhaseIdealLoop* phase) { bool hoisted = false; // Recursively promote predicates if (_child) { hoisted = _child->loop_predication( phase); } - // self + // Self if (can_apply_loop_predication()) { hoisted |= phase->loop_predication_impl(this); } - if (_next) { //sibling + // Sibling + if (_next) { hoisted |= _next->loop_predication( phase); } @@ -1534,5 +1535,9 @@ bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) { } bool IdealLoopTree::can_apply_loop_predication() { - return _head->is_Loop() && !_irreducible && !tail()->is_top(); + return !_head->is_Root() && + _head->is_Loop() && + !_head->is_OuterStripMinedLoop() && + !_irreducible && + !tail()->is_top(); } diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 24861cf2725ef..f2022d35cf651 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -2772,7 +2772,7 @@ Node* PhaseIdealLoop::add_range_check_elimination_assertion_predicate(IdealLoopT Node* offset, Node* limit, jint stride_con, Node* value) { bool overflow = false; - BoolNode* bol = rc_predicate(loop, ctrl, scale_con, offset, value, nullptr, stride_con, + BoolNode* bol = rc_predicate(ctrl, scale_con, offset, value, nullptr, stride_con, limit, (stride_con > 0) != (scale_con > 0), overflow); Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1)); register_new_node(opaque_bol, ctrl); diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index fcd0e1a4df2ca..fac7cf32f60bc 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -4320,7 +4320,7 @@ void PhaseIdealLoop::mark_loop_associated_parse_predicates_useful() { } void PhaseIdealLoop::mark_useful_parse_predicates_for_loop(IdealLoopTree* loop) { - Node* entry = loop->_head->in(LoopNode::EntryControl); + Node* entry = loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl); const Predicates predicates(entry); ParsePredicateIterator iterator(predicates); while (iterator.has_next()) { @@ -4359,7 +4359,7 @@ void PhaseIdealLoop::collect_useful_template_assertion_predicates(Unique_Node_Li void PhaseIdealLoop::collect_useful_template_assertion_predicates_for_loop(IdealLoopTree* loop, Unique_Node_List &useful_predicates) { - Node* entry = loop->_head->in(LoopNode::EntryControl); + Node* entry = loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl); const Predicates predicates(entry); if (UseProfiledLoopPredicate) { const PredicateBlock* profiled_loop_predicate_block = predicates.profiled_loop_predicate_block(); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 75276aae36d22..f7ba4578a51b2 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1337,7 +1337,7 @@ class PhaseIdealLoop : public PhaseTransform { bool* p_short_scale, int depth); // Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted - IfProjNode* create_new_if_for_predicate(ParsePredicateSuccessProj* parse_predicate_proj, Node* new_entry, + IfTrueNode* create_new_if_for_predicate(ParsePredicateSuccessProj* parse_predicate_proj, Node* new_entry, Deoptimization::DeoptReason reason, int opcode, bool rewire_uncommon_proj_phi_inputs = false); @@ -1360,7 +1360,7 @@ class PhaseIdealLoop : public PhaseTransform { } // Construct a range check for a predicate if - BoolNode* rc_predicate(IdealLoopTree* loop, Node* ctrl, int scale, Node* offset, Node* init, Node* limit, + BoolNode* rc_predicate(Node* ctrl, int scale, Node* offset, Node* init, Node* limit, jint stride, Node* range, bool upper, bool& overflow); // Implementation of the loop predication to promote checks outside the loop From 15862a2f116331b7f439619c3aa1b5965e737044 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 6 May 2024 08:48:46 +0000 Subject: [PATCH 093/203] 8331708: jdk/internal/jline/RedirectedStdOut.java times-out on macosx-aarch64 Reviewed-by: asotona --- test/jdk/jdk/internal/jline/RedirectedStdOut.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/jdk/jdk/internal/jline/RedirectedStdOut.java b/test/jdk/jdk/internal/jline/RedirectedStdOut.java index 7cbf913219a7d..fb614e3d7540f 100644 --- a/test/jdk/jdk/internal/jline/RedirectedStdOut.java +++ b/test/jdk/jdk/internal/jline/RedirectedStdOut.java @@ -29,9 +29,11 @@ * @modules jdk.internal.le * @library /test/lib * @run main RedirectedStdOut runRedirectAllTest - * @run main/othervm RedirectedStdOut runRedirectOutOnly + * @run main/othervm --enable-native-access=ALL-UNNAMED RedirectedStdOut runRedirectOutOnly */ +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; @@ -58,7 +60,6 @@ public static void main(String... args) throws Throwable { //verify the case where neither stdin/out/err is attached to a terminal, //this test is weaker, but more reliable: void runRedirectAllTest() throws Exception { - if (true) return ; ProcessBuilder builder = ProcessTools.createTestJavaProcessBuilder(ConsoleTest.class.getName()); OutputAnalyzer output = ProcessTools.executeProcess(builder); @@ -147,6 +148,10 @@ void runRedirectOutOnly() throws Throwable { loginttyDescriptor); logintty.invoke(child.get(ValueLayout.JAVA_INT, 0)); + //createTestJavaProcessBuilder logs to (current process') System.out, but + //that may not work since the redirect. Setting System.out to a scratch value: + System.setOut(new PrintStream(new ByteArrayOutputStream())); + ProcessBuilder builder = ProcessTools.createTestJavaProcessBuilder(ConsoleTest.class.getName()); From 6c7764118ef1a684edddb302a4eaff36d80c783f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Casta=C3=B1eda=20Lozano?= Date: Mon, 6 May 2024 09:26:53 +0000 Subject: [PATCH 094/203] 8331418: ZGC: generalize barrier liveness logic Reviewed-by: mdoerr, aboldtch, fyang, eosterlund --- .../gc/shared/barrierSetAssembler_aarch64.cpp | 12 ++--- .../ppc/gc/shared/barrierSetAssembler_ppc.cpp | 7 +-- .../ppc/gc/shared/barrierSetAssembler_ppc.hpp | 1 - .../gc/shared/barrierSetAssembler_riscv.cpp | 10 ++-- .../x86/gc/shared/barrierSetAssembler_x86.cpp | 9 +--- .../share/gc/shared/c2/barrierSetC2.cpp | 51 +++++++++++++++---- .../share/gc/shared/c2/barrierSetC2.hpp | 19 ++++++- src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp | 15 +++--- src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp | 3 -- 9 files changed, 75 insertions(+), 52 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp index 62414611cce5f..6c2b12fc7a8f2 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp @@ -476,7 +476,7 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) { GrowableArray registers; VMReg prev_vm_reg = VMRegImpl::Bad(); - RegMaskIterator rmi(stub->live()); + RegMaskIterator rmi(stub->preserve_set()); while (rmi.has_next()) { OptoReg::Name opto_reg = rmi.next(); VMReg vm_reg = OptoReg::as_VMReg(opto_reg); @@ -491,7 +491,7 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) { index = registers.append(reg_data); } } else if (vm_reg->is_FloatRegister()) { - // We have size encoding in OptoReg of stub->live() + // We have size encoding in OptoReg of stub->preserve_set() // After encoding, float/neon/sve register has only one slot in regmask // Decode it to get the actual size VMReg vm_reg_base = vm_reg->as_FloatRegister()->as_VMReg(); @@ -532,12 +532,8 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) { } } - // Remove C-ABI SOE registers, scratch regs and _ref register that will be updated - if (stub->result() != noreg) { - _gp_regs -= RegSet::range(r19, r30) + RegSet::of(r8, r9, stub->result()); - } else { - _gp_regs -= RegSet::range(r19, r30) + RegSet::of(r8, r9); - } + // Remove C-ABI SOE registers and scratch regs + _gp_regs -= RegSet::range(r19, r30) + RegSet::of(r8, r9); // Remove C-ABI SOE fp registers _fp_regs -= FloatRegSet::range(v8, v15); diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp index 3bb205d659f0c..16de0b6a7ddd5 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp @@ -282,7 +282,7 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na #define __ _masm-> SaveLiveRegisters::SaveLiveRegisters(MacroAssembler *masm, BarrierStubC2 *stub) - : _masm(masm), _reg_mask(stub->live()), _result_reg(stub->result()) { + : _masm(masm), _reg_mask(stub->preserve_set()) { const int register_save_size = iterate_over_register_mask(ACTION_COUNT_ONLY) * BytesPerWord; _frame_size = align_up(register_save_size, frame::alignment_in_bytes) @@ -317,11 +317,6 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of if (vm_reg->is_Register()) { Register std_reg = vm_reg->as_Register(); - // '_result_reg' will hold the end result of the operation. Its content must thus not be preserved. - if (std_reg == _result_reg) { - continue; - } - if (std_reg->encoding() >= R2->encoding() && std_reg->encoding() <= R12->encoding()) { reg_save_index++; diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp index d70fce77acc91..9c1cef5eea46c 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp @@ -98,7 +98,6 @@ class BarrierSetAssembler: public CHeapObj { class SaveLiveRegisters { MacroAssembler* _masm; RegMask _reg_mask; - Register _result_reg; int _frame_size; public: diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp index f411a5572c7c8..cbf8de7341d0d 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp @@ -396,7 +396,7 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na void SaveLiveRegisters::initialize(BarrierStubC2* stub) { // Record registers that needs to be saved/restored - RegMaskIterator rmi(stub->live()); + RegMaskIterator rmi(stub->preserve_set()); while (rmi.has_next()) { const OptoReg::Name opto_reg = rmi.next(); if (OptoReg::is_reg(opto_reg)) { @@ -414,12 +414,8 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) { } } - // Remove C-ABI SOE registers, tmp regs and _ref register that will be updated - if (stub->result() != noreg) { - _gp_regs -= RegSet::range(x18, x27) + RegSet::of(x2) + RegSet::of(x8, x9) + RegSet::of(x5, stub->result()); - } else { - _gp_regs -= RegSet::range(x18, x27) + RegSet::of(x2, x5) + RegSet::of(x8, x9); - } + // Remove C-ABI SOE registers and tmp regs + _gp_regs -= RegSet::range(x18, x27) + RegSet::of(x2, x5) + RegSet::of(x8, x9); } SaveLiveRegisters::SaveLiveRegisters(MacroAssembler* masm, BarrierStubC2* stub) diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index a06fde061f85f..a6801f594bd09 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -613,19 +613,12 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) { caller_saved.Insert(OptoReg::as_OptoReg(r10->as_VMReg())); caller_saved.Insert(OptoReg::as_OptoReg(r11->as_VMReg())); - if (stub->result() != noreg) { - caller_saved.Remove(OptoReg::as_OptoReg(stub->result()->as_VMReg())); - } - - // Create mask of live registers - RegMask live = stub->live(); - int gp_spill_size = 0; int opmask_spill_size = 0; int xmm_spill_size = 0; // Record registers that needs to be saved/restored - RegMaskIterator rmi(live); + RegMaskIterator rmi(stub->preserve_set()); while (rmi.has_next()) { const OptoReg::Name opto_reg = rmi.next(); const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index 3f712c9d3912a..53e4d7fdf8fb7 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -87,15 +87,16 @@ static BarrierSetC2State* barrier_set_state() { return reinterpret_cast(Compile::current()->barrier_set_state()); } -BarrierStubC2::BarrierStubC2(const MachNode* node) - : _node(node), - _entry(), - _continuation() {} - RegMask& BarrierStubC2::live() const { return *barrier_set_state()->live(_node); } +BarrierStubC2::BarrierStubC2(const MachNode* node) + : _node(node), + _entry(), + _continuation(), + _preserve(live()) {} + Label* BarrierStubC2::entry() { // The _entry will never be bound when in_scratch_emit_size() is true. // However, we still need to return a label that is not bound now, but @@ -108,6 +109,27 @@ Label* BarrierStubC2::continuation() { return &_continuation; } +void BarrierStubC2::preserve(Register r) { + const VMReg vm_reg = r->as_VMReg(); + assert(vm_reg->is_Register(), "r must be a general-purpose register"); + _preserve.Insert(OptoReg::as_OptoReg(vm_reg)); +} + +void BarrierStubC2::dont_preserve(Register r) { + VMReg vm_reg = r->as_VMReg(); + assert(vm_reg->is_Register(), "r must be a general-purpose register"); + // Subtract the given register and all its sub-registers (e.g. {R11, R11_H} + // for r11 in aarch64). + do { + _preserve.Remove(OptoReg::as_OptoReg(vm_reg)); + vm_reg = vm_reg->next(); + } while (vm_reg->is_Register() && !vm_reg->is_concrete()); +} + +const RegMask& BarrierStubC2::preserve_set() const { + return _preserve; +} + Node* BarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const { DecoratorSet decorators = access.decorators(); @@ -828,6 +850,7 @@ void BarrierSetC2::compute_liveness_at_stubs() const { PhaseRegAlloc* const regalloc = C->regalloc(); RegMask* const live = NEW_ARENA_ARRAY(A, RegMask, cfg->number_of_blocks() * sizeof(RegMask)); BarrierSetAssembler* const bs = BarrierSet::barrier_set()->barrier_set_assembler(); + BarrierSetC2State* bs_state = barrier_set_state(); Block_List worklist; for (uint i = 0; i < cfg->number_of_blocks(); ++i) { @@ -850,6 +873,14 @@ void BarrierSetC2::compute_liveness_at_stubs() const { for (int i = block->number_of_nodes() - 1; i >= 0; --i) { const Node* const node = block->get_node(i); + // If this node tracks out-liveness, update it + if (!bs_state->needs_livein_data()) { + RegMask* const regs = bs_state->live(node); + if (regs != nullptr) { + regs->OR(new_live); + } + } + // Remove def bits const OptoReg::Name first = bs->refine_register(node, regalloc->get_reg_first(node)); const OptoReg::Name second = bs->refine_register(node, regalloc->get_reg_second(node)); @@ -873,10 +904,12 @@ void BarrierSetC2::compute_liveness_at_stubs() const { } } - // If this node tracks liveness, update it - RegMask* const regs = barrier_set_state()->live(node); - if (regs != NULL) { - regs->OR(new_live); + // If this node tracks in-liveness, update it + if (bs_state->needs_livein_data()) { + RegMask* const regs = bs_state->live(node); + if (regs != nullptr) { + regs->OR(new_live); + } } } diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp index aa2df96412da7..8787fe83d1470 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp @@ -227,6 +227,7 @@ class BarrierSetC2State : public ArenaObj { } virtual bool needs_liveness_data(const MachNode* mach) const = 0; + virtual bool needs_livein_data() const = 0; }; // This class represents the slow path in a C2 barrier. It is defined by a @@ -238,14 +239,28 @@ class BarrierStubC2 : public ArenaObj { const MachNode* _node; Label _entry; Label _continuation; + RegMask _preserve; + + // Registers that are live-in/live-out of the entire memory access + // implementation (possibly including multiple barriers). Whether live-in or + // live-out registers are returned depends on + // BarrierSetC2State::needs_livein_data(). + RegMask& live() const; public: BarrierStubC2(const MachNode* node); - RegMask& live() const; + + // Entry point to the stub. Label* entry(); + // Return point from the stub (typically end of barrier). Label* continuation(); - virtual Register result() const = 0; + // Preserve the value in reg across runtime calls in this barrier. + void preserve(Register reg); + // Do not preserve the value in reg across runtime calls in this barrier. + void dont_preserve(Register reg); + // Set of registers whose value needs to be preserved across runtime calls in this barrier. + const RegMask& preserve_set() const; }; // This is the top-level class for the backend of the Access API in C2. diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp index 85d4555320290..4b79b56824128 100644 --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp @@ -142,6 +142,10 @@ class ZBarrierSetC2State : public BarrierSetC2State { return mach->barrier_data() != ZBarrierElided; } + bool needs_livein_data() const { + return true; + } + void inc_trampoline_stubs_count() { assert(_trampoline_stubs_count != INT_MAX, "Overflow"); ++_trampoline_stubs_count; @@ -200,6 +204,9 @@ ZLoadBarrierStubC2::ZLoadBarrierStubC2(const MachNode* node, Address ref_addr, R _ref(ref) { assert_different_registers(ref, ref_addr.base()); assert_different_registers(ref, ref_addr.index()); + // The runtime call updates the value of ref, so we should not spill and + // reload its outdated value. + dont_preserve(ref); } Address ZLoadBarrierStubC2::ref_addr() const { @@ -210,10 +217,6 @@ Register ZLoadBarrierStubC2::ref() const { return _ref; } -Register ZLoadBarrierStubC2::result() const { - return ref(); -} - address ZLoadBarrierStubC2::slow_path() const { const uint8_t barrier_data = _node->barrier_data(); DecoratorSet decorators = DECORATORS_NONE; @@ -272,10 +275,6 @@ bool ZStoreBarrierStubC2::is_atomic() const { return _is_atomic; } -Register ZStoreBarrierStubC2::result() const { - return noreg; -} - void ZStoreBarrierStubC2::emit_code(MacroAssembler& masm) { ZBarrierSet::assembler()->generate_c2_store_barrier_stub(&masm, static_cast(this)); } diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp index f8892defcfff5..bf46780226eea 100644 --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp @@ -51,7 +51,6 @@ static int stubs_start_offset(); ZBarrierStubC2(const MachNode* node); public: - virtual Register result() const = 0; virtual void emit_code(MacroAssembler& masm) = 0; }; @@ -70,7 +69,6 @@ class ZLoadBarrierStubC2 : public ZBarrierStubC2 { Register ref() const; address slow_path() const; - virtual Register result() const; virtual void emit_code(MacroAssembler& masm); }; @@ -94,7 +92,6 @@ class ZStoreBarrierStubC2 : public ZBarrierStubC2 { bool is_native() const; bool is_atomic() const; - virtual Register result() const; virtual void emit_code(MacroAssembler& masm); }; From 9b0bb03366642dd787b02809b3759ed714da9b81 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 6 May 2024 09:41:07 +0000 Subject: [PATCH 095/203] 8331285: Deprecate and obsolete OldSize Reviewed-by: dholmes, eosterlund --- src/hotspot/share/gc/shared/gc_globals.hpp | 2 +- src/hotspot/share/runtime/arguments.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 13583874d84a0..42d9e028b5e0c 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -541,7 +541,7 @@ constraint(SoftMaxHeapSizeConstraintFunc,AfterMemoryInit) \ \ product(size_t, OldSize, ScaleForWordSize(4*M), \ - "Initial tenured generation size (in bytes)") \ + "(Deprecated) Initial tenured generation size (in bytes)") \ range(0, max_uintx) \ \ product(size_t, NewSize, ScaleForWordSize(1*M), \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index f2b370037311c..ee8c7b24541bc 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -502,6 +502,7 @@ static SpecialFlag const special_jvm_flags[] = { { "UseSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "RegisterFinalizersAtInit", JDK_Version::jdk(22), JDK_Version::jdk(23), JDK_Version::jdk(24) }, { "DontYieldALot", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, + { "OldSize", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, { "PreserveAllAnnotations", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, { "UseNotificationThread", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, { "UseEmptySlotsInSupers", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::jdk(25) }, From e8a2d5669cda59d0f9a10e5a8035c20b8678d3d8 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 6 May 2024 11:01:55 +0000 Subject: [PATCH 096/203] 8331653: JFR: Improve logging for jdk/jfr/api/consumer/recordingstream;TestStop.java Reviewed-by: mgronlun --- .../consumer/recordingstream/TestStop.java | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java index 5cabd9e688456..58dcbbcbe2079 100644 --- a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java +++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java @@ -24,9 +24,10 @@ package jdk.jfr.api.consumer.recordingstream; import java.nio.file.Path; +import java.time.Instant; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicLong; +import java.util.Collections; import jdk.jfr.Event; import jdk.jfr.consumer.RecordedEvent; @@ -106,10 +107,10 @@ private static void testStopFromOtherThread() throws Exception { } private static void testNestedStop() throws Exception { - AtomicLong outerCount = new AtomicLong(); - AtomicLong innerCount = new AtomicLong(); + List outerStream = Collections.synchronizedList(new ArrayList<>()); + List innerStream = Collections.synchronizedList(new ArrayList<>()); try (RecordingStream outer = new RecordingStream()) { - outer.onEvent(e -> outerCount.incrementAndGet()); + outer.onEvent(e -> outerStream.add(eventToText(e))); outer.setMaxSize(100_000_000); outer.startAsync(); @@ -119,7 +120,7 @@ private static void testNestedStop() throws Exception { try (RecordingStream inner = new RecordingStream()) { inner.setMaxSize(100_000_000); - inner.onEvent(e -> innerCount.incrementAndGet()); + inner.onEvent(e -> innerStream.add(eventToText(e))); inner.startAsync(); MarkEvent b = new MarkEvent(); @@ -138,30 +139,49 @@ private static void testNestedStop() throws Exception { Path fileInner = Path.of("inner.jfr"); inner.dump(fileInner); outer.dump(fileOuter); - System.out.println("RecordingStream outer:"); + System.out.println("Outer dump:"); var dumpOuter = RecordingFile.readAllEvents(fileOuter); - System.out.println(dumpOuter); - System.out.println("RecordingStream inner:"); + for (RecordedEvent e : dumpOuter) { + System.out.println(eventToText(e)); + } + System.out.println("Inner dump:"); var dumpInner = RecordingFile.readAllEvents(fileInner); - System.out.println(dumpInner); - System.out.println("Outer count: " + outerCount); - System.out.println("Inner count: " + innerCount); + for (RecordedEvent e : dumpInner) { + System.out.println(eventToText(e)); + } + System.out.println(); + System.out.println("Outer stream:"); + for (String s : outerStream) { + System.out.println(s); + } + System.out.println("Inner stream:"); + for (String s : innerStream) { + System.out.println(s); + } if (dumpOuter.size() != 3) { throw new AssertionError("Expected outer dump to have 3 events"); } - if (outerCount.get() != 3) { + if (outerStream.size() != 3) { throw new AssertionError("Expected outer stream to have 3 events"); } if (dumpInner.size() != 1) { throw new AssertionError("Expected inner dump to have 1 event"); } - if (innerCount.get() != 1) { + if (innerStream.size() != 1) { throw new AssertionError("Expected inner stream to have 1 event"); } } } } + private static String eventToText(RecordedEvent event) { + Instant timestamp = event.getEndTime(); + long s = timestamp.getEpochSecond(); + int n = timestamp.getNano(); + String id = event.getString("id"); + return id + ": n=" + n + " s=" + s + " t=" + timestamp; + } + static void testStopClosed() { try (RecordingStream rs = new RecordingStream()) { rs.close(); From 1eec30a6c03b7f4028405dc9bdb4d2a663b3987d Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 6 May 2024 11:17:39 +0000 Subject: [PATCH 097/203] 8331573: Rename CollectedHeap::is_gc_active to be explicitly about STW GCs Reviewed-by: stefank, zgu, tschatzl, gli --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 4 +-- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 2 +- .../share/gc/g1/g1CollectedHeap.inline.hpp | 4 +-- src/hotspot/share/gc/g1/g1FullGCScope.hpp | 2 +- src/hotspot/share/gc/g1/g1RemSet.cpp | 2 +- src/hotspot/share/gc/g1/g1VMOperations.cpp | 2 +- .../gc/parallel/parallelScavengeHeap.cpp | 2 +- .../share/gc/parallel/psParallelCompact.cpp | 10 +++---- src/hotspot/share/gc/parallel/psScavenge.cpp | 10 +++---- src/hotspot/share/gc/serial/serialHeap.cpp | 4 +-- src/hotspot/share/gc/shared/collectedHeap.cpp | 2 +- src/hotspot/share/gc/shared/collectedHeap.hpp | 12 ++++----- .../share/gc/shared/isGCActiveMark.cpp | 26 +++++++++---------- .../share/gc/shared/isGCActiveMark.hpp | 14 +++++----- src/hotspot/share/gc/shared/memAllocator.cpp | 2 +- src/hotspot/share/gc/shared/vmStructs_gc.hpp | 2 +- .../share/gc/shenandoah/shenandoahUtils.hpp | 2 +- src/hotspot/share/gc/x/xDriver.cpp | 2 +- src/hotspot/share/gc/z/zGeneration.cpp | 2 +- src/hotspot/share/gc/z/zVerify.cpp | 2 +- src/hotspot/share/jvmci/jvmciRuntime.cpp | 2 +- src/hotspot/share/memory/universe.cpp | 4 +-- src/hotspot/share/memory/universe.hpp | 2 +- src/hotspot/share/oops/method.cpp | 2 +- src/hotspot/share/oops/oop.cpp | 2 +- src/hotspot/share/prims/forte.cpp | 2 +- src/hotspot/share/runtime/jniHandles.cpp | 4 +-- 27 files changed, 62 insertions(+), 64 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index f8031c35b9a3a..a7b9852f55170 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2399,7 +2399,7 @@ void G1CollectedHeap::expand_heap_after_young_collection(){ bool G1CollectedHeap::do_collection_pause_at_safepoint() { assert_at_safepoint_on_vm_thread(); - guarantee(!is_gc_active(), "collection is not reentrant"); + guarantee(!is_stw_gc_active(), "collection is not reentrant"); do_collection_pause_at_safepoint_helper(); return true; @@ -2469,7 +2469,7 @@ void G1CollectedHeap::flush_region_pin_cache() { void G1CollectedHeap::do_collection_pause_at_safepoint_helper() { ResourceMark rm; - IsGCActiveMark active_gc_mark; + IsSTWGCActiveMark active_gc_mark; GCIdMark gc_id_mark; SvcGCMarker sgcm(SvcGCMarker::MINOR); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 3aaa6d8b72342..4695d12b43514 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -749,7 +749,7 @@ class G1CollectedHeap : public CollectedHeap { // false if unable to do the collection due to the GC locker being // active, true otherwise. // precondition: at safepoint on VM thread - // precondition: !is_gc_active() + // precondition: !is_stw_gc_active() bool do_collection_pause_at_safepoint(); // Helper for do_collection_pause_at_safepoint, containing the guts diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp index 30ca270e1b568..0a4ee053548dc 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp @@ -265,7 +265,7 @@ inline bool G1CollectedHeap::is_obj_dead(const oop obj, const HeapRegion* hr) co inline void G1CollectedHeap::pin_object(JavaThread* thread, oop obj) { assert(obj != nullptr, "obj must not be null"); - assert(!is_gc_active(), "must not pin objects during a GC"); + assert(!is_stw_gc_active(), "must not pin objects during a GC pause"); assert(obj->is_typeArray(), "must be typeArray"); uint obj_region_idx = heap_region_containing(obj)->hrm_index(); @@ -274,7 +274,7 @@ inline void G1CollectedHeap::pin_object(JavaThread* thread, oop obj) { inline void G1CollectedHeap::unpin_object(JavaThread* thread, oop obj) { assert(obj != nullptr, "obj must not be null"); - assert(!is_gc_active(), "must not unpin objects during a GC"); + assert(!is_stw_gc_active(), "must not unpin objects during a GC pause"); uint obj_region_idx = heap_region_containing(obj)->hrm_index(); G1ThreadLocalData::pin_count_cache(thread).dec_count(obj_region_idx); diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.hpp b/src/hotspot/share/gc/g1/g1FullGCScope.hpp index f3d89c7646f61..ab3b99fea0494 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.hpp @@ -52,7 +52,7 @@ class G1FullGCScope : public StackObj { SvcGCMarker _svc_marker; STWGCTimer _timer; G1FullGCTracer* _tracer; - IsGCActiveMark _active; + IsSTWGCActiveMark _active; G1FullGCJFRTracerMark _tracer_mark; ClearedAllSoftRefs _soft_refs; G1FullGCMonitoringScope _monitoring_scope; diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index 65aa0ff18ab0c..a47fd379a7038 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1564,7 +1564,7 @@ bool G1RemSet::clean_card_before_refine(CardValue** const card_ptr_addr) { void G1RemSet::refine_card_concurrently(CardValue* const card_ptr, const uint worker_id) { - assert(!_g1h->is_gc_active(), "Only call concurrently"); + assert(!_g1h->is_stw_gc_active(), "Only call concurrently"); check_card_ptr(card_ptr, _ct); // Construct the MemRegion representing the card. diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index c2254e4287f38..11702c9841658 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -146,7 +146,7 @@ void VM_G1PauseConcurrent::doit() { G1ConcGCMonitoringScope monitoring_scope(g1h->monitoring_support()); SvcGCMarker sgcm(SvcGCMarker::CONCURRENT); - IsGCActiveMark x; + IsSTWGCActiveMark x; work(); } diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 0ced8ed9336e8..f4df7c57bfc19 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -459,7 +459,7 @@ void ParallelScavengeHeap::do_full_collection(bool clear_all_soft_refs) { HeapWord* ParallelScavengeHeap::failed_mem_allocate(size_t size) { assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread"); - assert(!is_gc_active(), "not reentrant"); + assert(!is_stw_gc_active(), "not reentrant"); assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); // We assume that allocation in eden will fail unless we collect. diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 8ac16e059b1ea..4f5c0e1603fb5 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1269,9 +1269,9 @@ bool PSParallelCompact::invoke(bool maximum_heap_compaction) { "should be in vm thread"); ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - assert(!heap->is_gc_active(), "not reentrant"); + assert(!heap->is_stw_gc_active(), "not reentrant"); - IsGCActiveMark mark; + IsSTWGCActiveMark mark; const bool clear_all_soft_refs = heap->soft_ref_policy()->should_clear_all_soft_refs(); @@ -1492,7 +1492,7 @@ class PCAddThreadRootsMarkingTaskClosure : public ThreadClosure { public: PCAddThreadRootsMarkingTaskClosure(uint worker_id) : _worker_id(worker_id) { } void do_thread(Thread* thread) { - assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); + assert(ParallelScavengeHeap::heap()->is_stw_gc_active(), "called outside gc"); ResourceMark rm; @@ -1509,7 +1509,7 @@ class PCAddThreadRootsMarkingTaskClosure : public ThreadClosure { }; void steal_marking_work(TaskTerminator& terminator, uint worker_id) { - assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); + assert(ParallelScavengeHeap::heap()->is_stw_gc_active(), "called outside gc"); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(worker_id); @@ -1986,7 +1986,7 @@ void PSParallelCompact::write_block_fill_histogram() #endif // #ifdef ASSERT static void compaction_with_stealing_work(TaskTerminator* terminator, uint worker_id) { - assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); + assert(ParallelScavengeHeap::heap()->is_stw_gc_active(), "called outside gc"); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(worker_id); diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index ac7ca1bb8b7b3..c39cf96645dd2 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -84,7 +84,7 @@ ParallelScavengeTracer PSScavenge::_gc_tracer; CollectorCounters* PSScavenge::_counters = nullptr; static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_id) { - assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); + assert(ParallelScavengeHeap::heap()->is_stw_gc_active(), "called outside gc"); PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(worker_id); PSPromoteRootsClosure roots_to_old_closure(pm); @@ -115,7 +115,7 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i } static void steal_work(TaskTerminator& terminator, uint worker_id) { - assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); + assert(ParallelScavengeHeap::heap()->is_stw_gc_active(), "called outside gc"); PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(worker_id); @@ -232,11 +232,11 @@ class ParallelScavengeRefProcProxyTask : public RefProcProxyTask { bool PSScavenge::invoke() { assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread"); - assert(!ParallelScavengeHeap::heap()->is_gc_active(), "not reentrant"); + assert(!ParallelScavengeHeap::heap()->is_stw_gc_active(), "not reentrant"); ParallelScavengeHeap* const heap = ParallelScavengeHeap::heap(); PSAdaptiveSizePolicy* policy = heap->size_policy(); - IsGCActiveMark mark; + IsSTWGCActiveMark mark; const bool scavenge_done = PSScavenge::invoke_no_policy(); const bool need_full_gc = !scavenge_done; @@ -264,7 +264,7 @@ class PSThreadRootsTaskClosure : public ThreadClosure { public: PSThreadRootsTaskClosure(uint worker_id) : _worker_id(worker_id) { } virtual void do_thread(Thread* thread) { - assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc"); + assert(ParallelScavengeHeap::heap()->is_stw_gc_active(), "called outside gc"); PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(_worker_id); PSScavengeRootsClosure roots_closure(pm); diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index efcc5307e9fef..b5bcd949c949a 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -484,7 +484,7 @@ void SerialHeap::do_collection(bool full, assert(my_thread->is_VM_thread(), "only VM thread"); assert(Heap_lock->is_locked(), "the requesting thread should have the Heap_lock"); - guarantee(!is_gc_active(), "collection is not reentrant"); + guarantee(!is_stw_gc_active(), "collection is not reentrant"); if (GCLocker::check_active_before_gc()) { return; // GC is disabled (e.g. JNI GetXXXCritical operation) @@ -495,7 +495,7 @@ void SerialHeap::do_collection(bool full, ClearedAllSoftRefs casr(do_clear_all_soft_refs, soft_ref_policy()); - IsGCActiveMark active_gc_mark; + IsSTWGCActiveMark active_gc_mark; bool complete = full && (max_generation == OldGen); bool old_collects_young = complete; diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 2e79d6c567cb1..82eaaf9a39673 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -243,7 +243,7 @@ CollectedHeap::CollectedHeap() : _capacity_at_last_gc(0), _used_at_last_gc(0), _soft_ref_policy(), - _is_gc_active(false), + _is_stw_gc_active(false), _last_whole_heap_examined_time_ns(os::javaTimeNanos()), _total_collections(0), _total_full_collections(0), diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index b2ec4b6732587..6fbe6d708972b 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -90,8 +90,8 @@ class ParallelObjectIterator : public StackObj { class CollectedHeap : public CHeapObj { friend class VMStructs; friend class JVMCIVMStructs; - friend class IsGCActiveMark; // Block structured external access to _is_gc_active - friend class DisableIsGCActiveMark; // Disable current IsGCActiveMark + friend class IsSTWGCActiveMark; // Block structured external access to _is_stw_gc_active + friend class DisableIsSTWGCActiveMark; // Disable current IsSTWGCActiveMark friend class MemAllocator; friend class ParallelObjectIterator; @@ -112,7 +112,7 @@ class CollectedHeap : public CHeapObj { // Not used by all GCs MemRegion _reserved; - bool _is_gc_active; + bool _is_stw_gc_active; // (Minimum) Alignment reserve for TLABs and PLABs. static size_t _lab_alignment_reserve; @@ -374,10 +374,8 @@ class CollectedHeap : public CHeapObj { // allocated object. virtual bool requires_barriers(stackChunkOop obj) const = 0; - // Returns "true" iff there is a stop-world GC in progress. (I assume - // that it should answer "false" for the concurrent part of a concurrent - // collector -- dld). - bool is_gc_active() const { return _is_gc_active; } + // Returns "true" iff there is a stop-world GC in progress. + bool is_stw_gc_active() const { return _is_stw_gc_active; } // Total number of GC collections (started) unsigned int total_collections() const { return _total_collections; } diff --git a/src/hotspot/share/gc/shared/isGCActiveMark.cpp b/src/hotspot/share/gc/shared/isGCActiveMark.cpp index c797ff43e5aeb..add6acaa01a22 100644 --- a/src/hotspot/share/gc/shared/isGCActiveMark.cpp +++ b/src/hotspot/share/gc/shared/isGCActiveMark.cpp @@ -29,28 +29,28 @@ #include "utilities/debug.hpp" // This class provides a method for block structured setting of the -// _is_gc_active state without requiring accessors in CollectedHeap +// _is_stw_gc_active state without requiring accessors in CollectedHeap -IsGCActiveMark::IsGCActiveMark() { +IsSTWGCActiveMark::IsSTWGCActiveMark() { CollectedHeap* heap = Universe::heap(); - assert(!heap->is_gc_active(), "Not reentrant"); - heap->_is_gc_active = true; + assert(!heap->is_stw_gc_active(), "Not reentrant"); + heap->_is_stw_gc_active = true; } -IsGCActiveMark::~IsGCActiveMark() { +IsSTWGCActiveMark::~IsSTWGCActiveMark() { CollectedHeap* heap = Universe::heap(); - assert(heap->is_gc_active(), "Sanity"); - heap->_is_gc_active = false; + assert(heap->is_stw_gc_active(), "Sanity"); + heap->_is_stw_gc_active = false; } -DisableIsGCActiveMark::DisableIsGCActiveMark() { +DisableIsSTWGCActiveMark::DisableIsSTWGCActiveMark() { CollectedHeap* heap = Universe::heap(); - assert(heap->is_gc_active(), "Not reentrant"); - heap->_is_gc_active = false; + assert(heap->is_stw_gc_active(), "Not reentrant"); + heap->_is_stw_gc_active = false; } -DisableIsGCActiveMark::~DisableIsGCActiveMark() { +DisableIsSTWGCActiveMark::~DisableIsSTWGCActiveMark() { CollectedHeap* heap = Universe::heap(); - assert(!heap->is_gc_active(), "Sanity"); - heap->_is_gc_active = true; + assert(!heap->is_stw_gc_active(), "Sanity"); + heap->_is_stw_gc_active = true; } diff --git a/src/hotspot/share/gc/shared/isGCActiveMark.hpp b/src/hotspot/share/gc/shared/isGCActiveMark.hpp index c6d95d8a6340d..c65c7ebe56a68 100644 --- a/src/hotspot/share/gc/shared/isGCActiveMark.hpp +++ b/src/hotspot/share/gc/shared/isGCActiveMark.hpp @@ -28,18 +28,18 @@ #include "memory/allocation.hpp" // This class provides a method for block structured setting of the -// _is_gc_active state without requiring accessors in CollectedHeap +// _is_stw_gc_active state without requiring accessors in CollectedHeap -class IsGCActiveMark : public StackObj { +class IsSTWGCActiveMark : public StackObj { public: - IsGCActiveMark(); - ~IsGCActiveMark(); + IsSTWGCActiveMark(); + ~IsSTWGCActiveMark(); }; -class DisableIsGCActiveMark : public StackObj { +class DisableIsSTWGCActiveMark : public StackObj { public: - DisableIsGCActiveMark(); - ~DisableIsGCActiveMark(); + DisableIsSTWGCActiveMark(); + ~DisableIsSTWGCActiveMark(); }; #endif // SHARE_GC_SHARED_ISGCACTIVEMARK_HPP diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp index ed38c44859072..ddd33d8f43adb 100644 --- a/src/hotspot/share/gc/shared/memAllocator.cpp +++ b/src/hotspot/share/gc/shared/memAllocator.cpp @@ -147,7 +147,7 @@ void MemAllocator::Allocation::verify_before() { JavaThread* THREAD = _thread; // For exception macros. assert(!HAS_PENDING_EXCEPTION, "Should not allocate with exception pending"); debug_only(check_for_valid_allocation_state()); - assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); + assert(!Universe::heap()->is_stw_gc_active(), "Allocation during GC pause not allowed"); } #ifdef ASSERT diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index 786f7b635e77e..c4acb0b1ed6ca 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -92,7 +92,7 @@ nonstatic_field(CardTableBarrierSet, _card_table, CardTable*) \ \ nonstatic_field(CollectedHeap, _reserved, MemRegion) \ - nonstatic_field(CollectedHeap, _is_gc_active, bool) \ + nonstatic_field(CollectedHeap, _is_stw_gc_active, bool) \ nonstatic_field(CollectedHeap, _total_collections, unsigned int) \ \ nonstatic_field(ContiguousSpace, _bottom, HeapWord*) \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp index af32a20013a45..15f0ee61407b1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp @@ -132,7 +132,7 @@ class ShenandoahGCPauseMark : public StackObj { ShenandoahHeap* const _heap; const GCIdMark _gc_id_mark; const SvcGCMarker _svc_gc_mark; - const IsGCActiveMark _is_gc_active_mark; + const IsSTWGCActiveMark _is_gc_active_mark; TraceMemoryManagerStats _trace_pause; public: diff --git a/src/hotspot/share/gc/x/xDriver.cpp b/src/hotspot/share/gc/x/xDriver.cpp index f76d9f4e58688..b78e155d3a726 100644 --- a/src/hotspot/share/gc/x/xDriver.cpp +++ b/src/hotspot/share/gc/x/xDriver.cpp @@ -116,7 +116,7 @@ class VM_XOperation : public VM_Operation { // Setup GC id and active marker GCIdMark gc_id_mark(_gc_id); - IsGCActiveMark gc_active_mark; + IsSTWGCActiveMark gc_active_mark; // Verify before operation XVerify::before_zoperation(); diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index 50973f2562111..049edc802cc98 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -438,7 +438,7 @@ class VM_ZOperation : public VM_Operation { virtual void doit() { // Setup GC id and active marker GCIdMark gc_id_mark(_gc_id); - IsGCActiveMark gc_active_mark; + IsSTWGCActiveMark gc_active_mark; // Verify before operation ZVerify::before_zoperation(); diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index f7c373903db7b..d8f78eb26e211 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -484,7 +484,7 @@ void ZVerify::after_mark() { } if (ZVerifyObjects) { // Workaround OopMapCacheAlloc_lock reordering with the StackWatermark_lock - DisableIsGCActiveMark mark; + DisableIsSTWGCActiveMark mark; objects(false /* verify_weaks */); guarantee(zverify_broken_object == zaddress::null, "Verification failed"); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 3a8a040db4616..fc4bb5a6a0674 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -879,7 +879,7 @@ static OopStorage* object_handles() { } jlong JVMCIRuntime::make_oop_handle(const Handle& obj) { - assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(!Universe::heap()->is_stw_gc_active(), "can't extend the root set during GC pause"); assert(oopDesc::is_oop(obj()), "not an oop"); oop* ptr = OopHandle(object_handles(), obj()).ptr_raw(); diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index e640482aa04da..187bdf25af85a 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -1342,8 +1342,8 @@ bool Universe::release_fullgc_alot_dummy() { return true; } -bool Universe::is_gc_active() { - return heap()->is_gc_active(); +bool Universe::is_stw_gc_active() { + return heap()->is_stw_gc_active(); } bool Universe::is_in_heap(const void* p) { diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index 19acbdc09b21b..d5a38658e482f 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -295,7 +295,7 @@ class Universe: AllStatic { // The particular choice of collected heap. static CollectedHeap* heap() { return _collectedHeap; } - DEBUG_ONLY(static bool is_gc_active();) + DEBUG_ONLY(static bool is_stw_gc_active();) DEBUG_ONLY(static bool is_in_heap(const void* p);) DEBUG_ONLY(static bool is_in_heap_or_null(const void* p) { return p == nullptr || is_in_heap(p); }) diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index f5c35abb683a2..929c8b87d39d5 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -312,7 +312,7 @@ void Method::mask_for(int bci, InterpreterOopMap* mask) { methodHandle h_this(Thread::current(), this); // Only GC uses the OopMapCache during thread stack root scanning // any other uses generate an oopmap but do not save it in the cache. - if (Universe::heap()->is_gc_active()) { + if (Universe::heap()->is_stw_gc_active()) { method_holder()->mask_for(h_this, bci, mask); } else { OopMapCache::compute_one_oop_map(h_this, bci, mask); diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index 7d4492ea21a4e..fde91969ea5ef 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -226,6 +226,6 @@ bool oopDesc::size_might_change() { // the grey portion of an already copied array. This will cause the first // disjunct below to fail if the two comparands are computed across such // a concurrent change. - return Universe::heap()->is_gc_active() && is_objArray() && is_forwarded() && (UseParallelGC || UseG1GC); + return Universe::heap()->is_stw_gc_active() && is_objArray() && is_forwarded() && (UseParallelGC || UseG1GC); } #endif diff --git a/src/hotspot/share/prims/forte.cpp b/src/hotspot/share/prims/forte.cpp index b5973d4ad0277..2edaae66158f5 100644 --- a/src/hotspot/share/prims/forte.cpp +++ b/src/hotspot/share/prims/forte.cpp @@ -602,7 +602,7 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { return; } - if (Universe::heap()->is_gc_active()) { + if (Universe::heap()->is_stw_gc_active()) { trace->num_frames = ticks_GC_active; // -2 return; } diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp index 25c8aa8b10b6e..a74b56063dcea 100644 --- a/src/hotspot/share/runtime/jniHandles.cpp +++ b/src/hotspot/share/runtime/jniHandles.cpp @@ -83,7 +83,7 @@ static void report_handle_allocation_failure(AllocFailType alloc_failmode, } jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) { - assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(!Universe::heap()->is_stw_gc_active(), "can't extend the root set during GC pause"); assert(!current_thread_in_native(), "must not be in native"); jobject res = nullptr; if (!obj.is_null()) { @@ -105,7 +105,7 @@ jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) { } jweak JNIHandles::make_weak_global(Handle obj, AllocFailType alloc_failmode) { - assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(!Universe::heap()->is_stw_gc_active(), "can't extend the root set during GC pause"); assert(!current_thread_in_native(), "must not be in native"); jweak res = nullptr; if (!obj.is_null()) { From a8e62af733cb1acc1370561c9dd374b3f9c2c294 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Mon, 6 May 2024 11:43:07 +0000 Subject: [PATCH 098/203] 8331389: runtime/ErrorHandling/TestDwarf.java fails with "Crash JVM should not exit gracefully" Reviewed-by: chagedorn --- test/hotspot/jtreg/runtime/ErrorHandling/TestDwarf.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/TestDwarf.java b/test/hotspot/jtreg/runtime/ErrorHandling/TestDwarf.java index 8c0c23e2a8b01..80ded6f898d5d 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/TestDwarf.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/TestDwarf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,13 +108,12 @@ public static void main(String[] args) throws Exception { // Crash the VM in different ways in order to verify that DWARF parsing is able to print the source information // in the hs_err_files for each VM and C stack frame. private static void test() throws Exception { - runAndCheck(new Flags("-Xcomp", "-XX:CICrashAt=1", "--version")); + runAndCheck(new Flags("-Xcomp", "-XX:+CICountNative", "-XX:CICrashAt=1", "--version")); runAndCheck(new Flags("-Xmx100M", "-XX:ErrorHandlerTest=15", "-XX:TestCrashInErrorHandler=14", "--version")); runAndCheck(new Flags("-XX:+CrashGCForDumpingJavaThread", "--version")); runAndCheck(new Flags("-Xmx10m", "-XX:+CrashOnOutOfMemoryError", TestDwarf.class.getCanonicalName(), "outOfMemory")); - // Use -XX:-TieredCompilation as C1 is currently not aborting the VM (JDK-8264899). runAndCheck(new Flags(TestDwarf.class.getCanonicalName(), "unsafeAccess")); - runAndCheck(new Flags("-XX:-TieredCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:AbortVMOnException=MyException", + runAndCheck(new Flags("-XX:+UnlockDiagnosticVMOptions", "-XX:AbortVMOnException=MyException", TestDwarf.class.getCanonicalName(), "abortVMOnException")); if (Platform.isX64() || Platform.isX86()) { // Not all platforms raise SIGFPE but x86_32 and x86_64 do. From fa02667d838f08cac7d41dfb4c3e8056ae6165cc Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 6 May 2024 12:21:15 +0000 Subject: [PATCH 099/203] 8322726: C2: Unloaded signature class kills argument value Reviewed-by: kvn, dlong, thartmann --- src/hotspot/share/opto/callGenerator.cpp | 28 ++--- src/hotspot/share/opto/graphKit.cpp | 11 ++ src/hotspot/share/opto/graphKit.hpp | 2 + .../runtime/unloaded/TestMHUnloaded.java | 50 +++++++++ .../unloaded/TestMHUnloadedHelper.java | 103 ++++++++++++++++++ 5 files changed, 181 insertions(+), 13 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloaded.java create mode 100644 test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloadedHelper.java diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index c8bb39c8cdeb7..433d0316b9dad 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -1089,13 +1089,14 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* const int receiver_skip = target->is_static() ? 0 : 1; // Cast receiver to its type. if (!target->is_static()) { - Node* arg = kit.argument(0); - const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); - const Type* sig_type = TypeOopPtr::make_from_klass(signature->accessing_klass()); - if (arg_type != nullptr && !arg_type->higher_equal(sig_type)) { - const Type* recv_type = arg_type->filter_speculative(sig_type); // keep speculative part - Node* cast_obj = gvn.transform(new CheckCastPPNode(kit.control(), arg, recv_type)); - kit.set_argument(0, cast_obj); + Node* recv = kit.argument(0); + Node* casted_recv = kit.maybe_narrow_object_type(recv, signature->accessing_klass()); + if (casted_recv->is_top()) { + print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(), + "argument types mismatch"); + return nullptr; // FIXME: effectively dead; issue a halt node instead + } else if (casted_recv != recv) { + kit.set_argument(0, casted_recv); } } // Cast reference arguments to its type. @@ -1103,12 +1104,13 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* ciType* t = signature->type_at(i); if (t->is_klass()) { Node* arg = kit.argument(receiver_skip + j); - const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); - const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass()); - if (arg_type != nullptr && !arg_type->higher_equal(sig_type)) { - const Type* narrowed_arg_type = arg_type->filter_speculative(sig_type); // keep speculative part - Node* cast_obj = gvn.transform(new CheckCastPPNode(kit.control(), arg, narrowed_arg_type)); - kit.set_argument(receiver_skip + j, cast_obj); + Node* casted_arg = kit.maybe_narrow_object_type(arg, t->as_klass()); + if (casted_arg->is_top()) { + print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(), + "argument types mismatch"); + return nullptr; // FIXME: effectively dead; issue a halt node instead + } else if (casted_arg != arg) { + kit.set_argument(receiver_skip + j, casted_arg); } } j += t->size(); // long and double take two slots diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 6bfdae1cf5ca9..794403611e574 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -4271,3 +4271,14 @@ Node* GraphKit::make_constant_from_field(ciField* field, Node* obj) { } return nullptr; } + +Node* GraphKit::maybe_narrow_object_type(Node* obj, ciKlass* type) { + const TypeOopPtr* obj_type = obj->bottom_type()->isa_oopptr(); + const TypeOopPtr* sig_type = TypeOopPtr::make_from_klass(type); + if (obj_type != nullptr && sig_type->is_loaded() && !obj_type->higher_equal(sig_type)) { + const Type* narrow_obj_type = obj_type->filter_speculative(sig_type); // keep speculative part + Node* casted_obj = gvn().transform(new CheckCastPPNode(control(), obj, narrow_obj_type)); + return casted_obj; + } + return obj; +} diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp index 3f917ec882b07..e7f17c72a1b99 100644 --- a/src/hotspot/share/opto/graphKit.hpp +++ b/src/hotspot/share/opto/graphKit.hpp @@ -441,6 +441,8 @@ class GraphKit : public Phase { // Replace all occurrences of one node by another. void replace_in_map(Node* old, Node* neww); + Node* maybe_narrow_object_type(Node* obj, ciKlass* type); + void push(Node* n) { map_not_null(); _map->set_stack(_map->_jvms, _sp++ , n); } Node* pop() { map_not_null(); return _map->stack( _map->_jvms, --_sp ); } Node* peek(int off = 0) { map_not_null(); return _map->stack( _map->_jvms, _sp - off - 1 ); } diff --git a/test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloaded.java b/test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloaded.java new file mode 100644 index 0000000000000..23c6e83a6c5c5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloaded.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +/* + * @test + * @bug 8322726 + * @library /test/lib + * @modules java.base/jdk.internal.org.objectweb.asm + * + * @compile TestMHUnloaded.java TestMHUnloadedHelper.java + * @run driver jdk.test.lib.helpers.ClassFileInstaller compiler.runtime.unloaded.TestMHUnloadedHelper + * @run main/othervm -Xbootclasspath/a:. + * -Xbatch -XX:-TieredCompilation -XX:CompileCommand=exclude,*::test + * -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining + * compiler.runtime.unloaded.TestMHUnloaded + */ + +package compiler.runtime.unloaded; + +import java.lang.invoke.MethodHandles; + +public class TestMHUnloaded { + public static void main(String[] args) { + TestMHUnloadedHelper.test(MethodHandles.lookup()); // launch test in bootstrap loader context + TestMHUnloadedHelper.testConstant(MethodHandles.lookup()); // launch test in bootstrap loader context + System.out.println("TEST PASSED"); + } +} diff --git a/test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloadedHelper.java b/test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloadedHelper.java new file mode 100644 index 0000000000000..176945572e8f3 --- /dev/null +++ b/test/hotspot/jtreg/compiler/runtime/unloaded/TestMHUnloadedHelper.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package compiler.runtime.unloaded; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.function.BiPredicate; +import jdk.internal.org.objectweb.asm.ClassWriter; + +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +// Operates in bootstrap loader context. +public class TestMHUnloadedHelper { + private static final MethodType METHOD_TYPE = MethodType.methodType(BiPredicate.class, + BiPredicate.class, BiPredicate.class); + + static byte[] generateClassFile(Class caller) { + var cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + String name = caller.getName().replace('.', '/'); + cw.visit(V19, ACC_PUBLIC | ACC_SUPER, name, null, "java/lang/Object", null); + { + var mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", METHOD_TYPE.toMethodDescriptorString(), null, null); + mv.visitCode(); + mv.visitIntInsn(ALOAD, 1); + mv.visitInsn(ARETURN); + mv.visitMaxs(0, 0); + } + return cw.toByteArray(); + } + + public static MethodHandle generateTest(MethodHandles.Lookup caller) { + // Loaded in the caller context. + byte[] classBytes = generateClassFile(caller.lookupClass()); + try { + MethodHandles.Lookup lookup = caller.defineHiddenClass(classBytes, true); + MethodHandle test = lookup.findStatic(lookup.lookupClass(), "test", METHOD_TYPE); + test = MethodHandles.permuteArguments(test, test.type(), 1, 0); // mix arguments + return test; + } catch (Throwable e) { + throw new AssertionError(e); + } + } + + static BiPredicate[] ps = new BiPredicate[] { (a, b) -> false, + (a, b) -> true }; + + public static void test(MethodHandles.Lookup caller) { + MethodHandle test = generateTest(caller); + + for (int i = 0; i < 20_000; i++) { + try { + BiPredicate pr = (BiPredicate)test.invokeExact(ps[1], ps[0]); + if (pr != ps[1]) { + throw new AssertionError("mismatch"); + } + } catch (Throwable e) { + throw new AssertionError(e); + } + } + } + + public static void testConstant(MethodHandles.Lookup caller) { + MethodHandle test = generateTest(caller); + + // testMH() { return test(ps2, ps1); } where test(a, b) { return b; }. + test = test.bindTo(ps[1]).bindTo(ps[0]); // make argument concrete types visible to the JIT-compiler + + for (int i = 0; i < 20_000; i++) { + try { + BiPredicate pr = (BiPredicate)test.invokeExact(); + if (pr != ps[1]) { + throw new AssertionError("mismatch"); + } + } catch (Throwable e) { + throw new AssertionError(e); + } + } + } +} From 7a35f922f06c4649f9ea8a1fb1782b2a670311ce Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Mon, 6 May 2024 13:25:36 +0000 Subject: [PATCH 100/203] 8331660: Parallel: Cleanup includes in parallelScavangeHeap files Reviewed-by: gli, ayang --- src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp | 2 -- src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp | 7 +------ .../share/gc/parallel/parallelScavengeHeap.inline.hpp | 3 +-- src/hotspot/share/gc/parallel/psParallelCompact.cpp | 1 + src/hotspot/share/gc/parallel/psParallelCompact.hpp | 3 ++- src/hotspot/share/gc/parallel/psScavenge.cpp | 1 + src/hotspot/share/gc/parallel/psScavenge.hpp | 3 ++- src/hotspot/share/gc/parallel/psVMOperations.cpp | 1 + 8 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index f4df7c57bfc19..318b5b5e1377a 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -23,7 +23,6 @@ */ #include "precompiled.hpp" -#include "code/codeCache.hpp" #include "gc/parallel/objectStartArray.inline.hpp" #include "gc/parallel/parallelArguments.hpp" #include "gc/parallel/parallelInitLogger.hpp" @@ -35,7 +34,6 @@ #include "gc/parallel/psScavenge.hpp" #include "gc/parallel/psVMOperations.hpp" #include "gc/shared/gcHeapSummary.hpp" -#include "gc/shared/gcInitLogger.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "gc/shared/gcWhen.hpp" #include "gc/shared/genArguments.hpp" diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index 48dce98b55b71..38a1f2acc4bbf 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #ifndef SHARE_GC_PARALLEL_PARALLELSCAVENGEHEAP_HPP #define SHARE_GC_PARALLEL_PARALLELSCAVENGEHEAP_HPP -#include "gc/parallel/objectStartArray.hpp" #include "gc/parallel/psGCAdaptivePolicyCounters.hpp" #include "gc/parallel/psOldGen.hpp" #include "gc/parallel/psYoungGen.hpp" @@ -34,13 +33,9 @@ #include "gc/shared/gcPolicyCounters.hpp" #include "gc/shared/gcWhen.hpp" #include "gc/shared/preGCValues.hpp" -#include "gc/shared/referenceProcessor.hpp" -#include "gc/shared/softRefPolicy.hpp" -#include "gc/shared/strongRootsScope.hpp" #include "gc/shared/workerThread.hpp" #include "logging/log.hpp" #include "utilities/growableArray.hpp" -#include "utilities/ostream.hpp" class GCHeapSummary; class HeapBlockClaimer; diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp index ef5f6dedd2975..93a90b3d0b50a 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ #include "gc/parallel/parallelScavengeHeap.hpp" -#include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/psScavenge.hpp" inline bool ParallelScavengeHeap::should_alloc_in_eden(const size_t size) const { diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 4f5c0e1603fb5..b85457c015683 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -58,6 +58,7 @@ #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" #include "gc/shared/spaceDecorator.inline.hpp" +#include "gc/shared/strongRootsScope.hpp" #include "gc/shared/taskTerminator.hpp" #include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/workerPolicy.hpp" diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 6ca23947ca413..a36acc72a9ba4 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "gc/parallel/parMarkBitMap.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectorCounters.hpp" +#include "gc/shared/referenceProcessor.hpp" #include "gc/shared/taskTerminator.hpp" #include "oops/oop.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index c39cf96645dd2..3e90529a53478 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -51,6 +51,7 @@ #include "gc/shared/referenceProcessorPhaseTimes.hpp" #include "gc/shared/scavengableNMethods.hpp" #include "gc/shared/spaceDecorator.inline.hpp" +#include "gc/shared/strongRootsScope.hpp" #include "gc/shared/taskTerminator.hpp" #include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/workerPolicy.hpp" diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index 0c61bc9c30e1e..c99034e04b5f8 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "gc/parallel/psCardTable.hpp" #include "gc/parallel/psVirtualspace.hpp" #include "gc/shared/collectorCounters.hpp" +#include "gc/shared/referenceProcessor.hpp" #include "gc/shared/gcTrace.hpp" #include "memory/allStatic.hpp" #include "oops/oop.hpp" diff --git a/src/hotspot/share/gc/parallel/psVMOperations.cpp b/src/hotspot/share/gc/parallel/psVMOperations.cpp index 47eeffb34a546..db4d9a3660624 100644 --- a/src/hotspot/share/gc/parallel/psVMOperations.cpp +++ b/src/hotspot/share/gc/parallel/psVMOperations.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/parallelScavengeHeap.inline.hpp" #include "gc/parallel/psScavenge.hpp" #include "gc/parallel/psVMOperations.hpp" From ae60d845007c7137895e3a5f86623d0731fee81f Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Mon, 6 May 2024 15:54:40 +0000 Subject: [PATCH 101/203] 8328501: Incorrect `@since` tags for java security interfaces Reviewed-by: mullan --- .../share/classes/java/security/interfaces/DSAPrivateKey.java | 3 +-- .../share/classes/java/security/interfaces/DSAPublicKey.java | 3 +-- .../share/classes/java/security/interfaces/ECPrivateKey.java | 3 +-- .../share/classes/java/security/interfaces/ECPublicKey.java | 3 +-- .../classes/java/security/interfaces/EdECPrivateKey.java | 3 +-- .../share/classes/java/security/interfaces/EdECPublicKey.java | 3 +-- .../share/classes/java/security/interfaces/RSAPrivateKey.java | 4 ++-- .../share/classes/java/security/interfaces/RSAPublicKey.java | 4 ++-- .../share/classes/java/security/interfaces/XECPrivateKey.java | 3 +-- .../share/classes/java/security/interfaces/XECPublicKey.java | 3 +-- .../share/classes/javax/crypto/interfaces/DHPrivateKey.java | 3 +-- .../share/classes/javax/crypto/interfaces/DHPublicKey.java | 3 +-- 12 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/java.base/share/classes/java/security/interfaces/DSAPrivateKey.java b/src/java.base/share/classes/java/security/interfaces/DSAPrivateKey.java index ea842b6e12e27..efef7daca297d 100644 --- a/src/java.base/share/classes/java/security/interfaces/DSAPrivateKey.java +++ b/src/java.base/share/classes/java/security/interfaces/DSAPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,6 @@ public interface DSAPrivateKey extends DSAKey, java.security.PrivateKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default DSAParams getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/DSAPublicKey.java b/src/java.base/share/classes/java/security/interfaces/DSAPublicKey.java index 9ddf6d8406fee..a58333b38baf3 100644 --- a/src/java.base/share/classes/java/security/interfaces/DSAPublicKey.java +++ b/src/java.base/share/classes/java/security/interfaces/DSAPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,6 @@ public interface DSAPublicKey extends DSAKey, java.security.PublicKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default DSAParams getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java b/src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java index 1694f46d4ab7c..53c1f358d52e0 100644 --- a/src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java +++ b/src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,6 @@ public interface ECPrivateKey extends PrivateKey, ECKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default ECParameterSpec getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/ECPublicKey.java b/src/java.base/share/classes/java/security/interfaces/ECPublicKey.java index 5e8efb90db5c5..d78f863cc7627 100644 --- a/src/java.base/share/classes/java/security/interfaces/ECPublicKey.java +++ b/src/java.base/share/classes/java/security/interfaces/ECPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ public interface ECPublicKey extends PublicKey, ECKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default ECParameterSpec getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/EdECPrivateKey.java b/src/java.base/share/classes/java/security/interfaces/EdECPrivateKey.java index b3522fec4fe51..2a1b194a90a40 100644 --- a/src/java.base/share/classes/java/security/interfaces/EdECPrivateKey.java +++ b/src/java.base/share/classes/java/security/interfaces/EdECPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,6 @@ public interface EdECPrivateKey extends EdECKey, PrivateKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default NamedParameterSpec getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/EdECPublicKey.java b/src/java.base/share/classes/java/security/interfaces/EdECPublicKey.java index 664e76b6971fe..f5a0f3c319449 100644 --- a/src/java.base/share/classes/java/security/interfaces/EdECPublicKey.java +++ b/src/java.base/share/classes/java/security/interfaces/EdECPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,6 @@ public interface EdECPublicKey extends EdECKey, PublicKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default NamedParameterSpec getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/RSAPrivateKey.java b/src/java.base/share/classes/java/security/interfaces/RSAPrivateKey.java index 6e4ea536e32f9..8f74b476f9921 100644 --- a/src/java.base/share/classes/java/security/interfaces/RSAPrivateKey.java +++ b/src/java.base/share/classes/java/security/interfaces/RSAPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ public interface RSAPrivateKey extends java.security.PrivateKey, RSAKey * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 + * @since 11 */ @Override default AlgorithmParameterSpec getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/RSAPublicKey.java b/src/java.base/share/classes/java/security/interfaces/RSAPublicKey.java index 2e1d89723e4f8..a02b454abb2d8 100644 --- a/src/java.base/share/classes/java/security/interfaces/RSAPublicKey.java +++ b/src/java.base/share/classes/java/security/interfaces/RSAPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public interface RSAPublicKey extends java.security.PublicKey, RSAKey * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 + * @since 11 */ @Override default AlgorithmParameterSpec getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java b/src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java index b555f587fb67d..6bd45c4f219b2 100644 --- a/src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java +++ b/src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,6 @@ public interface XECPrivateKey extends XECKey, PrivateKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default AlgorithmParameterSpec getParams() { diff --git a/src/java.base/share/classes/java/security/interfaces/XECPublicKey.java b/src/java.base/share/classes/java/security/interfaces/XECPublicKey.java index 6b1806df0ebf8..dbeaf9381072f 100644 --- a/src/java.base/share/classes/java/security/interfaces/XECPublicKey.java +++ b/src/java.base/share/classes/java/security/interfaces/XECPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,6 @@ public interface XECPublicKey extends XECKey, PublicKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default AlgorithmParameterSpec getParams() { diff --git a/src/java.base/share/classes/javax/crypto/interfaces/DHPrivateKey.java b/src/java.base/share/classes/javax/crypto/interfaces/DHPrivateKey.java index fb7d2f83108b7..49a93c02b42d8 100644 --- a/src/java.base/share/classes/javax/crypto/interfaces/DHPrivateKey.java +++ b/src/java.base/share/classes/javax/crypto/interfaces/DHPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,6 @@ public interface DHPrivateKey extends DHKey, java.security.PrivateKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default DHParameterSpec getParams() { diff --git a/src/java.base/share/classes/javax/crypto/interfaces/DHPublicKey.java b/src/java.base/share/classes/javax/crypto/interfaces/DHPublicKey.java index 8785b8dfec84c..631d8a20e66c4 100644 --- a/src/java.base/share/classes/javax/crypto/interfaces/DHPublicKey.java +++ b/src/java.base/share/classes/javax/crypto/interfaces/DHPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,6 @@ public interface DHPublicKey extends DHKey, java.security.PublicKey { * The default implementation returns {@code null}. * * @return {@inheritDoc java.security.AsymmetricKey} - * @since 22 */ @Override default DHParameterSpec getParams() { From a8b3f194e811eed6b20bce71c752705c7cd50d24 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Mon, 6 May 2024 17:01:11 +0000 Subject: [PATCH 102/203] 8330077: Allow max number of events to be buffered to be configurable to avoid OVERFLOW_EVENT Reviewed-by: bpb, alanb --- .../classes/java/nio/file/WatchService.java | 16 ++- .../classes/sun/nio/fs/AbstractWatchKey.java | 28 +++- .../nio/file/WatchService/LotsOfEntries.java | 120 ++++++++++++++++++ 3 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 test/jdk/java/nio/file/WatchService/LotsOfEntries.java diff --git a/src/java.base/share/classes/java/nio/file/WatchService.java b/src/java.base/share/classes/java/nio/file/WatchService.java index 1975dd2693a2c..2490d14823fdf 100644 --- a/src/java.base/share/classes/java/nio/file/WatchService.java +++ b/src/java.base/share/classes/java/nio/file/WatchService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,20 @@ * it is not required that changes to files carried out on remote systems be * detected. * + * @implNote + * The JDK's {@code WatchService} implementations buffer up to 512 pending + * events for each registered watchable object. If this limit is exceeded, + * pending events are discarded and the special + * {@link StandardWatchEventKinds#OVERFLOW OVERFLOW} event is queued. This + * special event is the trigger to re-examine the state of the object, e.g. + * scan a watched directory to get an updated list of the files in the + * directory. The limit for the pending events can be changed from its default + * with the system property + * {@systemProperty jdk.nio.file.WatchService.maxEventsPerPoll} + * set to a value that parses as a positive integer. This may be useful in + * environments where there is a high volume of changes and where the impact + * of discarded events is high. + * * @since 1.7 * * @see FileSystem#newWatchService diff --git a/src/java.base/share/classes/sun/nio/fs/AbstractWatchKey.java b/src/java.base/share/classes/sun/nio/fs/AbstractWatchKey.java index 710e38fc607bb..bdb7920b20ae6 100644 --- a/src/java.base/share/classes/sun/nio/fs/AbstractWatchKey.java +++ b/src/java.base/share/classes/sun/nio/fs/AbstractWatchKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,16 +28,38 @@ import java.nio.file.*; import java.util.*; +import jdk.internal.util.ArraysSupport; +import sun.security.action.GetPropertyAction; + /** * Base implementation class for watch keys. */ abstract class AbstractWatchKey implements WatchKey { + private static final int DEFAULT_MAX_EVENT_LIST_SIZE = 512; + /** - * Maximum size of event list (in the future this may be tunable) + * Maximum size of event list before dropping events and signalling OVERFLOW */ - static final int MAX_EVENT_LIST_SIZE = 512; + static final int MAX_EVENT_LIST_SIZE; + static { + String rawValue = GetPropertyAction.privilegedGetProperty( + "jdk.nio.file.WatchService.maxEventsPerPoll", + String.valueOf(DEFAULT_MAX_EVENT_LIST_SIZE)); + int intValue; + try { + // Clamp to max array length to signal OVERFLOW and drop events + // before OOMing. + intValue = Math.clamp( + Long.decode(rawValue), + 1, + ArraysSupport.SOFT_MAX_ARRAY_LENGTH); + } catch (NumberFormatException e) { + intValue = DEFAULT_MAX_EVENT_LIST_SIZE; + } + MAX_EVENT_LIST_SIZE = intValue; + } /** * Special event to signal overflow diff --git a/test/jdk/java/nio/file/WatchService/LotsOfEntries.java b/test/jdk/java/nio/file/WatchService/LotsOfEntries.java new file mode 100644 index 0000000000000..b12daac9f27d7 --- /dev/null +++ b/test/jdk/java/nio/file/WatchService/LotsOfEntries.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8330077 + * @summary Tests WatchService behavior with more entries in a watched directory + * than the default event limit + * @library .. + * @run main/othervm LotsOfEntries 600 fail + * @run main/othervm -Djdk.nio.file.WatchService.maxEventsPerPoll=invalid LotsOfEntries 600 fail + * @run main/othervm -Djdk.nio.file.WatchService.maxEventsPerPoll=-5 LotsOfEntries 5 fail + * @run main/othervm -Djdk.nio.file.WatchService.maxEventsPerPoll=5 LotsOfEntries 5 pass + * @run main/othervm -Djdk.nio.file.WatchService.maxEventsPerPoll=5 LotsOfEntries 6 fail + * @run main/othervm -Djdk.nio.file.WatchService.maxEventsPerPoll=700 LotsOfEntries 600 pass + * @run main/othervm -Djdk.nio.file.WatchService.maxEventsPerPoll=3000000000 LotsOfEntries 600 pass + */ + +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKinds.*; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +public class LotsOfEntries { + + static void testCreateLotsOfEntries(Path dir, int numEvents, boolean fail) throws Exception { + try (WatchService watcher = FileSystems.getDefault().newWatchService()) { + System.out.format("register %s for events\n", dir); + WatchKey key = dir.register(watcher, ENTRY_CREATE); + + System.out.format("create %d entries\n", numEvents); + Set entries = new HashSet<>(); + for (int i = 0; i < numEvents; i++) { + Path entry = dir.resolve("entry" + i); + entries.add(entry); + Files.createFile(entry); + } + + // Wait for all events to be signalled - the timeout is long to + // allow for polling implementations. Since we specifically want to + // test the maximum number of events buffered for a single + // WatchKey#pollEvents call, we need to poll on the WatchService + // repeatedly until all (not just some) events have been signalled. + System.out.println("poll watcher..."); + WatchKey signalledKey; + do { + signalledKey = watcher.poll(10, TimeUnit.SECONDS); + if (signalledKey != null && signalledKey != key) { + throw new RuntimeException("Unexpected key returned from poll"); + } + } while (signalledKey != null); + + if (fail) { + System.out.println("poll expecting overflow..."); + var events = key.pollEvents(); + if (events.size() != 1) { + throw new RuntimeException( + "Expected overflow event, got: " + toString(events)); + } + if (!events.getFirst().kind().equals(OVERFLOW)) { + throw new RuntimeException( + "Expected overflow event, got: " + toString(events)); + } + } else { + System.out.println("poll not expecting overflow..."); + List> events = key.pollEvents(); + Set contexts = events.stream() + .map(WatchEvent::context) + .map(Path.class::cast) + .map(entry -> dir.resolve(entry)) + .collect(Collectors.toSet()); + if (!entries.equals(contexts)) { + throw new RuntimeException( + "Expected events on: " + entries + ", got: " + toString(events)); + } + } + } + } + + static String toString(List> events) { + return events.stream() + .map(LotsOfEntries::toString) + .collect(Collectors.joining(", ")); + } + + static String toString(WatchEvent event) { + return String.format("%s(%d): %s", event.kind(), event.count(), event.context()); + } + + public static void main(String[] args) throws Exception { + Path dir = TestUtil.createTemporaryDirectory(); + int numEvents = Integer.parseInt(args[0]); + boolean fail = args[1].equals("fail"); + try { + testCreateLotsOfEntries(dir, numEvents, fail); + } finally { + TestUtil.removeAll(dir); + } + } +} From f308e107ce8b993641ee3d0a0d5d52bf5cd3b94e Mon Sep 17 00:00:00 2001 From: Bhavana Kilambi Date: Mon, 6 May 2024 22:59:14 +0000 Subject: [PATCH 103/203] 8331400: AArch64: Sync aarch64_vector.ad with aarch64_vector_ad.m4 Reviewed-by: aph, kvn, eliu --- src/hotspot/cpu/aarch64/aarch64_vector.ad | 2 +- src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index 4e8eb47ee5fa2..b14295ca15c88 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -1,6 +1,6 @@ // // Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2020, 2023, Arm Limited. All rights reserved. +// Copyright (c) 2020, 2024, Arm Limited. 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 diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index d31a4e05799c2..060bb4a11d4ad 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -1,6 +1,6 @@ // // Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2020, 2023, Arm Limited. All rights reserved. +// Copyright (c) 2020, 2024, Arm Limited. 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 @@ -159,9 +159,7 @@ source %{ case Op_VectorMaskGen: case Op_LoadVectorMasked: case Op_StoreVectorMasked: - case Op_LoadVectorGather: case Op_StoreVectorScatter: - case Op_LoadVectorGatherMasked: case Op_StoreVectorScatterMasked: case Op_PopulateIndex: case Op_CompressM: @@ -170,6 +168,12 @@ source %{ return false; } break; + case Op_LoadVectorGather: + case Op_LoadVectorGatherMasked: + if (UseSVE == 0 || is_subword_type(bt)) { + return false; + } + break; case Op_MulAddVS2VI: if (length_in_bytes != 16) { return false; From 3b8227ba24c7bc05a8ea23801e3816e8fc80de4e Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Tue, 7 May 2024 05:28:45 +0000 Subject: [PATCH 104/203] 8326836: Incorrect `@since` tags for ClassSignature methods Reviewed-by: asotona --- .../share/classes/java/lang/classfile/ClassSignature.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/java.base/share/classes/java/lang/classfile/ClassSignature.java b/src/java.base/share/classes/java/lang/classfile/ClassSignature.java index 57d899eb59061..b3050b78a8568 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassSignature.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassSignature.java @@ -54,6 +54,7 @@ public sealed interface ClassSignature * {@return a class signature} * @param superclassSignature the superclass * @param superinterfaceSignatures the interfaces + * @since 23 */ public static ClassSignature of(Signature.ClassTypeSig superclassSignature, Signature.ClassTypeSig... superinterfaceSignatures) { @@ -65,6 +66,7 @@ public static ClassSignature of(Signature.ClassTypeSig superclassSignature, * @param typeParameters the type parameters * @param superclassSignature the superclass * @param superinterfaceSignatures the interfaces + * @since 23 */ public static ClassSignature of(List typeParameters, Signature.ClassTypeSig superclassSignature, From df1ff056f19ce569e05b0b87584e289840fc5d5c Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Tue, 7 May 2024 07:08:32 +0000 Subject: [PATCH 105/203] 8331085: Crash in MergePrimitiveArrayStores::is_compatible_store() Reviewed-by: thartmann, chagedorn --- src/hotspot/share/opto/memnode.cpp | 7 ++- .../c2/TestMergeStoresNullAdrType.java | 58 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestMergeStoresNullAdrType.java diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index e0eed9e3f57a8..fa26825e19f50 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2971,7 +2971,11 @@ StoreNode* MergePrimitiveArrayStores::run() { } // Only merge stores on arrays, and the stores must have the same size as the elements. - const TypeAryPtr* aryptr_t = _store->adr_type()->isa_aryptr(); + const TypePtr* ptr_t = _store->adr_type(); + if (ptr_t == nullptr) { + return nullptr; + } + const TypeAryPtr* aryptr_t = ptr_t->isa_aryptr(); if (aryptr_t == nullptr) { return nullptr; } @@ -3016,6 +3020,7 @@ bool MergePrimitiveArrayStores::is_compatible_store(const StoreNode* other_store if (other_store == nullptr || _store->Opcode() != other_store->Opcode() || + other_store->adr_type() == nullptr || other_store->adr_type()->isa_aryptr() == nullptr) { return false; } diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStoresNullAdrType.java b/test/hotspot/jtreg/compiler/c2/TestMergeStoresNullAdrType.java new file mode 100644 index 0000000000000..d96eae33df23a --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStoresNullAdrType.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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; + +/* + * @test + * @bug 8318446 8331085 + * @summary Test merge stores, when "adr_type() == nullptr" because of TOP somewhere in the address. + * @run main/othervm -XX:CompileCommand=compileonly,compiler.c2.TestMergeStoresNullAdrType::test + * -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:+StressCCP + * -XX:RepeatCompilation=1000 + * compiler.c2.TestMergeStoresNullAdrType + * @run main compiler.c2.TestMergeStoresNullAdrType + */ + +public class TestMergeStoresNullAdrType { + static int arr[] = new int[100]; + + static void test() { + boolean b = false; + for (int k = 269; k > 10; --k) { + b = b; + int j = 6; + while ((j -= 3) > 0) { + if (b) { + } else { + arr[j] >>= 2; + } + } + } + } + + public static void main(String[] args) { + test(); + } +} From a2584a8341b2dc9c102abd373a890b2108d3f57e Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 7 May 2024 08:30:26 +0000 Subject: [PATCH 106/203] 8331714: Make OopMapCache installation lock-free Reviewed-by: zgu, coleenp --- src/hotspot/share/oops/instanceKlass.cpp | 17 +++++++++-------- src/hotspot/share/runtime/mutexLocker.cpp | 2 -- src/hotspot/share/runtime/mutexLocker.hpp | 1 - 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 0069f336e886b..3b3a4ac10a662 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1634,16 +1634,17 @@ void InstanceKlass::call_class_initializer(TRAPS) { void InstanceKlass::mask_for(const methodHandle& method, int bci, InterpreterOopMap* entry_for) { - // Lazily create the _oop_map_cache at first request - // Lock-free access requires load_acquire. + // Lazily create the _oop_map_cache at first request. + // Load_acquire is needed to safely get instance published with CAS by another thread. OopMapCache* oop_map_cache = Atomic::load_acquire(&_oop_map_cache); if (oop_map_cache == nullptr) { - MutexLocker x(OopMapCacheAlloc_lock); - // Check if _oop_map_cache was allocated while we were waiting for this lock - if ((oop_map_cache = _oop_map_cache) == nullptr) { - oop_map_cache = new OopMapCache(); - // Ensure _oop_map_cache is stable, since it is examined without a lock - Atomic::release_store(&_oop_map_cache, oop_map_cache); + // Try to install new instance atomically. + oop_map_cache = new OopMapCache(); + OopMapCache* other = Atomic::cmpxchg(&_oop_map_cache, (OopMapCache*)nullptr, oop_map_cache); + if (other != nullptr) { + // Someone else managed to install before us, ditch local copy and use the existing one. + delete oop_map_cache; + oop_map_cache = other; } } // _oop_map_cache is constant after init; lookup below does its own locking. diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index d945037324ee5..dec40136336f1 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -100,7 +100,6 @@ Mutex* tty_lock = nullptr; Mutex* RawMonitor_lock = nullptr; Mutex* PerfDataMemAlloc_lock = nullptr; Mutex* PerfDataManager_lock = nullptr; -Mutex* OopMapCacheAlloc_lock = nullptr; Mutex* FreeList_lock = nullptr; Mutex* OldSets_lock = nullptr; @@ -349,7 +348,6 @@ void mutex_init() { MUTEX_DEFL(PSOldGenExpand_lock , PaddedMutex , Heap_lock, true); } #endif - MUTEX_DEFL(OopMapCacheAlloc_lock , PaddedMutex , Threads_lock, true); MUTEX_DEFL(Module_lock , PaddedMutex , ClassLoaderDataGraph_lock); MUTEX_DEFL(SystemDictionary_lock , PaddedMonitor, Module_lock); MUTEX_DEFL(JNICritical_lock , PaddedMonitor, AdapterHandlerLibrary_lock); // used for JNI critical regions diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 8b71a097812ea..91310364b8f0b 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -96,7 +96,6 @@ extern Mutex* FullGCALot_lock; // a lock to make FullGCALot MT extern Mutex* RawMonitor_lock; extern Mutex* PerfDataMemAlloc_lock; // a lock on the allocator for PerfData memory for performance data extern Mutex* PerfDataManager_lock; // a long on access to PerfDataManager resources -extern Mutex* OopMapCacheAlloc_lock; // protects allocation of oop_map caches extern Mutex* FreeList_lock; // protects the free region list during safepoints extern Mutex* OldSets_lock; // protects the old region sets From 23a72a1f2f651d5e8e9a0eb1e75e2b44572a13da Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Tue, 7 May 2024 08:32:48 +0000 Subject: [PATCH 107/203] 8331626: unsafe.cpp:162:38: runtime error in index_oop_from_field_offset_long - applying non-zero offset 4563897424 to null pointer Reviewed-by: mbaesken, stefank --- src/hotspot/share/prims/unsafe.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp index 88672fe16b90e..880f1f6ab5d56 100644 --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -154,13 +154,9 @@ static inline void assert_field_offset_sane(oop p, jlong field_offset) { static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { assert_field_offset_sane(p, field_offset); - jlong byte_offset = field_offset_to_byte_offset(field_offset); - - if (sizeof(char*) == sizeof(jint)) { // (this constant folds!) - return cast_from_oop
(p) + (jint) byte_offset; - } else { - return cast_from_oop
(p) + byte_offset; - } + uintptr_t base_address = cast_from_oop(p); + uintptr_t byte_offset = (uintptr_t)field_offset_to_byte_offset(field_offset); + return (void*)(base_address + byte_offset); } // Externally callable versions: From 02a799c05576a52b03b74a4ece901e7811dfda76 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 7 May 2024 12:41:28 +0000 Subject: [PATCH 108/203] 8331695: Serial: DefNewGeneration:_promotion_failed used without being initialized Reviewed-by: gli, stefank --- src/hotspot/share/gc/serial/defNewGeneration.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 43c8be36148cf..ff65a6dd45033 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -226,6 +226,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, size_t max_size, const char* policy) : Generation(rs, initial_size), + _promotion_failed(false), _preserved_marks_set(false /* in_c_heap */), _promo_failure_drain_in_progress(false), _should_allocate_from_space(false), From 02c95a6d7eb77ed17ae64d0f585197e87a67cc4a Mon Sep 17 00:00:00 2001 From: robertengels Date: Tue, 7 May 2024 13:18:24 +0000 Subject: [PATCH 109/203] 6968351: httpserver clashes with delayed TCP ACKs for low Content-Length Reviewed-by: dfuchs, djelinski, michaelm, jpai --- .../net/httpserver/ChunkedOutputStream.java | 10 +- .../sun/net/httpserver/ExchangeImpl.java | 8 +- .../sun/net/httpserver/ServerImpl.java | 4 +- .../net/httpserver/TcpNoDelayNotRequired.java | 144 ++++++++++++++++++ .../simpleserver/StressDirListings.java | 2 +- test/jdk/java/net/Authenticator/B4769350.java | 4 +- .../net/www/http/KeepAliveCache/B8293562.java | 3 +- 7 files changed, 164 insertions(+), 11 deletions(-) create mode 100644 test/jdk/com/sun/net/httpserver/TcpNoDelayNotRequired.java diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java index 11ad6c3eaaab2..aefb9b5d1fcc1 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,8 +137,14 @@ public void close () throws IOException { if (closed) { return; } - flush(); try { + /* + * write any pending chunk data. manually write chunk rather than + * calling flush to avoid sending small packets + */ + if (count > 0) { + writeChunk(); + } /* write an empty chunk */ writeChunk(); out.flush(); diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java index 770642fda117d..1119d1e386b3e 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -207,7 +207,7 @@ public void sendResponseHeaders (int rCode, long contentLen) } this.rcode = rCode; String statusLine = "HTTP/1.1 "+rCode+Code.msg(rCode)+"\r\n"; - OutputStream tmpout = new BufferedOutputStream (ros); + ByteArrayOutputStream tmpout = new ByteArrayOutputStream(); PlaceholderOutputStream o = getPlaceholderResponseBody(); tmpout.write (bytes(statusLine, 0), 0, statusLine.length()); boolean noContentToSend = false; // assume there is content @@ -278,11 +278,11 @@ public void sendResponseHeaders (int rCode, long contentLen) write (rspHdrs, tmpout); this.rspContentLen = contentLen; - tmpout.flush() ; - tmpout = null; + tmpout.writeTo(ros); sentHeaders = true; logger.log(Level.TRACE, "Sent headers: noContentToSend=" + noContentToSend); if (noContentToSend) { + ros.flush(); close(); } server.logReply (rCode, req.requestLine(), null); diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index add5092033662..49377475719c7 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -686,6 +687,7 @@ public void run () { ServerImpl.this, chan ); } + rawout = new BufferedOutputStream(rawout); connection.raw = rawin; connection.rawout = rawout; } diff --git a/test/jdk/com/sun/net/httpserver/TcpNoDelayNotRequired.java b/test/jdk/com/sun/net/httpserver/TcpNoDelayNotRequired.java new file mode 100644 index 0000000000000..b736618882153 --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/TcpNoDelayNotRequired.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 6968351 + * @summary tcp no delay not required for small payloads + * @library /test/lib + * @run main/othervm/timeout=5 -Dsun.net.httpserver.nodelay=false TcpNoDelayNotRequired + */ + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.logging.StreamHandler; + +public class TcpNoDelayNotRequired { + + public static final Logger LOGGER = Logger.getLogger("sun.net.www.protocol.http"); + + public static void main (String[] args) throws Exception { + + java.util.logging.Handler outHandler = new StreamHandler(System.out, + new SimpleFormatter()); + outHandler.setLevel(Level.FINEST); + LOGGER.setLevel(Level.FINEST); + LOGGER.addHandler(outHandler); + + InetAddress loopback = InetAddress.getLoopbackAddress(); + InetSocketAddress addr = new InetSocketAddress (loopback, 0); + + SSLContext sslContext = new SimpleSSLContext().get(); + + HttpServer httpServer = HttpServer.create (addr, 0); + testHttpServer("http",httpServer,sslContext); + + HttpsServer httpsServer = HttpsServer.create (addr, 0); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext)); + + testHttpServer("https",httpsServer,sslContext); + } + + private static void testHttpServer(String scheme,HttpServer server,SSLContext sslContext) throws Exception { + HttpContext ctx = server.createContext ("/test", new Handler()); + HttpContext ctx2 = server.createContext ("/chunked", new ChunkedHandler()); + ExecutorService executor = Executors.newCachedThreadPool(); + server.setExecutor (executor); + server.start (); + try { + try (HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build()) { + long start = System.currentTimeMillis(); + for (int i = 0; i < 1000; i++) { + var uri = URIBuilder.newBuilder().scheme(scheme).loopback().port(server.getAddress().getPort()).path("/test").build(); + var response = client.send(HttpRequest.newBuilder(uri).build(), HttpResponse.BodyHandlers.ofString()); + if (!response.body().equals("hello")) + throw new IllegalStateException("incorrect body " + response.body()); + } + for (int i = 0; i < 1000; i++) { + var uri = URIBuilder.newBuilder().scheme(scheme).loopback().port(server.getAddress().getPort()).path("/chunked").build(); + var response = client.send(HttpRequest.newBuilder(uri).build(), HttpResponse.BodyHandlers.ofString()); + if (!response.body().equals("hello")) + throw new IllegalStateException("incorrect body " + response.body()); + } + long time = System.currentTimeMillis() - start; + System.out.println("time " + time); + } + } finally { + server.stop(0); + } + executor.shutdown(); + } + + static class Handler implements HttpHandler { + public void handle (HttpExchange t) + throws IOException + { + Headers rmap = t.getResponseHeaders(); + try (var is = t.getRequestBody()) { + is.readAllBytes(); + } + rmap.add("content-type","text/plain"); + t.sendResponseHeaders(200,5); + try (var os = t.getResponseBody()) { + os.write("hello".getBytes(StandardCharsets.ISO_8859_1)); + } + } + } + static class ChunkedHandler implements HttpHandler { + public void handle (HttpExchange t) + throws IOException + { + Headers rmap = t.getResponseHeaders(); + try (var is = t.getRequestBody()) { + is.readAllBytes(); + } + rmap.add("content-type","text/plain"); + t.sendResponseHeaders(200,0); + try (var os = t.getResponseBody()) { + os.write("hello".getBytes(StandardCharsets.ISO_8859_1)); + } + } + } +} diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/StressDirListings.java b/test/jdk/com/sun/net/httpserver/simpleserver/StressDirListings.java index 8197fd436e759..18a1f060c4897 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/StressDirListings.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/StressDirListings.java @@ -25,7 +25,7 @@ * @test * @summary Test to stress directory listings * @library /test/lib - * @run testng/othervm/timeout=180 -Dsun.net.httpserver.nodelay=true StressDirListings + * @run testng/othervm/timeout=180 StressDirListings */ import java.io.IOException; diff --git a/test/jdk/java/net/Authenticator/B4769350.java b/test/jdk/java/net/Authenticator/B4769350.java index aba41d222ea8e..813bf02de93c5 100644 --- a/test/jdk/java/net/Authenticator/B4769350.java +++ b/test/jdk/java/net/Authenticator/B4769350.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -355,7 +355,7 @@ static void proxyReply (HttpExchange exchange, String reply) throws IOException { exchange.getResponseHeaders().add("Proxy-Authenticate", reply); - exchange.sendResponseHeaders(407, 0); + exchange.sendResponseHeaders(407, -1); } static void okReply (HttpExchange exchange) throws IOException { diff --git a/test/jdk/sun/net/www/http/KeepAliveCache/B8293562.java b/test/jdk/sun/net/www/http/KeepAliveCache/B8293562.java index 2e6dbb84e2da6..0a6e7ef141622 100644 --- a/test/jdk/sun/net/www/http/KeepAliveCache/B8293562.java +++ b/test/jdk/sun/net/www/http/KeepAliveCache/B8293562.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,6 +244,7 @@ static class NotFoundHandler implements HttpHandler { public void handle(HttpExchange t) throws IOException { t.sendResponseHeaders(404, 3); t.getResponseBody().write("abc".getBytes(StandardCharsets.UTF_8)); + t.getResponseBody().close(); } } } From 5746137e8a46e1eb964fe8c4de015a62dc17a745 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 7 May 2024 14:23:39 +0000 Subject: [PATCH 110/203] 8331771: ZGC: Remove OopMapCacheAlloc_lock ordering workaround Reviewed-by: eosterlund, stefank, zgu --- src/hotspot/share/gc/shared/collectedHeap.hpp | 1 - src/hotspot/share/gc/shared/isGCActiveMark.cpp | 12 ------------ src/hotspot/share/gc/shared/isGCActiveMark.hpp | 6 ------ src/hotspot/share/gc/z/zVerify.cpp | 3 --- 4 files changed, 22 deletions(-) diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 6fbe6d708972b..0a586e71ac989 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -91,7 +91,6 @@ class CollectedHeap : public CHeapObj { friend class VMStructs; friend class JVMCIVMStructs; friend class IsSTWGCActiveMark; // Block structured external access to _is_stw_gc_active - friend class DisableIsSTWGCActiveMark; // Disable current IsSTWGCActiveMark friend class MemAllocator; friend class ParallelObjectIterator; diff --git a/src/hotspot/share/gc/shared/isGCActiveMark.cpp b/src/hotspot/share/gc/shared/isGCActiveMark.cpp index add6acaa01a22..7c400f2acc082 100644 --- a/src/hotspot/share/gc/shared/isGCActiveMark.cpp +++ b/src/hotspot/share/gc/shared/isGCActiveMark.cpp @@ -42,15 +42,3 @@ IsSTWGCActiveMark::~IsSTWGCActiveMark() { assert(heap->is_stw_gc_active(), "Sanity"); heap->_is_stw_gc_active = false; } - -DisableIsSTWGCActiveMark::DisableIsSTWGCActiveMark() { - CollectedHeap* heap = Universe::heap(); - assert(heap->is_stw_gc_active(), "Not reentrant"); - heap->_is_stw_gc_active = false; -} - -DisableIsSTWGCActiveMark::~DisableIsSTWGCActiveMark() { - CollectedHeap* heap = Universe::heap(); - assert(!heap->is_stw_gc_active(), "Sanity"); - heap->_is_stw_gc_active = true; -} diff --git a/src/hotspot/share/gc/shared/isGCActiveMark.hpp b/src/hotspot/share/gc/shared/isGCActiveMark.hpp index c65c7ebe56a68..e523c600ace5c 100644 --- a/src/hotspot/share/gc/shared/isGCActiveMark.hpp +++ b/src/hotspot/share/gc/shared/isGCActiveMark.hpp @@ -36,10 +36,4 @@ class IsSTWGCActiveMark : public StackObj { ~IsSTWGCActiveMark(); }; -class DisableIsSTWGCActiveMark : public StackObj { - public: - DisableIsSTWGCActiveMark(); - ~DisableIsSTWGCActiveMark(); -}; - #endif // SHARE_GC_SHARED_ISGCACTIVEMARK_HPP diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index d8f78eb26e211..fba8adfb3c16f 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -483,9 +483,6 @@ void ZVerify::after_mark() { roots_strong(true /* verify_after_old_mark */); } if (ZVerifyObjects) { - // Workaround OopMapCacheAlloc_lock reordering with the StackWatermark_lock - DisableIsSTWGCActiveMark mark; - objects(false /* verify_weaks */); guarantee(zverify_broken_object == zaddress::null, "Verification failed"); } From 95d2f8072e91e8df80e49e341f4fdb4464a2616e Mon Sep 17 00:00:00 2001 From: Daniel Skantz Date: Tue, 7 May 2024 15:50:15 +0000 Subject: [PATCH 111/203] 8330016: Stress seed should be initialized for runtime stub compilation Reviewed-by: rcastanedalo, chagedorn --- src/hotspot/share/opto/compile.cpp | 29 ++++++++++++++++++----------- src/hotspot/share/opto/compile.hpp | 3 +++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index d5ed95187a893..25c7ced8aebfe 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -844,19 +844,9 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, if (failing()) return; NOT_PRODUCT( verify_graph_edges(); ) - // If any phase is randomized for stress testing, seed random number - // generation and log the seed for repeatability. if (StressLCM || StressGCM || StressIGVN || StressCCP || StressIncrementalInlining || StressMacroExpansion) { - if (FLAG_IS_DEFAULT(StressSeed) || (FLAG_IS_ERGO(StressSeed) && directive->RepeatCompilationOption)) { - _stress_seed = static_cast(Ticks::now().nanoseconds()); - FLAG_SET_ERGO(StressSeed, _stress_seed); - } else { - _stress_seed = StressSeed; - } - if (_log != nullptr) { - _log->elem("stress_test seed='%u'", _stress_seed); - } + initialize_stress_seed(directive); } // Now optimize @@ -983,6 +973,11 @@ Compile::Compile( ciEnv* ci_env, _igvn_worklist = new (comp_arena()) Unique_Node_List(comp_arena()); _types = new (comp_arena()) Type_Array(comp_arena()); _node_hash = new (comp_arena()) NodeHash(comp_arena(), 255); + + if (StressLCM || StressGCM) { + initialize_stress_seed(directive); + } + { PhaseGVN gvn; set_initial_gvn(&gvn); // not significant, but GraphKit guys use it pervasively @@ -5068,6 +5063,18 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) { // Auxiliary methods to support randomized stressing/fuzzing. +void Compile::initialize_stress_seed(const DirectiveSet* directive) { + if (FLAG_IS_DEFAULT(StressSeed) || (FLAG_IS_ERGO(StressSeed) && directive->RepeatCompilationOption)) { + _stress_seed = static_cast(Ticks::now().nanoseconds()); + FLAG_SET_ERGO(StressSeed, _stress_seed); + } else { + _stress_seed = StressSeed; + } + if (_log != nullptr) { + _log->elem("stress_test seed='%u'", _stress_seed); + } +} + int Compile::random() { _stress_seed = os::next_random(_stress_seed); return static_cast(_stress_seed); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index df93b388daa8d..e1d9b61f7f8d1 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1278,6 +1278,9 @@ class Compile : public Phase { int random(); bool randomized_select(int count); + // seed random number generation and log the seed for repeatability. + void initialize_stress_seed(const DirectiveSet* directive); + // supporting clone_map CloneMap& clone_map(); void set_clone_map(Dict* d); From 524aaad98317b1a50453e5a9a44922f481fb3b1e Mon Sep 17 00:00:00 2001 From: Sonia Zaldana Calles Date: Tue, 7 May 2024 15:59:44 +0000 Subject: [PATCH 112/203] 8319957: PhaseOutput::code_size is unused and should be removed Reviewed-by: thartmann, chagedorn --- src/hotspot/share/opto/output.cpp | 1 - src/hotspot/share/opto/output.hpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 4d623144a8407..3f48567c09363 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -1280,7 +1280,6 @@ void PhaseOutput::estimate_buffer_size(int& const_req) { } // Compute prolog code size - _method_size = 0; _frame_slots = OptoReg::reg2stack(C->matcher()->_old_SP) + C->regalloc()->_framesize; assert(_frame_slots >= 0 && _frame_slots < 1000000, "sanity check"); diff --git a/src/hotspot/share/opto/output.hpp b/src/hotspot/share/opto/output.hpp index b58b97e77455e..1717955360256 100644 --- a/src/hotspot/share/opto/output.hpp +++ b/src/hotspot/share/opto/output.hpp @@ -77,7 +77,6 @@ class BufferSizingData { class PhaseOutput : public Phase { private: // Instruction bits passed off to the VM - int _method_size; // Size of nmethod code segment in bytes CodeBuffer _code_buffer; // Where the code is assembled int _first_block_size; // Size of unvalidated entry point code / OSR poison code ExceptionHandlerTable _handler_table; // Table of native-code exception handlers @@ -166,7 +165,6 @@ class PhaseOutput : public Phase { void install(); // Instruction bits passed off to the VM - int code_size() { return _method_size; } CodeBuffer* code_buffer() { return &_code_buffer; } int first_block_size() { return _first_block_size; } void set_frame_complete(int off) { if (!in_scratch_emit_size()) { _code_offsets.set_value(CodeOffsets::Frame_Complete, off); } } From 8d78e8cadcc06aea7179ec97d3bf8b7cee63b447 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 7 May 2024 18:59:41 +0000 Subject: [PATCH 113/203] 8319997: JFR: Reduce use of dynamic proxies Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/EventType.java | 11 ++--- .../jdk/jfr/internal/AnnotationConstruct.java | 33 +++++++------ .../jdk/jfr/internal/EventControl.java | 46 +++++-------------- .../jdk/jfr/internal/MetadataRepository.java | 8 ++-- .../share/classes/jdk/jfr/internal/Type.java | 8 ++++ 5 files changed, 46 insertions(+), 60 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/EventType.java b/src/jdk.jfr/share/classes/jdk/jfr/EventType.java index 07c82d5bf53fa..d9b4e50fca829 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/EventType.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/EventType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ */ public final class EventType { private static final String UNKNOWN = new String(); - private static final List UNCATEGORIZED = List.of("Uncategorized"); + private static final String[] UNCATEGORIZED = { "Uncategorized" }; private final PlatformEventType platformEventType; private Map cache; // create lazy to avoid memory overhead private String label = UNKNOWN; @@ -235,11 +235,8 @@ public List getSettingDescriptors() { * @see Category */ public List getCategoryNames() { - Category c = platformEventType.getAnnotation(Category.class); - if (c == null) { - return UNCATEGORIZED; - } - return List.of(c.value()); + String[] categories = platformEventType.getAnnotationValue(Category.class, UNCATEGORIZED); + return List.of(categories); } // package private diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/AnnotationConstruct.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/AnnotationConstruct.java index 8b5b45fb223fb..9a203ff372537 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/AnnotationConstruct.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/AnnotationConstruct.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,19 +72,11 @@ public void setAnnotationElements(List elements) { } public String getLabel() { - Label label = getAnnotation(Label.class); - if (label == null) { - return null; - } - return label.value(); + return getAnnotationValue(Label.class, null); } public String getDescription() { - Description description = getAnnotation(Description.class); - if (description == null) { - return null; - } - return description.value(); + return getAnnotationValue(Description.class, null); } @SuppressWarnings("unchecked") @@ -100,7 +92,20 @@ public List getUnmodifiableAnnotationElements() { return annotationElements; } - private AnnotationElement getAnnotationElement(Class clazz) { + /** + * Convenience method that returns the annotation value, or a default value + * if the type lacks the annotation. + */ + @SuppressWarnings("unchecked") + public T getAnnotationValue(Class clazz, T defaultValue) { + AnnotationElement ae = getAnnotationElement(clazz); + if (ae == null) { + return defaultValue; + } + return (T) ae.getValues().get(0); + } + + AnnotationElement getAnnotationElement(Class clazz) { // if multiple annotation elements with the same name exists, prioritize // the one with the same id. Note, id alone is not a guarantee, since it // may differ between JVM instances. @@ -123,8 +128,8 @@ public boolean hasUnsigned() { // Must be initialized lazily since some annotation elements // are added after construction if (unsignedFlag < 0) { - Unsigned unsigned = getAnnotation(Unsigned.class); - unsignedFlag = (byte) (unsigned == null ? 0 :1); + AnnotationElement ae = getAnnotationElement(Unsigned.class); + unsignedFlag = (byte) (ae == null ? 0 :1); } return unsignedFlag == (byte)1 ? true : false; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java index 68aa3eb84781d..2a758aa8addc6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -290,72 +290,48 @@ private SettingControl instantiateSettingControl(Class } private static Control defineEnabled(PlatformEventType type) { - Enabled enabled = type.getAnnotation(Enabled.class); // Java events are enabled by default, // JVM events are not, maybe they should be? Would lower learning curve // there too. - String def = type.isJVM() ? "false" : "true"; - if (enabled != null) { - def = Boolean.toString(enabled.value()); - } + Boolean defaultValue = Boolean.valueOf(!type.isJVM()); + String def = type.getAnnotationValue(Enabled.class, defaultValue).toString(); type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_ENABLED, Enabled.NAME, def, Collections.emptyList())); return new Control(new EnabledSetting(type, def), def); } private static Control defineThreshold(PlatformEventType type) { - Threshold threshold = type.getAnnotation(Threshold.class); - String def = "0 ns"; - if (threshold != null) { - def = threshold.value(); - } + String def = type.getAnnotationValue(Threshold.class, "0 ns"); type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_THRESHOLD, Threshold.NAME, def, Collections.emptyList())); return new Control(new ThresholdSetting(type), def); } private static Control defineStackTrace(PlatformEventType type) { - StackTrace stackTrace = type.getAnnotation(StackTrace.class); - String def = "true"; - if (stackTrace != null) { - def = Boolean.toString(stackTrace.value()); - } + String def = type.getAnnotationValue(StackTrace.class, Boolean.TRUE).toString(); type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_STACK_TRACE, StackTrace.NAME, def, Collections.emptyList())); return new Control(new StackTraceSetting(type, def), def); } private static Control defineCutoff(PlatformEventType type) { - Cutoff cutoff = type.getAnnotation(Cutoff.class); - String def = Cutoff.INFINITY; - if (cutoff != null) { - def = cutoff.value(); - } + String def = type.getAnnotationValue(Cutoff.class, Cutoff.INFINITY); type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_CUTOFF, Cutoff.NAME, def, Collections.emptyList())); return new Control(new CutoffSetting(type), def); } private static Control defineThrottle(PlatformEventType type) { - Throttle throttle = type.getAnnotation(Throttle.class); - String def = Throttle.DEFAULT; - if (throttle != null) { - def = throttle.value(); - } + String def = type.getAnnotationValue(Throttle.class, Throttle.DEFAULT); type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_THROTTLE, Throttle.NAME, def, Collections.emptyList())); return new Control(new ThrottleSetting(type), def); } private static Control defineLevel(PlatformEventType type) { - Level level = type.getAnnotation(Level.class); - String[] values = level.value(); - String def = values[0]; + String[] levels = type.getAnnotationValue(Level.class, new String[0]); + String def = levels[0]; // Level value always exists type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_LEVEL, Level.NAME, def, Collections.emptyList())); - return new Control(new LevelSetting(type, values), def); + return new Control(new LevelSetting(type, levels), def); } private static Control definePeriod(PlatformEventType type) { - Period period = type.getAnnotation(Period.class); - String def = "everyChunk"; - if (period != null) { - def = period.value(); - } + String def = type.getAnnotationValue(Period.class, "everyChunk"); type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_PERIOD, PeriodSetting.NAME, def, Collections.emptyList())); return new Control(new PeriodSetting(type), def); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java index 7d61d3c984fe2..9a2bbfe4c6314 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -73,10 +73,10 @@ private void initializeJVMEventTypes() { for (Type type : TypeLibrary.getTypes()) { if (type instanceof PlatformEventType pEventType) { EventType eventType = PrivateAccess.getInstance().newEventType(pEventType); - pEventType.setHasCutoff(eventType.getAnnotation(Cutoff.class) != null); - pEventType.setHasThrottle(eventType.getAnnotation(Throttle.class) != null); - pEventType.setHasLevel(eventType.getAnnotation(Level.class) != null); - pEventType.setHasPeriod(eventType.getAnnotation(Period.class) != null); + pEventType.setHasCutoff(type.hasAnnotation(Cutoff.class)); + pEventType.setHasThrottle(type.hasAnnotation(Throttle.class)); + pEventType.setHasLevel(type.hasAnnotation(Level.class)); + pEventType.setHasPeriod(type.hasAnnotation(Period.class)); // Must add hook before EventControl is created as it removes // annotations, such as Period and Threshold. if (pEventType.hasPeriod()) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java index bc949b8c7ff9d..0306541b4f781 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java @@ -264,6 +264,10 @@ public List getAnnotationElements() { return annos.getUnmodifiableAnnotationElements(); } + public T getAnnotationValue(Class clazz, T defaultValue) { + return annos.getAnnotationValue(clazz, defaultValue); + } + public T getAnnotation(Class clazz) { return annos.getAnnotation(clazz); } @@ -359,4 +363,8 @@ public void setInternal(boolean internal) { public boolean isInternal() { return internal; } + + public boolean hasAnnotation(Class clazz) { + return annos.getAnnotationElement(clazz) != null; + } } From f12ed061ae3fa9d5620a7c6c7ea441f9f33bb745 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 7 May 2024 19:06:36 +0000 Subject: [PATCH 114/203] 8048691: Spliterator.SORTED characteristics gets cleared for BaseStream.spliterator Reviewed-by: psandoz, alanb --- .../java/util/stream/StreamSpliterators.java | 7 +++++- .../util/stream/StreamSpliteratorTest.java | 23 ++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/stream/StreamSpliterators.java b/src/java.base/share/classes/java/util/stream/StreamSpliterators.java index a098bb2f2acab..196cd76c8f821 100644 --- a/src/java.base/share/classes/java/util/stream/StreamSpliterators.java +++ b/src/java.base/share/classes/java/util/stream/StreamSpliterators.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,6 +248,11 @@ public final int characteristics() { c |= (spliterator.characteristics() & (Spliterator.SIZED | Spliterator.SUBSIZED)); } + // It's not allowed for a Spliterator to report SORTED if not also ORDERED + if ((c & Spliterator.SORTED) != 0 && (c & Spliterator.ORDERED) == 0) { + c &= ~(Spliterator.SORTED); + } + return c; } diff --git a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java index d3b0d254c4156..1a281885b3169 100644 --- a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java +++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -605,6 +605,27 @@ public void testDoubleParSpliterators(String name, TestData.OfDouble data) { } } + @Test + public void testCharacteristicsForSortedUnorderedStreamSpliterators() { + assertValidCombinationOfSortedAndOrdered( + DoubleStream.of(3d,2d,4d,1d,5d).sorted().unordered().spliterator() + ); + assertValidCombinationOfSortedAndOrdered( + IntStream.of(3,2,4,1,5).sorted().unordered().spliterator() + ); + assertValidCombinationOfSortedAndOrdered( + LongStream.of(3L,2L,4L,1L,5L).sorted().unordered().spliterator() + ); + assertValidCombinationOfSortedAndOrdered( + Stream.of(3,2,4,1,5).sorted().unordered().spliterator() + ); + } + + void assertValidCombinationOfSortedAndOrdered(Spliterator s) { + if (s.hasCharacteristics(Spliterator.SORTED)) + Assert.assertTrue(s.hasCharacteristics(Spliterator.ORDERED)); + } + private List> doubleStreamFunctions; List> doubleStreamFunctions() { From b91083341aba952befadd79020079920f9540999 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 7 May 2024 23:46:04 +0000 Subject: [PATCH 115/203] 8331864: Update Public Suffix List to 1cbd6e7 Reviewed-by: mullan --- .../share/data/publicsuffixlist/VERSION | 4 +- .../publicsuffixlist/public_suffix_list.dat | 605 +++++++++++++----- src/java.base/share/legal/public_suffix.md | 2 +- .../util/RegisteredDomain/ParseNames.java | 2 +- .../security/util/RegisteredDomain/tests.dat | 11 + 5 files changed, 464 insertions(+), 160 deletions(-) diff --git a/src/java.base/share/data/publicsuffixlist/VERSION b/src/java.base/share/data/publicsuffixlist/VERSION index f86d2df03ca38..24f4407cc89ab 100644 --- a/src/java.base/share/data/publicsuffixlist/VERSION +++ b/src/java.base/share/data/publicsuffixlist/VERSION @@ -1,2 +1,2 @@ -Github: https://raw.githubusercontent.com/publicsuffix/list/b5bf572c52988dbe9d865b8f090ea819024a9936/public_suffix_list.dat -Date: 2023-11-09 +Github: https://raw.githubusercontent.com/publicsuffix/list/1cbd6e71a9b83620b1d0b11e49d3d9ff48c27e22/public_suffix_list.dat +Date: 2024-05-07 diff --git a/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat b/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat index fff6e9a494d64..34733674ea00f 100644 --- a/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat +++ b/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat @@ -6710,7 +6710,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-11-03T15:13:18Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2024-05-04T15:12:50Z // This list is auto-generated, don't edit it manually. // aaa : American Automobile Association, Inc. // https://www.iana.org/domains/root/db/aaa.html @@ -6896,7 +6896,7 @@ anquan // https://www.iana.org/domains/root/db/anz.html anz -// aol : Oath Inc. +// aol : Yahoo Inc. // https://www.iana.org/domains/root/db/aol.html aol @@ -6988,10 +6988,6 @@ auto // https://www.iana.org/domains/root/db/autos.html autos -// avianca : Avianca Inc. -// https://www.iana.org/domains/root/db/avianca.html -avianca - // aws : AWS Registry LLC // https://www.iana.org/domains/root/db/aws.html aws @@ -7016,10 +7012,6 @@ baidu // https://www.iana.org/domains/root/db/banamex.html banamex -// bananarepublic : The Gap, Inc. -// https://www.iana.org/domains/root/db/bananarepublic.html -bananarepublic - // band : Dog Beach, LLC // https://www.iana.org/domains/root/db/band.html band @@ -7544,10 +7536,6 @@ college // https://www.iana.org/domains/root/db/cologne.html cologne -// comcast : Comcast IP Holdings I, LLC -// https://www.iana.org/domains/root/db/comcast.html -comcast - // commbank : COMMONWEALTH BANK OF AUSTRALIA // https://www.iana.org/domains/root/db/commbank.html commbank @@ -7752,6 +7740,10 @@ dental // https://www.iana.org/domains/root/db/dentist.html dentist +// desi +// https://www.iana.org/domains/root/db/desi.html +desi + // design : Registry Services, LLC // https://www.iana.org/domains/root/db/design.html design @@ -7796,7 +7788,7 @@ discover // https://www.iana.org/domains/root/db/dish.html dish -// diy : Lifestyle Domain Holdings, Inc. +// diy : Internet Naming Company LLC // https://www.iana.org/domains/root/db/diy.html diy @@ -7928,10 +7920,6 @@ esq // https://www.iana.org/domains/root/db/estate.html estate -// etisalat : Emirates Telecommunications Corporation (trading as Etisalat) -// https://www.iana.org/domains/root/db/etisalat.html -etisalat - // eurovision : European Broadcasting Union (EBU) // https://www.iana.org/domains/root/db/eurovision.html eurovision @@ -8104,7 +8092,7 @@ fly // https://www.iana.org/domains/root/db/foo.html foo -// food : Lifestyle Domain Holdings, Inc. +// food : Internet Naming Company LLC // https://www.iana.org/domains/root/db/food.html food @@ -8164,7 +8152,7 @@ ftr // https://www.iana.org/domains/root/db/fujitsu.html fujitsu -// fun : Radix FZC DMCC +// fun : Radix Technologies Inc. // https://www.iana.org/domains/root/db/fun.html fun @@ -8312,7 +8300,7 @@ goldpoint // https://www.iana.org/domains/root/db/golf.html golf -// goo : NTT Resonant Inc. +// goo : NTT DOCOMO, INC. // https://www.iana.org/domains/root/db/goo.html goo @@ -8364,10 +8352,6 @@ grocery // https://www.iana.org/domains/root/db/group.html group -// guardian : The Guardian Life Insurance Company of America -// https://www.iana.org/domains/root/db/guardian.html -guardian - // gucci : Guccio Gucci S.p.a. // https://www.iana.org/domains/root/db/gucci.html gucci @@ -8500,7 +8484,7 @@ horse // https://www.iana.org/domains/root/db/hospital.html hospital -// host : Radix FZC DMCC +// host : Radix Technologies Inc. // https://www.iana.org/domains/root/db/host.html host @@ -8720,7 +8704,7 @@ jpmorgan // https://www.iana.org/domains/root/db/jprs.html jprs -// juegos : Internet Naming Company LLC +// juegos : Dog Beach, LLC // https://www.iana.org/domains/root/db/juegos.html juegos @@ -8908,7 +8892,7 @@ life // https://www.iana.org/domains/root/db/lifeinsurance.html lifeinsurance -// lifestyle : Lifestyle Domain Holdings, Inc. +// lifestyle : Internet Naming Company LLC // https://www.iana.org/domains/root/db/lifestyle.html lifestyle @@ -8948,7 +8932,7 @@ lipsy // https://www.iana.org/domains/root/db/live.html live -// living : Lifestyle Domain Holdings, Inc. +// living : Internet Naming Company LLC // https://www.iana.org/domains/root/db/living.html living @@ -9392,10 +9376,6 @@ olayan // https://www.iana.org/domains/root/db/olayangroup.html olayangroup -// oldnavy : The Gap, Inc. -// https://www.iana.org/domains/root/db/oldnavy.html -oldnavy - // ollo : Dish DBS Corporation // https://www.iana.org/domains/root/db/ollo.html ollo @@ -9416,7 +9396,7 @@ ong // https://www.iana.org/domains/root/db/onl.html onl -// online : Radix FZC DMCC +// online : Radix Technologies Inc. // https://www.iana.org/domains/root/db/online.html online @@ -9620,7 +9600,7 @@ pramerica // https://www.iana.org/domains/root/db/praxi.html praxi -// press : Radix FZC DMCC +// press : Radix Technologies Inc. // https://www.iana.org/domains/root/db/press.html press @@ -9928,10 +9908,6 @@ sbi // https://www.iana.org/domains/root/db/sbs.html sbs -// sca : SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) -// https://www.iana.org/domains/root/db/sca.html -sca - // scb : The Siam Commercial Bank Public Company Limited ("SCB") // https://www.iana.org/domains/root/db/scb.html scb @@ -10076,7 +10052,7 @@ sina // https://www.iana.org/domains/root/db/singles.html singles -// site : Radix FZC DMCC +// site : Radix Technologies Inc. // https://www.iana.org/domains/root/db/site.html site @@ -10156,7 +10132,7 @@ soy // https://www.iana.org/domains/root/db/spa.html spa -// space : Radix FZC DMCC +// space : Radix Technologies Inc. // https://www.iana.org/domains/root/db/space.html space @@ -10208,7 +10184,7 @@ stockholm // https://www.iana.org/domains/root/db/storage.html storage -// store : Radix FZC DMCC +// store : Radix Technologies Inc. // https://www.iana.org/domains/root/db/store.html store @@ -10324,7 +10300,7 @@ tdk // https://www.iana.org/domains/root/db/team.html team -// tech : Radix FZC DMCC +// tech : Radix Technologies Inc. // https://www.iana.org/domains/root/db/tech.html tech @@ -10508,7 +10484,7 @@ unicom // https://www.iana.org/domains/root/db/university.html university -// uno : Radix FZC DMCC +// uno : Radix Technologies Inc. // https://www.iana.org/domains/root/db/uno.html uno @@ -10524,7 +10500,7 @@ ups // https://www.iana.org/domains/root/db/vacations.html vacations -// vana : Lifestyle Domain Holdings, Inc. +// vana : Internet Naming Company LLC // https://www.iana.org/domains/root/db/vana.html vana @@ -10608,10 +10584,6 @@ vlaanderen // https://www.iana.org/domains/root/db/vodka.html vodka -// volkswagen : Volkswagen Group of America Inc. -// https://www.iana.org/domains/root/db/volkswagen.html -volkswagen - // volvo : Volvo Holding Sverige Aktiebolag // https://www.iana.org/domains/root/db/volvo.html volvo @@ -10676,10 +10648,14 @@ webcam // https://www.iana.org/domains/root/db/weber.html weber -// website : Radix FZC DMCC +// website : Radix Technologies Inc. // https://www.iana.org/domains/root/db/website.html website +// wed +// https://www.iana.org/domains/root/db/wed.html +wed + // wedding : Registry Services, LLC // https://www.iana.org/domains/root/db/wedding.html wedding @@ -10768,10 +10744,6 @@ xbox // https://www.iana.org/domains/root/db/xerox.html xerox -// xfinity : Comcast IP Holdings I, LLC -// https://www.iana.org/domains/root/db/xfinity.html -xfinity - // xihuan : Beijing Qihu Keji Co., Ltd. // https://www.iana.org/domains/root/db/xihuan.html xihuan @@ -11012,10 +10984,6 @@ xin // https://www.iana.org/domains/root/db/xn--mgba7c0bbn0a.html العليان -// xn--mgbaakc7dvf : Emirates Telecommunications Corporation (trading as Etisalat) -// https://www.iana.org/domains/root/db/xn--mgbaakc7dvf.html -اتصالات - // xn--mgbab2bd : CORE Association // https://www.iana.org/domains/root/db/xn--mgbab2bd.html بازار @@ -11152,7 +11120,7 @@ xyz // https://www.iana.org/domains/root/db/yachts.html yachts -// yahoo : Oath Inc. +// yahoo : Yahoo Inc. // https://www.iana.org/domains/root/db/yahoo.html yahoo @@ -11217,6 +11185,12 @@ zuerich // ===BEGIN PRIVATE DOMAINS=== // (Note: these are in alphabetical order by company name) +// 12CHARS: https://12chars.com +// Submitted by Kenny Niehage +12chars.dev +12chars.it +12chars.pro + // 1GB LLC : https://www.1gb.ua/ // Submitted by 1GB LLC cc.ua @@ -11226,6 +11200,15 @@ ltd.ua // 611coin : https://611project.org/ 611.to +// AAA workspace : https://aaa.vodka +// Submitted by Kirill Rezraf +aaa.vodka + +// A2 Hosting +// Submitted by Tyler Hall +a2hosted.com +cpserver.com + // Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za // Submitted by Aaron Marais graphox.us @@ -11242,12 +11225,18 @@ graphox.us // Submitted by Ofer Kalaora activetrail.biz +// Adaptable.io : https://adaptable.io +// Submitted by Mark Terrel +adaptable.app + // Adobe : https://www.adobe.com/ // Submitted by Ian Boston and Lars Trieloff adobeaemcloud.com *.dev.adobeaemcloud.com +aem.live hlx.live adobeaemcloud.net +aem.page hlx.page hlx3.page @@ -11319,7 +11308,7 @@ myamaze.net // Amazon API Gateway // Submitted by AWS Security -// Reference: 4d863337-ff98-4501-a6f2-361eba8445d6 +// Reference: 9e37648f-a66c-4655-9ab1-5981f8737197 execute-api.cn-north-1.amazonaws.com.cn execute-api.cn-northwest-1.amazonaws.com.cn execute-api.af-south-1.amazonaws.com @@ -11334,6 +11323,7 @@ execute-api.ap-southeast-2.amazonaws.com execute-api.ap-southeast-3.amazonaws.com execute-api.ap-southeast-4.amazonaws.com execute-api.ca-central-1.amazonaws.com +execute-api.ca-west-1.amazonaws.com execute-api.eu-central-1.amazonaws.com execute-api.eu-central-2.amazonaws.com execute-api.eu-north-1.amazonaws.com @@ -11360,23 +11350,28 @@ cloudfront.net // Amazon Cognito // Submitted by AWS Security -// Reference: 7bee1013-f456-47df-bfe8-03c78d946d61 +// Reference: 09588633-91fe-49d8-b4e7-ec36496d11f3 auth.af-south-1.amazoncognito.com auth.ap-northeast-1.amazoncognito.com auth.ap-northeast-2.amazoncognito.com auth.ap-northeast-3.amazoncognito.com auth.ap-south-1.amazoncognito.com +auth.ap-south-2.amazoncognito.com auth.ap-southeast-1.amazoncognito.com auth.ap-southeast-2.amazoncognito.com auth.ap-southeast-3.amazoncognito.com +auth.ap-southeast-4.amazoncognito.com auth.ca-central-1.amazoncognito.com auth.eu-central-1.amazoncognito.com +auth.eu-central-2.amazoncognito.com auth.eu-north-1.amazoncognito.com auth.eu-south-1.amazoncognito.com +auth.eu-south-2.amazoncognito.com auth.eu-west-1.amazoncognito.com auth.eu-west-2.amazoncognito.com auth.eu-west-3.amazoncognito.com auth.il-central-1.amazoncognito.com +auth.me-central-1.amazoncognito.com auth.me-south-1.amazoncognito.com auth.sa-east-1.amazoncognito.com auth.us-east-1.amazoncognito.com @@ -11399,7 +11394,7 @@ us-east-1.amazonaws.com // Amazon EMR // Submitted by AWS Security -// Reference: 597f3f8e-9283-4e48-8e32-7ee25a1ff6ab +// Reference: 82f43f9f-bbb8-400e-8349-854f5a62f20d emrappui-prod.cn-north-1.amazonaws.com.cn emrnotebooks-prod.cn-north-1.amazonaws.com.cn emrstudio-prod.cn-north-1.amazonaws.com.cn @@ -11424,6 +11419,9 @@ emrstudio-prod.ap-northeast-3.amazonaws.com emrappui-prod.ap-south-1.amazonaws.com emrnotebooks-prod.ap-south-1.amazonaws.com emrstudio-prod.ap-south-1.amazonaws.com +emrappui-prod.ap-south-2.amazonaws.com +emrnotebooks-prod.ap-south-2.amazonaws.com +emrstudio-prod.ap-south-2.amazonaws.com emrappui-prod.ap-southeast-1.amazonaws.com emrnotebooks-prod.ap-southeast-1.amazonaws.com emrstudio-prod.ap-southeast-1.amazonaws.com @@ -11433,18 +11431,30 @@ emrstudio-prod.ap-southeast-2.amazonaws.com emrappui-prod.ap-southeast-3.amazonaws.com emrnotebooks-prod.ap-southeast-3.amazonaws.com emrstudio-prod.ap-southeast-3.amazonaws.com +emrappui-prod.ap-southeast-4.amazonaws.com +emrnotebooks-prod.ap-southeast-4.amazonaws.com +emrstudio-prod.ap-southeast-4.amazonaws.com emrappui-prod.ca-central-1.amazonaws.com emrnotebooks-prod.ca-central-1.amazonaws.com emrstudio-prod.ca-central-1.amazonaws.com +emrappui-prod.ca-west-1.amazonaws.com +emrnotebooks-prod.ca-west-1.amazonaws.com +emrstudio-prod.ca-west-1.amazonaws.com emrappui-prod.eu-central-1.amazonaws.com emrnotebooks-prod.eu-central-1.amazonaws.com emrstudio-prod.eu-central-1.amazonaws.com +emrappui-prod.eu-central-2.amazonaws.com +emrnotebooks-prod.eu-central-2.amazonaws.com +emrstudio-prod.eu-central-2.amazonaws.com emrappui-prod.eu-north-1.amazonaws.com emrnotebooks-prod.eu-north-1.amazonaws.com emrstudio-prod.eu-north-1.amazonaws.com emrappui-prod.eu-south-1.amazonaws.com emrnotebooks-prod.eu-south-1.amazonaws.com emrstudio-prod.eu-south-1.amazonaws.com +emrappui-prod.eu-south-2.amazonaws.com +emrnotebooks-prod.eu-south-2.amazonaws.com +emrstudio-prod.eu-south-2.amazonaws.com emrappui-prod.eu-west-1.amazonaws.com emrnotebooks-prod.eu-west-1.amazonaws.com emrstudio-prod.eu-west-1.amazonaws.com @@ -11454,6 +11464,9 @@ emrstudio-prod.eu-west-2.amazonaws.com emrappui-prod.eu-west-3.amazonaws.com emrnotebooks-prod.eu-west-3.amazonaws.com emrstudio-prod.eu-west-3.amazonaws.com +emrappui-prod.il-central-1.amazonaws.com +emrnotebooks-prod.il-central-1.amazonaws.com +emrstudio-prod.il-central-1.amazonaws.com emrappui-prod.me-central-1.amazonaws.com emrnotebooks-prod.me-central-1.amazonaws.com emrstudio-prod.me-central-1.amazonaws.com @@ -11484,9 +11497,11 @@ emrstudio-prod.us-west-2.amazonaws.com // Amazon Managed Workflows for Apache Airflow // Submitted by AWS Security -// Reference: 4ab55e6f-90c0-4a8d-b6a0-52ca5dbb1c2e +// Reference: 87f24ece-a77e-40e8-bb4a-f6b74fe9f975 *.cn-north-1.airflow.amazonaws.com.cn *.cn-northwest-1.airflow.amazonaws.com.cn +*.af-south-1.airflow.amazonaws.com +*.ap-east-1.airflow.amazonaws.com *.ap-northeast-1.airflow.amazonaws.com *.ap-northeast-2.airflow.amazonaws.com *.ap-south-1.airflow.amazonaws.com @@ -11495,17 +11510,20 @@ emrstudio-prod.us-west-2.amazonaws.com *.ca-central-1.airflow.amazonaws.com *.eu-central-1.airflow.amazonaws.com *.eu-north-1.airflow.amazonaws.com +*.eu-south-1.airflow.amazonaws.com *.eu-west-1.airflow.amazonaws.com *.eu-west-2.airflow.amazonaws.com *.eu-west-3.airflow.amazonaws.com +*.me-south-1.airflow.amazonaws.com *.sa-east-1.airflow.amazonaws.com *.us-east-1.airflow.amazonaws.com *.us-east-2.airflow.amazonaws.com +*.us-west-1.airflow.amazonaws.com *.us-west-2.airflow.amazonaws.com // Amazon S3 // Submitted by AWS Security -// Reference: 0e801048-08f2-4064-9cb8-e7373e0b57f4 +// Reference: cd5c8b3a-67b7-4b40-9236-c87ce81a3d10 s3.dualstack.cn-north-1.amazonaws.com.cn s3-accesspoint.dualstack.cn-north-1.amazonaws.com.cn s3-website.dualstack.cn-north-1.amazonaws.com.cn @@ -11604,6 +11622,16 @@ s3-accesspoint-fips.ca-central-1.amazonaws.com s3-fips.ca-central-1.amazonaws.com s3-object-lambda.ca-central-1.amazonaws.com s3-website.ca-central-1.amazonaws.com +s3.dualstack.ca-west-1.amazonaws.com +s3-accesspoint.dualstack.ca-west-1.amazonaws.com +s3-accesspoint-fips.dualstack.ca-west-1.amazonaws.com +s3-fips.dualstack.ca-west-1.amazonaws.com +s3-website.dualstack.ca-west-1.amazonaws.com +s3.ca-west-1.amazonaws.com +s3-accesspoint.ca-west-1.amazonaws.com +s3-accesspoint-fips.ca-west-1.amazonaws.com +s3-fips.ca-west-1.amazonaws.com +s3-website.ca-west-1.amazonaws.com s3.dualstack.eu-central-1.amazonaws.com s3-accesspoint.dualstack.eu-central-1.amazonaws.com s3-website.dualstack.eu-central-1.amazonaws.com @@ -11784,9 +11812,25 @@ s3-fips.us-west-2.amazonaws.com s3-object-lambda.us-west-2.amazonaws.com s3-website.us-west-2.amazonaws.com +// Amazon SageMaker Ground Truth +// Submitted by AWS Security +// Reference: 98dbfde4-7802-48c3-8751-b60f204e0d9c +labeling.ap-northeast-1.sagemaker.aws +labeling.ap-northeast-2.sagemaker.aws +labeling.ap-south-1.sagemaker.aws +labeling.ap-southeast-1.sagemaker.aws +labeling.ap-southeast-2.sagemaker.aws +labeling.ca-central-1.sagemaker.aws +labeling.eu-central-1.sagemaker.aws +labeling.eu-west-1.sagemaker.aws +labeling.eu-west-2.sagemaker.aws +labeling.us-east-1.sagemaker.aws +labeling.us-east-2.sagemaker.aws +labeling.us-west-2.sagemaker.aws + // Amazon SageMaker Notebook Instances // Submitted by AWS Security -// Reference: fe8c9e94-5a22-486d-8750-991a3a9b13c6 +// Reference: b5ea56df-669e-43cc-9537-14aa172f5dfc notebook.af-south-1.sagemaker.aws notebook.ap-east-1.sagemaker.aws notebook.ap-northeast-1.sagemaker.aws @@ -11799,6 +11843,9 @@ notebook.ap-southeast-2.sagemaker.aws notebook.ap-southeast-3.sagemaker.aws notebook.ap-southeast-4.sagemaker.aws notebook.ca-central-1.sagemaker.aws +notebook-fips.ca-central-1.sagemaker.aws +notebook.ca-west-1.sagemaker.aws +notebook-fips.ca-west-1.sagemaker.aws notebook.eu-central-1.sagemaker.aws notebook.eu-central-2.sagemaker.aws notebook.eu-north-1.sagemaker.aws @@ -11820,6 +11867,7 @@ notebook-fips.us-gov-east-1.sagemaker.aws notebook.us-gov-west-1.sagemaker.aws notebook-fips.us-gov-west-1.sagemaker.aws notebook.us-west-1.sagemaker.aws +notebook-fips.us-west-1.sagemaker.aws notebook.us-west-2.sagemaker.aws notebook-fips.us-west-2.sagemaker.aws notebook.cn-north-1.sagemaker.com.cn @@ -11827,7 +11875,7 @@ notebook.cn-northwest-1.sagemaker.com.cn // Amazon SageMaker Studio // Submitted by AWS Security -// Reference: 057ee397-6bf8-4f20-b807-d7bc145ac980 +// Reference: 69c723d9-6e1a-4bff-a203-48eecd203183 studio.af-south-1.sagemaker.aws studio.ap-east-1.sagemaker.aws studio.ap-northeast-1.sagemaker.aws @@ -11841,6 +11889,7 @@ studio.ca-central-1.sagemaker.aws studio.eu-central-1.sagemaker.aws studio.eu-north-1.sagemaker.aws studio.eu-south-1.sagemaker.aws +studio.eu-south-2.sagemaker.aws studio.eu-west-1.sagemaker.aws studio.eu-west-2.sagemaker.aws studio.eu-west-3.sagemaker.aws @@ -11885,7 +11934,7 @@ analytics-gateway.us-west-2.amazonaws.com // AWS Cloud9 // Submitted by: AWS Security -// Reference: 05c44955-977c-4b57-938a-f2af92733f9f +// Reference: 30717f72-4007-4f0f-8ed4-864c6f2efec9 webview-assets.aws-cloud9.af-south-1.amazonaws.com vfs.cloud9.af-south-1.amazonaws.com webview-assets.cloud9.af-south-1.amazonaws.com @@ -11931,6 +11980,8 @@ webview-assets.cloud9.eu-west-2.amazonaws.com webview-assets.aws-cloud9.eu-west-3.amazonaws.com vfs.cloud9.eu-west-3.amazonaws.com webview-assets.cloud9.eu-west-3.amazonaws.com +webview-assets.aws-cloud9.il-central-1.amazonaws.com +vfs.cloud9.il-central-1.amazonaws.com webview-assets.aws-cloud9.me-south-1.amazonaws.com vfs.cloud9.me-south-1.amazonaws.com webview-assets.cloud9.me-south-1.amazonaws.com @@ -11950,6 +12001,11 @@ webview-assets.aws-cloud9.us-west-2.amazonaws.com vfs.cloud9.us-west-2.amazonaws.com webview-assets.cloud9.us-west-2.amazonaws.com +// AWS Directory Service +// Submitted by AWS Security +// Reference: a13203e8-42dc-4045-a0d2-2ee67bed1068 +awsapps.com + // AWS Elastic Beanstalk // Submitted by AWS Security // Reference: bb5a965c-dec3-4967-aa22-e306ad064797 @@ -11993,6 +12049,11 @@ us-west-2.elasticbeanstalk.com // Reference: d916759d-a08b-4241-b536-4db887383a6a awsglobalaccelerator.com +// AWS re:Post Private +// Submitted by AWS Security +// Reference: 83385945-225f-416e-9aa0-ad0632bfdcee +*.private.repost.aws + // eero // Submitted by Yue Kang // Reference: 264afe70-f62c-4c02-8ab9-b5281ed24461 @@ -12010,6 +12071,10 @@ tele.amune.org // Submitted by Apigee Security Team apigee.io +// Apis Networks: https://apisnetworks.com +// Submitted by Matt Saladna +panel.dev + // Apphud : https://apphud.com // Submitted by Alexander Selivanov siiites.com @@ -12027,6 +12092,10 @@ appudo.net // Submitted by Thomas Orozco on-aptible.com +// Aquapal : https://aquapal.net/ +// Submitted by Aki Ueno +f5.si + // ASEINet : https://www.aseinet.com/ // Submitted by Asei SEKIGUCHI user.aseinet.ne.jp @@ -12062,6 +12131,7 @@ autocode.dev // AVM : https://avm.de // Submitted by Andreas Weise +myfritz.link myfritz.net // AVStack Pte. Ltd. : https://avstack.io @@ -12121,10 +12191,18 @@ beagleboard.io // Submitted by Lev Nekrasov *.beget.app +// Besties : https://besties.house +// Submitted by Hazel Cora +pages.gay + // BetaInABox // Submitted by Adrian betainabox.com +// University of Bielsko-Biala regional domain: http://dns.bielsko.pl/ +// Submitted by Marcin +bielsko.pl + // BinaryLane : http://www.binarylane.com // Submitted by Nathan O'Sullivan bnr.la @@ -12166,8 +12244,13 @@ square7.de bplaced.net square7.net +// Brave : https://brave.com +// Submitted by Andrea Brancaleoni +*.s.brave.io + // Brendly : https://brendly.rs -// Submitted by Dusan Radovanovic +// Submitted by Dusan Radovanovic +shop.brendly.hr shop.brendly.rs // BrowserSafetyMark @@ -12191,7 +12274,9 @@ mycd.eu // Canva Pty Ltd : https://canva.com/ // Submitted by Joel Aquilina canva-apps.cn +*.my.canvasite.cn canva-apps.com +*.my.canva.site // Carrd : https://carrd.co // Submitted by AJ @@ -12329,6 +12414,12 @@ pages.dev r2.dev workers.dev +// cloudscale.ch AG : https://www.cloudscale.ch/ +// Submitted by Gaudenz Steinlin +cust.cloudscale.ch +objects.lpg.cloudscale.ch +objects.rma.cloudscale.ch + // Clovyr : https://clovyr.io // Submitted by Patrick Nielsen wnext.app @@ -12346,22 +12437,33 @@ co.cz // CDN77.com : http://www.cdn77.com // Submitted by Jan Krpes -c.cdn77.org +cdn77-storage.com +rsc.contentproxy9.cz cdn77-ssl.net r.cdn77.net -rsc.cdn77.org ssl.origin.cdn77-secure.org +c.cdn77.org +rsc.cdn77.org // Cloud DNS Ltd : http://www.cloudns.net -// Submitted by Aleksander Hristov +// Submitted by Aleksander Hristov & Boyan Peychev cloudns.asia +cloudns.be cloudns.biz -cloudns.club cloudns.cc +cloudns.ch +cloudns.cl +cloudns.club +dnsabr.com +cloudns.cx cloudns.eu cloudns.in cloudns.info +dns-cloud.net +dns-dynamic.net +cloudns.nz cloudns.org +cloudns.ph cloudns.pro cloudns.pw cloudns.us @@ -12374,6 +12476,11 @@ cnpy.gdn // Submitted by Moritz Marquardt codeberg.page +// CodeSandbox B.V. : https://codesandbox.io +// Submitted by Ives van Hoorne +csb.app +preview.csb.app + // CoDNS B.V. co.nl co.no @@ -12383,6 +12490,10 @@ co.no webhosting.be hosting-cluster.nl +// Convex : https://convex.dev/ +// Submitted by James Cowling +convex.site + // Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/ // Submitted by George Georgievsky ac.ru @@ -12404,10 +12515,18 @@ feste-ip.net knx-server.net static-access.net +// cPanel L.L.C. : https://www.cpanel.net/ +// Submitted by Dustin Scherer +*.cprapid.com + // Craynic, s.r.o. : http://www.craynic.com/ // Submitted by Ales Krajnik realm.cz +// Crisp IM SAS : https://crisp.chat/ +// Submitted by Baptiste Jamin +on.crisp.email + // Cryptonomic : https://cryptonomic.net/ // Submitted by Andrew Cady *.cryptonomic.net @@ -12428,6 +12547,13 @@ curv.dev *.ocp.customer-oci.com *.ocs.customer-oci.com +// Cyclic Software : https://www.cyclic.sh +// Submitted by Kam Lasater +cyclic.app +cyclic.cloud +cyclic-app.com +cyclic.co.in + // cyon GmbH : https://www.cyon.ch/ // Submitted by Dominic Luechinger cyon.link @@ -12473,6 +12599,7 @@ dyndns.dappnode.io // Dark, Inc. : https://darklang.com // Submitted by Paul Biggar builtwithdark.com +darklang.io // DataDetect, LLC. : https://datadetect.com // Submitted by Andrew Banchich @@ -12871,6 +12998,10 @@ ondigitalocean.app // Submitted by Robin H. Johnson *.digitaloceanspaces.com +// DigitalPlat : https://www.digitalplat.org/ +// Submitted by Edward Hsing +us.kg + // dnstrace.pro : https://dnstrace.pro/ // Submitted by Chris Partridge bci.dnstrace.pro @@ -12908,6 +13039,18 @@ e4.cz easypanel.app easypanel.host +// EasyWP : https://www.easywp.com +// Submitted by +*.ewp.live + +// Electromagnetic Field : https://www.emfcamp.org +// Submitted by +at.emf.camp + +// Elefunc, Inc. : https://elefunc.com +// Submitted by Cetin Sert +rt.ht + // Elementor : Elementor Ltd. // Submitted by Anton Barkan elementor.cloud @@ -13022,10 +13165,6 @@ url.tw // Submitted by Eric Jiang onfabrica.com -// Facebook, Inc. -// Submitted by Peter Ruibal -apps.fbsbx.com - // FAITID : https://faitid.org/ // Submitted by Maxim Alzoba // https://www.flexireg.net/stat_info @@ -13183,6 +13322,10 @@ flap.id onflashdrive.app fldrv.com +// FlutterFlow : https://flutterflow.io +// Submitted by Anton Emelyanov +flutterflow.app + // fly.io: https://fly.io // Submitted by Kurt Mackey fly.dev @@ -13193,13 +13336,14 @@ shw.io // Submitted by Jonathan Rudenberg flynnhosting.net -// Forgerock : https://www.forgerock.com +// Forgerock : https://www.forgerock.com // Submitted by Roderick Parr forgeblocks.com id.forgerock.io // Framer : https://www.framer.com -// Submitted by Koen Rouwhorst +// Submitted by Koen Rouwhorst +framer.ai framer.app framercanvas.com framer.media @@ -13240,6 +13384,24 @@ freemyip.com // Submitted by Daniel A. Maierhofer wien.funkfeuer.at +// Future Versatile Group. :https://www.fvg-on.net/ +// T.Kabu +daemon.asia +dix.asia +mydns.bz +0am.jp +0g0.jp +0j0.jp +0t0.jp +mydns.jp +pgw.jp +wjg.jp +keyword-on.net +live-on.net +server-on.net +mydns.tw +mydns.vc + // Futureweb GmbH : https://www.futureweb.at // Submitted by Andreas Schnederle-Wagner *.futurecms.at @@ -13251,6 +13413,10 @@ futuremailing.at *.kunden.ortsinfo.at *.statics.cloud +// GCom Internet : https://www.gcom.net.au +// Submitted by Leo Julius +aliases121.com + // GDS : https://www.gov.uk/service-manual/technology/managing-domain-names // Submitted by Stephen Ford independent-commission.uk @@ -13279,9 +13445,11 @@ gentlentapis.com lab.ms cdn-edges.net -// Ghost Foundation : https://ghost.org -// Submitted by Matt Hanley -ghost.io +// Getlocalcert: https://www.getlocalcert.net +// Submitted by Robert Alexander +localcert.net +localhostcert.net +corpnet.work // GignoSystemJapan: http://gsj.bz // Submitted by GignoSystemJapan @@ -13425,6 +13593,10 @@ whitesnow.jp zombie.jp heteml.net +// GoDaddy Registry : https://registry.godaddy +// Submitted by Rohan Durrant +graphic.design + // GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ // Submitted by Tom Whitwell cloudapps.digital @@ -13434,10 +13606,6 @@ london.cloudapps.digital // Submitted by Richard Baker pymnt.uk -// UKHomeOffice : https://www.gov.uk/government/organisations/home-office -// Submitted by Jon Shanks -homeoffice.gov.uk - // GlobeHosting, Inc. // Submitted by Zoltan Egresi ro.im @@ -13448,8 +13616,7 @@ goip.de // Google, Inc. // Submitted by Eduardo Vela -run.app -a.run.app +*.run.app web.app *.0emm.com appspot.com @@ -13549,6 +13716,10 @@ goupile.fr // Submitted by gov.nl +// GrayJay Web Solutions Inc. : https://grayjaysports.ca +// Submitted by Matt Yamkowy +grayjayleagues.com + // Group 53, LLC : https://www.group53.com // Submitted by Tyler Todd awsmppl.com @@ -13583,6 +13754,11 @@ hasura-app.io // Submitted by Richard Zowalla pages.it.hs-heilbronn.de +// Helio Networks : https://heliohost.org +// Submitted by Ben Frede +helioho.st +heliohost.us + // Hepforge : https://www.hepforge.org // Submitted by David Grellscheid hepforge.org @@ -13596,7 +13772,6 @@ herokussl.com // Submitted by Oren Eini ravendb.cloud ravendb.community -ravendb.me development.run ravendb.run @@ -13604,6 +13779,12 @@ ravendb.run // Submitted by Krzysztof Wolski homesklep.pl +// Homebase : https://homebase.id/ +// Submitted by Jason Babo +*.kin.one +*.id.pub +*.kin.pub + // Hong Kong Productivity Council: https://www.hkpc.org/ // Submitted by SECaaS Team secaas.hk @@ -13681,7 +13862,7 @@ biz.at info.at // info.cx : http://info.cx -// Submitted by Jacob Slater +// Submitted by June Slater info.cx // Interlegis : http://www.interlegis.leg.br @@ -13730,6 +13911,14 @@ iopsys.se // Submitted by Matthew Hardeman ipifony.net +// is-a.dev : https://www.is-a.dev +// Submitted by William Harrison +is-a.dev + +// ir.md : https://nic.ir.md +// Submitted by Ali Soizi +ir.md + // IServ GmbH : https://iserv.de // Submitted by Mario Hoberg iservschule.de @@ -13838,6 +14027,11 @@ myjino.ru // Submitted by Daniel Fariña jotelulu.cloud +// JouwWeb B.V. : https://www.jouwweb.nl +// Submitted by Camilo Sperberg +jouwweb.site +webadorsite.com + // Joyent : https://www.joyent.com/ // Submitted by Brian Bennett *.triton.zone @@ -13911,6 +14105,10 @@ lpusercontent.com // Submitted by Lelux Admin lelux.site +// Libre IT Ltd : https://libre.nz +// Submitted by Tomas Maggio +runcontainers.dev + // Lifetime Hosting : https://Lifetime.Hosting/ // Submitted by Mike Fillator co.business @@ -13921,10 +14119,6 @@ co.network co.place co.technology -// Lightmaker Property Manager, Inc. : https://app.lmpm.com/ -// Submitted by Greg Holland -app.lmpm.com - // linkyard ldt: https://www.linkyard.ch/ // Submitted by Mario Siegenthaler linkyard.cloud @@ -14057,6 +14251,11 @@ memset.net // Submitted by Ruben Schmidmeister messerli.app +// Meta Platforms, Inc. : https://meta.com/ +// Submitted by Jacob Cordero +atmeta.com +apps.fbsbx.com + // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ // Submitted by Zdeněk Šustr *.cloud.metacentrum.cz @@ -14077,10 +14276,14 @@ co.pl // Microsoft Corporation : http://microsoft.com // Submitted by Public Suffix List Admin +// Managed by Corporate Domains +// Microsoft Azure : https://home.azure *.azurecontainer.io +azure-api.net +azureedge.net +azurefd.net azurewebsites.net azure-mobile.net -cloudapp.net azurestaticapps.net 1.azurestaticapps.net 2.azurestaticapps.net @@ -14094,6 +14297,10 @@ eastasia.azurestaticapps.net eastus2.azurestaticapps.net westeurope.azurestaticapps.net westus2.azurestaticapps.net +cloudapp.net +trafficmanager.net +blob.core.windows.net +servicebus.windows.net // minion.systems : http://minion.systems // Submitted by Robert Böttinger @@ -14107,6 +14314,10 @@ mintere.site // Submitted by Grayson Martin forte.id +// MODX Systems LLC : https://modx.com +// Submitted by Elizabeth Southwell +modx.dev + // Mozilla Corporation : https://mozilla.com // Submitted by Ben Francis mozilla-iot.org @@ -14153,6 +14364,10 @@ netlify.app // Submitted by Trung Tran 4u.com +// NGO.US Registry : https://nic.ngo.us +// Submitted by Alstra Solutions Ltd. Networking Team +ngo.us + // ngrok : https://ngrok.com/ // Submitted by Alan Shreve ngrok.app @@ -14168,18 +14383,24 @@ jp.ngrok.io sa.ngrok.io us.ngrok.io ngrok.pizza +ngrok.pro // Nicolaus Copernicus University in Torun - MSK TORMAN (https://www.man.torun.pl) torun.pl // Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ -// Submitted by Nicholas Ford +// Submitted by Nicholas Ford nh-serv.co.uk +nimsite.uk // NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ // Submitted by Jeff Wheelhouse nfshost.com +// NFT.Storage : https://nft.storage/ +// Submitted by Vasco Santos or +ipfs.nftstorage.link + // Noop : https://noop.app // Submitted by Nathaniel Schweinberg *.developer.app @@ -14330,6 +14551,10 @@ pcloud.host // Submitted by Matthew Brown nyc.mn +// O3O.Foundation : https://o3o.foundation/ +// Submitted by the prvcy.page Registry Team +prvcy.page + // Observable, Inc. : https://observablehq.com // Submitted by Mike Bostock static.observableusercontent.com @@ -14359,7 +14584,6 @@ omniwe.site 123minsida.se 123miweb.es 123paginaweb.pt -123sait.ru 123siteweb.fr 123webseite.at 123webseite.de @@ -14377,6 +14601,13 @@ simplesite.pl // Submitted by Eddie Jones nid.io +// Open Domains : https://open-domains.net +// Submitted by William Harrison +is-cool.dev +is-not-a.dev +localplayer.dev +is-local.org + // Open Social : https://www.getopensocial.com/ // Submitted by Alexander Varwijk opensocial.site @@ -14397,6 +14628,11 @@ operaunite.com // Submitted by Alexandre Linte tech.orange +// OsSav Technology Ltd. : https://ossav.com/ +// TLD Nic: http://nic.can.re - TLD Whois Server: whois.can.re +// Submitted by OsSav Technology Ltd. +can.re + // Oursky Limited : https://authgear.com/, https://skygear.io/ // Submitted by Authgear Team , Skygear Developer authgear-staging.com @@ -14447,10 +14683,11 @@ pagexl.com // pcarrier.ca Software Inc: https://pcarrier.ca/ // Submitted by Pierre Carrier -bar0.net -bar1.net -bar2.net -rdv.to +*.xmit.co +xmit.dev +srv.us +gh.srv.us +gl.srv.us // .pl domains (grandfathered) art.pl @@ -14483,7 +14720,8 @@ on-web.fr // Platform.sh : https://platform.sh // Submitted by Nikola Kotur -bc.platform.sh +*.upsun.app +upsunapp.com ent.platform.sh eu.platform.sh us.platform.sh @@ -14502,6 +14740,10 @@ pdns.page plesk.page pleskns.com +// Pley AB : https://www.pley.com/ +// Submitted by Henning Pohl +pley.games + // Port53 : https://port53.io/ // Submitted by Maximilian Schieder dyn53.io @@ -14533,10 +14775,6 @@ xen.prgmr.com // Submitted by registry priv.at -// privacytools.io : https://www.privacytools.io/ -// Submitted by Jonah Aragon -prvcy.page - // Protocol Labs : https://protocol.ai/ // Submitted by Michael Burns *.dweb.link @@ -14578,6 +14816,8 @@ qbuser.com // Rad Web Hosting: https://radwebhosting.com // Submitted by Scott Claeys cloudsite.builders +myradweb.net +servername.us // Redgate Software: https://red-gate.com // Submitted by Andrew Farries @@ -14601,9 +14841,12 @@ qcx.io *.sys.qcx.io // QNAP System Inc : https://www.qnap.com -// Submitted by Nick Chang -dev-myqnapcloud.com +// Submitted by Nick Chang +myqnapcloud.cn alpha-myqnapcloud.com +dev-myqnapcloud.com +mycloudnas.com +mynascloud.com myqnapcloud.com // Quip : https://quip.com @@ -14644,11 +14887,40 @@ app.render.com onrender.com // Repl.it : https://repl.it -// Submitted by Lincoln Bergeson +// Submitted by Lincoln Bergeson +replit.app +id.replit.app firewalledreplit.co id.firewalledreplit.co repl.co id.repl.co +replit.dev +archer.replit.dev +bones.replit.dev +canary.replit.dev +global.replit.dev +hacker.replit.dev +id.replit.dev +janeway.replit.dev +kim.replit.dev +kira.replit.dev +kirk.replit.dev +odo.replit.dev +paris.replit.dev +picard.replit.dev +pike.replit.dev +prerelease.replit.dev +reed.replit.dev +riker.replit.dev +sisko.replit.dev +spock.replit.dev +staging.replit.dev +sulu.replit.dev +tarpit.replit.dev +teams.replit.dev +tucker.replit.dev +wesley.replit.dev +worf.replit.dev repl.run // Resin.io : https://resin.io @@ -14745,10 +15017,11 @@ from.tv sakura.tv // Salesforce.com, Inc. https://salesforce.com/ -// Submitted by Michael Biven +// Submitted by Michael Biven and Aaron Romeo *.builder.code.com *.dev-builder.code.com *.stg-builder.code.com +*.001.test.code-builder-stg.platform.salesforce.com // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia @@ -14764,6 +15037,7 @@ logoip.com fr-par-1.baremetal.scw.cloud fr-par-2.baremetal.scw.cloud nl-ams-1.baremetal.scw.cloud +cockpit.fr-par.scw.cloud fnc.fr-par.scw.cloud functions.fnc.fr-par.scw.cloud k8s.fr-par.scw.cloud @@ -14774,11 +15048,13 @@ whm.fr-par.scw.cloud priv.instances.scw.cloud pub.instances.scw.cloud k8s.scw.cloud +cockpit.nl-ams.scw.cloud k8s.nl-ams.scw.cloud nodes.k8s.nl-ams.scw.cloud s3.nl-ams.scw.cloud s3-website.nl-ams.scw.cloud whm.nl-ams.scw.cloud +cockpit.pl-waw.scw.cloud k8s.pl-waw.scw.cloud nodes.k8s.pl-waw.scw.cloud s3.pl-waw.scw.cloud @@ -14800,6 +15076,10 @@ service.gov.scot // Submitted by Shante Adam scrysec.com +// Scrypted : https://scrypted.app +// Submitted by Koushik Dutta +client.scrypted.io + // Securepoint GmbH : https://www.securepoint.de // Submitted by Erik Anders firewall-gateway.com @@ -14839,6 +15119,10 @@ biz.ua co.ua pp.ua +// Sheezy.Art : https://sheezy.art +// Submitted by Nyoom +sheezy.games + // Shift Crypto AG : https://shiftcrypto.ch // Submitted by alex shiftcrypto.dev @@ -14887,7 +15171,7 @@ alpha.bounty-full.com beta.bounty-full.com // Smallregistry by Promopixel SARL: https://www.smallregistry.net -// Former AFNIC's SLDs +// Former AFNIC's SLDs // Submitted by Jérôme Lipowicz aeroport.fr avocat.fr @@ -14909,9 +15193,9 @@ small-web.org vp4.me // Snowflake Inc : https://www.snowflake.com/ -// Submitted by Faith Olapade -snowflake.app -privatelink.snowflake.app +// Submitted by Sam Haar +*.snowflake.app +*.privatelink.snowflake.app streamlit.app streamlitapp.com @@ -14923,10 +15207,24 @@ try-snowplow.com // Submitted by Drew DeVault srht.site +// StackBlitz : https://stackblitz.com +// Submitted by Dominic Elm +w-corp-staticblitz.com +w-credentialless-staticblitz.com +w-staticblitz.com + // Stackhero : https://www.stackhero.io // Submitted by Adrien Gillon stackhero-network.com +// STACKIT : https://www.stackit.de/en/ +// Submitted by STACKIT-DNS Team (Simon Stier) +runs.onstackit.cloud +stackit.gg +stackit.rocks +stackit.run +stackit.zone + // Staclar : https://staclar.com // Submitted by Q Misell musician.io @@ -14993,6 +15291,19 @@ myspreadshop.co.uk // Submitted by Jacob Lee api.stdlib.com +// stereosense GmbH : https://www.involve.me +// Submitted by Florian Burmann +feedback.ac +forms.ac +assessments.cx +calculators.cx +funnels.cx +paynow.cx +quizzes.cx +researched.cx +tests.cx +surveys.so + // Storipress : https://storipress.com // Submitted by Benno Liu storipress.app @@ -15001,6 +15312,12 @@ storipress.app // Submitted by Philip Hutchins storj.farm +// Streak : https://streak.com +// Submitted by Blake Kadatz +streak-link.com +streaklinks.com +streakusercontent.com + // Studenten Net Twente : http://www.snt.utwente.nl/ // Submitted by Silke Hofstra utwente.io @@ -15063,6 +15380,7 @@ taifun-dns.de // Submitted by David Anderson beta.tailscale.net ts.net +*.c.ts.net // TASK geographical domains (www.task.gda.pl/uslugi/dns) gda.pl @@ -15196,6 +15514,10 @@ inc.hk // Submitted by ITComdomains it.com +// Unison Computing, PBC : https://unison.cloud +// Submitted by Simon Højberg +unison-services.cloud + // UNIVERSAL DOMAIN REGISTRY : https://www.udr.org.yt/ // see also: whois -h whois.udr.org.yt help // Submitted by Atanunu Igbunuroghene @@ -15245,48 +15567,6 @@ v-info.info // Submitted by Nathan van Bakel voorloper.cloud -// Voxel.sh DNS : https://voxel.sh/dns/ -// Submitted by Mia Rehlinger -neko.am -nyaa.am -be.ax -cat.ax -es.ax -eu.ax -gg.ax -mc.ax -us.ax -xy.ax -nl.ci -xx.gl -app.gp -blog.gt -de.gt -to.gt -be.gy -cc.hn -blog.kg -io.kg -jp.kg -tv.kg -uk.kg -us.kg -de.ls -at.md -de.md -jp.md -to.md -indie.porn -vxl.sh -ch.tc -me.tc -we.tc -nyan.to -at.vg -blog.vu -dev.vu -me.vu - // V.UA Domain Administrator : https://domain.v.ua/ // Submitted by Serhii Rostilo v.ua @@ -15299,6 +15579,11 @@ v.ua // Submitted by Masayuki Note wafflecell.com +// Webflow, Inc. : https://www.webflow.com +// Submitted by Webflow Security Team +webflow.io +webflowtest.io + // WebHare bv: https://www.webhare.com/ // Submitted by Arnold Hendriks *.webhare.dev @@ -15310,6 +15595,10 @@ reserve-online.com bookonline.app hotelwithflight.com +// WebWaddle Ltd: https://webwaddle.com/ +// Submitted by Merlin Glander +*.wadl.top + // WeDeploy by Liferay, Inc. : https://www.wedeploy.com // Submitted by Henrique Vicente wedeploy.io @@ -15418,6 +15707,10 @@ noho.st za.net za.org +// ZAP-Hosting GmbH & Co. KG : https://zap-hosting.com +// Submitted by Julian Alker +zap.cloud + // Zine EOOD : https://zine.bg/ // Submitted by Martin Angelov bss.design diff --git a/src/java.base/share/legal/public_suffix.md b/src/java.base/share/legal/public_suffix.md index 493f3b1680dfb..02481558af654 100644 --- a/src/java.base/share/legal/public_suffix.md +++ b/src/java.base/share/legal/public_suffix.md @@ -11,7 +11,7 @@ If you do not wish to use the Public Suffix List, you may remove the The Source Code of this file is available under the Mozilla Public License, v. 2.0 and is located at -https://raw.githubusercontent.com/publicsuffix/list/b5bf572c52988dbe9d865b8f090ea819024a9936/public_suffix_list.dat. +https://raw.githubusercontent.com/publicsuffix/list/1cbd6e71a9b83620b1d0b11e49d3d9ff48c27e22/public_suffix_list.dat. If a copy of the MPL was not distributed with this file, you can obtain one at https://mozilla.org/MPL/2.0/. diff --git a/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java b/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java index 74045b533c295..904f672ba4016 100644 --- a/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java +++ b/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8228969 8244087 8255266 8302182 + * @bug 8228969 8244087 8255266 8302182 8331864 * @modules java.base/sun.security.util * @summary unit test for RegisteredDomain */ diff --git a/test/jdk/sun/security/util/RegisteredDomain/tests.dat b/test/jdk/sun/security/util/RegisteredDomain/tests.dat index 280e66ff93bce..7fe95c979ea83 100644 --- a/test/jdk/sun/security/util/RegisteredDomain/tests.dat +++ b/test/jdk/sun/security/util/RegisteredDomain/tests.dat @@ -161,6 +161,17 @@ site.ai.vn ai.vn site.ai.vn foo.السعودية السعودية foo.السعودية w.foo.السعودية السعودية foo.السعودية +# newGTLDs + +# This is not a GTLD +www.site.unknown www.site.unknown null + +# GTLD added in 1cbd6e7 +www.site.wed wed site.wed + +# GTLD removed in 1cbd6e7 +www.site.oldnavy www.site.oldnavy null + # Microsoft 1.azurestaticapps.net 1.azurestaticapps.net null app.1.azurestaticapps.net 1.azurestaticapps.net app.1.azurestaticapps.net From 8af606fb8cdb3a6ecdfe4cddd79f228b64d5fc80 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 8 May 2024 01:12:17 +0000 Subject: [PATCH 116/203] 8331334: com/sun/net/httpserver/HttpsParametersClientAuthTest.java fails in testServerNeedClientAuth(false) Reviewed-by: dfuchs --- .../httpserver/HttpsParametersClientAuthTest.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/jdk/com/sun/net/httpserver/HttpsParametersClientAuthTest.java b/test/jdk/com/sun/net/httpserver/HttpsParametersClientAuthTest.java index ded0474071b15..291b74f26692b 100644 --- a/test/jdk/com/sun/net/httpserver/HttpsParametersClientAuthTest.java +++ b/test/jdk/com/sun/net/httpserver/HttpsParametersClientAuthTest.java @@ -50,6 +50,7 @@ import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsParameters; import com.sun.net.httpserver.HttpsServer; +import jdk.internal.util.OperatingSystem; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; import org.junit.jupiter.api.Test; @@ -68,12 +69,14 @@ * @bug 8326381 * @summary verifies that the setNeedClientAuth() and setWantClientAuth() * methods on HttpsParameters class work as expected + * @modules java.base/jdk.internal.util * @library /test/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.test.lib.net.URIBuilder * @run junit HttpsParametersClientAuthTest */ public class HttpsParametersClientAuthTest { + private static final boolean IS_WINDOWS = OperatingSystem.isWindows(); private static final AtomicInteger TID = new AtomicInteger(); private static final ThreadFactory SRV_THREAD_FACTORY = (r) -> { final Thread t = new Thread(r); @@ -220,9 +223,11 @@ public void configure(final HttpsParameters params) { throw ioe; } // verify it failed due to right reason - Throwable cause = ioe; + Throwable cause = ioe.getCause(); while (cause != null) { - // either of SocketException or SSLHandshakeException are OK + // either of SocketException or SSLHandshakeException are OK. + // additionally on Windows we accept even IOException + // (caused by WSAECONNABORTED) if (cause instanceof SocketException se) { final String msg = se.getMessage(); assertTrue(msg != null && msg.contains("Connection reset"), @@ -235,6 +240,12 @@ public void configure(final HttpsParameters params) { "unexpected message in SSLHandshakeException: " + msg); System.out.println("received the expected exception: " + she); break; + } else if (IS_WINDOWS && cause instanceof IOException winIOE) { + // on Windows we sometimes receive this exception, which is + // acceptable + System.out.println("(windows) received the expected exception: " + + winIOE); + break; } cause = cause.getCause(); } From 466a21d8646c05d91f29d607c6347afd34c75629 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Wed, 8 May 2024 05:03:06 +0000 Subject: [PATCH 117/203] 8331863: DUIterator_Fast used before it is constructed Reviewed-by: kvn, shade --- src/hotspot/share/opto/node.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index bb58c2ff8cee6..04631dcbae237 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1569,8 +1569,8 @@ Node* Node::last_out(DUIterator_Last& i) const { class SimpleDUIterator : public StackObj { private: Node* node; - DUIterator_Fast i; DUIterator_Fast imax; + DUIterator_Fast i; public: SimpleDUIterator(Node* n): node(n), i(n->fast_outs(imax)) {} bool has_next() { return i < imax; } From 7b79426a1da5896b0f00cf6e5fb4d2e754149e54 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Wed, 8 May 2024 05:48:07 +0000 Subject: [PATCH 118/203] 8278353: Provide Duke as default favicon in Simple Web Server Reviewed-by: dfuchs --- make/modules/jdk.httpserver/Java.gmk | 4 +- .../simpleserver/FileServerHandler.java | 41 +++++++++++- .../simpleserver/resources/favicon.ico | Bin 0 -> 15086 bytes .../simpleserver/SimpleFileServerTest.java | 63 +++++++++++++++++- 4 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/favicon.ico diff --git a/make/modules/jdk.httpserver/Java.gmk b/make/modules/jdk.httpserver/Java.gmk index d7b2b2f70ca21..799ff8695a74c 100644 --- a/make/modules/jdk.httpserver/Java.gmk +++ b/make/modules/jdk.httpserver/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,3 +24,5 @@ # DISABLED_WARNINGS_java += missing-explicit-ctor this-escape + +COPY += .ico diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java index 6d217174fddb7..81ddb58eecf0b 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,9 @@ public final class FileServerHandler implements HttpHandler { private static final List SUPPORTED_METHODS = List.of("HEAD", "GET"); private static final List UNSUPPORTED_METHODS = List.of("CONNECT", "DELETE", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"); + private static final String FAVICON_RESOURCE_PATH = + "/sun/net/httpserver/simpleserver/resources/favicon.ico"; + private static final String FAVICON_LAST_MODIFIED = "Mon, 23 May 1995 11:11:11 GMT"; private final Path root; private final UnaryOperator mimeTable; @@ -250,6 +253,31 @@ private static Path indexFile(Path path) { return Files.exists(html) ? html : Files.exists(htm) ? htm : null; } + private static boolean isFavIconRequest(HttpExchange exchange) { + return "/favicon.ico".equals(exchange.getRequestURI().getPath()); + } + + private void serveDefaultFavIcon(HttpExchange exchange, boolean writeBody) + throws IOException + { + var respHdrs = exchange.getResponseHeaders(); + try (var stream = getClass().getModule().getResourceAsStream(FAVICON_RESOURCE_PATH)) { + var bytes = stream.readAllBytes(); + respHdrs.set("Content-Type", "image/x-icon"); + respHdrs.set("Last-Modified", FAVICON_LAST_MODIFIED); + if (writeBody) { + exchange.sendResponseHeaders(200, bytes.length); + try (OutputStream os = exchange.getResponseBody()) { + os.write(bytes); + } + } else { + respHdrs.set("Content-Length", Integer.toString(bytes.length)); + exchange.sendResponseHeaders(200, -1); + } + } + } + + private void serveFile(HttpExchange exchange, Path path, boolean writeBody) throws IOException { @@ -371,17 +399,26 @@ public void handle(HttpExchange exchange) throws IOException { assert List.of("GET", "HEAD").contains(exchange.getRequestMethod()); try (exchange) { discardRequestBody(exchange); + boolean isHeadRequest = exchange.getRequestMethod().equals("HEAD"); Path path = mapToPath(exchange, root); if (path != null) { exchange.setAttribute("request-path", path.toString()); // store for OutputFilter if (!Files.exists(path) || !Files.isReadable(path) || isHiddenOrSymLink(path)) { handleNotFound(exchange); - } else if (exchange.getRequestMethod().equals("HEAD")) { + } else if (isHeadRequest) { handleHEAD(exchange, path); } else { handleGET(exchange, path); } } else { + if (isFavIconRequest(exchange)) { + try { + serveDefaultFavIcon(exchange, !isHeadRequest); + return; + } catch (IOException ignore) { + // fall through to send the not-found response + } + } exchange.setAttribute("request-path", "could not resolve request URI path"); handleNotFound(exchange); } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/favicon.ico b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/resources/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f24905abf621fae487224136f14656387d19fc7a GIT binary patch literal 15086 zcmeHO33OED6@D=ZAz(7u$vQLH_hhn>gsdXFh=K-bi4+lw5kz*iSXKpTK$ap9tWrP< z3W7vdA%Le;fl?@>wy6Y2SQ;P(hAjk=%?;e|i6M z?>~ZIC)f)rl>n*~HiZj9cR>)8O5L-YAe=**8z{ej)j<&EAwv}MfJGPyaJqPfY03Y8 z|MzMjSQ%#T?d==p<=HLT-!G_hN0b0E9sGO)d;4|^cquSY;nfi`+mfM>hYZQ;kz4&_ z&)!!?%j zsiE1k=V~G&V)j5^qIGh9%I)Lh_hg^m{Vtc6|Bck@n^agh;s)9_=cgPUcjsX5d~Tz-!%n{4si1exclH-P1D4_wU;;%HtoFhc=#RxfIKD zIy!Xr?ALd|X|8+e(r7ev;x8v?%$TAFQBkpFu<2Qp<8gCR@!pB^rKM*4{fjMIiDgLF zpZ|QEl9N)mgWu7djP~9s6`}S(7r;)+i~9HI-K*cp%a<=p>h$#P-Mdt}y_ALx8-5pk zYA=}rzEGH?2(ys zX3*2m-k3CTO7rH;Td20S)|gd%zIpQ&4J{aUv5T`yh@{sR3cCvd4KUh(-(HoNyyfW8 zV<}4*lNdM zdqMjEjlkOm_6unH;;mb^wbI*B30&^i$Bn-wbM?qH)Z5-Y?92l`0#*XyKrV0}n8m!H zj)1?PU*Lof7A^kigX<{6b#l0UCQX`h*G=Y`+n&va?_t}k0NYEzx4=5x{bo>C;8(!; zzyQVHUMm{c*won6!Io>q@mMrv^3-~FH?Mp{``WvQZ8G3p;0nNHkWi2NGN6vrI zzp!l)a00jq@VH}W`vW}B1KeQ0Kh`~qH-En6k=TFz`gIyS__^~KKjp^tYwj7g-2wgu zYzImKwpl8}KHR%X{Fpn3&6z#-k$eD^XDTTtJO5h;`_3+sK1(R<>jgvt4uA)+7T_{* z8MXk}5os@17x(zW;UliyxpSw(+u$JPBpIe-d{zy6;per6ePQK_Riu=Es6Y-|+!TU2Ch6Lj$y_(xzOU~j0`+I#Txx4anm5-0*f0auKp#nI7m4;C)` zfX<(<68BDn2M?i0@1d08yqz*Se`N+c@UE01Jzu0(M!!P4&<~4V9ZLxbNgBvq2>EG% zAFu)#Vy(@_`5}YHq&R@>p98!Ps1=G3Vq|CKVa@dhsS;C3IAl*55+9^A?Kqe~Ogg0YBq9kZwvh(vyH6fbyuwm>mi6 zs#4f}0poKm_9Is96O83UW(ZITzy|b#pcu*vdykIn)9w#XeOE`^7E(K8cIIz)JH>mw zLBR^16Qs5aEI`6}I9wN*;^hAD7%F4{9oUEMY=&0EDy}W#F_7_2>9k85b zYY{@hK?#%}_a;pnzK?#<;}B&!v(0D&=dG0LQbMslBVl`se$Tw)C3}r2-gO4{v;6R| zNXkghq}Z5v3JZ;7z6(IKF^@IR;LiorfW8b0IqrSCQ-sg66yx(E#dP~Q`b&Qb2~r`C z{(IHs54~j02E5}s`k3WMghyk2mrLkF6c?Mo2ELArh^AgWdr=DPkBN@sHP(mi@mlg8vU%^u`(|rw=e#_wDB9D3Jlu!Y1Kjs3 zhdeuY&Wpnfi&9h4IxLz2**unVeOglnULUr*)<+&5^LcN@vOA>Cjq40@y#QW!S!(}X z_vbh{)zZX+7EJ=ghp#b|VEGffx$medMTwc?OJ`m7(mhjk;2eNrA z+6Y);f2;LETRI^x9@qu&nk%@id>xSv`6&R;E9S~jgZBy6=tF*<#~y0EW2rvqnF5&m zmfIckE!FiX^1*gDz+i3KqAhryD0mclJ5nZW*b4ns5J8 zcAC=*+rt2pdn|K&|9|)2Ujtevq#(4S7l{;v^lwNb(nHjwrFji9PCq28V%m5}5KPgM zDsB4gSy~Dr=0mbbg^@a{)>5^O-q+D4i8cs=6ZB{#IzbQuME!!0!xZVcOq&E@#!OI+ zAk4JaQLN7SnV51OiO%NdS#~5*c&UjF+0kN=+G}Z*M4f02r>mVr8Pp(AnfAF!M^R0z zgR4uVs6H({sH0?x@;NOfkPqn3X}RIyf9UGk#nlhz4uW9vW7e4M?d2N<0iCC5j@!aya-W{NVhyVK5Q_O<1K=)|MlxausP9Ntprw{W0`xC|h zVw?yu&EDI;ENu~x;jme& zW}w}!AvPE*=`cm1uMhAVz;hw{t6v1{aNZ*cajP?2_qJYZ*RJQYU&*HQN@>tF3*i0n zG2j}&YrA*gLpxva{0k`BZClmT`gNbG@g1c|x=c~%@&?`oq&<2g?r$RoP?3?5b>-~Y zb2jV$X!Y-Eaqc9}lwK(fx;PeB0o($3P0sPr1vr=C6&sr{rfh$iO%1^377))n13dwf zE>je`rU5;HQ2_6O*>9T4d2wbVv7}_R>4QzE71m*R*37V?I2Ju_-1u)G#-jBVbh1C} z7XbTY`1|I|ZR*rFkMXxGT`YIkuAMYv#ta%eb{tKfJeih%xSUR&JV6|@ldkIOYRb#& zS&8v5Mk}iQU+CriJo_W`F@Pb1pI=p7tvz3O^X5&OI%OI~EAuJRV+6&>5HoZeOOakL zP)b~1TDJ7J`uJyA*#XfvjCj~P?Q8xi2Xu3L%mu`AtBAc%m(E9R+_aIR{GX<@t~ld} zxPcVUWM6zrm*0^pxPbQV-Ak2~X9@F0J>uSnAm;-BC#NmDkk!=FiuNyT}b)4ec{jVfqooP2K_vy`2aHjsZA|11o<5Se_%M5 zBPd9T*jfywxGblPPCKZ3rT|LU&aj}!$3dx?KgqXFqgj*9u~C* zv5sO;i{dok<9aCPI7L`M51Ko%lumtnoknIJrtXf~_))TK0fh#oa=o+uGN8qoQ9M6^ zzF5z33XZoVCM4DH9530}9tA&-k)r%Cc?zY5j3SlSG%>aw-EAm^$P*;ptRJh{mKV~J zpuZ0DHzlc3IBs+s}hnZ zEj68EH5Wre!p)A&hSq@J0aycY`OIMp-ka=ODE~CXE1L6i^Y>N#Kn=aBw(^)u2QSybD!`O(PUCsZ7@MFg z0r){@g9fzdVdUAu3!OYJ-vQ15N?T++3=ed2pXT-JyoZtVFuc&+73lD@BoAYgHN4V# zO*8X8JPc~m$f`uw#&x(H82C_W7Qn8L8sMG|jkAQAB-p{-VSk5x-3Rf)Js zYFUj4cy-vrBSMo0brNuki~SVrmQVtEKSevELuhD(8^&^zV>e>C-k9Ueo;92|@BJC; z)_r;a|9Rju#nL`jz#7N1WYy}8D^{#phxAr+2--Oi=`QQnf4Z92!N-sPzK@;SYQ2>aNp~BS(M0{MNz-@FoIpz$cNlU_tR>{(lBvOfOx!+>En&ngz?k;m5$i20a?CmqIlp52t}vXm5o z(Q1GHfDEi{x&b3`CgC}pF>193#@fY09u)Fje&$db(XWJ5viB&$zaPf)kOR;mj^jAX zup|-dwU}t}{H;_BJw?8Wyw+6&h2#89IP>y+Fj>j~{ll=%yO@-iJV{D3q{u4=P6N_B z!s{#j**e@8zz_27l10VrV=;Ll&&xmqz%n)g`Zzl76%3P%xC?#i^SJnZAVcTy0l;Y+QOAs4U&Q0vfuQa1PsLKFV!#?a&eGci~( HND%%FA}!mI literal 0 HcmV?d00001 diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java index b313464092508..3206b62188a69 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/SimpleFileServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,6 +76,8 @@ public class SimpleFileServerTest { static final boolean ENABLE_LOGGING = true; static final Logger LOGGER = Logger.getLogger("com.sun.net.httpserver"); + static final String EXPECTED_LAST_MODIFIED_OF_FAVICON = "Mon, 23 May 1995 11:11:11 GMT"; + @BeforeTest public void setup() throws IOException { if (ENABLE_LOGGING) { @@ -142,6 +144,65 @@ public void testDirectoryGET() throws Exception { } } + @Test + public void testFavIconGET() throws Exception { + var root = Files.createDirectory(TEST_DIR.resolve("testFavIconGET")); + + var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); + server.start(); + try { + // expect built-in icon + var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); + var request = HttpRequest.newBuilder(uri(server, "favicon.ico")).build(); + var response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 200); + assertEquals(response.headers().firstValue("content-type").get(), "image/x-icon"); + assertEquals(response.headers().firstValue("last-modified").get(), EXPECTED_LAST_MODIFIED_OF_FAVICON); + + // expect custom (and broken) icon + var file = Files.writeString(root.resolve("favicon.ico"), "broken icon", CREATE); + try { + var lastModified = getLastModified(file); + var expectedLength = Long.toString(Files.size(file)); + response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 200); + assertEquals(response.headers().firstValue("content-type").get(), "application/octet-stream"); + assertEquals(response.headers().firstValue("content-length").get(), expectedLength); + assertEquals(response.headers().firstValue("last-modified").get(), lastModified); + } finally { + Files.delete(file); + } + + // expect built-in icon + response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 200); + assertEquals(response.headers().firstValue("content-type").get(), "image/x-icon"); + assertEquals(response.headers().firstValue("last-modified").get(), EXPECTED_LAST_MODIFIED_OF_FAVICON); + } finally { + server.stop(0); + } + } + + @Test + public void testFavIconHEAD() throws Exception { + var root = Files.createDirectory(TEST_DIR.resolve("testFavIconHEAD")); + + var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, OutputLevel.VERBOSE); + server.start(); + try { + var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); + var request = HttpRequest.newBuilder(uri(server, "favicon.ico")) + .method("HEAD", BodyPublishers.noBody()).build(); + var response = client.send(request, BodyHandlers.ofString()); + assertEquals(response.statusCode(), 200); + assertEquals(response.headers().firstValue("content-type").get(), "image/x-icon"); + assertEquals(response.headers().firstValue("last-modified").get(), EXPECTED_LAST_MODIFIED_OF_FAVICON); + assertEquals(response.body(), ""); + } finally { + server.stop(0); + } + } + @Test public void testFileHEAD() throws Exception { var root = Files.createDirectory(TEST_DIR.resolve("testFileHEAD")); From 2baacfc16916220846743c6e49a99a6c41cac510 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 8 May 2024 07:05:27 +0000 Subject: [PATCH 119/203] 8331789: ubsan: deoptimization.cpp:403:29: runtime error: load of value 208, which is not a valid value for type 'bool' Reviewed-by: stefank, aboldtch --- src/hotspot/share/runtime/deoptimization.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 7a4a59a855315..0c78242c4adcb 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -535,7 +535,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread #if COMPILER2_OR_JVMCI if ((jvmci_enabled COMPILER2_PRESENT( || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks) )) && !EscapeBarrier::objs_are_deoptimized(current, deoptee.id())) { - bool unused; + bool unused = false; restore_eliminated_locks(current, chunk, realloc_failures, deoptee, exec_mode, unused); } #endif // COMPILER2_OR_JVMCI From 7f299043a99406dbd666d4f7f30445d26f3eae82 Mon Sep 17 00:00:00 2001 From: Raffaello Giulietti Date: Wed, 8 May 2024 08:27:13 +0000 Subject: [PATCH 120/203] 8330005: RandomGeneratorFactory.getDefault() throws exception when the runtime image only has java.base module Reviewed-by: jpai, alanb --- .../util/random/RandomGeneratorFactory.java | 15 ++--- .../java/util/random/package-info.java | 7 +-- .../internal}/random/L128X1024MixRandom.java | 4 +- .../internal}/random/L128X128MixRandom.java | 4 +- .../internal}/random/L128X256MixRandom.java | 4 +- .../jdk/internal}/random/L32X64MixRandom.java | 4 +- .../internal}/random/L64X1024MixRandom.java | 4 +- .../internal}/random/L64X128MixRandom.java | 4 +- .../random/L64X128StarStarRandom.java | 4 +- .../internal}/random/L64X256MixRandom.java | 4 +- .../random/Xoroshiro128PlusPlus.java | 4 +- .../internal}/random/Xoshiro256PlusPlus.java | 4 +- src/java.base/share/classes/module-info.java | 17 +++-- src/jdk.random/share/classes/module-info.java | 63 ------------------- 14 files changed, 38 insertions(+), 104 deletions(-) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L128X1024MixRandom.java (99%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L128X128MixRandom.java (99%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L128X256MixRandom.java (99%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L32X64MixRandom.java (98%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L64X1024MixRandom.java (99%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L64X128MixRandom.java (98%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L64X128StarStarRandom.java (98%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/L64X256MixRandom.java (99%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/Xoroshiro128PlusPlus.java (99%) rename src/{jdk.random/share/classes/jdk => java.base/share/classes/jdk/internal}/random/Xoshiro256PlusPlus.java (99%) delete mode 100644 src/jdk.random/share/classes/module-info.java diff --git a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java index 7b7339e2772a8..a7c063713684b 100644 --- a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java +++ b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,8 +142,9 @@ private static class FactoryMapHolder { * @return Map of RandomGeneratorFactory classes. */ private static Map> createFactoryMap() { + FactoryMapHolder.class.getModule().addUses(RandomGenerator.class); return ServiceLoader - .load(RandomGenerator.class) + .load(RandomGenerator.class, ClassLoader.getPlatformClassLoader()) .stream() .filter(p -> !p.type().isInterface()) .collect(Collectors.toMap(p -> p.type().getSimpleName(), Function.identity())); @@ -341,9 +342,6 @@ private void ensureConstructors() { * {@link RandomGenerator} that utilize the {@code name} * algorithm. * - * @implSpec Availability is determined by RandomGeneratorFactory using the - * service provider API to locate implementations of the RandomGenerator interface. - * * @param name Name of random number generator * algorithm * @param Sub-interface of {@link RandomGenerator} to produce @@ -376,12 +374,9 @@ public static RandomGeneratorFactory getDefault() { /** * Returns a non-empty stream of available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}. - * + *

* RandomGenerators that are marked as deprecated are not included in the result. * - * @implSpec Availability is determined by RandomGeneratorFactory using the service provider API - * to locate implementations of the RandomGenerator interface. - * * @return a non-empty stream of all available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}. */ public static Stream> all() { @@ -615,5 +610,3 @@ public T create(byte[] seed) { } } - - diff --git a/src/java.base/share/classes/java/util/random/package-info.java b/src/java.base/share/classes/java/util/random/package-info.java index b4dfe28f796c4..2e16b319f44bb 100644 --- a/src/java.base/share/classes/java/util/random/package-info.java +++ b/src/java.base/share/classes/java/util/random/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,7 @@ *

The principal supporting class is {@link RandomGeneratorFactory}. This * can be used to generate multiple random number generators for a specific * algorithm. {@link RandomGeneratorFactory} also provides methods for - * selecting random number generator algorithms. RandomGeneratorFactory - * registers implementations of {@link RandomGenerator} interface using the - * service provider API. + * selecting random number generator algorithms. * *

An important subsidiary interface is * {@link RandomGenerator.StreamableGenerator}, which provides methods for @@ -636,4 +634,3 @@ * @since 17 */ package java.util.random; - diff --git a/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java index 46f8a642d54ad..e6f4f896dc0bf 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java index ac12b96b4d227..d03fcfc086485 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java index f34956e40a1e8..81440d7316a50 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java similarity index 98% rename from src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java index 1b64a4b28cd92..0f6beea7bc796 100644 --- a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java index 9ec81997bde05..e4eb82d450ef2 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java similarity index 98% rename from src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java index 4188e85e89f31..7dd757f312b1e 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java similarity index 98% rename from src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java index 139b27223b678..15b9bc312da3a 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java index 0c0cbb43687d8..bb605df5fdc87 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java b/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java rename to src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java index ba8daaf724661..d20b3cf9e6afa 100644 --- a/src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java +++ b/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java b/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java rename to src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java index 5c9cc606597b1..fdefe02dd035d 100644 --- a/src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java +++ b/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 17a66b856a1e4..edbbad78c9da9 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -268,8 +268,6 @@ jdk.jfr; exports jdk.internal.util.xml.impl to jdk.jfr; - exports jdk.internal.util.random to - jdk.random; exports jdk.internal.util to java.desktop, java.prefs, @@ -396,7 +394,6 @@ uses java.time.chrono.AbstractChronology; uses java.time.chrono.Chronology; uses java.time.zone.ZoneRulesProvider; - uses java.util.random.RandomGenerator; uses java.util.spi.CalendarDataProvider; uses java.util.spi.CalendarNameProvider; uses java.util.spi.CurrencyNameProvider; @@ -425,6 +422,16 @@ provides java.util.random.RandomGenerator with java.security.SecureRandom, java.util.Random, - java.util.SplittableRandom; + java.util.SplittableRandom, + jdk.internal.random.L32X64MixRandom, + jdk.internal.random.L64X128MixRandom, + jdk.internal.random.L64X128StarStarRandom, + jdk.internal.random.L64X256MixRandom, + jdk.internal.random.L64X1024MixRandom, + jdk.internal.random.L128X128MixRandom, + jdk.internal.random.L128X256MixRandom, + jdk.internal.random.L128X1024MixRandom, + jdk.internal.random.Xoroshiro128PlusPlus, + jdk.internal.random.Xoshiro256PlusPlus; } diff --git a/src/jdk.random/share/classes/module-info.java b/src/jdk.random/share/classes/module-info.java deleted file mode 100644 index 3d82090f31334..0000000000000 --- a/src/jdk.random/share/classes/module-info.java +++ /dev/null @@ -1,63 +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. - */ - -import jdk.internal.util.random.RandomSupport; - -/** - * Defines implementations of the - * {@linkplain java.util.random.RandomGenerator RandomGenerator Interface}. - * - * @provides jdk.random.L128X1024MixRandom - * @provides jdk.random.L128X128MixRandom - * @provides jdk.random.L128X256MixRandom - * @provides jdk.random.L32X64MixRandom - * @provides jdk.random.L64X1024MixRandom - * @provides jdk.random.L64X128MixRandom - * @provides jdk.random.L64X128StarStarRandom - * @provides jdk.random.L64X256MixRandom - * @provides jdk.random.Xoroshiro128PlusPlus - * @provides jdk.random.Xoshiro256PlusPlus - * - * @uses java.util.random.RandomGenerator - * - * @moduleGraph - * @since 16 - */ -module jdk.random { - exports jdk.random to - java.base; - - provides java.util.random.RandomGenerator with - jdk.random.L32X64MixRandom, - jdk.random.L64X128MixRandom, - jdk.random.L64X128StarStarRandom, - jdk.random.L64X256MixRandom, - jdk.random.L64X1024MixRandom, - jdk.random.L128X128MixRandom, - jdk.random.L128X256MixRandom, - jdk.random.L128X1024MixRandom, - jdk.random.Xoroshiro128PlusPlus, - jdk.random.Xoshiro256PlusPlus; -} From 0e1dca75ef1f145bcf1ad76a2bf21d647ddaf76b Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 8 May 2024 08:45:27 +0000 Subject: [PATCH 121/203] 8331715: Remove virtual specifiers in ContiguousSpace Reviewed-by: gli, tschatzl --- src/hotspot/share/gc/shared/space.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 2a831ddad89bc..8dcd954dcf479 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -73,8 +73,11 @@ class ContiguousSpace: public CHeapObj { // Accessors HeapWord* bottom() const { return _bottom; } HeapWord* end() const { return _end; } + HeapWord* top() const { return _top; } + void set_bottom(HeapWord* value) { _bottom = value; } void set_end(HeapWord* value) { _end = value; } + void set_top(HeapWord* value) { _top = value; } // Testers bool is_empty() const { return used() == 0; } @@ -112,10 +115,6 @@ class ContiguousSpace: public CHeapObj { // had allocation performed in it, but is now to be considered empty. void clear(bool mangle_space); - // Accessors - HeapWord* top() const { return _top; } - void set_top(HeapWord* value) { _top = value; } - // Used to save the space's current top for later use during mangling. void set_top_for_allocations() PRODUCT_RETURN; @@ -139,9 +138,9 @@ class ContiguousSpace: public CHeapObj { // Allocation (return null if full). Assumes the caller has established // mutually exclusive access to the space. - virtual HeapWord* allocate(size_t word_size); + HeapWord* allocate(size_t word_size); // Allocation (return null if full). Enforces mutual exclusion internally. - virtual HeapWord* par_allocate(size_t word_size); + HeapWord* par_allocate(size_t word_size); // Iteration void object_iterate(ObjectClosure* blk); From c6f611cfe0f3d6807b450be19ec00713229dbf42 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 8 May 2024 08:48:11 +0000 Subject: [PATCH 122/203] 8331798: Remove unused arg of checkErgonomics() in TestMaxHeapSizeTools.java Reviewed-by: tschatzl --- .../gc/arguments/TestMaxHeapSizeTools.java | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java b/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java index 5af005063c171..fd78486166327 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java @@ -71,42 +71,42 @@ public static void checkMinInitialErgonomics(String gcflag) throws Exception { long maxHeapSize = largeValue + (2 * 1024 * 1024); // -Xms is not set - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue }, values, smallValue, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + largeValue }, values, largeValue, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=0" }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue }, smallValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + largeValue }, largeValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=0" }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, -1, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, -1, -1); // Some extra checks when both are set. - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, largeValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + smallValue }, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + largeValue }, smallValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:MinHeapSize=" + largeValue, "-XX:InitialHeapSize=" + largeValue }, largeValue, largeValue); // -Xms is set to zero - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue }, values, smallValue, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + largeValue }, values, largeValue, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=0" }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, largeValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue }, smallValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + largeValue }, largeValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=0" }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, -1, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + smallValue }, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + smallValue, "-XX:InitialHeapSize=" + largeValue }, smallValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:MinHeapSize=" + largeValue, "-XX:InitialHeapSize=" + largeValue }, largeValue, largeValue); // -Xms is set to small value - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:MinHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:MinHeapSize=0" }, values, -1, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:MinHeapSize=" + smallValue }, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:MinHeapSize=0" }, -1, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, smallValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, smallValue, -1); // -Xms is set to large value - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, values, largeValue, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:MinHeapSize=0" }, values, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, largeValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, largeValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:MinHeapSize=0" }, -1, largeValue); } private static long align_up(long value, long alignment) { @@ -244,7 +244,7 @@ private static void getMinInitialMaxHeap(String[] args, MinInitialMaxValues val) * Verify whether the VM automatically synchronizes minimum and initial heap size if only * one is given for the GC specified. */ - public static void checkErgonomics(String[] args, long[] newoldsize, + public static void checkErgonomics(String[] args, long expectedMin, long expectedInitial) throws Exception { MinInitialMaxValues v = new MinInitialMaxValues(); From 0eff492e4107abc5624f0c3445877bf38629a980 Mon Sep 17 00:00:00 2001 From: Sean Coffey Date: Wed, 8 May 2024 09:30:23 +0000 Subject: [PATCH 123/203] 8330278: Have SSLSocketTemplate.doClientSide use loopback address Reviewed-by: ssahoo, rhalade --- test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java | 4 ++-- test/jdk/javax/net/ssl/templates/TLSBase.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java index 3515ca9c2fff1..b67f897830473 100644 --- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -273,7 +273,7 @@ protected void doClientSide() throws Exception { configureClientSocket(sslSocket); InetAddress serverAddress = this.serverAddress; InetSocketAddress connectAddress = serverAddress == null - ? new InetSocketAddress("localhost", serverPort) + ? new InetSocketAddress(InetAddress.getLoopbackAddress(), serverPort) : new InetSocketAddress(serverAddress, serverPort); sslSocket.connect(connectAddress, 15000); } catch (IOException ioe) { diff --git a/test/jdk/javax/net/ssl/templates/TLSBase.java b/test/jdk/javax/net/ssl/templates/TLSBase.java index 414e7e106b327..812aea09fea11 100644 --- a/test/jdk/javax/net/ssl/templates/TLSBase.java +++ b/test/jdk/javax/net/ssl/templates/TLSBase.java @@ -23,6 +23,7 @@ import javax.net.ssl.*; import java.io.*; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.security.KeyStore; import java.security.cert.PKIXBuilderParameters; @@ -334,7 +335,7 @@ public SSLSocket connect() { sslContext = SSLContext.getInstance("TLS"); sslContext.init(TLSBase.getKeyManager(km), TLSBase.getTrustManager(tm), null); sock = (SSLSocket)sslContext.getSocketFactory().createSocket(); - sock.connect(new InetSocketAddress("localhost", serverPort)); + sock.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), serverPort)); System.err.println("Client connected using port " + sock.getLocalPort()); name = "client(" + sock.toString() + ")"; From 1aebab780c5b84a85b6f10884d05bb29bae3c3bf Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Wed, 8 May 2024 09:37:42 +0000 Subject: [PATCH 124/203] 8320995: RISC-V: C2 PopCountVI 8320996: RISC-V: C2 PopCountVL Reviewed-by: luhenry, fyang --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 10 ++++++ src/hotspot/cpu/riscv/globals_riscv.hpp | 1 + src/hotspot/cpu/riscv/riscv_v.ad | 34 +++++++++++++++++++ src/hotspot/cpu/riscv/vm_version_riscv.cpp | 6 ++++ src/hotspot/cpu/riscv/vm_version_riscv.hpp | 1 + .../ir_framework/test/IREncodingPrinter.java | 4 ++- .../superword/TestGeneralizedReductions.java | 7 +++- .../vectorization/TestPopCountVector.java | 18 +++++++--- .../vectorization/TestPopCountVectorLong.java | 18 +++++++--- 9 files changed, 87 insertions(+), 12 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 388e7f9eb941f..0fe91d99066fa 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1904,6 +1904,16 @@ enum Nf { #undef INSN +#define INSN(NAME, op, funct3, Vs1, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Vs1, Vs2, vm, funct6); \ + } + + // Vector Basic Bit-manipulation (Zvbb) Extension + INSN(vcpop_v, 0b1010111, 0b010, 0b01110, 0b010010); + +#undef INSN + #undef patch_VArith // ==================================== diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index e22456cacc603..c39b29f6ee4a7 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -115,6 +115,7 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZtso, false, EXPERIMENTAL, "Assume Ztso memory model") \ product(bool, UseZihintpause, false, EXPERIMENTAL, \ "Use Zihintpause instructions") \ + product(bool, UseZvbb, false, EXPERIMENTAL, "Use Zvbb instructions") \ product(bool, UseZvfh, false, EXPERIMENTAL, "Use Zvfh instructions") \ product(bool, UseZvkn, false, EXPERIMENTAL, \ "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 7869d6156e590..0879f62600e40 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -73,6 +73,9 @@ source %{ return false; } break; + case Op_PopCountVL: + case Op_PopCountVI: + return UseZvbb; case Op_LoadVectorGather: case Op_LoadVectorGatherMasked: if (is_subword_type(bt)) { @@ -3784,6 +3787,37 @@ instruct vconvF2HF(vReg dst, vReg src, vReg vtmp, vRegMask_V0 v0, iRegINoSp tmp) ins_pipe(pipe_slow); %} + +// ------------------------------ Popcount vector ------------------------------ + +instruct vpopcount_mask(vReg dst, vReg src, vRegMask_V0 v0) %{ + match(Set dst (PopCountVI src v0)); + match(Set dst (PopCountVL src v0)); + ins_cost(VEC_COST); + format %{ "vcpop_v $dst, $src, $v0\t# vcpop_v with mask" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vcpop_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vpopcount(vReg dst, vReg src) %{ + match(Set dst (PopCountVI src)); + match(Set dst (PopCountVL src)); + ins_cost(VEC_COST); + format %{ "vcpop_v $dst, $src\t# vcpop_v without mask" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vcpop_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + // ------------------------------ Vector Load Gather --------------------------- instruct gather_load(vReg dst, indirect mem, vReg idx) %{ diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 848ffe709d882..995e8b722485d 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -245,6 +245,12 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } + // UseZvbb (depends on RVV). + if (UseZvbb && !UseRVV) { + FLAG_SET_DEFAULT(UseZvbb, false); + warning("Cannot enable UseZvbb on cpu without RVV support."); + } + // SHA's if (FLAG_IS_DEFAULT(UseSHA)) { FLAG_SET_DEFAULT(UseSHA, true); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index d26b16941dbfe..f3a834b72379c 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -161,6 +161,7 @@ class VM_Version : public Abstract_VM_Version { decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \ decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \ decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \ + decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvbb)) \ decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvfh)) \ decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvkn)) \ decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index 939267234bd09..47cec9f5e13b4 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -102,7 +102,9 @@ public class IREncodingPrinter { // AArch64 "sha3", "asimd", - "sve" + "sve", + // Riscv64 + "zvbb" )); public IREncodingPrinter() { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java index 60ecaf0e4c89e..2a27aad8d5aa1 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,6 +144,11 @@ private static long testReductionOnPartiallyUnrolledLoopWithSwappedInputs(long[] applyIfAnd = {"SuperWordReductions", "true","UsePopCountInstruction", "true"}, counts = {IRNode.ADD_REDUCTION_VI, ">= 1", IRNode.POPCOUNT_VL, ">= 1"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"zvbb", "true"}, + applyIfAnd = {"SuperWordReductions", "true","UsePopCountInstruction", "true"}, + counts = {IRNode.ADD_REDUCTION_VI, ">= 1", + IRNode.POPCOUNT_VL, ">= 1"}) private static long testMapReductionOnGlobalAccumulator(long[] array) { acc = 0; for (int i = 0; i < array.length; i++) { diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java index a6daa5bce063a..4a4370fd2d112 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,18 +40,22 @@ public class TestPopCountVector { public static void main(String args[]) { TestPopCountVector test = new TestPopCountVector(); + int err = 0; for (int i = 0; i < 10_000; ++i) { test.vectorizeBitCount(); } System.out.println("Checking popcount result"); - test.checkResult(); + err += test.checkResult(); for (int i = 0; i < 10_000; ++i) { test.vectorizeBitCount(); } System.out.println("Checking popcount result"); - test.checkResult(); + err += test.checkResult(); + if (err > 0) { + throw new RuntimeException("Error!"); + } } public TestPopCountVector() { @@ -68,13 +72,17 @@ public void vectorizeBitCount() { } } - public void checkResult() { + public int checkResult() { + int err = 0; for (int i = 0; i < LEN; ++i) { int expected = Integer.bitCount(input[i]); if (output[i] != expected) { - throw new RuntimeException("Invalid result: output[" + i + "] = " + output[i] + " != " + expected); + err++; + System.err.println("Invalid result: output[" + i + "] = " + output[i] + " != " + expected + + ", input[" + i + "] == " + Integer.toBinaryString(input[i])); } } + return err; } } diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java index 20912582b7f5d..e382e828790b6 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,14 @@ * @summary Test vectorization of popcount for Long * @requires vm.compiler2.enabled * @requires ((os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") & vm.cpu.features ~= ".*avx512bw.*") | -* os.simpleArch == "aarch64" +* os.simpleArch == "aarch64" | +* (os.arch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") * @library /test/lib / * @run driver compiler.vectorization.TestPopCountVectorLong */ package compiler.vectorization; + import compiler.lib.ir_framework.*; import java.util.Random; @@ -62,16 +64,22 @@ public void vectorizeBitCount() { for (int i = 0; i < LEN; ++i) { output[i] = Long.bitCount(input[i]); } - checkResult(); + if (checkResult() > 0) { + throw new RuntimeException("Error!"); + } } - public void checkResult() { + public int checkResult() { + int err = 0; for (int i = 0; i < LEN; ++i) { int expected = Long.bitCount(input[i]); if (output[i] != expected) { - throw new RuntimeException("Invalid result: output[" + i + "] = " + output[i] + " != " + expected); + err++; + System.err.println("Invalid result: output[" + i + "] = " + output[i] + " != " + expected + + ", input[" + i + "] == " + Long.toBinaryString(input[i])); } } + return err; } } From edd47c10ebfdc021368820dec6a109251554e8b0 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 8 May 2024 10:11:01 +0000 Subject: [PATCH 125/203] 8308033: The jcmd thread dump related tests should test virtual threads Reviewed-by: cjplummer, sspitsyn --- test/hotspot/jtreg/ProblemList-Virtual.txt | 6 +-- .../serviceability/dcmd/thread/PrintTest.java | 6 ++- .../tmtools/jstack/DaemonThreadTest.java | 3 +- test/jdk/ProblemList-Virtual.txt | 3 -- .../tools/jcmd/JcmdOutputEncodingTest.java | 41 +++++++++++++++++-- .../jdk/sun/tools/jstack/BasicJStackTest.java | 13 +++++- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList-Virtual.txt b/test/hotspot/jtreg/ProblemList-Virtual.txt index 7615e103d1a6a..e7627be7b8c0b 100644 --- a/test/hotspot/jtreg/ProblemList-Virtual.txt +++ b/test/hotspot/jtreg/ProblemList-Virtual.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,6 @@ serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java 8308026 generic-all serviceability/jvmti/GetThreadListStackTraces/OneGetThreadListStackTraces.java 8308027 generic-all serviceability/jvmti/Heap/IterateHeapWithEscapeAnalysisEnabled.java 8264699 generic-all -serviceability/dcmd/thread/PrintConcurrentLocksTest.java 8308033 generic-all -serviceability/dcmd/thread/PrintTest.java 8308033 generic-all -serviceability/dcmd/thread/ThreadDumpToFileTest.java 8308033 generic-all -serviceability/tmtools/jstack/DaemonThreadTest.java 8308033 generic-all #### ## Classes not unloaded as expected (TODO, need to check if FJ keeps a reference) diff --git a/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java b/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java index e4af11c32615c..29c462a56b393 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +import org.testng.SkipException; import org.testng.annotations.Test; import org.testng.Assert; @@ -171,6 +172,9 @@ public void run(CommandExecutor executor) { @Test public void jmx() { + if (Thread.currentThread().isVirtual()) { + throw new SkipException("skipping test since current thread is virtual thread"); + } run(new JMXExecutor()); } } diff --git a/test/hotspot/jtreg/serviceability/tmtools/jstack/DaemonThreadTest.java b/test/hotspot/jtreg/serviceability/tmtools/jstack/DaemonThreadTest.java index d7915e8901a8f..23e9474ad4a0c 100644 --- a/test/hotspot/jtreg/serviceability/tmtools/jstack/DaemonThreadTest.java +++ b/test/hotspot/jtreg/serviceability/tmtools/jstack/DaemonThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ public class DaemonThreadTest { static class NormalThread extends Thread { NormalThread() { + setDaemon(false); } @Override diff --git a/test/jdk/ProblemList-Virtual.txt b/test/jdk/ProblemList-Virtual.txt index c352e8a95c1d0..e3b0a92285746 100644 --- a/test/jdk/ProblemList-Virtual.txt +++ b/test/jdk/ProblemList-Virtual.txt @@ -33,9 +33,6 @@ com/sun/jdi/cds/CDSBreakpointTest.java 8307778 generic-all com/sun/jdi/cds/CDSDeleteAllBkptsTest.java 8307778 generic-all com/sun/jdi/cds/CDSFieldWatchpoints.java 8307778 generic-all -sun/tools/jcmd/JcmdOutputEncodingTest.java 8308033 generic-all -sun/tools/jstack/BasicJStackTest.java 8308033 generic-all - javax/management/remote/mandatory/connection/BrokenConnectionTest.java 8308035 windows-x64 javax/management/remote/mandatory/loading/MissingClassTest.java 8145413 windows-x64 diff --git a/test/jdk/sun/tools/jcmd/JcmdOutputEncodingTest.java b/test/jdk/sun/tools/jcmd/JcmdOutputEncodingTest.java index 14f5a2be1671b..01797a6a82af9 100644 --- a/test/jdk/sun/tools/jcmd/JcmdOutputEncodingTest.java +++ b/test/jdk/sun/tools/jcmd/JcmdOutputEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; @@ -31,7 +33,7 @@ /* * @test - * @bug 8222491 8273187 + * @bug 8222491 8273187 8308033 * @summary Tests if we handle the encoding of jcmd output correctly. * @library /test/lib * @run main JcmdOutputEncodingTest @@ -52,12 +54,43 @@ private static void testThreadDump() throws Exception { launcher.addVMArg("-Dfile.encoding=" + cs); launcher.addVMArg("-Dsun.stdout.encoding=" + cs); launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); - launcher.addToolArg("Thread.print"); + boolean isVirtualThread = Thread.currentThread().isVirtual(); + Path threadDumpFile = null; + if (isVirtualThread) { + // "jcmd Thread.print" will not print thread dumps of virtual threads. + // So we use "Thread.dump_to_file" command instead and dump the thread + // stacktraces in a file + threadDumpFile = Files.createTempFile(Path.of("."), "jcmd", ".tdump").toAbsolutePath(); + launcher.addToolArg("Thread.dump_to_file"); + launcher.addToolArg("-overwrite"); + launcher.addToolArg(threadDumpFile.toString()); + } else { + launcher.addToolArg("Thread.print"); + } ProcessBuilder processBuilder = new ProcessBuilder(); processBuilder.command(launcher.getCommand()); OutputAnalyzer output = ProcessTools.executeProcess(processBuilder, null, cs); output.shouldHaveExitValue(0); - output.shouldContain(marker); + if (isVirtualThread) { + // verify the file containing the thread dump has the expected text + try (var br = Files.newBufferedReader(threadDumpFile, cs)) { + String line = null; + boolean found = false; + while ((line = br.readLine()) != null) { + if (line.contains(marker)) { + found = true; + break; + } + } + if (!found) { + output.reportDiagnosticSummary(); + throw new RuntimeException("'" + marker + "' missing in thread dump in file " + + threadDumpFile); + } + } + } else { + output.shouldContain(marker); + } } } diff --git a/test/jdk/sun/tools/jstack/BasicJStackTest.java b/test/jdk/sun/tools/jstack/BasicJStackTest.java index e0a9c96d6ad2a..ec0a80e8d78cc 100644 --- a/test/jdk/sun/tools/jstack/BasicJStackTest.java +++ b/test/jdk/sun/tools/jstack/BasicJStackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,9 +30,11 @@ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.JDKToolLauncher; +import jtreg.SkippedException; + /* * @test - * @bug 8273187 + * @bug 8273187 8308033 * @summary Unit test for jstack utility * @library /test/lib * @run main BasicJStackTest @@ -42,6 +44,13 @@ public class BasicJStackTest { private static ProcessBuilder processBuilder = new ProcessBuilder(); public static void main(String[] args) throws Exception { + if (Thread.currentThread().isVirtual()) { + // This test runs jstack against the current process and then asserts the + // presence of current thread in the stacktraces. We skip this test + // when the current thread is a virtual thread since "jstack" command doesn't + // print the stacktraces of virtual threads. + throw new SkippedException("skipping test since current thread is a virtual thread"); + } testJstackNoArgs(); testJstack_l(); testJstackUTF8Encoding(); From aafa15fc173af07ebf5361a8c6a09c2a28981c38 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 8 May 2024 10:18:33 +0000 Subject: [PATCH 126/203] 8331208: Memory stress test that checks OutOfMemoryError stack trace fails Reviewed-by: dholmes, never --- src/hotspot/share/compiler/compileBroker.cpp | 2 ++ src/hotspot/share/gc/shared/memAllocator.cpp | 6 ++-- src/hotspot/share/gc/shared/memAllocator.hpp | 33 ++++++++++++++++++ src/hotspot/share/jvmci/jvmciRuntime.cpp | 35 ++++++-------------- src/hotspot/share/memory/universe.cpp | 11 +++--- src/hotspot/share/memory/universe.hpp | 3 +- src/hotspot/share/oops/klass.cpp | 4 +-- src/hotspot/share/runtime/deoptimization.cpp | 4 +++ src/hotspot/share/runtime/javaThread.cpp | 2 +- src/hotspot/share/runtime/javaThread.hpp | 14 ++++---- src/hotspot/share/runtime/thread.hpp | 8 ----- 11 files changed, 68 insertions(+), 54 deletions(-) diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 0935ea6a8e132..ddd5b2f0eb7e9 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -38,6 +38,7 @@ #include "compiler/compilerEvent.hpp" #include "compiler/compilerOracle.hpp" #include "compiler/directivesParser.hpp" +#include "gc/shared/memAllocator.hpp" #include "interpreter/linkResolver.hpp" #include "jvm.h" #include "jfr/jfrEvents.hpp" @@ -1396,6 +1397,7 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, assert(!HAS_PENDING_EXCEPTION, "No exception should be present"); // some prerequisites that are compiler specific if (comp->is_c2() || comp->is_jvmci()) { + InternalOOMEMark iom(THREAD); method->constants()->resolve_string_constants(CHECK_AND_CLEAR_NONASYNC_NULL); // Resolve all classes seen in the signature of the method // we are compiling. diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp index ddd33d8f43adb..156b55c104621 100644 --- a/src/hotspot/share/gc/shared/memAllocator.cpp +++ b/src/hotspot/share/gc/shared/memAllocator.cpp @@ -123,21 +123,21 @@ bool MemAllocator::Allocation::check_out_of_memory() { } const char* message = _overhead_limit_exceeded ? "GC overhead limit exceeded" : "Java heap space"; - if (!_thread->in_retryable_allocation()) { + if (!_thread->is_in_internal_oome_mark()) { // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support report_java_out_of_memory(message); - if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP, message); } + oop exception = _overhead_limit_exceeded ? Universe::out_of_memory_error_gc_overhead_limit() : Universe::out_of_memory_error_java_heap(); THROW_OOP_(exception, true); } else { - THROW_OOP_(Universe::out_of_memory_error_retry(), true); + THROW_OOP_(Universe::out_of_memory_error_java_heap_without_backtrace(), true); } } diff --git a/src/hotspot/share/gc/shared/memAllocator.hpp b/src/hotspot/share/gc/shared/memAllocator.hpp index 5d3f892ca14fd..f299dd633e510 100644 --- a/src/hotspot/share/gc/shared/memAllocator.hpp +++ b/src/hotspot/share/gc/shared/memAllocator.hpp @@ -114,4 +114,37 @@ class ClassAllocator: public MemAllocator { virtual oop initialize(HeapWord* mem) const; }; +// Manages a scope where a failed heap allocation results in +// suppression of JVMTI "resource exhausted" events and +// throwing a shared, backtrace-less OOME instance. +// Used for OOMEs that will not be propagated to user code. +class InternalOOMEMark: public StackObj { + private: + bool _outer; + JavaThread* _thread; + + public: + explicit InternalOOMEMark(JavaThread* thread) { + if (thread != nullptr) { + _outer = thread->is_in_internal_oome_mark(); + thread->set_is_in_internal_oome_mark(true); + _thread = thread; + } else { + _outer = false; + _thread = nullptr; + } + } + + ~InternalOOMEMark() { + if (_thread != nullptr) { + // Check that only InternalOOMEMark sets + // JavaThread::_is_in_internal_oome_mark + assert(_thread->is_in_internal_oome_mark(), "must be"); + _thread->set_is_in_internal_oome_mark(_outer); + } + } + + JavaThread* thread() const { return _thread; } +}; + #endif // SHARE_GC_SHARED_MEMALLOCATOR_HPP diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index fc4bb5a6a0674..99f427ee1688d 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -28,6 +28,7 @@ #include "classfile/vmClasses.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/memAllocator.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "jvmci/jniAccessMark.inline.hpp" #include "jvmci/jvmciCompilerToVM.hpp" @@ -92,39 +93,25 @@ static void deopt_caller() { } // Manages a scope for a JVMCI runtime call that attempts a heap allocation. -// If there is a pending nonasync exception upon closing the scope and the runtime +// If there is a pending OutOfMemoryError upon closing the scope and the runtime // call is of the variety where allocation failure returns null without an // exception, the following action is taken: -// 1. The pending nonasync exception is cleared +// 1. The pending OutOfMemoryError is cleared // 2. null is written to JavaThread::_vm_result -// 3. Checks that an OutOfMemoryError is Universe::out_of_memory_error_retry(). -class RetryableAllocationMark: public StackObj { +class RetryableAllocationMark { private: - JavaThread* _thread; + InternalOOMEMark _iom; public: - RetryableAllocationMark(JavaThread* thread, bool activate) { - if (activate) { - assert(!thread->in_retryable_allocation(), "retryable allocation scope is non-reentrant"); - _thread = thread; - _thread->set_in_retryable_allocation(true); - } else { - _thread = nullptr; - } - } + RetryableAllocationMark(JavaThread* thread, bool activate) : _iom(activate ? thread : nullptr) {} ~RetryableAllocationMark() { - if (_thread != nullptr) { - _thread->set_in_retryable_allocation(false); - JavaThread* THREAD = _thread; // For exception macros. + JavaThread* THREAD = _iom.thread(); // For exception macros. + if (THREAD != nullptr) { if (HAS_PENDING_EXCEPTION) { oop ex = PENDING_EXCEPTION; - // Do not clear probable async exceptions. - CLEAR_PENDING_NONASYNC_EXCEPTION; - oop retry_oome = Universe::out_of_memory_error_retry(); - if (ex->is_a(retry_oome->klass()) && retry_oome != ex) { - ResourceMark rm; - fatal("Unexpected exception in scope of retryable allocation: " INTPTR_FORMAT " of type %s", p2i(ex), ex->klass()->external_name()); + THREAD->set_vm_result(nullptr); + if (ex->is_a(vmClasses::OutOfMemoryError_klass())) { + CLEAR_PENDING_EXCEPTION; } - _thread->set_vm_result(nullptr); } } } diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 187bdf25af85a..4a16b3d89a878 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -135,7 +135,6 @@ enum OutOfMemoryInstance { _oom_java_heap, _oom_array_size, _oom_gc_overhead_limit, _oom_realloc_objects, - _oom_retry, _oom_count }; OopHandle Universe::_out_of_memory_errors; @@ -655,6 +654,10 @@ oop Universe::out_of_memory_error_java_heap() { return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_java_heap)); } +oop Universe::out_of_memory_error_java_heap_without_backtrace() { + return out_of_memory_errors()->obj_at(_oom_java_heap); +} + oop Universe::out_of_memory_error_c_heap() { return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_c_heap)); } @@ -679,9 +682,6 @@ oop Universe::out_of_memory_error_realloc_objects() { return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_realloc_objects)); } -// Throw default _out_of_memory_error_retry object as it will never propagate out of the VM -oop Universe::out_of_memory_error_retry() { return out_of_memory_errors()->obj_at(_oom_retry); } - oop Universe::class_init_out_of_memory_error() { return out_of_memory_errors()->obj_at(_oom_java_heap); } oop Universe::class_init_stack_overflow_error() { return _class_init_stack_overflow_error.resolve(); } oop Universe::delayed_stack_overflow_error_message() { return _delayed_stack_overflow_error_message.resolve(); } @@ -785,9 +785,6 @@ void Universe::create_preallocated_out_of_memory_errors(TRAPS) { msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK); java_lang_Throwable::set_message(oom_array->obj_at(_oom_realloc_objects), msg()); - msg = java_lang_String::create_from_str("Java heap space: failed retryable allocation", CHECK); - java_lang_Throwable::set_message(oom_array->obj_at(_oom_retry), msg()); - // Setup the array of errors that have preallocated backtrace int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0; objArrayOop instance = oopFactory::new_objArray(ik, len, CHECK); diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index d5a38658e482f..c7bdb8f233970 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -272,6 +272,7 @@ class Universe: AllStatic { // may or may not have a backtrace. If error has a backtrace then the stack trace is already // filled in. static oop out_of_memory_error_java_heap(); + static oop out_of_memory_error_java_heap_without_backtrace(); static oop out_of_memory_error_c_heap(); static oop out_of_memory_error_metaspace(); static oop out_of_memory_error_class_metaspace(); @@ -279,8 +280,6 @@ class Universe: AllStatic { static oop out_of_memory_error_gc_overhead_limit(); static oop out_of_memory_error_realloc_objects(); - // Throw default _out_of_memory_error_retry object as it will never propagate out of the VM - static oop out_of_memory_error_retry(); static oop delayed_stack_overflow_error_message(); // Saved StackOverflowError and OutOfMemoryError for use when diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 23a6770251a3d..ea3b5e756d082 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -873,12 +873,12 @@ void Klass::set_archived_java_mirror(int mirror_index) { void Klass::check_array_allocation_length(int length, int max_length, TRAPS) { if (length > max_length) { - if (!THREAD->in_retryable_allocation()) { + if (!THREAD->is_in_internal_oome_mark()) { report_java_out_of_memory("Requested array size exceeds VM limit"); JvmtiExport::post_array_size_exhausted(); THROW_OOP(Universe::out_of_memory_error_array_size()); } else { - THROW_OOP(Universe::out_of_memory_error_retry()); + THROW_OOP(Universe::out_of_memory_error_java_heap_without_backtrace()); } } else if (length < 0) { THROW_MSG(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 0c78242c4adcb..03e62075808bd 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -35,6 +35,7 @@ #include "compiler/compilationPolicy.hpp" #include "compiler/compilerDefinitions.inline.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/memAllocator.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" @@ -1237,6 +1238,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* InstanceKlass* ik = InstanceKlass::cast(k); if (obj == nullptr && !cache_init_error) { + InternalOOMEMark iom(THREAD); #if COMPILER2_OR_JVMCI if (EnableVectorSupport && VectorSupport::is_vector(ik)) { obj = VectorSupport::allocate_vector(ik, fr, reg_map, sv, THREAD); @@ -1251,9 +1253,11 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* TypeArrayKlass* ak = TypeArrayKlass::cast(k); assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length"); int len = sv->field_size() / type2size[ak->element_type()]; + InternalOOMEMark iom(THREAD); obj = ak->allocate(len, THREAD); } else if (k->is_objArray_klass()) { ObjArrayKlass* ak = ObjArrayKlass::cast(k); + InternalOOMEMark iom(THREAD); obj = ak->allocate(sv->field_size(), THREAD); } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 2e40c99455c9d..7ed67c4616b72 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -456,11 +456,11 @@ JavaThread::JavaThread() : #endif #endif _jni_attach_state(_not_attaching_via_jni), + _is_in_internal_oome_mark(false), #if INCLUDE_JVMCI _pending_deoptimization(-1), _pending_monitorenter(false), _pending_transfer_to_interpreter(false), - _in_retryable_allocation(false), _pending_failed_speculation(0), _jvmci{nullptr}, _libjvmci_runtime(nullptr), diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 6b6c9139b78eb..37fd8981acd48 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -52,6 +52,7 @@ class AsyncExceptionHandshake; class ContinuationEntry; class DeoptResourceMark; +class InternalOOMEMark; class JNIHandleBlock; class JVMCIRuntime; @@ -335,6 +336,8 @@ class JavaThread: public Thread { // of _attaching_via_jni and transitions to _attached_via_jni. volatile JNIAttachStates _jni_attach_state; + // In scope of an InternalOOMEMark? + bool _is_in_internal_oome_mark; #if INCLUDE_JVMCI // The _pending_* fields below are used to communicate extra information @@ -350,10 +353,6 @@ class JavaThread: public Thread { // Specifies if the DeoptReason for the last uncommon trap was Reason_transfer_to_interpreter bool _pending_transfer_to_interpreter; - // True if in a runtime call from compiled code that will deoptimize - // and re-execute a failed heap allocation in the interpreter. - bool _in_retryable_allocation; - // An id of a speculation that JVMCI compiled code can use to further describe and // uniquely identify the speculative optimization guarded by an uncommon trap. // See JVMCINMethodData::SPECULATION_LENGTH_BITS for further details. @@ -718,6 +717,10 @@ class JavaThread: public Thread { MemRegion deferred_card_mark() const { return _deferred_card_mark; } void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } + // Is thread in scope of an InternalOOMEMark? + bool is_in_internal_oome_mark() const { return _is_in_internal_oome_mark; } + void set_is_in_internal_oome_mark(bool b) { _is_in_internal_oome_mark = b; } + #if INCLUDE_JVMCI jlong pending_failed_speculation() const { return _pending_failed_speculation; } void set_pending_monitorenter(bool b) { _pending_monitorenter = b; } @@ -727,9 +730,6 @@ class JavaThread: public Thread { void set_jvmci_alternate_call_target(address a) { assert(_jvmci._alternate_call_target == nullptr, "must be"); _jvmci._alternate_call_target = a; } void set_jvmci_implicit_exception_pc(address a) { assert(_jvmci._implicit_exception_pc == nullptr, "must be"); _jvmci._implicit_exception_pc = a; } - virtual bool in_retryable_allocation() const { return _in_retryable_allocation; } - void set_in_retryable_allocation(bool b) { _in_retryable_allocation = b; } - JVMCIRuntime* libjvmci_runtime() const { return _libjvmci_runtime; } void set_libjvmci_runtime(JVMCIRuntime* rt) { assert((_libjvmci_runtime == nullptr && rt != nullptr) || (_libjvmci_runtime != nullptr && rt == nullptr), "must be"); diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index a3d6e091d28fa..ebf1b590ebd78 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -210,14 +210,6 @@ class Thread: public ThreadShadow { DEBUG_ONLY(bool _indirectly_safepoint_thread;) public: - // Determines if a heap allocation failure will be retried - // (e.g., by deoptimizing and re-executing in the interpreter). - // In this case, the failed allocation must raise - // Universe::out_of_memory_error_retry() and omit side effects - // such as JVMTI events and handling -XX:+HeapDumpOnOutOfMemoryError - // and -XX:OnOutOfMemoryError. - virtual bool in_retryable_allocation() const { return false; } - #ifdef ASSERT void set_suspendible_thread() { _suspendible_thread = true; } void clear_suspendible_thread() { _suspendible_thread = false; } From ad78b7fa67ba30cab2e8f496e4c765be15deeca6 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 8 May 2024 10:38:09 +0000 Subject: [PATCH 127/203] 8331185: Enable compiler memory limits in debug builds Reviewed-by: asmehra, kvn --- .../compiler/compilationMemoryStatistic.cpp | 34 +++++-- src/hotspot/share/compiler/compilerOracle.cpp | 33 +++++++ src/hotspot/share/compiler/compilerOracle.hpp | 1 + .../jtreg/compiler/c2/TestFindNode.java | 5 +- .../TestDeepGraphVerifyIterativeGVN.java | 5 +- .../print/CompileCommandMemLimit.java | 98 ++++++++++++------- .../print/CompileCommandPrintMemStat.java | 29 ++++-- 7 files changed, 154 insertions(+), 51 deletions(-) diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp index 585d55febb8e7..196a11fd06537 100644 --- a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp +++ b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp @@ -181,10 +181,16 @@ class MemStatEntry : public CHeapObj { int _num_recomp; // Compiling thread. Only for diagnostic purposes. Thread may not be alive anymore. const Thread* _thread; + // active limit for this compilation, if any + size_t _limit; + // peak usage, bytes, over all arenas size_t _total; + // usage in node arena when total peaked size_t _na_at_peak; + // usage in resource area when total peaked size_t _ra_at_peak; + // number of nodes (c2 only) when total peaked unsigned _live_nodes_at_peak; const char* _result; @@ -192,7 +198,7 @@ class MemStatEntry : public CHeapObj { MemStatEntry(FullMethodName method) : _method(method), _comptype(compiler_c1), - _time(0), _num_recomp(0), _thread(nullptr), + _time(0), _num_recomp(0), _thread(nullptr), _limit(0), _total(0), _na_at_peak(0), _ra_at_peak(0), _live_nodes_at_peak(0), _result(nullptr) { } @@ -200,6 +206,7 @@ class MemStatEntry : public CHeapObj { void set_comptype(CompilerType comptype) { _comptype = comptype; } void set_current_time() { _time = os::elapsedTime(); } void set_current_thread() { _thread = Thread::current(); } + void set_limit(size_t limit) { _limit = limit; } void inc_recompilation() { _num_recomp++; } void set_total(size_t n) { _total = n; } @@ -218,6 +225,7 @@ class MemStatEntry : public CHeapObj { st->print_cr(" RA : ...how much in resource areas"); st->print_cr(" result : Result: 'ok' finished successfully, 'oom' hit memory limit, 'err' compilation failed"); st->print_cr(" #nodes : ...how many nodes (c2 only)"); + st->print_cr(" limit : memory limit, if set"); st->print_cr(" time : time of last compilation (sec)"); st->print_cr(" type : compiler type"); st->print_cr(" #rc : how often recompiled"); @@ -225,7 +233,7 @@ class MemStatEntry : public CHeapObj { } static void print_header(outputStream* st) { - st->print_cr("total NA RA result #nodes time type #rc thread method"); + st->print_cr("total NA RA result #nodes limit time type #rc thread method"); } void print_on(outputStream* st, bool human_readable) const { @@ -260,7 +268,19 @@ class MemStatEntry : public CHeapObj { col += 8; st->fill_to(col); // Number of Nodes when memory peaked - st->print("%u ", _live_nodes_at_peak); + if (_live_nodes_at_peak > 0) { + st->print("%u ", _live_nodes_at_peak); + } else { + st->print("-"); + } + col += 8; st->fill_to(col); + + // Limit + if (_limit > 0) { + st->print(PROPERFMT " ", PROPERFMTARGS(_limit)); + } else { + st->print("-"); + } col += 8; st->fill_to(col); // TimeStamp @@ -322,7 +342,7 @@ class MemStatTable : void add(const FullMethodName& fmn, CompilerType comptype, size_t total, size_t na_at_peak, size_t ra_at_peak, - unsigned live_nodes_at_peak, const char* result) { + unsigned live_nodes_at_peak, size_t limit, const char* result) { assert_lock_strong(NMTCompilationCostHistory_lock); MemStatTableKey key(fmn, comptype); MemStatEntry** pe = get(key); @@ -343,6 +363,7 @@ class MemStatTable : e->set_na_at_peak(na_at_peak); e->set_ra_at_peak(ra_at_peak); e->set_live_nodes_at_peak(live_nodes_at_peak); + e->set_limit(limit); e->set_result(result); } @@ -430,6 +451,7 @@ void CompilationMemoryStatistic::on_end_compilation() { arena_stat->na_at_peak(), arena_stat->ra_at_peak(), arena_stat->live_nodes_at_peak(), + arena_stat->limit(), result); } if (print) { @@ -521,8 +543,8 @@ void CompilationMemoryStatistic::on_arena_change(ssize_t diff, const Arena* aren if (ct != compiler_none && name[0] != '\0') { ss.print("%s %s: ", compilertype2name(ct), name); } - ss.print("Hit MemLimit %s (limit: %zu now: %zu)", - (hit_limit_before ? "again" : ""), + ss.print("Hit MemLimit %s(limit: %zu now: %zu)", + (hit_limit_before ? "again " : ""), arena_stat->limit(), arena_stat->peak_since_start()); } diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index ea09e3ebb7f75..87d879feac0c7 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -42,6 +42,23 @@ #include "runtime/os.hpp" #include "utilities/parseInteger.hpp" +// Default compile commands, if defined, are parsed before any of the +// explicitly defined compile commands. Thus, explicitly defined compile +// commands take precedence over default compile commands. The effect is +// as if the default compile commands had been specified at the start of +// the command line. +static const char* const default_compile_commands[] = { +#ifdef ASSERT + // In debug builds, impose a (generous) per-compilation memory limit + // to catch pathological compilations during testing. The suboption + // "crash" will cause the JVM to assert. + // + // Note: to disable the default limit at the command line, + // set a limit of 0 (e.g. -XX:CompileCommand=MemLimit,*.*,0). + "MemLimit,*.*,1G~crash", +#endif + nullptr }; + static const char* optiontype_names[] = { #define enum_of_types(type, name) name, OPTION_TYPES(enum_of_types) @@ -905,6 +922,14 @@ class LineCopy : StackObj { } }; +bool CompilerOracle::parse_from_line_quietly(char* line) { + const bool quiet0 = _quiet; + _quiet = true; + const bool result = parse_from_line(line); + _quiet = quiet0; + return result; +} + bool CompilerOracle::parse_from_line(char* line) { if ((line[0] == '\0') || (line[0] == '#')) { return true; @@ -1107,6 +1132,14 @@ bool CompilerOracle::parse_from_string(const char* str, bool (*parse_line)(char* bool compilerOracle_init() { bool success = true; + // Register default compile commands first - any commands specified via CompileCommand will + // supersede these default commands. + for (int i = 0; default_compile_commands[i] != nullptr; i ++) { + char* s = os::strdup(default_compile_commands[i]); + success = CompilerOracle::parse_from_line_quietly(s); + os::free(s); + assert(success, "default compile command \"%s\" failed to parse", default_compile_commands[i]); + } if (!CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line)) { success = false; } diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index 43a30b30facec..f330b3b607599 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -179,6 +179,7 @@ class CompilerOracle : AllStatic { // Reads from string instead of file static bool parse_from_string(const char* option_string, bool (*parser)(char*)); static bool parse_from_line(char* line); + static bool parse_from_line_quietly(char* line); static bool parse_compile_only(char* line); // Fast check if there is any option set that compile control needs to know about diff --git a/test/hotspot/jtreg/compiler/c2/TestFindNode.java b/test/hotspot/jtreg/compiler/c2/TestFindNode.java index 91a4cdb8d1697..ea7649c713ac7 100644 --- a/test/hotspot/jtreg/compiler/c2/TestFindNode.java +++ b/test/hotspot/jtreg/compiler/c2/TestFindNode.java @@ -27,10 +27,13 @@ * @requires vm.debug == true & vm.flavor == "server" * @summary Test which uses some special flags in order to test Node::find() in debug builds which could result in an endless loop or a stack overflow crash. * - * @run main/othervm -Xbatch -XX:CompileCommand=option,*::*,bool,Vectorize,true -XX:+PrintOpto -XX:+TraceLoopOpts compiler.c2.TestFindNode + * @run main/othervm -Xbatch -XX:CompileCommand=option,*::*,bool,Vectorize,true -XX:CompileCommand=memlimit,compiler.c2.TestFindNode::*,0 + * -XX:+PrintOpto -XX:+TraceLoopOpts compiler.c2.TestFindNode */ package compiler.c2; +// Note; we disable the implicit memory limit of 1G in debug JVMs until JDK-8331283 is fixed + public class TestFindNode { static volatile int[] iArr; static volatile int x; diff --git a/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java b/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java index 87cbd8620d49b..bcb4a21136814 100644 --- a/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java +++ b/test/hotspot/jtreg/compiler/loopopts/TestDeepGraphVerifyIterativeGVN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,11 +28,14 @@ * @summary Test which causes a stack overflow segmentation fault with -XX:VerifyIterativeGVN=1 due to a too deep recursion in Node::verify_recur(). * * @run main/othervm/timeout=600 -Xcomp -XX:VerifyIterativeGVN=1 -XX:CompileCommand=compileonly,compiler.loopopts.TestDeepGraphVerifyIterativeGVN::* + * -XX:CompileCommand=memlimit,compiler.loopopts.TestDeepGraphVerifyIterativeGVN::*,0 * compiler.loopopts.TestDeepGraphVerifyIterativeGVN */ package compiler.loopopts; +// Note; we disable the implicit memory limit of 1G in debug JVMs until JDK-8331295 is fixed + public class TestDeepGraphVerifyIterativeGVN { static volatile int[] iArr; diff --git a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java index c3ac0ae9c81b1..f1565db47d991 100644 --- a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java +++ b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Red Hat, Inc. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +56,7 @@ package compiler.print; +import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -64,8 +66,12 @@ public class CompileCommandMemLimit { + // Method we don't specify; default memlimit should apply final static String METHOD1 = "method1"; + // Method we explicitly limit to 4K limit final static String METHOD2 = "method2"; + // Method for which we explicitly disable a limit on the command line. + final static String METHOD3 = "method3"; static boolean c2; static boolean test_crash; @@ -77,27 +83,22 @@ public static void main(String[] args) throws Exception { default: throw new RuntimeException("invalid argument"); } c2 = Boolean.parseBoolean(args[1]); - test(METHOD1, METHOD2); - test(METHOD2, METHOD1); - } - - private static void test(String include, String exclude) throws Exception { - - // A method that is known to cost compilers a bit of memory to compile List options = new ArrayList(); options.add("-Xcomp"); options.add("-XX:-Inline"); options.add("-Xmx100m"); + options.add("-XX:-CreateCoredumpOnCrash"); options.add("-XX:CompileCommand=compileonly," + getTestClass() + "::*"); - // We pass a very small size to guarantee the crash - options.add("-XX:CompileCommand=MemStat," + getTestMethod(include) + ",print"); - if (test_crash) { - options.add("-XX:CompileCommand=MemLimit," + getTestMethod(include) + ",4k~crash"); - options.add("-XX:-CreateCoredumpOnCrash"); - } else { - options.add("-XX:CompileCommand=MemLimit," + getTestMethod(include) + ",4k"); - } + + // We want a final report + options.add("-XX:CompileCommand=MemStat,*.*,print"); + + // We limit method 2 to a very small limit that is guaranteed to trigger + options.add("-XX:CompileCommand=MemLimit," + getTestMethod(METHOD2) + ",4k" + (test_crash ? "~crash" : "")); + + // We disable any limit set on method 3 + options.add("-XX:CompileCommand=MemLimit," + getTestMethod(METHOD3) + ",0"); if (c2) { options.add("-XX:-TieredCompilation"); @@ -110,20 +111,22 @@ private static void test(String include, String exclude) throws Exception { oa.reportDiagnosticSummary(); - String expectedNameIncl = getTestMethod(include) - .replace('.', '/') - .replace("$", "\\$"); - String expectedNameExcl = getTestMethod(exclude) - .replace('.', '/') - .replace("$", "\\$"); - + String method1regex = testMethodNameForRegex(getTestMethod(METHOD1)); + String method2regex = testMethodNameForRegex(getTestMethod(METHOD2)); + String method3regex = testMethodNameForRegex(getTestMethod(METHOD3)); String ct = c2 ? "c2" : "c1"; if (test_crash) { oa.shouldNotHaveExitValue(0); oa.shouldMatch("# *Internal Error.*"); - oa.shouldMatch("# *fatal error: " + ct + " *" + expectedNameIncl + ".*: Hit MemLimit .*limit: 4096.*"); - oa.shouldNotMatch(".*" + expectedNameExcl + ".*"); + + // method 2 should have hit its tiny limit + oa.shouldMatch("# *fatal error: " + ct + " *" + method2regex + ".*: Hit MemLimit .*limit: 4096.*"); + + // none of the other ones should have hit a limit + oa.shouldNotMatch(method1regex + ".*Hit MemLimit"); + oa.shouldNotMatch(method3regex + ".*Hit MemLimit"); + // Make sure we get a non-zero-sized replay file (JDK-8331314) oa.shouldContain("# Compiler replay data is saved as:"); String replayfile = oa.firstMatch("# (\\S+replay_pid\\d+\\.log)", 1); @@ -137,18 +140,38 @@ private static void test(String include, String exclude) throws Exception { if (f.length() == 0) { throw new RuntimeException("Replayfile " + replayfile + " has size 0"); } - } else { - // Should see trace output when methods are compiled - oa.shouldHaveExitValue(0) - .shouldMatch(".*" + expectedNameIncl + ".*") - .shouldNotMatch(".*" + expectedNameExcl + ".*"); + oa.shouldHaveExitValue(0); + + // In debug builds we have an inbuilt MemLimit. It is very high, so we don't expect it to fire in this test. + // But it will still show up in the final report. + String implicitMemoryLimit = Platform.isDebugBuild() ? "1024M" : "-"; + + // With C2, we print number of nodes, with C1 we don't + String numberNodesRegex = c2 ? "\\d+" : "-"; - // Expect this log line - oa.shouldMatch(".*" + expectedNameIncl + ".*Hit MemLimit.*"); + // method 2 should have hit its tiny limit + oa.shouldMatch(ct + " " + method2regex + ".*: Hit MemLimit \\(limit: 4096 now: \\d+\\)"); - // Expect final output to contain "oom" - oa.shouldMatch(".*oom.*" + expectedNameIncl + ".*"); + // neither of the other ones should have hit a limit + oa.shouldNotMatch(method1regex + ".*Hit MemLimit"); + oa.shouldNotMatch(method3regex + ".*Hit MemLimit"); + + // Final report: + // Method 1 should show up as "ok" and with the default limit, e.g. + // total NA RA result #nodes limit time type #rc thread method + // 32728 0 32728 ok - 1024M 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J) + oa.shouldMatch("\\d+ +\\d+ +\\d+ +ok +" + numberNodesRegex + " +" + implicitMemoryLimit + " +.* +" + method1regex); + + // Method 2 should show up as "oom" and with its tiny limit, e.g. + // total NA RA result #nodes limit time type #rc thread method + // 32728 0 32728 oom - 4096B 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J) + oa.shouldMatch("\\d+ +\\d+ +\\d+ +oom +" + numberNodesRegex + " +4096B +.* +" + method2regex); + + // Method 3 should show up as "ok", and with no limit, even in debug builds, e.g. + // total NA RA result #nodes limit time type #rc thread method + // 32728 0 32728 ok - - 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J) + oa.shouldMatch("\\d+ +\\d+ +\\d+ +ok +" + numberNodesRegex + " +- +.* +" + method3regex); } } @@ -161,16 +184,23 @@ public static String getTestMethod(String method) { return getTestClass() + "::" + method; } + private static String testMethodNameForRegex(String m) { + return m.replace('.', '/') + .replace("$", "\\$"); + } + public static class TestMain { public static void main(String[] args) { method1(); method2(); + method3(); } static long method1() { return System.currentTimeMillis(); } static void method2() {} + static void method3() {} } } diff --git a/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java b/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java index c0a99863fbf24..c2689d883721b 100644 --- a/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java +++ b/test/hotspot/jtreg/compiler/print/CompileCommandPrintMemStat.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Red Hat, Inc. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +32,7 @@ package compiler.print; +import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -68,17 +70,26 @@ private static void test(String include, String exclude) throws Exception { .replace("$", "\\$"); // Should see trace output when methods are compiled - oa.shouldHaveExitValue(0) - .shouldMatch(".*" + expectedNameIncl + ".*") - .shouldNotMatch(".*" + expectedNameExcl + ".*"); + oa.shouldHaveExitValue(0). + shouldMatch("Arena usage.*" + expectedNameIncl + ".*"). + shouldNotMatch("Arena usage.*" + expectedNameExcl + ".*"); + // Should see final report // Looks like this: - // total NA RA result #nodes time type #rc thread method - // 211488 66440 77624 ok 13 0.057 c2 2 0x00007fb49428db70 compiler/print/CompileCommandPrintMemStat$TestMain::method1(()V) - oa.shouldMatch("total.*method"); - oa.shouldMatch("\\d+ +\\d+ +\\d+ +\\S+ +\\d+.*" + expectedNameIncl + ".*"); - oa.shouldNotMatch("\\d+ +\\d+ +\\d+ +\\S+ +\\d+.*" + expectedNameExcl + ".*"); + // total NA RA result #nodes limit time type #rc thread method + // 2149912 0 1986272 ok - - 0.101 c1 1 0x000000015180a600 jdk/internal/org/objectweb/asm/Frame::execute((IILjdk/internal/org/objectweb/asm/Symbol;Ljdk/internal/org/objectweb/asm/SymbolTable;)V) oa.shouldMatch("total.*method"); + // or + // 537784 98184 208536 ok 267 - 0.096 c2 1 0x0000000153019c00 jdk/internal/classfile/impl/BufWriterImpl::writeU1((I)V) 4521912 0 1986272 ok - - 0.101 c1 1 0x000000015180a600 jdk/internal/org/objectweb/asm/Frame::execute((IILjdk/internal/org/objectweb/asm/Symbol;Ljdk/internal/org/objectweb/asm/SymbolTable;)V) oa.shouldMatch("total.*method"); + oa.shouldMatch("\\d+ +\\d+ +\\d+ +ok +(\\d+|-) +.*" + expectedNameIncl + ".*"); + + // In debug builds, we have a default memory limit enabled. That implies MemStat. Therefore we + // expect to see all methods, not just the one we specified on the command line. + if (Platform.isDebugBuild()) { + oa.shouldMatch("\\d+ +\\d+ +\\d+ +ok +(\\d+|-) +.*" + expectedNameExcl + ".*"); + } else { + oa.shouldNotMatch(".*" + expectedNameExcl + ".*"); + } } // Test class that is invoked by the sub process From c8452615b1f3c4e03caf70e2c72928d49cb816a7 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 8 May 2024 17:56:28 +0000 Subject: [PATCH 128/203] 8331924: Parallel: Remove unused MutableSpace::mangle_unused_area_complete Reviewed-by: tschatzl --- src/hotspot/share/gc/parallel/mutableNUMASpace.cpp | 5 +---- src/hotspot/share/gc/parallel/mutableNUMASpace.hpp | 2 +- src/hotspot/share/gc/parallel/mutableSpace.cpp | 4 ---- src/hotspot/share/gc/parallel/mutableSpace.hpp | 2 +- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 2a39ce7b4700d..b4ea195518201 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -79,10 +79,7 @@ void MutableNUMASpace::mangle_unused_area() { // This method should do nothing. // It can be called on a numa space during a full compaction. } -void MutableNUMASpace::mangle_unused_area_complete() { - // This method should do nothing. - // It can be called on a numa space during a full compaction. -} + void MutableNUMASpace::mangle_region(MemRegion mr) { // This method should do nothing because numa spaces are not mangled. } diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp index 18271fabd050d..9a6cf420c0d24 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp @@ -173,7 +173,7 @@ class MutableNUMASpace : public MutableSpace { virtual void clear(bool mangle_space); virtual void mangle_unused_area() PRODUCT_RETURN; - virtual void mangle_unused_area_complete() PRODUCT_RETURN; + virtual void mangle_region(MemRegion mr) PRODUCT_RETURN; virtual void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; virtual void check_mangled_unused_area_complete() PRODUCT_RETURN; diff --git a/src/hotspot/share/gc/parallel/mutableSpace.cpp b/src/hotspot/share/gc/parallel/mutableSpace.cpp index 4641b4ce5c611..7d881f73dbf3e 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp @@ -167,10 +167,6 @@ void MutableSpace::mangle_unused_area() { mangler()->mangle_unused_area(); } -void MutableSpace::mangle_unused_area_complete() { - mangler()->mangle_unused_area_complete(); -} - void MutableSpace::mangle_region(MemRegion mr) { SpaceMangler::mangle_region(mr); } diff --git a/src/hotspot/share/gc/parallel/mutableSpace.hpp b/src/hotspot/share/gc/parallel/mutableSpace.hpp index b77c1d80332e7..1cf0d306dc02e 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.hpp @@ -109,7 +109,7 @@ class MutableSpace: public CHeapObj { // Methods used in mangling. See descriptions under SpaceMangler. virtual void mangle_unused_area() PRODUCT_RETURN; - virtual void mangle_unused_area_complete() PRODUCT_RETURN; + virtual void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; virtual void check_mangled_unused_area_complete() PRODUCT_RETURN; virtual void set_top_for_allocations(HeapWord* v) PRODUCT_RETURN; From 230fac80f25e9608006c8928a8a7708bf13a818c Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 8 May 2024 17:57:46 +0000 Subject: [PATCH 129/203] 8331941: Make CollectedHeap::parallel_object_iterator public Reviewed-by: tschatzl --- src/hotspot/share/gc/shared/collectedHeap.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 0a586e71ac989..b413e3dfb438c 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -92,7 +92,6 @@ class CollectedHeap : public CHeapObj { friend class JVMCIVMStructs; friend class IsSTWGCActiveMark; // Block structured external access to _is_stw_gc_active friend class MemAllocator; - friend class ParallelObjectIterator; private: GCHeapLog* _gc_heap_log; @@ -400,12 +399,10 @@ class CollectedHeap : public CHeapObj { // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl) = 0; - protected: virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num) { return nullptr; } - public: // Keep alive an object that was loaded with AS_NO_KEEPALIVE. virtual void keep_alive(oop obj) {} From 42b1d858d15fd06de9ce41b08b430b12724652e9 Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Wed, 8 May 2024 20:26:02 +0000 Subject: [PATCH 130/203] 8330275: Crash in XMark::follow_array Reviewed-by: stefank, stuefe --- src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp | 8 +++++--- src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp index 6204f21270374..a9c53da3d0186 100644 --- a/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp @@ -142,9 +142,11 @@ // * 63-48 Fixed (16-bits, always zero) // -// Default value if probing is not implemented for a certain platform: 128TB -static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -// Minimum value returned, if probing fails: 64GB +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of XForwardingEntry or Partial array entry (see XMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fails static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; static size_t probe_valid_max_address_bit() { diff --git a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp index 6c3cea73d1a79..e140525bcbc5f 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp @@ -36,9 +36,11 @@ #include #endif // LINUX -// Default value if probing is not implemented for a certain platform: 128TB -static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -// Minimum value returned, if probing fails: 64GB +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of XForwardingEntry or Partial array entry (see XMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fail static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; static size_t probe_valid_max_address_bit() { From 0d1216c7a1dc215550ac769afc21dea91c638215 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 8 May 2024 21:57:44 +0000 Subject: [PATCH 131/203] 8331939: Add custom hook for TestImage Reviewed-by: mikael --- make/TestImage.gmk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/make/TestImage.gmk b/make/TestImage.gmk index b719d6824da30..f6d680fb69073 100644 --- a/make/TestImage.gmk +++ b/make/TestImage.gmk @@ -28,6 +28,9 @@ default: all include $(SPEC) include MakeBase.gmk +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, TestImage-pre.gmk)) + ############################################################################ BUILD_INFO_PROPERTIES := $(TEST_IMAGE_DIR)/build-info.properties From 588e314e4b96f2a48d46ab8a088a7b8d26be318d Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 8 May 2024 21:57:55 +0000 Subject: [PATCH 132/203] 8331886: Allow markdown src file overrides Reviewed-by: ihse --- make/Docs.gmk | 41 +++++++-------- make/common/ProcessMarkdown.gmk | 88 ++++++++++++++++++--------------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/make/Docs.gmk b/make/Docs.gmk index 2977f6f66f9e1..192843de9cdec 100644 --- a/make/Docs.gmk +++ b/make/Docs.gmk @@ -681,28 +681,25 @@ ifeq ($(ENABLE_PANDOC), true) $(TOPDIR)/make/jdk/src/classes/build/tools/pandocfilter) $(foreach m, $(ALL_MODULES), \ - $(eval MAN_$m := $(call FindModuleManDirs, $m)) \ - $(foreach d, $(MAN_$m), \ - $(foreach f, $(call ApplySpecFilter, $(filter %.md, $(call FindFiles, $d))), \ - $(eval $m_$f_NAME := MAN_TO_HTML_$m_$(strip $(call RelativePath, $f, $(TOPDIR)))) \ - $(eval $(call SetupProcessMarkdown, $($m_$f_NAME), \ - SRC := $d, \ - FILES := $f, \ - DEST := $(DOCS_OUTPUTDIR)/specs/man, \ - FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \ - CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ - REPLACEMENTS := \ - @@COPYRIGHT_YEAR@@ => $(COPYRIGHT_YEAR) ; \ - @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \ - @@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \ - OPTIONS := --toc -V include-before='$(SPECS_TOP)' -V include-after='$(SPECS_BOTTOM_1)', \ - POST_PROCESS := $(TOOL_FIXUPPANDOC) --insert-nav --nav-right-info '$(HEADER_RIGHT_SIDE_INFO)' \ - --nav-subdirs 1 --nav-link-guides, \ - EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ - $(PANDOC_HTML_MANPAGE_FILTER_SOURCE), \ - )) \ - $(eval JDK_SPECS_TARGETS += $($($m_$f_NAME))) \ - ) \ + $(eval MAN_$m := $(call ApplySpecFilter, $(filter %.md, $(call FindFiles, \ + $(call FindModuleManDirs, $m))))) \ + $(if $(MAN_$m), \ + $(eval $(call SetupProcessMarkdown, MAN_TO_HTML_$m, \ + FILES := $(MAN_$m), \ + DEST := $(DOCS_OUTPUTDIR)/specs/man, \ + FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \ + CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ + REPLACEMENTS := \ + @@COPYRIGHT_YEAR@@ => $(COPYRIGHT_YEAR) ; \ + @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \ + @@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \ + OPTIONS := --toc -V include-before='$(SPECS_TOP)' -V include-after='$(SPECS_BOTTOM_1)', \ + POST_PROCESS := $(TOOL_FIXUPPANDOC) --insert-nav --nav-right-info '$(HEADER_RIGHT_SIDE_INFO)' \ + --nav-subdirs 1 --nav-link-guides, \ + EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ + $(PANDOC_HTML_MANPAGE_FILTER_SOURCE), \ + )) \ + $(eval JDK_SPECS_TARGETS += $(MAN_TO_HTML_$m)) \ ) \ ) diff --git a/make/common/ProcessMarkdown.gmk b/make/common/ProcessMarkdown.gmk index e78c026a89c37..125892504f91a 100644 --- a/make/common/ProcessMarkdown.gmk +++ b/make/common/ProcessMarkdown.gmk @@ -38,48 +38,53 @@ define ProcessMarkdown $1_$2_INPUT_FILE := $3/$2 $1_$2_MARKER := $$(subst /,_,$1_$2) - ifneq ($$($1_REPLACEMENTS), ) - $1_$2_PANDOC_INPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_pre.tmp - - $$(eval $$(call SetupTextFileProcessing, $1_$2_PREPROCESSED, \ - SOURCE_FILES := $$($1_$2_INPUT_FILE), \ - OUTPUT_FILE := $$($1_$2_PANDOC_INPUT), \ - REPLACEMENTS := $$($1_REPLACEMENTS), \ - )) - else - $1_$2_PANDOC_INPUT := $$($1_$2_INPUT_FILE) - endif - - ifneq ($$($1_POST_PROCESS), ) - $1_$2_PANDOC_OUTPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post.tmp - else - $1_$2_PANDOC_OUTPUT := $$($1_$2_OUTPUT_FILE) - endif + # Only continue if this target file hasn't been processed already. This lets + # the first found source file override any other with the same name. + ifeq ($$($1_$2_OUTPUT_FILE_PROCESSED), ) + $1_$2_OUTPUT_FILE_PROCESSED := true + + ifneq ($$($1_REPLACEMENTS), ) + $1_$2_PANDOC_INPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_pre.tmp + + $$(eval $$(call SetupTextFileProcessing, $1_$2_PREPROCESSED, \ + SOURCE_FILES := $$($1_$2_INPUT_FILE), \ + OUTPUT_FILE := $$($1_$2_PANDOC_INPUT), \ + REPLACEMENTS := $$($1_REPLACEMENTS), \ + )) + else + $1_$2_PANDOC_INPUT := $$($1_$2_INPUT_FILE) + endif - ifneq ($$($1_CSS), ) - ifneq ($$(findstring https:/, $$($1_CSS)), ) - $1_$2_CSS_OPTION := --css '$$($1_CSS)' + ifneq ($$($1_POST_PROCESS), ) + $1_$2_PANDOC_OUTPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post.tmp else - $1_$2_CSS := $$(strip $$(call RelativePath, $$($1_CSS), $$($1_$2_TARGET_DIR))) - $1_$2_CSS_OPTION := --css '$$($1_$2_CSS)' + $1_$2_PANDOC_OUTPUT := $$($1_$2_OUTPUT_FILE) endif - endif - # This does not need to be included in VARDEPS since it's from the actual - # source file. Only run the shell if the recipe gets executed below. - $1_$2_OPTIONS_FROM_SRC = \ - $$(shell $$(GREP) _pandoc-options_: $3/$2 | $$(CUT) -d : -f 2-) + ifneq ($$($1_CSS), ) + ifneq ($$(findstring https:/, $$($1_CSS)), ) + $1_$2_CSS_OPTION := --css '$$($1_CSS)' + else + $1_$2_CSS := $$(strip $$(call RelativePath, $$($1_CSS), $$($1_$2_TARGET_DIR))) + $1_$2_CSS_OPTION := --css '$$($1_$2_CSS)' + endif + endif - ifneq ($$($1_FILTER), ) - $1_$2_OPTIONS := --filter $$($1_FILTER) - endif + # This does not need to be included in VARDEPS since it's from the actual + # source file. Only run the shell if the recipe gets executed below. + $1_$2_OPTIONS_FROM_SRC = \ + $$(shell $$(GREP) _pandoc-options_: $3/$2 | $$(CUT) -d : -f 2-) + + ifneq ($$($1_FILTER), ) + $1_$2_OPTIONS := --filter $$($1_FILTER) + endif - $1_$2_VARDEPS := $$($1_OPTIONS) $$($1_$2_OPTIONS) $$($1_CSS) \ - $$($1_REPLACEMENTS) $$($1_POST_PROCESS) - $1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, \ - $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER).vardeps) + $1_$2_VARDEPS := $$($1_OPTIONS) $$($1_$2_OPTIONS) $$($1_CSS) \ + $$($1_REPLACEMENTS) $$($1_POST_PROCESS) + $1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, \ + $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER).vardeps) - $$($1_$2_PANDOC_OUTPUT): $$($1_$2_PANDOC_INPUT) $$($1_$2_VARDEPS_FILE) $$($1_EXTRA_DEPS) + $$($1_$2_PANDOC_OUTPUT): $$($1_$2_PANDOC_INPUT) $$($1_$2_VARDEPS_FILE) $$($1_EXTRA_DEPS) $$(call LogInfo, Converting $2 to $$($1_FORMAT)) $$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT))) $$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \ @@ -96,17 +101,18 @@ define ProcessMarkdown fi endif - # If we have no post processing, PANDOC_OUTPUT is set to OUTPUT_FILE. Otherwise - # PANDOC_OUTPUT is a temporary file, and we must now create the real OUTPUT_FILE. - ifneq ($$($1_POST_PROCESS), ) - $$($1_$2_OUTPUT_FILE): $$($1_$2_PANDOC_OUTPUT) + # If we have no post processing, PANDOC_OUTPUT is set to OUTPUT_FILE. Otherwise + # PANDOC_OUTPUT is a temporary file, and we must now create the real OUTPUT_FILE. + ifneq ($$($1_POST_PROCESS), ) + $$($1_$2_OUTPUT_FILE): $$($1_$2_PANDOC_OUTPUT) $$(call LogInfo, Post-processing markdown file $2) $$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$($1_$2_TARGET_DIR)) $$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post, \ ( $$($1_POST_PROCESS) $$($1_$2_PANDOC_OUTPUT) > $$($1_$2_OUTPUT_FILE) ) ) - endif + endif - $1 += $$($1_$2_OUTPUT_FILE) + $1 += $$($1_$2_OUTPUT_FILE) + endif endef ################################################################################ From 2d622152b07bba0aba8fd5b1e24293e28d6e69f5 Mon Sep 17 00:00:00 2001 From: Vladimir Petko Date: Wed, 8 May 2024 22:36:25 +0000 Subject: [PATCH 133/203] 8331541: [i386] linking with libjvm.so fails after JDK-8283326 Reviewed-by: djelinski, ihse --- make/autoconf/flags-ldflags.m4 | 1 - src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index acb815515a24d..c4a75fb89c39d 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -118,7 +118,6 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], # Setup LDFLAGS for linking executables if test "x$TOOLCHAIN_TYPE" = xgcc; then - EXECUTABLE_LDFLAGS="$EXECUTABLE_LDFLAGS -Wl,--allow-shlib-undefined" # Enabling pie on 32 bit builds prevents the JVM from allocating a continuous # java heap. if test "x$OPENJDK_TARGET_CPU_BITS" != "x32"; then diff --git a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S index 54775cb7e8ede..a0f8577d8d199 100644 --- a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S +++ b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S @@ -36,7 +36,7 @@ # 8(%esp) : default value # 4(%esp) : crash address # 0(%esp) : return pc - .type _SafeFetch32_impl,@function + .type SafeFetch32_impl,@function SafeFetch32_impl: movl 4(%esp),%ecx # load address from stack _SafeFetch32_fault: From 964d60892eec5e64942b49182a4c6d4105620acd Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Thu, 9 May 2024 07:05:18 +0000 Subject: [PATCH 134/203] 8322753: RISC-V: C2 ReverseBytesV Reviewed-by: fyang --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 5 ++-- src/hotspot/cpu/riscv/riscv_v.ad | 29 ++++++++++++++++++- .../vectorapi/VectorReverseBytesTest.java | 3 +- .../vectorization/TestReverseBytes.java | 3 +- .../vectorization/runner/BasicCharOpTest.java | 3 ++ .../runner/BasicShortOpTest.java | 3 ++ 6 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 0fe91d99066fa..614e4ee3d1805 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1887,8 +1887,9 @@ enum Nf { } // Vector Bit-manipulation used in Cryptography (Zvkb) Extension - INSN(vbrev8_v, 0b1010111, 0b010, 0b01000, 0b010010); - INSN(vrev8_v, 0b1010111, 0b010, 0b01001, 0b010010); + INSN(vbrev_v, 0b1010111, 0b010, 0b01010, 0b010010); // reverse bits in every element + INSN(vbrev8_v, 0b1010111, 0b010, 0b01000, 0b010010); // reverse bits in every byte of element + INSN(vrev8_v, 0b1010111, 0b010, 0b01001, 0b010010); // reverse bytes in every elememt #undef INSN diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 0879f62600e40..863d37723795d 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -73,6 +73,7 @@ source %{ return false; } break; + case Op_ReverseBytesV: case Op_PopCountVL: case Op_PopCountVI: return UseZvbb; @@ -3756,6 +3757,32 @@ instruct vsignum_reg(vReg dst, vReg zero, vReg one, vRegMask_V0 v0) %{ ins_pipe(pipe_slow); %} +// -------------------------------- Reverse Bytes Vector Operations ------------------------ + +instruct vreverse_bytes_masked(vReg dst, vReg src, vRegMask_V0 v0) %{ + match(Set dst (ReverseBytesV src v0)); + format %{ "vreverse_bytes_masked $dst, $src, v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vrev8_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vreverse_bytes(vReg dst, vReg src) %{ + match(Set dst (ReverseBytesV src)); + format %{ "vreverse_bytes $dst, $src" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vrev8_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + // ---------------- Convert Half Floating to Floating Vector Operations ---------------- // half precision -> single @@ -3790,7 +3817,7 @@ instruct vconvF2HF(vReg dst, vReg src, vReg vtmp, vRegMask_V0 v0, iRegINoSp tmp) // ------------------------------ Popcount vector ------------------------------ -instruct vpopcount_mask(vReg dst, vReg src, vRegMask_V0 v0) %{ +instruct vpopcount_masked(vReg dst, vReg src, vRegMask_V0 v0) %{ match(Set dst (PopCountVI src v0)); match(Set dst (PopCountVL src v0)); ins_cost(VEC_COST); diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java index 154567922bd03..bfb95c0651c38 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java @@ -42,7 +42,8 @@ * @library /test/lib / * @summary [vectorapi] REVERSE_BYTES for byte type should not emit any instructions * @requires vm.compiler2.enabled - * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.arch == "aarch64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.arch == "aarch64" | + * (os.arch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") * @modules jdk.incubator.vector * * @run driver compiler.vectorapi.VectorReverseBytesTest diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java index 47813e2790e8e..71c9114121c14 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java @@ -25,7 +25,8 @@ * @bug 8288112 * @summary Auto-vectorization of ReverseBytes operations. * @requires vm.compiler2.enabled - * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.simpleArch == "AArch64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.simpleArch == "AArch64" | + * (os.simpleArch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") * @library /test/lib / * @run driver compiler.vectorization.TestReverseBytes */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java index d851af1ff59e2..6131e58d15624 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java @@ -227,6 +227,9 @@ public char[] vectorUnsignedShiftRight() { @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true"}, counts = {IRNode.REVERSE_BYTES_VS, ">0"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"zvbb", "true"}, + counts = {IRNode.REVERSE_BYTES_VS, ">0"}) public char[] reverseBytesWithChar() { char[] res = new char[SIZE]; for (int i = 0; i < SIZE; i++) { diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java index c9a06c113605a..363daf3a115ff 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java @@ -250,6 +250,9 @@ public short[] vectorUnsignedShiftRight() { @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true"}, counts = {IRNode.REVERSE_BYTES_VS, ">0"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"zvbb", "true"}, + counts = {IRNode.REVERSE_BYTES_VS, ">0"}) public short[] reverseBytesWithShort() { short[] res = new short[SIZE]; for (int i = 0; i < SIZE; i++) { From ac86f59e4f5382d5c3e8984532dd210611db7dcb Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 9 May 2024 07:43:03 +0000 Subject: [PATCH 135/203] 8330532: Improve line-oriented text parsing in HotSpot Co-authored-by: John R Rose Reviewed-by: matsaave, jsjolen --- src/hotspot/share/cds/classListParser.cpp | 129 +++--- src/hotspot/share/cds/classListParser.hpp | 22 +- src/hotspot/share/compiler/compilerOracle.cpp | 57 +-- src/hotspot/share/compiler/compilerOracle.hpp | 11 +- src/hotspot/share/utilities/istream.cpp | 368 +++++++++++++++++ src/hotspot/share/utilities/istream.hpp | 386 ++++++++++++++++++ src/hotspot/share/utilities/ostream.cpp | 19 +- src/hotspot/share/utilities/ostream.hpp | 19 +- test/hotspot/gtest/utilities/test_istream.cpp | 322 +++++++++++++++ .../runtime/cds/appcds/LongClassListPath.java | 3 +- .../appcds/customLoader/ClassListFormatA.java | 87 +++- 11 files changed, 1266 insertions(+), 157 deletions(-) create mode 100644 src/hotspot/share/utilities/istream.cpp create mode 100644 src/hotspot/share/utilities/istream.hpp create mode 100644 test/hotspot/gtest/utilities/test_istream.cpp diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index b17da725deb3f..4e49cd3d881c8 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,30 +50,24 @@ #include "runtime/javaCalls.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" +#include "utilities/utf8.hpp" volatile Thread* ClassListParser::_parsing_thread = nullptr; ClassListParser* ClassListParser::_instance = nullptr; -ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) { +ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : + _classlist_file(file), + _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE), + _file_input(do_open(file), /* need_close=*/true), + _input_stream(&_file_input) { log_info(cds)("Parsing %s%s", file, (parse_mode == _parse_lambda_forms_invokers_only) ? " (lambda form invokers only)" : ""); - _classlist_file = file; - _file = nullptr; - // Use os::open() because neither fopen() nor os::fopen() - // can handle long path name on Windows. - int fd = os::open(file, O_RDONLY, S_IREAD); - if (fd != -1) { - // Obtain a File* from the file descriptor so that fgets() - // can be used in parse_one_line() - _file = os::fdopen(fd, "r"); - } - if (_file == nullptr) { + if (!_file_input.is_open()) { char errmsg[JVM_MAXPATHLEN]; os::lasterror(errmsg, JVM_MAXPATHLEN); vm_exit_during_initialization("Loading classlist failed", errmsg); } - _line_no = 0; - _token = _line; + _token = _line = nullptr; _interfaces = new (mtClass) GrowableArray(10, mtClass); _indy_items = new (mtClass) GrowableArray(9, mtClass); _parse_mode = parse_mode; @@ -84,14 +78,24 @@ ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : _id2k Atomic::store(&_parsing_thread, Thread::current()); } +FILE* ClassListParser::do_open(const char* file) { + // Use os::open() because neither fopen() nor os::fopen() + // can handle long path name on Windows. (See JDK-8216184) + int fd = os::open(file, O_RDONLY, S_IREAD); + FILE* fp = nullptr; + if (fd != -1) { + // Obtain a FILE* from the file descriptor so that _input_stream + // can be used in ClassListParser::parse() + fp = os::fdopen(fd, "r"); + } + return fp; +} + bool ClassListParser::is_parsing_thread() { return Atomic::load(&_parsing_thread) == Thread::current(); } ClassListParser::~ClassListParser() { - if (_file != nullptr) { - fclose(_file); - } Atomic::store(&_parsing_thread, (Thread*)nullptr); delete _indy_items; delete _interfaces; @@ -101,7 +105,15 @@ ClassListParser::~ClassListParser() { int ClassListParser::parse(TRAPS) { int class_count = 0; - while (parse_one_line()) { + for (; !_input_stream.done(); _input_stream.next()) { + _line = _input_stream.current_line(); + if (*_line == '#') { // comment + continue; + } + if (!parse_one_line()) { + break; + } + if (lambda_form_line()) { // The current line is "@lambda-form-invoker ...". It has been recorded in LambdaFormInvokers, // and will be processed later. @@ -112,6 +124,7 @@ int ClassListParser::parse(TRAPS) { continue; } + check_class_name(_class_name); TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name); if (_indy_items->length() > 0) { // The current line is "@lambda-proxy class_name". Load the proxy class. @@ -165,43 +178,26 @@ int ClassListParser::parse(TRAPS) { } bool ClassListParser::parse_one_line() { - for (;;) { - if (fgets(_line, sizeof(_line), _file) == nullptr) { - return false; - } - ++ _line_no; - _line_len = (int)strlen(_line); - if (_line_len > _max_allowed_line_len) { - error("input line too long (must be no longer than %d chars)", _max_allowed_line_len); - } - if (*_line == '#') { // comment - continue; - } - - { - int len = (int)strlen(_line); - int i; - // Replace \t\r\n\f with ' ' - for (i=0; i 0) { - if (_line[len-1] == ' ') { - _line[len-1] = '\0'; - len --; - } else { - break; - } + // Remove trailing newline/space + while (len > 0) { + if (_line[len-1] == ' ') { + _line[len-1] = '\0'; + len --; + } else { + break; } - _line_len = len; } - - // valid line - break; + _line_len = len; } _class_name = _line; @@ -286,7 +282,7 @@ int ClassListParser::split_at_tag_from_line() { _token = _line; char* ptr; if ((ptr = strchr(_line, ' ')) == nullptr) { - error("Too few items following the @ tag \"%s\" line #%d", _line, _line_no); + error("Too few items following the @ tag \"%s\" line #%zu", _line, lineno()); return 0; } *ptr++ = '\0'; @@ -304,7 +300,7 @@ bool ClassListParser::parse_at_tags() { if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) { split_tokens_by_whitespace(offset); if (_indy_items->length() < 2) { - error("Line with @ tag has too few items \"%s\" line #%d", _token, _line_no); + error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno()); return false; } // set the class name @@ -315,7 +311,7 @@ bool ClassListParser::parse_at_tags() { _lambda_form_line = true; return true; } else { - error("Invalid @ tag at the beginning of line \"%s\" line #%d", _token, _line_no); + error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno()); return false; } } @@ -423,8 +419,8 @@ void ClassListParser::error(const char* msg, ...) { } jio_fprintf(defaultStream::error_stream(), - "An error has occurred while processing class list file %s %d:%d.\n", - _classlist_file, _line_no, (error_index + 1)); + "An error has occurred while processing class list file %s %zu:%d.\n", + _classlist_file, lineno(), (error_index + 1)); jio_vfprintf(defaultStream::error_stream(), msg, ap); if (_line_len <= 0) { @@ -450,6 +446,25 @@ void ClassListParser::error(const char* msg, ...) { va_end(ap); } +void ClassListParser::check_class_name(const char* class_name) { + const char* err = nullptr; + size_t len = strlen(class_name); + if (len > (size_t)Symbol::max_length()) { + err = "class name too long"; + } else { + assert(Symbol::max_length() < INT_MAX && len < INT_MAX, "must be"); + if (!UTF8::is_legal_utf8((const unsigned char*)class_name, (int)len, /*version_leq_47*/false)) { + err = "class name is not valid UTF8"; + } + } + if (err != nullptr) { + jio_fprintf(defaultStream::error_stream(), + "An error has occurred while processing class list file %s:%zu %s\n", + _classlist_file, lineno(), err); + vm_exit_during_initialization("class list format error.", nullptr); + } +} + // This function is used for loading classes for customized class loaders // during archive dumping. InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) { diff --git a/src/hotspot/share/cds/classListParser.hpp b/src/hotspot/share/cds/classListParser.hpp index 74a2ff10515f8..a383e04d8e6fe 100644 --- a/src/hotspot/share/cds/classListParser.hpp +++ b/src/hotspot/share/cds/classListParser.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "utilities/exceptions.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" +#include "utilities/istream.hpp" #include "utilities/resizeableResourceHash.hpp" #define LAMBDA_PROXY_TAG "@lambda-proxy" @@ -80,14 +81,6 @@ class ClassListParser : public StackObj { enum { _unspecified = -999, - - // Max number of bytes allowed per line in the classlist. - // Theoretically Java class names could be 65535 bytes in length. Also, an input line - // could have a very long path name up to JVM_MAXPATHLEN bytes in length. In reality, - // 4K bytes is more than enough. - _max_allowed_line_len = 4096, - _line_buf_extra = 10, // for detecting input too long - _line_buf_size = _max_allowed_line_len + _line_buf_extra }; // Use a small initial size in debug build to test resizing logic @@ -96,16 +89,14 @@ class ClassListParser : public StackObj { static volatile Thread* _parsing_thread; // the thread that created _instance static ClassListParser* _instance; // the singleton. const char* _classlist_file; - FILE* _file; ID2KlassTable _id2klass_table; - // The following field contains information from the *current* line being - // parsed. - char _line[_line_buf_size]; // The buffer that holds the current line. Some characters in + FileInput _file_input; + inputStream _input_stream; + char* _line; // The buffer that holds the current line. Some characters in // the buffer may be overwritten by '\0' during parsing. int _line_len; // Original length of the input line. - int _line_no; // Line number for current line being parsed const char* _class_name; GrowableArray* _indy_items; // items related to invoke dynamic for archiving lambda proxy classes int _id; @@ -132,6 +123,8 @@ class ClassListParser : public StackObj { bool parse_one_line(); Klass* load_current_class(Symbol* class_name_symbol, TRAPS); + size_t lineno() { return _input_stream.lineno(); } + FILE* do_open(const char* file); ClassListParser(const char* file, ParseMode _parse_mode); ~ClassListParser(); @@ -183,6 +176,7 @@ class ClassListParser : public StackObj { error("%s id %d is not yet loaded", which, id); } } + void check_class_name(const char* class_name); const char* current_class_name() { return _class_name; diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 87d879feac0c7..a81d60c9fc422 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -40,6 +40,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.hpp" #include "runtime/os.hpp" +#include "utilities/istream.hpp" #include "utilities/parseInteger.hpp" // Default compile commands, if defined, are parsed before any of the @@ -1081,55 +1082,29 @@ bool CompilerOracle::parse_from_file() { return true; } - char token[1024]; - int pos = 0; - int c = getc(stream); - bool success = true; - while(c != EOF && pos < (int)(sizeof(token)-1)) { - if (c == '\n') { - token[pos++] = '\0'; - if (!parse_from_line(token)) { - success = false; - } - pos = 0; - } else { - token[pos++] = c; - } - c = getc(stream); - } - token[pos++] = '\0'; - if (!parse_from_line(token)) { - success = false; - } - fclose(stream); - return success; + FileInput input(stream, /*need_close=*/ true); + return parse_from_input(&input, parse_from_line); } -bool CompilerOracle::parse_from_string(const char* str, bool (*parse_line)(char*)) { - char token[1024]; - int pos = 0; - const char* sp = str; - int c = *sp++; +bool CompilerOracle::parse_from_input(inputStream::Input* input, + CompilerOracle:: + parse_from_line_fn_t* parse_from_line) { bool success = true; - while (c != '\0' && pos < (int)(sizeof(token)-1)) { - if (c == '\n') { - token[pos++] = '\0'; - if (!parse_line(token)) { - success = false; - } - pos = 0; - } else { - token[pos++] = c; + for (inputStream in(input); !in.done(); in.next()) { + if (!parse_from_line(in.current_line())) { + success = false; } - c = *sp++; - } - token[pos++] = '\0'; - if (!parse_line(token)) { - success = false; } return success; } +bool CompilerOracle::parse_from_string(const char* str, + CompilerOracle:: + parse_from_line_fn_t* parse_from_line) { + MemoryInput input(str, strlen(str)); + return parse_from_input(&input, parse_from_line); +} + bool compilerOracle_init() { bool success = true; // Register default compile commands first - any commands specified via CompileCommand will diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index f330b3b607599..1a85e0629f93e 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -27,6 +27,7 @@ #include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" +#include "utilities/istream.hpp" class methodHandle; @@ -120,11 +121,18 @@ enum class MemStatAction { }; class CompilerOracle : AllStatic { + public: + typedef bool parse_from_line_fn_t(char*); + private: static bool _quiet; static void print_parse_error(char* error_msg, char* original_line); static void print_command(CompileCommandEnum option, const char* name, enum OptionType type); + // The core parser. + static bool parse_from_input(inputStream::Input* input, + parse_from_line_fn_t* parse_from_line); + public: // True if the command file has been specified or is implicit static bool has_command_file(); @@ -177,7 +185,8 @@ class CompilerOracle : AllStatic { static bool option_matches_type(CompileCommandEnum option, T& value); // Reads from string instead of file - static bool parse_from_string(const char* option_string, bool (*parser)(char*)); + static bool parse_from_string(const char* option_string, + parse_from_line_fn_t* parser); static bool parse_from_line(char* line); static bool parse_from_line_quietly(char* line); static bool parse_compile_only(char* line); diff --git a/src/hotspot/share/utilities/istream.cpp b/src/hotspot/share/utilities/istream.cpp new file mode 100644 index 0000000000000..cb082128c62ca --- /dev/null +++ b/src/hotspot/share/utilities/istream.cpp @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "memory/allocation.inline.hpp" +#include "runtime/orderAccess.hpp" +#include "utilities/istream.hpp" +#include "utilities/ostream.hpp" +#include "utilities/xmlstream.hpp" + +#ifndef ASSERT +#define COV(casen) {} +#else //ASSERT +// Support for coverage testing. Used by the gtest. +/* $ sed < istream.cpp '/^.* COV(\([A-Z][^)]*\)).*$/!d;s//COV_FN(\1)/' | + tr '\12' ' ' | fold -sw72 | sed 's| $||;s|.*| & \\|' + */ +#define DO_COV_CASES(COV_FN) \ + COV_FN(NXT_L) COV_FN(NXT_N) COV_FN(FIB_P) COV_FN(FIB_E) COV_FN(FIB_N) \ + COV_FN(FIB_L) COV_FN(PFB_C) COV_FN(PFB_P) COV_FN(PFB_A) \ + COV_FN(PFB_G) COV_FN(PFB_H) COV_FN(SBC_C) COV_FN(SBC_B) COV_FN(SBC_N) \ + COV_FN(SBC_L) COV_FN(EXB_R) COV_FN(EXB_A) + /**/ +#define COV_COUNT(casename) coverage_case_##casename +#define DECLARE_COV_CASE(casename) static int COV_COUNT(casename); +DO_COV_CASES(DECLARE_COV_CASE) +#undef DECLARE_COV_CASE + +static int current_coverage_mode = 0; +#define COV(casename) { \ + if (current_coverage_mode != 0) { \ + COV_COUNT(casename)++; \ + } } +#endif //ASSERT + +bool inputStream::next() { + // We have to look at the current line first, just in case nobody + // actually called current_line() or done(). + preload(); + if (definitely_done()) { + return false; // OK to call this->next() after done is true + } + // current line is at buffer[beg..end]; now skip past its '\0' + assert(have_current_line(), ""); + + set_buffer_content(_next, _content_end); + if (!need_to_read()) { // any next line was already in the buffer + COV(NXT_L); + assert(have_current_line(), ""); + return true; + } else { // go back to the source for more + COV(NXT_N); + return fill_buffer(); + } +} + +void inputStream::set_done() { + size_t end = _beg = _end = _content_end; + _next = end + NEXT_PHANTOM; + _line_ending = 0; + assert(definitely_done(), ""); +} + +void inputStream::set_error(bool error_condition) { + if (error_condition) { + set_done(); + _input_state = IState::ERR_STATE; + assert(error(), ""); + } else if (error()) { + _input_state = definitely_done() ? IState::EOF_STATE : IState::NTR_STATE; + } +} + +void inputStream::clear_buffer() { + _content_end = _beg = _end = _next = 0; + _line_ending = 0; +} + +const char* inputStream::next_content(size_t& next_content_length) const { + assert(is_sane(), ""); + size_t len = buffered_content_length(false); + next_content_length = len; + return len == 0 ? "" : &_buffer[_next]; +} + +void inputStream::set_input(inputStream::Input* input) { + clear_buffer(); + _input = input; + _input_state = IState::NTR_STATE; +} + +bool inputStream::fill_buffer() { + size_t fill_offset, fill_length; + assert(!definitely_done(), ""); // caller responsibility + while (need_to_read()) { + prepare_to_fill_buffer(fill_offset, fill_length); + if (error()) return false; + assert(fill_length > 0, ""); + assert(fill_offset < _buffer_size, ""); + assert(fill_offset + fill_length <= _buffer_size, ""); + size_t nr = 0; + if (_input != nullptr && _input_state == IState::NTR_STATE) { + nr = _input->read(&_buffer[fill_offset], fill_length); + if (nr == 0) _input_state = IState::EOF_STATE; // do not get EOF twice + } + bool last_partial = false; + if (nr > 0) { + fill_offset += nr; + } else if (_beg == _end) { // no partial line, so end it now + // we hit the end of the file (or there was never anything there) + COV(FIB_P); + assert(!definitely_done(), ""); + set_done(); + assert(definitely_done(), ""); + return false; + } else { + // pretend to read a newline, to complete the last partial line + COV(FIB_E); + _buffer[fill_offset++] = '\n'; // insert phantom newline + last_partial = true; + } + set_buffer_content(_beg, fill_offset); + assert(!definitely_done(), ""); + if (need_to_read()) { COV(FIB_N); } + else { COV(FIB_L); } + if (last_partial) { + assert(have_current_line(), ""); + _line_ending = 0; + _content_end -= 1; // reverse insertion of phantom newline + assert(_next == _content_end + NEXT_PHANTOM, ""); + assert(have_current_line(), ""); + } + } + return true; +} + +// Find some space in the buffer for reading. If there is already a +// partial line in the buffer, new space must follow it immediately. +// The partial line is between _beg and _end, and no other parts of +// the buffer are in use. +void inputStream::prepare_to_fill_buffer(size_t& fill_offset, + size_t& fill_length) { + assert(need_to_read(), ""); // _next pointer out of the way + size_t end = _content_end; + if (_beg == end) { // if no partial line present... + COV(PFB_C); + clear_buffer(); + fill_offset = 0; + fill_length = _buffer_size; + return; // use the whole buffer + } + // at this point we have a pending line that needs more input + if (_beg > 0 && (_input != nullptr || end == _buffer_size)) { + COV(PFB_P); + // compact the buffer by overwriting characters from previous lines + size_t shift_left = _beg; + ::memmove(_buffer, _buffer + shift_left, _content_end - _beg); + _beg -= shift_left; + _end -= shift_left; + _next -= shift_left; + _content_end -= shift_left; + end = _content_end; + } + if (end < _buffer_size) { + COV(PFB_A); + fill_offset = end; + fill_length = _buffer_size - end; + return; // use the whole buffer except partial line at the beginning + } + // the whole buffer contains a partial line, which means we must expand + COV(PFB_G); + size_t new_size = (_buffer_size < BIG_SIZE ? BIG_SIZE + : _buffer_size + _buffer_size / 2); + assert(new_size > _buffer_size, ""); + if (expand_buffer(new_size)) { + COV(PFB_H); + fill_offset = end; + fill_length = _buffer_size - end; + return; // use the expanded buffer, except the partial line + } + // no recovery from failed allocation; just set the error state and bail + set_error(); +} + +// The only buffer content is between the given offsets. +// Set _beg, _end, _next, and _content_end appropriately. +void inputStream::set_buffer_content(size_t content_start, + size_t content_end) { + assert(content_end <= _buffer_size, ""); + assert(content_start <= content_end + NEXT_PHANTOM, ""); + if (content_start >= content_end) { // empty content; clear buffer + COV(SBC_C); + clear_buffer(); + return; + } + COV(SBC_B); + size_t content_len = content_end - content_start; + _beg = content_start; + _content_end = content_end; + + // this is where we scan for newlines + char* nl = (char*) memchr(&_buffer[content_start], '\n', content_len); + if (nl == nullptr) { + COV(SBC_N); + _next = _end = content_end; + _line_ending = 0; + assert(need_to_read(), ""); + } else { + COV(SBC_L); + *nl = '\0'; // so that this->current_line() will work + ++_line_count; + size_t end = nl - &_buffer[0]; + _next = end + 1; + assert(_next != _content_end + NEXT_PHANTOM, ""); + if (end > content_start && nl[-1] == '\r') { // yuck + // again, for this->current_line(), remove '\r' before '\n' + nl[-1] = '\0'; + --end; + // Note: we could treat '\r' alone as a line ending on some + // platforms, but that is way too much work. Newline '\n' is + // supported everywhere, and some tools insist on accompanying + // it with return as well, so we remove that. But return '\r' + // by itself is an obsolete format, and also inconsistent with + // outputStream, which standarizes on '\n' and never emits '\r'. + // Postel's law suggests that we write '\n' only and grudgingly + // accept '\r' before '\n'. + } + _end = end; // now this->current_line() points to buf[beg..end] + _line_ending = (int)(_next - end); + assert(have_current_line(), ""); + assert(current_line() == &_buffer[_beg], ""); + assert(current_line_length() == _end - _beg, ""); + } +} + +// Return true iff we expanded the buffer to the given length. +bool inputStream::expand_buffer(size_t new_length) { + assert(new_length > _buffer_size, ""); + char* new_buf = nullptr; + assert(new_length > sizeof(_small_buffer), ""); + if (_buffer == &_small_buffer[0]) { + // fresh alloc from c-heap + COV(EXB_A); + new_buf = NEW_C_HEAP_ARRAY(char, new_length, mtInternal); + assert(new_buf != nullptr, "would have exited VM if OOM"); + if (_content_end > 0) { + assert(_content_end <= _buffer_size, ""); + ::memcpy(new_buf, _buffer, _content_end); // copy only the active content + } + } else { + // realloc + COV(EXB_R); + new_buf = REALLOC_C_HEAP_ARRAY(char, _buffer, new_length, mtInternal); + assert(new_buf != nullptr, "would have exited VM if OOM"); + } + + if (new_buf == nullptr) { + return false; // do not further update _buffer etc. + } + _buffer = new_buf; + _buffer_size = new_length; + return true; +} + +inputStream::~inputStream() { + if (has_c_heap_buffer()) { + FreeHeap(_buffer); + DEBUG_ONLY(_buffer = (char*)((uintptr_t)0xdeadbeef)); // sanity + } +} + +#ifdef ASSERT +void inputStream::dump(const char* what) { + int diff = (int)(_end - _beg); + if (!_buffer || _beg > _buffer_size || _end > _buffer_size) + diff = 0; + + bool ntr = (_next == _end), + hcl = (_beg < _content_end && _end < _next), + ddn = (_beg == _content_end && _next > _content_end); + tty->print_cr("%s%sistream %s%s%s%s%s [%d<%.*s>%d/%d..%d] LE=%d," + " B=%llx%s[%d], LN=%d, CH=%d", + what ? what : "", what ? ": " : "", + _buffer == nullptr ? "U" : "", + ntr ? "R" : "", + hcl ? "L" : "", + ddn ? "D" : "", + (_next < _content_end ? "" : + _next == _content_end ? "N" : "P"), + (int)_beg, + diff < 0 ? 0 : diff > 10 ? 10 : diff, + _buffer ? &_buffer[_beg] : "", + (int)_end, (int)_next, (int)_content_end, + _line_ending, + (unsigned long long)(intptr_t)_buffer, + _buffer == _small_buffer ? "(SB)" : "", + (int)_buffer_size, + (int)_line_count, + has_c_heap_buffer()); + assert(is_sane(), ""); +} +#endif + +#ifdef ASSERT +// More support for coverage testing. +int inputStream::coverage_mode(int start, + int& cases, int& total, int& zeroes) { + int old_mode = current_coverage_mode; + current_coverage_mode = start; + int num_cases = 0, zero_count = 0, case_count = 0; +#define COUNT_COV_CASE(casename) { \ + int tem = COV_COUNT(casename); \ + case_count += tem; \ + if (tem == 0) ++zero_count; \ + num_cases++; \ + } + DO_COV_CASES(COUNT_COV_CASE) +#undef COUNT_COV_CASE + if (start < 0) { + tty->print("istream coverage:"); + #define PRINT_COV_CASE(casename) \ + tty->print(" %s:%d", #casename, COV_COUNT(casename)); + DO_COV_CASES(PRINT_COV_CASE) + tty->cr(); + #undef PRINT_COV_CASE + if (zero_count != 0) { + case_count = -case_count; + #define ZERO_COV_CASE(casename) \ + if (COV_COUNT(casename) == 0) \ + tty->print_cr("%s: no coverage for %s", \ + __FILE__, #casename); \ + DO_COV_CASES(ZERO_COV_CASE) + #undef ZERO_COV_CASE + } + } + if (start >= 2 || start < 0) { + #define CLEAR_COV_CASE(casename) \ + COV_COUNT(casename) = 0; + DO_COV_CASES(CLEAR_COV_CASE) + #undef CLEAR_COV_CASE + } + cases = num_cases; + total = case_count; + zeroes = zero_count; + return old_mode; +} +#endif //ASSERT diff --git a/src/hotspot/share/utilities/istream.hpp b/src/hotspot/share/utilities/istream.hpp new file mode 100644 index 0000000000000..b6a58055b937c --- /dev/null +++ b/src/hotspot/share/utilities/istream.hpp @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_UTILITIES_ISTREAM_HPP +#define SHARE_UTILITIES_ISTREAM_HPP + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" +#include "utilities/ostream.hpp" + +// Input streams for reading line-oriented textual data. These streams +// treat newline '\n' very differently from all other bytes. Carriage +// return '\r' is just another bit of whitespace, although it is +// removed just before newline. +// +// Null '\0' is just a data byte, although it also terminates C +// strings; the `current_line` function adds a null after removing any +// line terminator but does not specially process any nulls embedded +// in the line. +// +// There are sizing access functions which allow lines to contain +// null, but the simpler function assumes null termination, and thus +// lines containing null will "look" shorter when viewed as C strings. +// Use the sizing access functions if you care about this. +// +// Formatting guidelines: +// +// Configuration data should be line-oriented. It should be readable +// by humans (though perhaps with difficulty). It should be easily +// processed by text editors and by widely available text processing +// tools such as grep, sed, and awk. +// +// Configuration data should not require "compilers" to generate, if +// possible. It should be editable by hand, if possible. In cases +// where binary data is strongly required, pick a binary format +// already native to Hotspot, such as classfile, jar, or jmod. +// +// Each line should be separately parseable; the parsing can be ad +// hoc. For constructs inherently larger than single lines (such as +// complex method configuration information), try to use a structuring +// principle that allows "leaf" data to be line-oriented, and delimits +// that data with markup lines of some sort. Try to pick a +// line-friendly version of a standard format like XML or Markdown. +// JSON is somewhat problematic because there is no line-friendly leaf +// syntax: everything at the leaves must be a quoted string in JSON. +// +// Use simple parsing via scanf-like formats for simple applications. +// But, keep in mind that these formats may lose data when applied to +// unusual strings, such as class names that contain spaces, or method +// names that contain punctuation. For more robust transmission of +// potentially unusual names, consider wrapping them in XML-flavored +// lines like . +// +// Note: Input streams are never MT-safe. + +class inputStream : public CHeapObjBase { + public: + class Input; + + private: + NONCOPYABLE(inputStream); + + static constexpr size_t SMALL_SIZE = 240 DEBUG_ONLY(*0 + 10); + static constexpr size_t BIG_SIZE = 2048 DEBUG_ONLY(*0 + 20); + + protected: + // Values for _input_state, to distinguish some phases of history: + // Do we need to read more input (NTR)? Did we see EOF already? + // Was there an error getting input or allocating buffer space? + enum class IState : int { NTR_STATE, EOF_STATE, ERR_STATE }; + + // Named offset for _next relative to _content_end, of phantom '\n'. + static const int NEXT_PHANTOM = 1; + + Input* _input; // where the input comes from or else nullptr + IState _input_state; // one of {NTR,EOF,ERR}_STATE + char _line_ending; // one of {0,1,2} for "", "\n", "\r\n" + char* _buffer; // scratch buffer holding at least the current line + size_t _buffer_size; // allocated size of buffer + size_t _content_end; // offset to end of valid contents of buffer + size_t _beg; // offset in buffer to start of current line + size_t _end; // offset to end of known current line (else content_end) + size_t _next; // offset to known start of next line (else =end) + size_t _line_count; // increasing non-resettable count of lines read + char _small_buffer[SMALL_SIZE]; // stack-allocated buffer for holding lines; + // will switch to C_HEAP allocation when necessary. + + bool has_c_heap_buffer() { + return _buffer != &_small_buffer[0]; + } + + // Buffer states + // + // The current line (less any line ending) is always [beg..end). + // It is always the case that 0 <= beg <= end <= con_end <= buffer_size. + // When there is a current line buffered, end < next <= 1+con_end. + // In that case, the value of next is end + max(1, strlen(lend)), + // where lend is "\n", "\r\n", or (for a last partial line) "". + // But if next == end, we need to read more input, or observe an EOF. + // + // beg ==end ==next == con_end => nothing buffered, we need to read + // beg <=end < next <= con_end => have current line, with terminator + // beg < end < next ==1+con_end => have partial current line (saw EOF) + // beg < end ==next == con_end => partial line, we need to read + // beg ==end < next ==1+con_end => definitely done; no more I/O + // + // These states are in three mutually exclusive groups: + // need_to_read() <= nothing or partial line in buffer + // have_current_line() <= beg/end point to valid line (partial only if EOF) + // definitely_done() <= consumed all lines && (hit EOF || hit error) + // These states are internal; the user can only look at next/done/error. + // + // Relative to these states, everything already read from the input + // before the first byte of the current line is logically present + // (but not accessible) before _beg, while everything not yet read + // from the input is after _content_end. The difference between + // these two pointers is constant, except when characters change + // from being in the current line to being (logically) before it, + // when next is called. + + bool is_sane() const { + assert(_buffer != nullptr, ""); + assert(_content_end <= _buffer_size, ""); + assert(_beg <= _end && _end <= _content_end, ""); + assert(_end <= _next && _next <= _content_end + NEXT_PHANTOM, ""); + assert(_buffer_size == 0 || _next <= _buffer_size, ""); + return true; + } + + bool need_to_read() const { + assert(is_sane(), ""); + return _next == _end; + } + bool have_current_line() const { + assert(is_sane(), ""); + // _beg < _content_end because there is an \0 (was \n) at _end, + // or else it is a non-empty partial line and the \0 is at + // _content_end. In either case, if _end == _next we are + // still searching for more input. + return (_beg < _content_end && _end < _next); + } + bool definitely_done() const { + assert(is_sane(), ""); + // If _beg < _content_end we still have a line of some sort. + // Otherwise, if _next > _content_end, we have seen EOF or error. + return (_beg == _content_end && _next > _content_end); + } + + // Reset indexes within the buffer to point to no content. + void clear_buffer(); + + // Reset indexes within the buffer to point to the given content. + // This is where we scan for newlines as well. + void set_buffer_content(size_t content_start, size_t content_end); + + // Try to make the buffer bigger. This may be necessary in order to + // buffer a very long line. Returns false if there was an + // allocation failure. + // + // On allocation failure, just make do with whatever buffer there + // was to start with; the caller must check for this condition and + // avoid buffering more data in the non-expanded buffer. However, + // the buffer will always be non-null, so at least one line can be + // buffered, if it is of normal size. + bool expand_buffer(size_t new_length); + + // Make sure there is at least one line in the buffer, and set + // _beg/_end to indicate where it is. Any content before _beg can + // be overwritten to make more room in the buffer. If there is no + // more input, set the state up to indicate we are done. + bool fill_buffer(); + + // Find some room in the buffer so we can call read on it. + // This might call expand_buffer but will try not to. + // The assumption is that read already buffers slow I/O calls. + // The purpose for the small buffer managed here is to store whole lines, + // and perhaps edit them in-place. + void prepare_to_fill_buffer(size_t& fill_offset, size_t& fill_length); + + // Quick check for an initially incomplete buffer... + void preload() const { + if (need_to_read()) { + const_cast(this)->fill_buffer(); + } + } + + // How much content is buffered (if any) after the current line? + size_t buffered_content_length(bool include_current) const { + return (include_current ? _content_end - _beg : + _content_end >= _next ? _content_end - _next : 0); + } + + // Returns a pointer and count to characters buffered after the + // current line, but not yet read from my input source. Only useful + // if you are trying to stack input streams on top of each other + // somehow. You can also ask the input source if it thinks it has + // more bytes. + const char* next_content(size_t& next_content_length) const; + + public: + // Create an empty input stream. + // Call push_back_input or set_input to configure. + inputStream() : + _input(nullptr), + _input_state(IState::NTR_STATE), + _line_ending(0), + _buffer(&_small_buffer[0]), + _buffer_size(sizeof(_small_buffer)), + _content_end(0), + _beg(0), + _end(0), + _next(0), + _line_count(0) {} + + // Take input from the given source. Buffer only a modest amount. + inputStream(Input* input) + : inputStream() + { + set_input(input); + } + + virtual ~inputStream(); + + // Discards any previous input and sets the given input source. + void set_input(Input* input); + + // Returns a pointer to a null terminated mutable copy of the current line. + // Note that embedded nulls may make the line appear shorter than it really is. + // This may trigger input activity if there is not enough data buffered. + // If there are no more lines, return an empty line, statically allocated. + char* current_line() const { + preload(); + if (definitely_done()) + return (char*)""; + return &_buffer[_beg]; + } + + // Return the size of the current line, exclusive of any line terminator. + // If no lines have been read yet, or there are none remaining, return zero. + size_t current_line_length() const { + preload(); + return _end - _beg; + } + + // Reports my current input source, if any, else a null pointer. + Input* input() const { return _input; } + + // Discards the current line, gets ready to report the next line. + // Returns true if there is one, which is always the opposite of done(). + // Fetches input if necessary. + bool next(); + + // Reports if there are no more lines. Fetches input if necessary. + bool done() const { + preload(); + return definitely_done(); + } + + // Discard pending input and do not read any more. + // Takes no action if already done, whether in an error state or not. + void set_done(); + + // Reports if this stream has had an error was reported on it. + bool error() const { + return _input_state == IState::ERR_STATE; + } + + // Set this stream done with an error, if the argument is true. + // If it is false but there is an error condition, clear the error. + // Otherwise do nothing. + void set_error(bool error_condition = true); + + // lineno is the 1-based ordinal of the current line; it starts at one + size_t lineno() const { preload(); return _line_count; } + + // Copy the current line to the given output stream. + void print_on(outputStream* out); + + // Copy the current line to the given output stream, and also call cr(). + void print_cr_on(outputStream* out) { + print_on(out); out->cr(); + } + +#ifdef ASSERT + void dump(const char* what = nullptr); + static int coverage_mode(int mode, int& cases, int& total, int& zeroes); +#else + void dump(const char* what = nullptr) { } +#endif + + + // Block-oriented input, which treats all bytes equally. + class Input : public CHeapObjBase { + public: + // Read some characters from an external source into the line buffer. + // If there are no more, return zero, otherwise return non-zero. + // It must be OK to call read even after it returns zero. + virtual size_t read(char* buf, size_t size) = 0; + // Example: read(b,s) { return fread(b, 1, s, _my_fp); } + // Example: read(b,s) { return 0; } // never more than the initial buffer + }; +}; + +// for reading lines from files +class FileInput : public inputStream::Input { + NONCOPYABLE(FileInput); + + protected: + fileStream& _fs; + fileStream _private_fs; + + // it does not seem likely there are such file streams around + FileInput(fileStream& fs) + : _fs(fs) + { } + + public: + // just forward all the constructor arguments to the wrapped line-input class + template + FileInput(Arg... arg) + : _fs(_private_fs), _private_fs(arg...) + { } + + FileInput(const char* file_name) + : FileInput(file_name, "rt") + { } + + bool is_open() const { return _fs.is_open(); } + + protected: + size_t read(char* buf, size_t size) override { + return _fs.read(buf, size); + } +}; + +class MemoryInput : public inputStream::Input { + const void* _base; + const size_t _limit; + size_t _offset; + + public: + MemoryInput(const void* base, size_t size, + size_t offset = 0) + : _base(base), _limit(size), _offset(offset) {} + + MemoryInput(const char* start) + : MemoryInput(start, 0, strlen(start)) + { } + + protected: + size_t read(char* buf, size_t size) override { + size_t nr = size; + if (nr > _limit - _offset) { + nr = _limit - _offset; + } + if (nr > 0) { + ::memcpy(buf, (char*)_base + _offset, nr); + _offset += nr; + } + return nr; + } +}; + +#endif // SHARE_UTILITIES_ISTREAM_HPP diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index a1575b3d2c6c8..89335f9cf4c62 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -397,7 +397,7 @@ char* stringStream::as_string(bool c_heap) const { char* copy = c_heap ? NEW_C_HEAP_ARRAY(char, _written + 1, mtInternal) : NEW_RESOURCE_ARRAY(char, _written + 1); ::memcpy(copy, _buffer, _written); - copy[_written] = 0; // terminating null + copy[_written] = '\0'; // terminating null if (c_heap) { // Need to ensure our content is written to memory before we return // the pointer to it. @@ -590,23 +590,10 @@ long fileStream::fileSize() { return size; } -char* fileStream::readln(char *data, int count ) { - char * ret = nullptr; - if (_file != nullptr) { - ret = ::fgets(data, count, _file); - // Get rid of annoying \n char only if it is present. - size_t len = ::strlen(data); - if (len > 0 && data[len - 1] == '\n') { - data[len - 1] = '\0'; - } - } - return ret; -} - fileStream::~fileStream() { if (_file != nullptr) { - if (_need_close) fclose(_file); - _file = nullptr; + close(); + _file = nullptr; } } diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp index 72cf804ed646d..d39fca29ba4c0 100644 --- a/src/hotspot/share/utilities/ostream.hpp +++ b/src/hotspot/share/utilities/ostream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,11 +242,20 @@ class fileStream : public outputStream { ~fileStream(); bool is_open() const { return _file != nullptr; } virtual void write(const char* c, size_t len); - size_t read(void *data, size_t size, size_t count) { return _file != nullptr ? ::fread(data, size, count, _file) : 0; } - char* readln(char *data, int count); - int eof() { return _file != nullptr ? feof(_file) : -1; } + // unlike other classes in this file, fileStream can perform input as well as output + size_t read(void* data, size_t size) { + if (_file == nullptr) return 0; + return ::fread(data, 1, size, _file); + } + size_t read(void *data, size_t size, size_t count) { + return read(data, size * count); + } + void close() { + if (_file == nullptr || !_need_close) return; + fclose(_file); + _need_close = false; + } long fileSize(); - void rewind() { if (_file != nullptr) ::rewind(_file); } void flush(); }; diff --git a/test/hotspot/gtest/utilities/test_istream.cpp b/test/hotspot/gtest/utilities/test_istream.cpp new file mode 100644 index 0000000000000..8dd3c6b00b4f8 --- /dev/null +++ b/test/hotspot/gtest/utilities/test_istream.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "jvm.h" +#include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/os.hpp" +#include "utilities/istream.hpp" +#include "unittest.hpp" + +template +class BlockInputStream : public inputStream { + BlockClass _input; + public: + template + BlockInputStream(Arg... arg) + : _input(arg...) { + set_input(&_input); + } +}; + +#define EXPECT_MEMEQ(s1, s2, len) \ + EXPECT_PRED_FORMAT3(CmpHelperMEMEQ, s1, s2, len) +// cf. ::testing::internal::CmpHelperSTREQ + +testing::AssertionResult CmpHelperMEMEQ(const char* s1_expression, + const char* s2_expression, + const char* len_expression, + const char* s1, const char* s2, + size_t len) { + if (s1 == nullptr || s2 == nullptr) { + return testing::internal::CmpHelperEQ(s1_expression, s2_expression, + s1, s2); + } + int c = ::memcmp(s1, s2, len); + if (c == 0) { + return testing::AssertionSuccess(); + } + ::std::string str1, str2; + for (auto which = 0; which <= 1; which++) { + auto s = which ? s1 : s2; + auto &str = which ? str1 : str2; + std::stringstream buf; + buf << "{"; + for (size_t i = 0; i < len; i++) { + char c = s[i]; + switch (c) { + case '\0': buf << "\\0"; break; + case '\n': buf << "\\n"; break; + case '\\': buf << "\\\\"; break; + default: buf << c; break; + } + } + buf << "}[" << len_expression << "=" << len << "]"; + str = buf.str(); + } + return testing::internal::CmpHelperSTREQ(s1_expression, s2_expression, + str1.c_str(), str2.c_str()); +} + +static int firstdiff(char* b1, char* b2, int blen) { + for (int i = 0; i < blen; i++) { + if (b1[i] != b2[i]) return i; + } + return -1; +} + +static char* get_temp_file(bool VERBOSE, const char* filename) { + const char* tmp_dir = os::get_temp_directory(); + const char* file_sep = os::file_separator(); + size_t temp_file_len = strlen(tmp_dir) + strlen(file_sep) + strlen(filename) + 28; + char* temp_file = NEW_C_HEAP_ARRAY(char, temp_file_len, mtInternal); + int ret = jio_snprintf(temp_file, temp_file_len, "%s%spid%d.%s", + tmp_dir, file_sep, + os::current_process_id(), filename); + if (VERBOSE) tty->print_cr("temp_file = %s", temp_file); + return temp_file; +} + +static const char* get_temp_file(bool VERBOSE) { + static const char* temp_file = get_temp_file(VERBOSE, "test_istream"); + return temp_file; +} + +#define EIGHTY 80 +#define LC0(x) ('/' + (((unsigned)(x)+1) % EIGHTY)) +#define LC(line,col) LC0((col) * (line)) + +#define COLS 30 + +static int cases, total, zeroes; +#ifdef ASSERT +#define istream_coverage_mode(mode, a,b,c) \ + inputStream::coverage_mode(mode, a,b,c) +#else +#define istream_coverage_mode(mode, a,b,c) +#endif + +// Fill in a test pattern of ascii characters. +// Each line is ncols long, plus a line termination of lelen (1 or 2). +// Each character is a fixed, static function of the line and column. +// This enables test logic to predict exactly what will be read in each line. +static void fill_pattern(bool VERBOSE, + char* pat, int patlen, int ncols, int lelen, + int& full_lines, int& partial_line, + const char* &line_end, + const char* &partial_line_end) { + full_lines = partial_line = 0; + for (int i = 0; i < patlen; i++) { + int line = (i / (ncols+lelen)) + 1; // 1-based line number + int col = (i % (ncols+lelen)) + 1; // 1-based column number + if (col <= ncols) { + pat[i] = LC(line, col); + partial_line = 1; + } else if (col < ncols+lelen) { + pat[i] = i == patlen - 1 ? '!' : '%'; + partial_line = 1; + } else { + assert(col == ncols+lelen, ""); + pat[i] = '!'; + full_lines++; + partial_line = 0; + } + } + pat[patlen] = '\0'; + if (VERBOSE) tty->print_cr("PATTERN=%d+%d[%s]", + full_lines, partial_line, pat); + for (int i = 0; i < patlen; i++) { + assert(pat[i] != '%' || (i+1 < patlen && pat[i+1] == '!'), ""); + if (pat[i] == '!') pat[i] = '\n'; + if (pat[i] == '%') pat[i] = '\r'; + } + assert(pat[patlen-1] != '\r', ""); + + line_end = (lelen == 2 ? "\r\n" : "\n"); + int partial_line_bytes = patlen - (full_lines * (ncols + lelen)); + assert(partial_line_bytes < ncols + lelen, ""); + partial_line_end = (partial_line_bytes == ncols + 1) ? "\n" : ""; +} + +static const int MAX_PATLEN = COLS * (COLS-1); + +static void istream_test_driver(const bool VERBOSE, + const int patlen, + const int ncols, + const int lelen, + const bool TEST_SET_POSITION, + const bool TEST_PUSH_BACK, + const bool TEST_EXPAND_REDUCE) { + DEBUG_ONLY( istream_coverage_mode(VERBOSE ? 2 : 1, cases, total, zeroes) ); + const char* temp_file = get_temp_file(VERBOSE); + unlink(temp_file); + char pat[MAX_PATLEN+1]; + int full_lines = 0, partial_line = 0; + const char* line_end = "\n"; + const char* partial_line_end = ""; + fill_pattern(VERBOSE, pat, patlen, ncols, lelen, + full_lines, partial_line, + line_end, partial_line_end); + + char pat2[sizeof(pat)]; // copy of pat to help detect scribbling + memcpy(pat2, pat, sizeof(pat)); + // Make three kinds of stream and test them all. + MemoryInput _min(pat2, patlen); + inputStream sin(&_min); + if (VERBOSE) { + tty->print("at %llx ", (unsigned long long)(intptr_t)&sin); + sin.dump("sin"); + } + { + fileStream tfs(temp_file); + guarantee(tfs.is_open(), "cannot open temp file"); + tfs.write(pat, patlen); + } + BlockInputStream fin(temp_file); + if (VERBOSE) { + tty->print("at %llx ", (unsigned long long)(intptr_t)&fin); + fin.dump("fin"); + } + BlockInputStream min(&pat2[0], patlen); + if (VERBOSE) { + tty->print("at %llx ", (unsigned long long)(intptr_t)&min); + sin.dump("min"); + } + inputStream* ins[] = { &sin, &fin, &min }; + const char* in_names[] = { "sin", "fin", "min" }; + const char* test_mode = (TEST_SET_POSITION + ? (!TEST_PUSH_BACK ? "(seek)" : "(seek/push)") + : TEST_EXPAND_REDUCE + ? (!TEST_PUSH_BACK ? "(exp/red)" : "(exp/red/push)") + : (!TEST_PUSH_BACK ? "(plain)" : "(push)")); + for (int which = 0; which < 3; which++) { + inputStream& in = *ins[which]; + const char* in_name = in_names[which]; + int lineno; + char* lp = (char*)"--"; +#define LPEQ \ + in_name << test_mode \ + << " ncols=" << ncols << " lelen=" << lelen \ + << " full=" << full_lines << " lineno=" << lineno \ + << " [" << lp << "]" << (in.dump("expect"), "") + if (VERBOSE) + tty->print_cr("testing %s%s patlen=%d ncols=%d full_lines=%d partial_line=%d", + in_name, test_mode, + patlen, ncols, full_lines, partial_line); + int pos_to_set = 0, line_to_set = 1; // for TEST_SET_POSITION only + for (int phase = 0; phase <= (TEST_SET_POSITION ? 1 : 0); phase++) { + lineno = 1; + for (; lineno <= full_lines + partial_line; lineno++) { + EXPECT_EQ(-1, firstdiff(pat, pat2, patlen + 1)); + if (VERBOSE) in.dump("!done?"); + bool done = in.done(); + EXPECT_TRUE(!done) < full_lines) + expect_len = MIN2(ncols, patlen % (ncols+lelen)); + EXPECT_EQ(len, expect_len) < SHORT_NCOLS) break; + } else if (ncols > COLS && ncols < patlen - COLS) { + ncols += ncols / 7; + if (ncols > patlen - COLS) ncols = (patlen - COLS); + } + for (int lelen = 1; lelen <= 2; lelen++) { // try both kinds of newline + istream_test_driver(VERBOSE, + patlen, ncols, lelen, + TEST_SET_POSITION, TEST_PUSH_BACK, TEST_EXPAND_REDUCE); + } + } +} + +TEST_VM(istream, basic) { + const bool VERBOSE = false; + istream_test_driver(VERBOSE, false, false, false); +} + +TEST_VM(istream, coverage) { + const bool VERBOSE = false; +#ifdef ASSERT + istream_coverage_mode(0, cases, total, zeroes); + if (cases == 0) return; + if (VERBOSE || zeroes != 0) + istream_coverage_mode(-1, cases, total, zeroes); + EXPECT_EQ(zeroes, 0) << "zeroes: " << zeroes << "/" << cases; +#endif //ASSERT +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LongClassListPath.java b/test/hotspot/jtreg/runtime/cds/appcds/LongClassListPath.java index b50b0ad47d943..6aa5964d8a693 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LongClassListPath.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LongClassListPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test + * @bug 8216184 * @summary Test the handling of long path to the classlist file. * @requires vm.cds * @library /test/lib diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/ClassListFormatA.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/ClassListFormatA.java index 1275f752c050e..37c59a0d0a3ea 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/ClassListFormatA.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/ClassListFormatA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,12 @@ * */ +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import jdk.test.lib.cds.CDSOptions; +import jdk.test.lib.cds.CDSTestUtils; + /* * @test * @summary Tests the format checking of class list format. @@ -94,39 +100,76 @@ appJar, classlist( // Good input: dumpShouldPass( - "TESTCASE A6: extraneous spaces, tab characters and trailing new line characters", + "TESTCASE A6: extraneous spaces, tab characters, trailing new line characters, and trailing comment line", appJar, classlist( "Hello ", // trailing spaces "java/lang/Object\tid:\t1", // \t instead of ' ' "CustomLoadee id: 2 super: 1 source: " + customJarPath, "CustomInterface2_ia id: 3 super: 1 source: " + customJarPath + " ", "CustomInterface2_ib id: 4 super: 1 source: " + customJarPath + "\t\t\r" , - "CustomLoadee2 id: 5 super: 1 interfaces: 3 4 source: " + customJarPath // preceding spaces + "CustomLoadee2 id: 5 super: 1 interfaces: 3 4 source: " + customJarPath, // preceding spaces + "#last line is a comment" )); - int _max_allowed_line = 4096; // Must match ClassListParser::_max_allowed_line in C code. - int _line_buf_extra = 10; // Must match ClassListParser::_line_buf_extra in C code. - StringBuffer sbuf = new StringBuffer(); - for (int i=0; i<_max_allowed_line+1; i++) { - sbuf.append("x"); + // Tests for corner cases in the C++ class LineReader, or invalid UTF8. These can't + // be tested with dumpShouldPass/dumpShouldFail as we need to prepare a special class + // list file. + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 6500; i++) { + sb.append("X123456789"); } - dumpShouldFail( - "TESTCASE A7: bad input - line too long", - appJar, classlist( - sbuf.toString() - ), - "input line too long (must be no longer than " + _max_allowed_line + " chars"); + { + System.out.println("TESTCASE A7.1: Long line (65000 chars)"); + String longName = sb.toString(); // 65000 chars long + String classList = "LongLine.classlist"; + try (FileWriter fw = new FileWriter(classList)) { + fw.write(longName + "\n"); + } + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + classList, "-Xlog:cds"); + CDSTestUtils.createArchiveAndCheck(opts) + .shouldContain("Preload Warning: Cannot find " + longName); + } - for (int i=0; i<_line_buf_extra + 1000; i++) { - sbuf.append("X"); + { + System.out.println("TESTCASE A7.2: Name Length > Symbol::max_length()"); + String tooLongName = sb.toString() + sb.toString(); + String classList = "TooLongLine.classlist"; + try (FileWriter fw = new FileWriter(classList)) { + fw.write("java/lang/Object\n"); + fw.write(tooLongName + "\n"); + } + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + classList, "-Xlog:cds"); + CDSTestUtils.createArchive(opts) + .shouldContain(classList + ":2 class name too long") // test line number as well. + .shouldHaveExitValue(1); } - dumpShouldFail( - "TESTCASE A8: bad input - line too long: try to overflow C buffer", - appJar, classlist( - sbuf.toString() - ), - "input line too long (must be no longer than " + _max_allowed_line + " chars"); + { + System.out.println("TESTCASE A7.3: File doesn't end with newline"); + String classList = "NoTrailingNewLine.classlist"; + try (FileWriter fw = new FileWriter(classList)) { + fw.write("No/Such/ClassABCD"); + } + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + classList, "-Xlog:cds"); + CDSTestUtils.createArchiveAndCheck(opts) + .shouldContain("Preload Warning: Cannot find No/Such/ClassABCD"); + } + { + System.out.println("TESTCASE A7.4: invalid UTF8 character"); + String classList = "BadUTF8.classlist"; + try (FileOutputStream fos = new FileOutputStream(classList)) { + byte chars[] = new byte[] { (byte)0xa0, (byte)0xa1, '\n'}; + fos.write(chars); + } + CDSOptions opts = (new CDSOptions()) + .addPrefix("-XX:ExtraSharedClassListFile=" + classList, "-Xlog:cds"); + CDSTestUtils.createArchive(opts) + .shouldContain(classList + ":1 class name is not valid UTF8") // test line number as well. + .shouldHaveExitValue(1); + } } } From ad0b54d429fdbd806c09aa06bb42f1ed4a0297e8 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 9 May 2024 11:47:45 +0000 Subject: [PATCH 136/203] 8314225: SIGSEGV in JavaThread::is_lock_owned Reviewed-by: dlong, dholmes --- .../leakprofiler/checkpoint/rootResolver.cpp | 8 +---- src/hotspot/share/runtime/deoptimization.cpp | 2 +- src/hotspot/share/runtime/javaThread.cpp | 33 +------------------ src/hotspot/share/runtime/javaThread.hpp | 12 +------ src/hotspot/share/runtime/monitorChunk.cpp | 3 +- src/hotspot/share/runtime/monitorChunk.hpp | 8 +---- src/hotspot/share/runtime/synchronizer.cpp | 4 ++- src/hotspot/share/runtime/thread.cpp | 10 ------ src/hotspot/share/runtime/thread.hpp | 3 -- src/hotspot/share/runtime/vframeArray.cpp | 25 +++++++++----- src/hotspot/share/runtime/vframeArray.hpp | 4 +-- 11 files changed, 28 insertions(+), 84 deletions(-) diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp index 9627259e26473..57b29a09d016f 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,12 +248,6 @@ bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) { ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt); if (jt->has_last_Java_frame()) { - // Traverse the monitor chunks - MonitorChunk* chunk = jt->monitor_chunks(); - for (; chunk != nullptr; chunk = chunk->next()) { - chunk->oops_do(&rcl); - } - if (rcl.complete()) { return true; } diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 03e62075808bd..53a0f2e9c3b51 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1736,7 +1736,7 @@ void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* ObjectSynchronizer::exit(src->obj(), src->lock(), thread); } } - array->element(i)->free_monitors(thread); + array->element(i)->free_monitors(); #ifdef ASSERT array->element(i)->set_removed_monitors(); #endif diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 7ed67c4616b72..97be533341364 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -430,8 +430,6 @@ JavaThread::JavaThread() : _active_handles(nullptr), _free_handle_block(nullptr), - _monitor_chunks(nullptr), - _suspend_flags(0), _thread_state(_thread_new), @@ -1050,13 +1048,7 @@ JavaThread* JavaThread::active() { bool JavaThread::is_lock_owned(address adr) const { assert(LockingMode != LM_LIGHTWEIGHT, "should not be called with new lightweight locking"); - if (Thread::is_lock_owned(adr)) return true; - - for (MonitorChunk* chunk = monitor_chunks(); chunk != nullptr; chunk = chunk->next()) { - if (chunk->contains(adr)) return true; - } - - return false; + return is_in_full_stack(adr); } oop JavaThread::exception_oop() const { @@ -1067,22 +1059,6 @@ void JavaThread::set_exception_oop(oop o) { Atomic::store(&_exception_oop, o); } -void JavaThread::add_monitor_chunk(MonitorChunk* chunk) { - chunk->set_next(monitor_chunks()); - set_monitor_chunks(chunk); -} - -void JavaThread::remove_monitor_chunk(MonitorChunk* chunk) { - guarantee(monitor_chunks() != nullptr, "must be non empty"); - if (monitor_chunks() == chunk) { - set_monitor_chunks(chunk->next()); - } else { - MonitorChunk* prev = monitor_chunks(); - while (prev->next() != chunk) prev = prev->next(); - prev->set_next(chunk->next()); - } -} - void JavaThread::handle_special_runtime_exit_condition() { if (is_obj_deopt_suspend()) { frame_anchor()->make_walkable(); @@ -1408,13 +1384,6 @@ void JavaThread::oops_do_no_frames(OopClosure* f, NMethodClosure* cf) { DEBUG_ONLY(verify_frame_info();) - if (has_last_Java_frame()) { - // Traverse the monitor chunks - for (MonitorChunk* chunk = monitor_chunks(); chunk != nullptr; chunk = chunk->next()) { - chunk->oops_do(f); - } - } - assert(vframe_array_head() == nullptr, "deopt in progress at a safepoint!"); // If we have deferred set_locals there might be oops waiting to be // written diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 37fd8981acd48..2541aaded00a3 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -193,10 +193,6 @@ class JavaThread: public Thread { void pop_jni_handle_block(); private: - MonitorChunk* _monitor_chunks; // Contains the off stack monitors - // allocated during deoptimization - // and by JNI_MonitorEnter/Exit - enum SuspendFlags { // NOTE: avoid using the sign-bit as cc generates different test code // when the sign-bit is used, and sometimes incorrectly - see CR 6398077 @@ -679,7 +675,7 @@ class JavaThread: public Thread { return (_suspend_flags & (_obj_deopt JFR_ONLY(| _trace_flag))) != 0; } - // Fast-locking support + // Stack-locking support (not for LM_LIGHTWEIGHT) bool is_lock_owned(address adr) const; // Accessors for vframe array top @@ -881,13 +877,7 @@ class JavaThread: public Thread { int depth_first_number() { return _depth_first_number; } void set_depth_first_number(int dfn) { _depth_first_number = dfn; } - private: - void set_monitor_chunks(MonitorChunk* monitor_chunks) { _monitor_chunks = monitor_chunks; } - public: - MonitorChunk* monitor_chunks() const { return _monitor_chunks; } - void add_monitor_chunk(MonitorChunk* chunk); - void remove_monitor_chunk(MonitorChunk* chunk); bool in_deopt_handler() const { return _in_deopt_handler > 0; } void inc_in_deopt_handler() { _in_deopt_handler++; } void dec_in_deopt_handler() { diff --git a/src/hotspot/share/runtime/monitorChunk.cpp b/src/hotspot/share/runtime/monitorChunk.cpp index c54ad685cdbbb..d18fc21d78d93 100644 --- a/src/hotspot/share/runtime/monitorChunk.cpp +++ b/src/hotspot/share/runtime/monitorChunk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ MonitorChunk::MonitorChunk(int number_on_monitors) { _number_of_monitors = number_on_monitors; _monitors = NEW_C_HEAP_ARRAY(BasicObjectLock, number_on_monitors, mtSynchronizer); - _next = nullptr; } diff --git a/src/hotspot/share/runtime/monitorChunk.hpp b/src/hotspot/share/runtime/monitorChunk.hpp index f16aa46fa6411..5c804b5c595ef 100644 --- a/src/hotspot/share/runtime/monitorChunk.hpp +++ b/src/hotspot/share/runtime/monitorChunk.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,23 +38,17 @@ class MonitorChunk: public CHeapObj { int _number_of_monitors; BasicObjectLock* _monitors; BasicObjectLock* monitors() const { return _monitors; } - MonitorChunk* _next; public: // Constructor MonitorChunk(int number_on_monitors); ~MonitorChunk(); - // link operations - MonitorChunk* next() const { return _next; } - void set_next(MonitorChunk* next) { _next = next; } - // Returns the number of monitors int number_of_monitors() const { return _number_of_monitors; } // Returns the index'th monitor BasicObjectLock* at(int index) { assert(index >= 0 && index < number_of_monitors(), "out of bounds check"); return &monitors()[index]; } - // Memory management void oops_do(OopClosure* f); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index f8d4b32315665..27b4163238aa9 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1056,7 +1056,9 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { } // Fall thru so we only have one place that installs the hash in // the ObjectMonitor. - } else if (LockingMode == LM_LEGACY && mark.has_locker() && current->is_lock_owned((address)mark.locker())) { + } else if (LockingMode == LM_LEGACY && mark.has_locker() + && current->is_Java_thread() + && JavaThread::cast(current)->is_lock_owned((address)mark.locker())) { // This is a stack-lock owned by the calling thread so fetch the // displaced markWord from the BasicLock on the stack. temp = mark.displaced_mark_helper(); diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 396f349a8856b..bbfeaefb1fe83 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -527,16 +527,6 @@ void Thread::print_owned_locks_on(outputStream* st) const { } #endif // ASSERT -// We had to move these methods here, because vm threads get into ObjectSynchronizer::enter -// However, there is a note in JavaThread::is_lock_owned() about the VM threads not being -// used for compilation in the future. If that change is made, the need for these methods -// should be revisited, and they should be removed if possible. - -bool Thread::is_lock_owned(address adr) const { - assert(LockingMode != LM_LIGHTWEIGHT, "should not be called with new lightweight locking"); - return is_in_full_stack(adr); -} - bool Thread::set_as_starting_thread() { assert(_starting_thread == nullptr, "already initialized: " "_starting_thread=" INTPTR_FORMAT, p2i(_starting_thread)); diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index ebf1b590ebd78..d0749b8101d85 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -475,9 +475,6 @@ class Thread: public ThreadShadow { } public: - // Used by fast lock support - virtual bool is_lock_owned(address adr) const; - // Check if address is within the given range of this thread's // stack: stack_base() > adr >= limit bool is_in_stack_range_incl(address adr, address limit) const { diff --git a/src/hotspot/share/runtime/vframeArray.cpp b/src/hotspot/share/runtime/vframeArray.cpp index cf7b087887fbd..d3bbbc283992a 100644 --- a/src/hotspot/share/runtime/vframeArray.cpp +++ b/src/hotspot/share/runtime/vframeArray.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/monitorChunk.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/synchronizer.hpp" #include "runtime/vframe.hpp" #include "runtime/vframeArray.hpp" #include "runtime/vframe_hp.hpp" @@ -48,11 +49,10 @@ int vframeArrayElement:: bci(void) const { return (_bci == SynchronizationEntryBCI ? 0 : _bci); } -void vframeArrayElement::free_monitors(JavaThread* jt) { +void vframeArrayElement::free_monitors() { if (_monitors != nullptr) { MonitorChunk* chunk = _monitors; _monitors = nullptr; - jt->remove_monitor_chunk(chunk); delete chunk; } } @@ -72,7 +72,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { int index; { - Thread* current_thread = Thread::current(); + JavaThread* current_thread = JavaThread::current(); ResourceMark rm(current_thread); HandleMark hm(current_thread); @@ -85,7 +85,6 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { // Allocate monitor chunk _monitors = new MonitorChunk(list->length()); - vf->thread()->add_monitor_chunk(_monitors); // Migrate the BasicLocks from the stack to the monitor chunk for (index = 0; index < list->length(); index++) { @@ -95,9 +94,16 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { if (monitor->owner_is_scalar_replaced()) { dest->set_obj(nullptr); } else { - assert(monitor->owner() == nullptr || !monitor->owner()->is_unlocked(), "object must be null or locked"); + assert(monitor->owner() != nullptr, "monitor owner must not be null"); + assert(!monitor->owner()->is_unlocked(), "monitor must be locked"); dest->set_obj(monitor->owner()); + assert(ObjectSynchronizer::current_thread_holds_lock(current_thread, Handle(current_thread, dest->obj())), + "should be held, before move_to"); + monitor->lock()->move_to(monitor->owner(), dest->lock()); + + assert(ObjectSynchronizer::current_thread_holds_lock(current_thread, Handle(current_thread, dest->obj())), + "should be held, after move_to"); } } } @@ -308,7 +314,11 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, top = iframe()->previous_monitor_in_interpreter_frame(top); BasicObjectLock* src = _monitors->at(index); top->set_obj(src->obj()); + assert(src->obj() != nullptr || ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, src->obj())), + "should be held, before move_to"); src->lock()->move_to(src->obj(), top->lock()); + assert(src->obj() != nullptr || ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, src->obj())), + "should be held, after move_to"); } if (ProfileInterpreter) { iframe()->interpreter_frame_set_mdp(0); // clear out the mdp. @@ -649,9 +659,8 @@ void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller } void vframeArray::deallocate_monitor_chunks() { - JavaThread* jt = JavaThread::current(); for (int index = 0; index < frames(); index++ ) { - element(index)->free_monitors(jt); + element(index)->free_monitors(); } } diff --git a/src/hotspot/share/runtime/vframeArray.hpp b/src/hotspot/share/runtime/vframeArray.hpp index 734703a94ae6f..b270046252dba 100644 --- a/src/hotspot/share/runtime/vframeArray.hpp +++ b/src/hotspot/share/runtime/vframeArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,7 +77,7 @@ class vframeArrayElement { MonitorChunk* monitors(void) const { return _monitors; } - void free_monitors(JavaThread* jt); + void free_monitors(); StackValueCollection* locals(void) const { return _locals; } From 0a4eeeaa3c63585244be959386dd94882398e87f Mon Sep 17 00:00:00 2001 From: Scott Gibbons Date: Thu, 9 May 2024 11:57:44 +0000 Subject: [PATCH 137/203] 8331033: EA fails with "EA unexpected CallLeaf unsafe_setmemory" after JDK-8329331 Co-authored-by: Jatin Bhateja Reviewed-by: kvn --- src/hotspot/share/opto/escape.cpp | 3 +- .../compiler/escapeAnalysis/Test8331033.java | 106 ++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/escapeAnalysis/Test8331033.java diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index c82eaad50e1ba..71051ee7bd10a 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2184,7 +2184,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "vectorizedMismatch") == 0 || strcmp(call->as_CallLeaf()->_name, "arraysort_stub") == 0 || strcmp(call->as_CallLeaf()->_name, "array_partition_stub") == 0 || - strcmp(call->as_CallLeaf()->_name, "get_class_id_intrinsic") == 0) + strcmp(call->as_CallLeaf()->_name, "get_class_id_intrinsic") == 0 || + strcmp(call->as_CallLeaf()->_name, "unsafe_setmemory") == 0) ))) { call->dump(); fatal("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name); diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/Test8331033.java b/test/hotspot/jtreg/compiler/escapeAnalysis/Test8331033.java new file mode 100644 index 0000000000000..68bedd48c8fd3 --- /dev/null +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/Test8331033.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8331033 + * @summary EA fails with "EA unexpected CallLeaf unsafe_setmemory" after JDK-8329331 + * @requires vm.compMode != "Xint" + * + * @run main/othervm -Xbatch -XX:-TieredCompilation Test8331033 + * + */ +import java.lang.foreign.*; + +class MyClass { + public int field1; + public int field2; + public int field3; + public int field4; + + public MyClass(int field1, int field2, int field3, int field4) { + this.field1 = field1; + this.field2 = field2; + this.field3 = field3; + this.field4 = field4; + } +} + +public class Test8331033 { + + public static int micro1(int ctr) { + // non-escaping object, EA sweepable, values are forwarded to users, additional + // bookeeping (SafepointScalarObjectNode) for eliminated objects at SafePoints + // With -XX:-Inline, constructor will not be inlined and hence AllocateNode are + // considered escapable. + MyClass obj = new MyClass(10, 20, 30, 40); + return obj.field1 * ctr + obj.field2 + obj.field3 + obj.field4; + } + + public static int micro2(int ctr) { + // small known length arrays of size less than + // -XX:+EliminateAllocationArraySizeLimit are eliminatable if non-escaping. + int[] arr = new int[5]; + arr[0] = 10; + arr[1] = 10; + arr[2] = 10; + arr[3] = 10; + arr[4] = 10; + // value forwarding will forward constants to expressions. + return ctr * arr[0] + arr[1] + arr[2] + arr[3] + arr[4]; + } + + public static int micro3(int ctr) { + int[] arr = new int[8]; + MemorySegment ms = MemorySegment.ofArray(arr); + ms.fill((byte) 10); + return ctr * ms.get(ValueLayout.JAVA_INT, 12) + + ms.get(ValueLayout.JAVA_INT, 16) + + ms.get(ValueLayout.JAVA_INT, 20) + + ms.get(ValueLayout.JAVA_INT, 24); + } + + public static void main(String[] args) { + { + int res = 0; + for (int i = 0; i < 100000; i++) { + res += micro1(i); + } + System.out.println("[res] " + res); + } + { + int res = 0; + for (int i = 0; i < 100000; i++) { + res += micro2(i); + } + System.out.println("[res] " + res); + } + { + int res = 0; + for (int i = 0; i < 100000; i++) { + res += micro3(i); + } + System.out.println("[res] " + res); + } + } +} From aaa90b3005c85852971203ce6feb88e7091e167b Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Thu, 9 May 2024 13:54:04 +0000 Subject: [PATCH 138/203] 8327476: Upgrade JLine to 3.26.1 Reviewed-by: ihse, vromero --- make/conf/module-loader-map.conf | 1 + make/modules/jdk.internal.le/Lib.gmk | 45 - .../jline/terminal/impl/jna/JDKNativePty.java | 50 - .../jline/terminal/impl/jna/JDKNativePty.java | 51 - .../terminal/impl/jna/linux/CLibrary.java | 389 ------ .../terminal/impl/jna/linux/CLibraryImpl.java | 61 - .../impl/jna/linux/LinuxNativePty.java | 122 -- .../impl/jna/linux/UtilLibraryImpl.java | 37 - .../linux/native/lible/CLibrary.cpp | 207 --- .../jline/terminal/impl/jna/JDKNativePty.java | 51 - .../jline/terminal/impl/jna/osx/CLibrary.java | 394 ------ .../terminal/impl/jna/osx/CLibraryImpl.java | 66 - .../terminal/impl/jna/osx/NativeLong.java | 43 - .../terminal/impl/jna/osx/OsXNativePty.java | 106 -- .../macosx/native/lible/CLibrary.cpp | 211 --- .../org/jline/keymap/BindingReader.java | 8 +- .../jdk/internal/org/jline/keymap/KeyMap.java | 11 +- .../internal/org/jline/reader/Binding.java | 7 +- .../jdk/internal/org/jline/reader/Buffer.java | 10 +- .../internal/org/jline/reader/Candidate.java | 20 +- .../internal/org/jline/reader/Completer.java | 5 +- .../jline/reader/CompletingParsedLine.java | 5 +- .../org/jline/reader/CompletionMatcher.java | 12 +- .../internal/org/jline/reader/EOFError.java | 20 +- .../jdk/internal/org/jline/reader/Editor.java | 4 +- .../org/jline/reader/EndOfFileException.java | 5 +- .../internal/org/jline/reader/Expander.java | 3 +- .../org/jline/reader/Highlighter.java | 2 +- .../internal/org/jline/reader/History.java | 12 +- .../internal/org/jline/reader/LineReader.java | 53 +- .../org/jline/reader/LineReaderBuilder.java | 11 +- .../jdk/internal/org/jline/reader/Macro.java | 5 +- .../org/jline/reader/MaskingCallback.java | 3 +- .../internal/org/jline/reader/ParsedLine.java | 3 +- .../jdk/internal/org/jline/reader/Parser.java | 6 +- .../org/jline/reader/PrintAboveWriter.java | 2 +- .../internal/org/jline/reader/Reference.java | 5 +- .../org/jline/reader/SyntaxError.java | 18 +- .../jline/reader/UserInterruptException.java | 12 +- .../jdk/internal/org/jline/reader/Widget.java | 3 +- .../org/jline/reader/impl/BufferImpl.java | 15 +- .../reader/impl/CompletionMatcherImpl.java | 83 +- .../jline/reader/impl/DefaultExpander.java | 33 +- .../jline/reader/impl/DefaultHighlighter.java | 8 +- .../org/jline/reader/impl/DefaultParser.java | 144 +- .../org/jline/reader/impl/InputRC.java | 394 ++++++ .../org/jline/reader/impl/KillRing.java | 2 +- .../org/jline/reader/impl/LineReaderImpl.java | 1202 ++++++++++------- .../org/jline/reader/impl/ReaderUtils.java | 8 +- .../reader/impl/SimpleMaskingCallback.java | 9 +- .../org/jline/reader/impl/UndoTree.java | 4 +- .../impl/completer/AggregateCompleter.java | 11 +- .../impl/completer/ArgumentCompleter.java | 11 +- .../reader/impl/completer/EnumCompleter.java | 5 +- .../impl/completer/FileNameCompleter.java | 20 +- .../reader/impl/completer/NullCompleter.java | 9 +- .../impl/completer/StringsCompleter.java | 7 +- .../impl/completer/SystemCompleter.java | 27 +- .../reader/impl/history/DefaultHistory.java | 77 +- .../org/jline/terminal/Attributes.java | 146 +- .../internal/org/jline/terminal/Cursor.java | 2 +- .../org/jline/terminal/MouseEvent.java | 15 +- .../jdk/internal/org/jline/terminal/Size.java | 8 +- .../internal/org/jline/terminal/Terminal.java | 59 +- .../org/jline/terminal/TerminalBuilder.java | 538 +++++--- .../terminal/impl/AbstractPosixTerminal.java | 16 +- .../org/jline/terminal/impl/AbstractPty.java | 164 ++- .../jline/terminal/impl/AbstractTerminal.java | 39 +- .../impl/AbstractWindowsConsoleWriter.java | 9 +- .../impl/AbstractWindowsTerminal.java | 164 ++- .../jline/terminal/impl/CursorSupport.java | 13 +- .../org/jline/terminal/impl/Diag.java | 64 +- .../org/jline/terminal/impl/DumbTerminal.java | 69 +- .../terminal/impl/DumbTerminalProvider.java | 92 ++ .../jline/terminal/impl/ExternalTerminal.java | 81 +- .../terminal/impl/LineDisciplineTerminal.java | 132 +- .../org/jline/terminal/impl/MouseSupport.java | 22 +- .../terminal/impl/NativeSignalHandler.java | 5 +- .../jline/terminal/impl/PosixPtyTerminal.java | 34 +- .../jline/terminal/impl/PosixSysTerminal.java | 16 +- .../terminal/impl/{ => exec}/ExecPty.java | 111 +- .../impl/exec/ExecTerminalProvider.java | 228 +++- .../org/jline/terminal/impl/ffm/CLibrary.java | 1170 ++++++++++++++++ .../jline/terminal/impl/ffm/FfmNativePty.java | 175 +++ .../impl/ffm/FfmTerminalProvider.java | 133 ++ .../org/jline/terminal/impl/ffm/Kernel32.java | 927 +++++++++++++ .../impl/ffm/NativeWinConsoleWriter.java | 35 + .../impl/ffm/NativeWinSysTerminal.java | 302 +++++ .../terminal/impl/ffm/WindowsAnsiWriter.java | 407 ++++++ .../terminal/impl/jna/LastErrorException.java | 36 - .../internal/org/jline/terminal/spi/Pty.java | 5 +- .../org/jline/terminal/spi/SystemStream.java | 15 + .../org/jline/terminal/spi/TerminalExt.java | 31 + .../jline/terminal/spi/TerminalProvider.java | 67 +- .../internal/org/jline/utils/AnsiWriter.java | 155 +-- .../jline/utils/AttributedCharSequence.java | 40 +- .../org/jline/utils/AttributedString.java | 33 +- .../jline/utils/AttributedStringBuilder.java | 127 +- .../org/jline/utils/AttributedStyle.java | 96 +- .../org/jline/utils/ClosedException.java | 5 +- .../org/jline/utils/ColorPalette.java | 25 +- .../jdk/internal/org/jline/utils/Colors.java | 165 ++- .../jdk/internal/org/jline/utils/Curses.java | 33 +- .../internal/org/jline/utils/DiffHelper.java | 39 +- .../jdk/internal/org/jline/utils/Display.java | 98 +- .../internal/org/jline/utils/ExecHelper.java | 8 +- .../jline/utils/FastBufferedOutputStream.java | 61 + .../jdk/internal/org/jline/utils/InfoCmp.java | 968 ++++++------- .../org/jline/utils/InputStreamReader.java | 32 +- .../internal/org/jline/utils/Levenshtein.java | 8 +- .../jdk/internal/org/jline/utils/Log.java | 11 +- .../internal/org/jline/utils/NonBlocking.java | 21 +- .../jline/utils/NonBlockingInputStream.java | 8 +- .../utils/NonBlockingInputStreamImpl.java | 42 +- .../utils/NonBlockingPumpInputStream.java | 12 +- .../jline/utils/NonBlockingPumpReader.java | 9 +- .../org/jline/utils/NonBlockingReader.java | 6 +- .../jline/utils/NonBlockingReaderImpl.java | 47 +- .../jdk/internal/org/jline/utils/OSUtils.java | 122 +- .../internal/org/jline/utils/PumpReader.java | 5 +- .../org/jline/utils/ShutdownHooks.java | 17 +- .../jdk/internal/org/jline/utils/Signals.java | 13 +- .../jdk/internal/org/jline/utils/Status.java | 285 ++-- .../org/jline/utils/StyleResolver.java | 14 +- .../jdk/internal/org/jline/utils/Timeout.java | 3 +- .../jdk/internal/org/jline/utils/WCWidth.java | 159 +-- .../org/jline/utils/WriterOutputStream.java | 12 +- .../org/jline/utils/windows-conemu.caps | 3 + src/jdk.internal.le/share/legal/jline.md | 4 +- .../jline/terminal/impl/jna/JnaNativePty.java | 204 --- .../impl/jna/JnaTerminalProvider.java | 105 -- .../impl/jna/JnaTerminalProvider.java | 106 -- .../terminal/impl/jna/win/IntByReference.java | 35 - .../impl/jna/win/JnaWinConsoleWriter.java | 37 - .../impl/jna/win/JnaWinSysTerminal.java | 228 ---- .../jline/terminal/impl/jna/win/Kernel32.java | 634 --------- .../terminal/impl/jna/win/Kernel32Impl.java | 85 -- .../jline/terminal/impl/jna/win/Pointer.java | 34 - .../impl/jna/win/WindowsAnsiWriter.java | 353 ----- .../windows/native/lible/Kernel32.cpp | 710 ---------- .../jline/AbstractWindowsTerminalTest.java | 14 +- .../jdk/internal/jline/KeyConversionTest.java | 13 +- .../jdk/jshell/ExecPtyGetFlagsToSetTest.java | 11 +- 143 files changed, 7584 insertions(+), 7149 deletions(-) delete mode 100644 make/modules/jdk.internal.le/Lib.gmk delete mode 100644 src/jdk.internal.le/aix/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java delete mode 100644 src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java delete mode 100644 src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary.java delete mode 100644 src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibraryImpl.java delete mode 100644 src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/LinuxNativePty.java delete mode 100644 src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/UtilLibraryImpl.java delete mode 100644 src/jdk.internal.le/linux/native/lible/CLibrary.cpp delete mode 100644 src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java delete mode 100644 src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary.java delete mode 100644 src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibraryImpl.java delete mode 100644 src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/NativeLong.java delete mode 100644 src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/OsXNativePty.java delete mode 100644 src/jdk.internal.le/macosx/native/lible/CLibrary.cpp create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java rename src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/{ => exec}/ExecPty.java (71%) create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/CLibrary.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmNativePty.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmTerminalProvider.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/Kernel32.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinConsoleWriter.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinSysTerminal.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/WindowsAnsiWriter.java delete mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/jna/LastErrorException.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java delete mode 100644 src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaNativePty.java delete mode 100644 src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/IntByReference.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Pointer.java delete mode 100644 src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java delete mode 100644 src/jdk.internal.le/windows/native/lible/Kernel32.cpp diff --git a/make/conf/module-loader-map.conf b/make/conf/module-loader-map.conf index 5b72bf78aa013..e904031186dee 100644 --- a/make/conf/module-loader-map.conf +++ b/make/conf/module-loader-map.conf @@ -120,6 +120,7 @@ NATIVE_ACCESS_MODULES= \ jdk.dynalink \ jdk.httpserver \ jdk.incubator.vector \ + jdk.internal.le \ jdk.internal.vm.ci \ jdk.jfr \ jdk.jsobject \ diff --git a/make/modules/jdk.internal.le/Lib.gmk b/make/modules/jdk.internal.le/Lib.gmk deleted file mode 100644 index e81137e0d5387..0000000000000 --- a/make/modules/jdk.internal.le/Lib.gmk +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# 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. -# - -include LibCommon.gmk - -ifeq ($(call isTargetOs, aix), false) - ############################################################################## - ## Build lible - ############################################################################## - - $(eval $(call SetupJdkLibrary, BUILD_LIBLE, \ - NAME := le, \ - LINK_TYPE := C++, \ - OPTIMIZATION := LOW, \ - EXTRA_HEADER_DIRS := \ - java.base:libjava \ - java.base:libjvm, \ - LD_SET_ORIGIN := false, \ - LIBS_windows := user32.lib, \ - )) - - TARGETS += $(BUILD_LIBLE) -endif diff --git a/src/jdk.internal.le/aix/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java b/src/jdk.internal.le/aix/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java deleted file mode 100644 index fe5e10e7e5d35..0000000000000 --- a/src/jdk.internal.le/aix/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna; - -import java.io.IOException; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.spi.TerminalProvider; - -class JDKNativePty { - - static JnaNativePty current(TerminalProvider.Stream console) throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - static JnaNativePty open(Attributes attr, Size size) throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - static int isatty(int fd) { - throw new UnsupportedOperationException("Not supported."); - } - - static String ttyname(int fd) { - throw new UnsupportedOperationException("Not supported."); - } - -} diff --git a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java b/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java deleted file mode 100644 index 199e80d9dde5a..0000000000000 --- a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna; - -import java.io.IOException; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty; -import jdk.internal.org.jline.terminal.spi.TerminalProvider; - -class JDKNativePty { - - static JnaNativePty current(TerminalProvider.Stream console) throws IOException { - return LinuxNativePty.current(console); - } - - static JnaNativePty open(Attributes attr, Size size) throws IOException { - return LinuxNativePty.open(attr, size); - } - - static int isatty(int fd) { - return LinuxNativePty.isatty(fd); - } - - static String ttyname(int fd) { - return LinuxNativePty.ttyname(fd); - } - -} diff --git a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary.java b/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary.java deleted file mode 100644 index 5a3a43c6f5e9d..0000000000000 --- a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2002-2020, the original author or authors. - * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the documentation provided with this software. - * - * https://opensource.org/licenses/BSD-3-Clause - */ -package jdk.internal.org.jline.terminal.impl.jna.linux; - -import java.util.Arrays; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.List; - -//import com.sun.jna.LastErrorException; -//import com.sun.jna.Platform; -//import com.sun.jna.Structure; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Attributes.ControlChar; -import jdk.internal.org.jline.terminal.Attributes.ControlFlag; -import jdk.internal.org.jline.terminal.Attributes.InputFlag; -import jdk.internal.org.jline.terminal.Attributes.LocalFlag; -import jdk.internal.org.jline.terminal.Attributes.OutputFlag; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.impl.jna.LastErrorException; - -public interface CLibrary {//extends com.sun.jna.Library { - - void tcgetattr(int fd, termios termios) throws LastErrorException; - - void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException; - - void ioctl(int fd, int cmd, winsize data) throws LastErrorException; - - int isatty(int fd); - - void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException; - - class winsize { //extends Structure { - public short ws_row; - public short ws_col; - public short ws_xpixel; - public short ws_ypixel; - - public winsize() { - } - - public winsize(Size ws) { - ws_row = (short) ws.getRows(); - ws_col = (short) ws.getColumns(); - } - - public Size toSize() { - return new Size(ws_col, ws_row); - } - -// @Override -// protected List getFieldOrder() { -// return Arrays.asList(// -// "ws_row",// -// "ws_col",// -// "ws_xpixel",// -// "ws_ypixel"// -// ); -// } - - } - - class termios {// extends Structure { - - public int c_iflag; - public int c_oflag; - public int c_cflag; - public int c_lflag; - public byte c_line; - public byte[] c_cc = new byte[32]; - public int c_ispeed; - public int c_ospeed; - -// @Override -// protected List getFieldOrder() { -// return Arrays.asList(// -// "c_iflag",// -// "c_oflag",// -// "c_cflag",// -// "c_lflag",// -// "c_line",// -// "c_cc",// -// "c_ispeed",// -// "c_ospeed"// -// ); -// } - - public termios() { - } - - public termios(Attributes t) { - // Input flags - c_iflag = setFlag(t.getInputFlag(InputFlag.IGNBRK), IGNBRK, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.BRKINT), BRKINT, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.IGNPAR), IGNPAR, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.PARMRK), PARMRK, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.INPCK), INPCK, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.ISTRIP), ISTRIP, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.INLCR), INLCR, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.IGNCR), IGNCR, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.ICRNL), ICRNL, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.IXON), IXON, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.IXOFF), IXOFF, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.IXANY), IXANY, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.IMAXBEL), IMAXBEL, c_iflag); - c_iflag = setFlag(t.getInputFlag(InputFlag.IUTF8), IUTF8, c_iflag); - // Output flags - c_oflag = setFlag(t.getOutputFlag(OutputFlag.OPOST), OPOST, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONLCR), ONLCR, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.OCRNL), OCRNL, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONOCR), ONOCR, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONLRET), ONLRET, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.OFILL), OFILL, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.NLDLY), NLDLY, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.TABDLY), TABDLY, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.CRDLY), CRDLY, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.FFDLY), FFDLY, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.BSDLY), BSDLY, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.VTDLY), VTDLY, c_oflag); - c_oflag = setFlag(t.getOutputFlag(OutputFlag.OFDEL), OFDEL, c_oflag); - // Control flags - c_cflag = setFlag(t.getControlFlag(ControlFlag.CS5), CS5, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.CS6), CS6, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.CS7), CS7, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.CS8), CS8, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.CSTOPB), CSTOPB, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.CREAD), CREAD, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.PARENB), PARENB, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.PARODD), PARODD, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.HUPCL), HUPCL, c_cflag); - c_cflag = setFlag(t.getControlFlag(ControlFlag.CLOCAL), CLOCAL, c_cflag); - // Local flags - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOKE), ECHOKE, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOE), ECHOE, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOK), ECHOK, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHO), ECHO, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHONL), ECHONL, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOPRT), ECHOPRT, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOCTL), ECHOCTL, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ISIG), ISIG, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.ICANON), ICANON, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.EXTPROC), EXTPROC, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.TOSTOP), TOSTOP, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.FLUSHO), FLUSHO, c_lflag); - c_lflag = setFlag(t.getLocalFlag(LocalFlag.NOFLSH), NOFLSH, c_lflag); - // Control chars - c_cc[VEOF] = (byte) t.getControlChar(ControlChar.VEOF); - c_cc[VEOL] = (byte) t.getControlChar(ControlChar.VEOL); - c_cc[VEOL2] = (byte) t.getControlChar(ControlChar.VEOL2); - c_cc[VERASE] = (byte) t.getControlChar(ControlChar.VERASE); - c_cc[VWERASE] = (byte) t.getControlChar(ControlChar.VWERASE); - c_cc[VKILL] = (byte) t.getControlChar(ControlChar.VKILL); - c_cc[VREPRINT] = (byte) t.getControlChar(ControlChar.VREPRINT); - c_cc[VINTR] = (byte) t.getControlChar(ControlChar.VINTR); - c_cc[VQUIT] = (byte) t.getControlChar(ControlChar.VQUIT); - c_cc[VSUSP] = (byte) t.getControlChar(ControlChar.VSUSP); - c_cc[VSTART] = (byte) t.getControlChar(ControlChar.VSTART); - c_cc[VSTOP] = (byte) t.getControlChar(ControlChar.VSTOP); - c_cc[VLNEXT] = (byte) t.getControlChar(ControlChar.VLNEXT); - c_cc[VDISCARD] = (byte) t.getControlChar(ControlChar.VDISCARD); - c_cc[VMIN] = (byte) t.getControlChar(ControlChar.VMIN); - c_cc[VTIME] = (byte) t.getControlChar(ControlChar.VTIME); - } - - private int setFlag(boolean flag, int value, int org) { - return flag ? (org | value) : org; - } - - public Attributes toAttributes() { - Attributes attr = new Attributes(); - // Input flags - EnumSet iflag = attr.getInputFlags(); - addFlag(c_iflag, iflag, InputFlag.IGNBRK, IGNBRK); - addFlag(c_iflag, iflag, InputFlag.IGNBRK, IGNBRK); - addFlag(c_iflag, iflag, InputFlag.BRKINT, BRKINT); - addFlag(c_iflag, iflag, InputFlag.IGNPAR, IGNPAR); - addFlag(c_iflag, iflag, InputFlag.PARMRK, PARMRK); - addFlag(c_iflag, iflag, InputFlag.INPCK, INPCK); - addFlag(c_iflag, iflag, InputFlag.ISTRIP, ISTRIP); - addFlag(c_iflag, iflag, InputFlag.INLCR, INLCR); - addFlag(c_iflag, iflag, InputFlag.IGNCR, IGNCR); - addFlag(c_iflag, iflag, InputFlag.ICRNL, ICRNL); - addFlag(c_iflag, iflag, InputFlag.IXON, IXON); - addFlag(c_iflag, iflag, InputFlag.IXOFF, IXOFF); - addFlag(c_iflag, iflag, InputFlag.IXANY, IXANY); - addFlag(c_iflag, iflag, InputFlag.IMAXBEL, IMAXBEL); - addFlag(c_iflag, iflag, InputFlag.IUTF8, IUTF8); - // Output flags - EnumSet oflag = attr.getOutputFlags(); - addFlag(c_oflag, oflag, OutputFlag.OPOST, OPOST); - addFlag(c_oflag, oflag, OutputFlag.ONLCR, ONLCR); - addFlag(c_oflag, oflag, OutputFlag.OCRNL, OCRNL); - addFlag(c_oflag, oflag, OutputFlag.ONOCR, ONOCR); - addFlag(c_oflag, oflag, OutputFlag.ONLRET, ONLRET); - addFlag(c_oflag, oflag, OutputFlag.OFILL, OFILL); - addFlag(c_oflag, oflag, OutputFlag.NLDLY, NLDLY); - addFlag(c_oflag, oflag, OutputFlag.TABDLY, TABDLY); - addFlag(c_oflag, oflag, OutputFlag.CRDLY, CRDLY); - addFlag(c_oflag, oflag, OutputFlag.FFDLY, FFDLY); - addFlag(c_oflag, oflag, OutputFlag.BSDLY, BSDLY); - addFlag(c_oflag, oflag, OutputFlag.VTDLY, VTDLY); - addFlag(c_oflag, oflag, OutputFlag.OFDEL, OFDEL); - // Control flags - EnumSet cflag = attr.getControlFlags(); - addFlag(c_cflag, cflag, ControlFlag.CS5, CS5); - addFlag(c_cflag, cflag, ControlFlag.CS6, CS6); - addFlag(c_cflag, cflag, ControlFlag.CS7, CS7); - addFlag(c_cflag, cflag, ControlFlag.CS8, CS8); - addFlag(c_cflag, cflag, ControlFlag.CSTOPB, CSTOPB); - addFlag(c_cflag, cflag, ControlFlag.CREAD, CREAD); - addFlag(c_cflag, cflag, ControlFlag.PARENB, PARENB); - addFlag(c_cflag, cflag, ControlFlag.PARODD, PARODD); - addFlag(c_cflag, cflag, ControlFlag.HUPCL, HUPCL); - addFlag(c_cflag, cflag, ControlFlag.CLOCAL, CLOCAL); - // Local flags - EnumSet lflag = attr.getLocalFlags(); - addFlag(c_lflag, lflag, LocalFlag.ECHOKE, ECHOKE); - addFlag(c_lflag, lflag, LocalFlag.ECHOE, ECHOE); - addFlag(c_lflag, lflag, LocalFlag.ECHOK, ECHOK); - addFlag(c_lflag, lflag, LocalFlag.ECHO, ECHO); - addFlag(c_lflag, lflag, LocalFlag.ECHONL, ECHONL); - addFlag(c_lflag, lflag, LocalFlag.ECHOPRT, ECHOPRT); - addFlag(c_lflag, lflag, LocalFlag.ECHOCTL, ECHOCTL); - addFlag(c_lflag, lflag, LocalFlag.ISIG, ISIG); - addFlag(c_lflag, lflag, LocalFlag.ICANON, ICANON); - addFlag(c_lflag, lflag, LocalFlag.EXTPROC, EXTPROC); - addFlag(c_lflag, lflag, LocalFlag.TOSTOP, TOSTOP); - addFlag(c_lflag, lflag, LocalFlag.FLUSHO, FLUSHO); - addFlag(c_lflag, lflag, LocalFlag.NOFLSH, NOFLSH); - // Control chars - EnumMap cc = attr.getControlChars(); - cc.put(ControlChar.VEOF, (int) c_cc[VEOF]); - cc.put(ControlChar.VEOL, (int) c_cc[VEOL]); - cc.put(ControlChar.VEOL2, (int) c_cc[VEOL2]); - cc.put(ControlChar.VERASE, (int) c_cc[VERASE]); - cc.put(ControlChar.VWERASE, (int) c_cc[VWERASE]); - cc.put(ControlChar.VKILL, (int) c_cc[VKILL]); - cc.put(ControlChar.VREPRINT, (int) c_cc[VREPRINT]); - cc.put(ControlChar.VINTR, (int) c_cc[VINTR]); - cc.put(ControlChar.VQUIT, (int) c_cc[VQUIT]); - cc.put(ControlChar.VSUSP, (int) c_cc[VSUSP]); - cc.put(ControlChar.VSTART, (int) c_cc[VSTART]); - cc.put(ControlChar.VSTOP, (int) c_cc[VSTOP]); - cc.put(ControlChar.VLNEXT, (int) c_cc[VLNEXT]); - cc.put(ControlChar.VDISCARD, (int) c_cc[VDISCARD]); - cc.put(ControlChar.VMIN, (int) c_cc[VMIN]); - cc.put(ControlChar.VTIME, (int) c_cc[VTIME]); - // Return - return attr; - } - - private > void addFlag(int value, EnumSet flags, T flag, int v) { - if ((value & v) != 0) { - flags.add(flag); - } - } - } - - // CONSTANTS - - int TIOCGWINSZ = /*Platform.isMIPS() || Platform.isPPC() || Platform.isSPARC() ? 0x40087468 : */0x00005413; - int TIOCSWINSZ = /*Platform.isMIPS() || Platform.isPPC() || Platform.isSPARC() ? 0x80087467 : */0x00005414; - - int VINTR = 0; - int VQUIT = 1; - int VERASE = 2; - int VKILL = 3; - int VEOF = 4; - int VTIME = 5; - int VMIN = 6; - int VSWTC = 7; - int VSTART = 8; - int VSTOP = 9; - int VSUSP = 10; - int VEOL = 11; - int VREPRINT = 12; - int VDISCARD = 13; - int VWERASE = 14; - int VLNEXT = 15; - int VEOL2 = 16; - - int IGNBRK = 0x0000001; - int BRKINT = 0x0000002; - int IGNPAR = 0x0000004; - int PARMRK = 0x0000008; - int INPCK = 0x0000010; - int ISTRIP = 0x0000020; - int INLCR = 0x0000040; - int IGNCR = 0x0000080; - int ICRNL = 0x0000100; - int IUCLC = 0x0000200; - int IXON = 0x0000400; - int IXANY = 0x0000800; - int IXOFF = 0x0001000; - int IMAXBEL = 0x0002000; - int IUTF8 = 0x0004000; - - int OPOST = 0x0000001; - int OLCUC = 0x0000002; - int ONLCR = 0x0000004; - int OCRNL = 0x0000008; - int ONOCR = 0x0000010; - int ONLRET = 0x0000020; - int OFILL = 0x0000040; - int OFDEL = 0x0000080; - int NLDLY = 0x0000100; - int NL0 = 0x0000000; - int NL1 = 0x0000100; - int CRDLY = 0x0000600; - int CR0 = 0x0000000; - int CR1 = 0x0000200; - int CR2 = 0x0000400; - int CR3 = 0x0000600; - int TABDLY = 0x0001800; - int TAB0 = 0x0000000; - int TAB1 = 0x0000800; - int TAB2 = 0x0001000; - int TAB3 = 0x0001800; - int XTABS = 0x0001800; - int BSDLY = 0x0002000; - int BS0 = 0x0000000; - int BS1 = 0x0002000; - int VTDLY = 0x0004000; - int VT0 = 0x0000000; - int VT1 = 0x0004000; - int FFDLY = 0x0008000; - int FF0 = 0x0000000; - int FF1 = 0x0008000; - - int CBAUD = 0x000100f; - int B0 = 0x0000000; - int B50 = 0x0000001; - int B75 = 0x0000002; - int B110 = 0x0000003; - int B134 = 0x0000004; - int B150 = 0x0000005; - int B200 = 0x0000006; - int B300 = 0x0000007; - int B600 = 0x0000008; - int B1200 = 0x0000009; - int B1800 = 0x000000a; - int B2400 = 0x000000b; - int B4800 = 0x000000c; - int B9600 = 0x000000d; - int B19200 = 0x000000e; - int B38400 = 0x000000f; - int EXTA = B19200; - int EXTB = B38400; - int CSIZE = 0x0000030; - int CS5 = 0x0000000; - int CS6 = 0x0000010; - int CS7 = 0x0000020; - int CS8 = 0x0000030; - int CSTOPB = 0x0000040; - int CREAD = 0x0000080; - int PARENB = 0x0000100; - int PARODD = 0x0000200; - int HUPCL = 0x0000400; - int CLOCAL = 0x0000800; - - int ISIG = 0x0000001; - int ICANON = 0x0000002; - int XCASE = 0x0000004; - int ECHO = 0x0000008; - int ECHOE = 0x0000010; - int ECHOK = 0x0000020; - int ECHONL = 0x0000040; - int NOFLSH = 0x0000080; - int TOSTOP = 0x0000100; - int ECHOCTL = 0x0000200; - int ECHOPRT = 0x0000400; - int ECHOKE = 0x0000800; - int FLUSHO = 0x0001000; - int PENDIN = 0x0002000; - int IEXTEN = 0x0008000; - int EXTPROC = 0x0010000; - - int TCSANOW = 0x0; - int TCSADRAIN = 0x1; - int TCSAFLUSH = 0x2; - -} diff --git a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibraryImpl.java b/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibraryImpl.java deleted file mode 100644 index 732f2d15d1e11..0000000000000 --- a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/CLibraryImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna.linux; - -import jdk.internal.org.jline.terminal.impl.jna.LastErrorException; - -public final class CLibraryImpl implements CLibrary { - - static { - System.loadLibrary("le"); - initIDs(); - } - - private static native void initIDs(); - - @Override - public native void tcgetattr(int fd, termios termios) throws LastErrorException; - - @Override - public native void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException; - - @Override - public void ioctl(int fd, int cmd, winsize data) throws LastErrorException { - if (cmd == CLibrary.TIOCGWINSZ || cmd == CLibrary.TIOCSWINSZ) { - ioctl0(fd, cmd, data); - } else { - throw new UnsupportedOperationException("Command: " + cmd + ", not supported."); - } - } - - private native void ioctl0(int fd, int cmd, winsize data) throws LastErrorException; - - @Override - public native int isatty(int fd); - - @Override - public native void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException; - -} diff --git a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/LinuxNativePty.java b/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/LinuxNativePty.java deleted file mode 100644 index b2cd60c08e72d..0000000000000 --- a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/LinuxNativePty.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2002-2020, the original author or authors. - * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the documentation provided with this software. - * - * https://opensource.org/licenses/BSD-3-Clause - */ -package jdk.internal.org.jline.terminal.impl.jna.linux; - -import java.io.FileDescriptor; -import java.io.IOException; - -//import com.sun.jna.LastErrorException; -//import com.sun.jna.Native; -//import com.sun.jna.Platform; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.impl.jna.JnaNativePty; -import jdk.internal.org.jline.terminal.impl.jna.LastErrorException; -import jdk.internal.org.jline.terminal.spi.TerminalProvider; - -import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TCSADRAIN; -import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TIOCGWINSZ; -import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TIOCSWINSZ; -import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.termios; -import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.winsize; - -public class LinuxNativePty extends JnaNativePty { - -// private static final CLibrary C_LIBRARY = Native.load(Platform.C_LIBRARY_NAME, CLibrary.class); - private static final CLibrary C_LIBRARY = new CLibraryImpl(); - - public interface UtilLibrary {// extends com.sun.jna.Library { - - void openpty(int[] master, int[] slave, byte[] name, CLibrary.termios t, CLibrary.winsize s) throws LastErrorException; - -// UtilLibrary INSTANCE = Native.load("util", UtilLibrary.class); - UtilLibrary INSTANCE = new UtilLibraryImpl(); - } - - public static LinuxNativePty current(TerminalProvider.Stream consoleStream) throws IOException { - switch (consoleStream) { - case Output: - return new LinuxNativePty(-1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(0)); - case Error: - return new LinuxNativePty(-1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(0)); - default: - throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream); - } - } - - public static LinuxNativePty open(Attributes attr, Size size) throws IOException { - int[] master = new int[1]; - int[] slave = new int[1]; - byte[] buf = new byte[64]; - UtilLibrary.INSTANCE.openpty(master, slave, buf, - attr != null ? new termios(attr) : null, - size != null ? new winsize(size) : null); - int len = 0; - while (buf[len] != 0) { - len++; - } - String name = new String(buf, 0, len); - return new LinuxNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name); - } - - public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) { - super(master, masterFD, slave, slaveFD, name); - } - - public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) { - super(master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name); - } - - @Override - public Attributes getAttr() throws IOException { - termios termios = new termios(); - C_LIBRARY.tcgetattr(getSlave(), termios); - return termios.toAttributes(); - } - - @Override - protected void doSetAttr(Attributes attr) throws IOException { - termios termios = new termios(attr); - termios org = new termios(); - C_LIBRARY.tcgetattr(getSlave(), org); - org.c_iflag = termios.c_iflag; - org.c_oflag = termios.c_oflag; - org.c_lflag = termios.c_lflag; - System.arraycopy(termios.c_cc, 0, org.c_cc, 0, termios.c_cc.length); - C_LIBRARY.tcsetattr(getSlave(), TCSADRAIN, org); - } - - @Override - public Size getSize() throws IOException { - winsize sz = new winsize(); - C_LIBRARY.ioctl(getSlave(), TIOCGWINSZ, sz); - return sz.toSize(); - } - - @Override - public void setSize(Size size) throws IOException { - winsize sz = new winsize(size); - C_LIBRARY.ioctl(getSlave(), TIOCSWINSZ, sz); - } - - public static int isatty(int fd) { - return C_LIBRARY.isatty(fd); - } - - public static String ttyname(int slave) { - byte[] buf = new byte[64]; - C_LIBRARY.ttyname_r(slave, buf, buf.length); - int len = 0; - while (buf[len] != 0) { - len++; - } - return new String(buf, 0, len); - } - -} diff --git a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/UtilLibraryImpl.java b/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/UtilLibraryImpl.java deleted file mode 100644 index 0bc8fa3994ed5..0000000000000 --- a/src/jdk.internal.le/linux/classes/jdk/internal/org/jline/terminal/impl/jna/linux/UtilLibraryImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna.linux; - -import jdk.internal.org.jline.terminal.impl.jna.LastErrorException; -import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty.UtilLibrary; - -public final class UtilLibraryImpl implements UtilLibrary { - - @Override - public void openpty(int[] master, int[] slave, byte[] name, CLibrary.termios t, CLibrary.winsize s) throws LastErrorException { - throw new UnsupportedOperationException(); - } - -} diff --git a/src/jdk.internal.le/linux/native/lible/CLibrary.cpp b/src/jdk.internal.le/linux/native/lible/CLibrary.cpp deleted file mode 100644 index 3215e1f5013bf..0000000000000 --- a/src/jdk.internal.le/linux/native/lible/CLibrary.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ - -#include "jni.h" -#include "jni_util.h" -#include "jvm.h" -#include "jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl.h" - -#include -#include -#include -#include -#include - -static jclass lastErrorExceptionClass; -static jmethodID lastErrorExceptionConstructor; - -static jclass termios_j; -static jfieldID c_iflag; -static jfieldID c_oflag; -static jfieldID c_cflag; -static jfieldID c_lflag; -static jfieldID c_line; -static jfieldID c_cc; -static jfieldID c_ispeed; -static jfieldID c_ospeed; - -static jclass winsize_j; -static jfieldID ws_row; -static jfieldID ws_col; -static jfieldID ws_xpixel; -static jfieldID ws_ypixel; - -static void throw_errno(JNIEnv *env); - -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_initIDs - (JNIEnv *env, jclass unused) { - jclass cls; - cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException"); - CHECK_NULL(cls); - lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls); - lastErrorExceptionConstructor = env->GetMethodID(lastErrorExceptionClass, "", "(J)V"); - CHECK_NULL(lastErrorExceptionConstructor); - - cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary$termios"); - CHECK_NULL(cls); - termios_j = (jclass) env->NewGlobalRef(cls); - c_iflag = env->GetFieldID(termios_j, "c_iflag", "I"); - CHECK_NULL(c_iflag); - c_oflag = env->GetFieldID(termios_j, "c_oflag", "I"); - CHECK_NULL(c_oflag); - c_cflag = env->GetFieldID(termios_j, "c_cflag", "I"); - CHECK_NULL(c_cflag); - c_lflag = env->GetFieldID(termios_j, "c_lflag", "I"); - CHECK_NULL(c_lflag); - c_line = env->GetFieldID(termios_j, "c_line", "B"); - CHECK_NULL(c_line); - c_cc = env->GetFieldID(termios_j, "c_cc", "[B"); - CHECK_NULL(c_cc); - c_ispeed = env->GetFieldID(termios_j, "c_ispeed", "I"); - CHECK_NULL(c_ispeed); - c_ospeed = env->GetFieldID(termios_j, "c_ospeed", "I"); - CHECK_NULL(c_ospeed); - - cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary$winsize"); - CHECK_NULL(cls); - winsize_j = (jclass) env->NewGlobalRef(cls); - ws_row = env->GetFieldID(winsize_j, "ws_row", "S"); - CHECK_NULL(ws_row); - ws_col = env->GetFieldID(winsize_j, "ws_col", "S"); - CHECK_NULL(ws_col); - ws_xpixel= env->GetFieldID(winsize_j, "ws_xpixel", "S"); - CHECK_NULL(ws_xpixel); - ws_ypixel= env->GetFieldID(winsize_j, "ws_ypixel", "S"); - CHECK_NULL(ws_ypixel); -} - -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_tcgetattr - (JNIEnv *env, jobject, jint fd, jobject result) { - termios data; - - if (tcgetattr(fd, &data) != 0) { - throw_errno(env); - return ; - } - - env->SetIntField(result, c_iflag, data.c_iflag); - env->SetIntField(result, c_oflag, data.c_oflag); - env->SetIntField(result, c_cflag, data.c_cflag); - env->SetIntField(result, c_lflag, data.c_lflag); - env->SetIntField(result, c_line, data.c_line); - jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(result, c_cc); - env->SetByteArrayRegion(c_ccValue, 0, NCCS, (signed char *) data.c_cc);//TODO: cast? - env->SetIntField(result, c_ispeed, cfgetispeed(&data)); - env->SetIntField(result, c_ospeed, cfgetospeed(&data)); -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl - * Method: tcsetattr - * Signature: (IILjdk/internal/org/jline/terminal/impl/jna/linux/CLibrary/termios;)V - */ -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_tcsetattr - (JNIEnv *env, jobject, jint fd, jint cmd, jobject input) { - termios data; - - data.c_iflag = env->GetIntField(input, c_iflag); - data.c_oflag = env->GetIntField(input, c_oflag); - data.c_cflag = env->GetIntField(input, c_cflag); - data.c_lflag = env->GetIntField(input, c_lflag); - data.c_line = env->GetIntField(input, c_line); - jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(input, c_cc); - env->GetByteArrayRegion(c_ccValue, 0, NCCS, (jbyte *) data.c_cc); - cfsetispeed(&data, env->GetIntField(input, c_ispeed)); - cfsetospeed(&data, env->GetIntField(input, c_ospeed)); - - if (tcsetattr(fd, cmd, &data) != 0) { - throw_errno(env); - } -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl - * Method: ioctl0 - * Signature: (IILjdk/internal/org/jline/terminal/impl/jna/linux/CLibrary/winsize;)V - */ -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_ioctl0 - (JNIEnv *env, jobject, jint fd, jint cmd, jobject data) { - winsize ws; - - ws.ws_row = env->GetShortField(data, ws_row); - ws.ws_col = env->GetShortField(data, ws_col); - ws.ws_xpixel = env->GetShortField(data, ws_xpixel); - ws.ws_ypixel = env->GetShortField(data, ws_ypixel); - - if (ioctl(fd, cmd, &ws) != 0) { - throw_errno(env); - return ; - } - - env->SetShortField(data, ws_row, ws.ws_row); - env->SetShortField(data, ws_col, ws.ws_col); - env->SetShortField(data, ws_xpixel, ws.ws_xpixel); - env->SetShortField(data, ws_ypixel, ws.ws_ypixel); -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl - * Method: isatty - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_isatty - (JNIEnv *, jobject, jint fd) { - return isatty(fd); -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl - * Method: ttyname_r - * Signature: (I[BI)V - */ -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_ttyname_1r - (JNIEnv *env, jobject, jint fd, jbyteArray buf, jint len) { - char *data = new char[len]; - int error = ttyname_r(fd, data, len); - - if (error != 0) { - delete[] data; - throw_errno(env); - return ; - } - - env->SetByteArrayRegion(buf, 0, len, (jbyte *) data); - delete[] data; -} - -/* - * Throws LastErrorException based on the errno: - */ -static void throw_errno(JNIEnv *env) { - jobject exc = env->NewObject(lastErrorExceptionClass, - lastErrorExceptionConstructor, - errno); - env->Throw((jthrowable) exc); -} diff --git a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java b/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java deleted file mode 100644 index 24b6213ca8967..0000000000000 --- a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/JDKNativePty.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna; - -import java.io.IOException; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.impl.jna.osx.OsXNativePty; -import jdk.internal.org.jline.terminal.spi.TerminalProvider; - -class JDKNativePty { - - static JnaNativePty current(TerminalProvider.Stream console) throws IOException { - return OsXNativePty.current(console); - } - - static JnaNativePty open(Attributes attr, Size size) throws IOException { - return OsXNativePty.open(attr, size); - } - - static int isatty(int fd) { - return OsXNativePty.isatty(fd); - } - - static String ttyname(int fd) { - return OsXNativePty.ttyname(fd); - } - -} diff --git a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary.java b/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary.java deleted file mode 100644 index 02c2b9224e413..0000000000000 --- a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (c) 2002-2020, the original author or authors. - * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the documentation provided with this software. - * - * https://opensource.org/licenses/BSD-3-Clause - */ -package jdk.internal.org.jline.terminal.impl.jna.osx; - -import java.util.Arrays; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.List; - -//import com.sun.jna.LastErrorException; -//import com.sun.jna.NativeLong; -//import com.sun.jna.Structure; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Attributes.ControlChar; -import jdk.internal.org.jline.terminal.Attributes.ControlFlag; -import jdk.internal.org.jline.terminal.Attributes.InputFlag; -import jdk.internal.org.jline.terminal.Attributes.LocalFlag; -import jdk.internal.org.jline.terminal.Attributes.OutputFlag; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.impl.jna.LastErrorException; - -public interface CLibrary {//extends com.sun.jna.Library { - - void tcgetattr(int fd, termios termios) throws LastErrorException; - - void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException; - - void ioctl(int fd, NativeLong cmd, winsize data) throws LastErrorException; - - int isatty(int fd); - - void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException; - - void openpty(int[] master, int[] slave, byte[] name, termios t, winsize s) throws LastErrorException; - - class winsize { //extends Structure { - public short ws_row; - public short ws_col; - public short ws_xpixel; - public short ws_ypixel; - - public winsize() { - } - - public winsize(Size ws) { - ws_row = (short) ws.getRows(); - ws_col = (short) ws.getColumns(); - } - - public Size toSize() { - return new Size(ws_col, ws_row); - } - -// @Override -// protected List getFieldOrder() { -// return Arrays.asList(// -// "ws_row",// -// "ws_col",// -// "ws_xpixel",// -// "ws_ypixel"// -// ); -// } - - } - - class termios { //extends Structure { - - public NativeLong c_iflag; - public NativeLong c_oflag; - public NativeLong c_cflag; - public NativeLong c_lflag; - public byte[] c_cc = new byte[20]; - public NativeLong c_ispeed; - public NativeLong c_ospeed; - -// @Override -// protected List getFieldOrder() { -// return Arrays.asList(// -// "c_iflag",// -// "c_oflag",// -// "c_cflag",// -// "c_lflag",// -// "c_cc",// -// "c_ispeed",// -// "c_ospeed"// -// ); -// } - - { - c_iflag = new NativeLong(0); - c_oflag = new NativeLong(0); - c_cflag = new NativeLong(0); - c_lflag = new NativeLong(0); - c_ispeed = new NativeLong(0); - c_ospeed = new NativeLong(0); - } - - public termios() { - } - - public termios(Attributes t) { - // Input flags - setFlag(t.getInputFlag(InputFlag.IGNBRK), IGNBRK, c_iflag); - setFlag(t.getInputFlag(InputFlag.BRKINT), BRKINT, c_iflag); - setFlag(t.getInputFlag(InputFlag.IGNPAR), IGNPAR, c_iflag); - setFlag(t.getInputFlag(InputFlag.PARMRK), PARMRK, c_iflag); - setFlag(t.getInputFlag(InputFlag.INPCK), INPCK, c_iflag); - setFlag(t.getInputFlag(InputFlag.ISTRIP), ISTRIP, c_iflag); - setFlag(t.getInputFlag(InputFlag.INLCR), INLCR, c_iflag); - setFlag(t.getInputFlag(InputFlag.IGNCR), IGNCR, c_iflag); - setFlag(t.getInputFlag(InputFlag.ICRNL), ICRNL, c_iflag); - setFlag(t.getInputFlag(InputFlag.IXON), IXON, c_iflag); - setFlag(t.getInputFlag(InputFlag.IXOFF), IXOFF, c_iflag); - setFlag(t.getInputFlag(InputFlag.IXANY), IXANY, c_iflag); - setFlag(t.getInputFlag(InputFlag.IMAXBEL), IMAXBEL, c_iflag); - setFlag(t.getInputFlag(InputFlag.IUTF8), IUTF8, c_iflag); - // Output flags - setFlag(t.getOutputFlag(OutputFlag.OPOST), OPOST, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.ONLCR), ONLCR, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.OXTABS), OXTABS, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.ONOEOT), ONOEOT, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.OCRNL), OCRNL, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.ONOCR), ONOCR, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.ONLRET), ONLRET, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.OFILL), OFILL, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.NLDLY), NLDLY, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.TABDLY), TABDLY, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.CRDLY), CRDLY, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.FFDLY), FFDLY, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.BSDLY), BSDLY, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.VTDLY), VTDLY, c_oflag); - setFlag(t.getOutputFlag(OutputFlag.OFDEL), OFDEL, c_oflag); - // Control flags - setFlag(t.getControlFlag(ControlFlag.CIGNORE), CIGNORE, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CS5), CS5, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CS6), CS6, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CS7), CS7, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CS8), CS8, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CSTOPB), CSTOPB, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CREAD), CREAD, c_cflag); - setFlag(t.getControlFlag(ControlFlag.PARENB), PARENB, c_cflag); - setFlag(t.getControlFlag(ControlFlag.PARODD), PARODD, c_cflag); - setFlag(t.getControlFlag(ControlFlag.HUPCL), HUPCL, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CLOCAL), CLOCAL, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CCTS_OFLOW), CCTS_OFLOW, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CRTS_IFLOW), CRTS_IFLOW, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CDTR_IFLOW), CDTR_IFLOW, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CDSR_OFLOW), CDSR_OFLOW, c_cflag); - setFlag(t.getControlFlag(ControlFlag.CCAR_OFLOW), CCAR_OFLOW, c_cflag); - // Local flags - setFlag(t.getLocalFlag(LocalFlag.ECHOKE), ECHOKE, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ECHOE), ECHOE, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ECHOK), ECHOK, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ECHO), ECHO, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ECHONL), ECHONL, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ECHOPRT), ECHOPRT, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ECHOCTL), ECHOCTL, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ISIG), ISIG, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ICANON), ICANON, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.ALTWERASE), ALTWERASE, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.IEXTEN), IEXTEN, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.EXTPROC), EXTPROC, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.TOSTOP), TOSTOP, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.FLUSHO), FLUSHO, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.NOKERNINFO), NOKERNINFO, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.PENDIN), PENDIN, c_lflag); - setFlag(t.getLocalFlag(LocalFlag.NOFLSH), NOFLSH, c_lflag); - // Control chars - c_cc[VEOF] = (byte) t.getControlChar(ControlChar.VEOF); - c_cc[VEOL] = (byte) t.getControlChar(ControlChar.VEOL); - c_cc[VEOL2] = (byte) t.getControlChar(ControlChar.VEOL2); - c_cc[VERASE] = (byte) t.getControlChar(ControlChar.VERASE); - c_cc[VWERASE] = (byte) t.getControlChar(ControlChar.VWERASE); - c_cc[VKILL] = (byte) t.getControlChar(ControlChar.VKILL); - c_cc[VREPRINT] = (byte) t.getControlChar(ControlChar.VREPRINT); - c_cc[VINTR] = (byte) t.getControlChar(ControlChar.VINTR); - c_cc[VQUIT] = (byte) t.getControlChar(ControlChar.VQUIT); - c_cc[VSUSP] = (byte) t.getControlChar(ControlChar.VSUSP); - c_cc[VDSUSP] = (byte) t.getControlChar(ControlChar.VDSUSP); - c_cc[VSTART] = (byte) t.getControlChar(ControlChar.VSTART); - c_cc[VSTOP] = (byte) t.getControlChar(ControlChar.VSTOP); - c_cc[VLNEXT] = (byte) t.getControlChar(ControlChar.VLNEXT); - c_cc[VDISCARD] = (byte) t.getControlChar(ControlChar.VDISCARD); - c_cc[VMIN] = (byte) t.getControlChar(ControlChar.VMIN); - c_cc[VTIME] = (byte) t.getControlChar(ControlChar.VTIME); - c_cc[VSTATUS] = (byte) t.getControlChar(ControlChar.VSTATUS); - } - - private void setFlag(boolean flag, long value, NativeLong org) { - org.setValue(flag ? org.longValue() | value : org.longValue()); - } - - public Attributes toAttributes() { - Attributes attr = new Attributes(); - // Input flags - EnumSet iflag = attr.getInputFlags(); - addFlag(c_iflag.longValue(), iflag, InputFlag.IGNBRK, IGNBRK); - addFlag(c_iflag.longValue(), iflag, InputFlag.IGNBRK, IGNBRK); - addFlag(c_iflag.longValue(), iflag, InputFlag.BRKINT, BRKINT); - addFlag(c_iflag.longValue(), iflag, InputFlag.IGNPAR, IGNPAR); - addFlag(c_iflag.longValue(), iflag, InputFlag.PARMRK, PARMRK); - addFlag(c_iflag.longValue(), iflag, InputFlag.INPCK, INPCK); - addFlag(c_iflag.longValue(), iflag, InputFlag.ISTRIP, ISTRIP); - addFlag(c_iflag.longValue(), iflag, InputFlag.INLCR, INLCR); - addFlag(c_iflag.longValue(), iflag, InputFlag.IGNCR, IGNCR); - addFlag(c_iflag.longValue(), iflag, InputFlag.ICRNL, ICRNL); - addFlag(c_iflag.longValue(), iflag, InputFlag.IXON, IXON); - addFlag(c_iflag.longValue(), iflag, InputFlag.IXOFF, IXOFF); - addFlag(c_iflag.longValue(), iflag, InputFlag.IXANY, IXANY); - addFlag(c_iflag.longValue(), iflag, InputFlag.IMAXBEL, IMAXBEL); - addFlag(c_iflag.longValue(), iflag, InputFlag.IUTF8, IUTF8); - // Output flags - EnumSet oflag = attr.getOutputFlags(); - addFlag(c_oflag.longValue(), oflag, OutputFlag.OPOST, OPOST); - addFlag(c_oflag.longValue(), oflag, OutputFlag.ONLCR, ONLCR); - addFlag(c_oflag.longValue(), oflag, OutputFlag.OXTABS, OXTABS); - addFlag(c_oflag.longValue(), oflag, OutputFlag.ONOEOT, ONOEOT); - addFlag(c_oflag.longValue(), oflag, OutputFlag.OCRNL, OCRNL); - addFlag(c_oflag.longValue(), oflag, OutputFlag.ONOCR, ONOCR); - addFlag(c_oflag.longValue(), oflag, OutputFlag.ONLRET, ONLRET); - addFlag(c_oflag.longValue(), oflag, OutputFlag.OFILL, OFILL); - addFlag(c_oflag.longValue(), oflag, OutputFlag.NLDLY, NLDLY); - addFlag(c_oflag.longValue(), oflag, OutputFlag.TABDLY, TABDLY); - addFlag(c_oflag.longValue(), oflag, OutputFlag.CRDLY, CRDLY); - addFlag(c_oflag.longValue(), oflag, OutputFlag.FFDLY, FFDLY); - addFlag(c_oflag.longValue(), oflag, OutputFlag.BSDLY, BSDLY); - addFlag(c_oflag.longValue(), oflag, OutputFlag.VTDLY, VTDLY); - addFlag(c_oflag.longValue(), oflag, OutputFlag.OFDEL, OFDEL); - // Control flags - EnumSet cflag = attr.getControlFlags(); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CIGNORE, CIGNORE); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CS5, CS5); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CS6, CS6); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CS7, CS7); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CS8, CS8); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CSTOPB, CSTOPB); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CREAD, CREAD); - addFlag(c_cflag.longValue(), cflag, ControlFlag.PARENB, PARENB); - addFlag(c_cflag.longValue(), cflag, ControlFlag.PARODD, PARODD); - addFlag(c_cflag.longValue(), cflag, ControlFlag.HUPCL, HUPCL); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CLOCAL, CLOCAL); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CCTS_OFLOW, CCTS_OFLOW); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CRTS_IFLOW, CRTS_IFLOW); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CDSR_OFLOW, CDSR_OFLOW); - addFlag(c_cflag.longValue(), cflag, ControlFlag.CCAR_OFLOW, CCAR_OFLOW); - // Local flags - EnumSet lflag = attr.getLocalFlags(); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOKE, ECHOKE); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOE, ECHOE); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOK, ECHOK); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHO, ECHO); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHONL, ECHONL); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOPRT, ECHOPRT); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOCTL, ECHOCTL); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ISIG, ISIG); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ICANON, ICANON); - addFlag(c_lflag.longValue(), lflag, LocalFlag.ALTWERASE, ALTWERASE); - addFlag(c_lflag.longValue(), lflag, LocalFlag.IEXTEN, IEXTEN); - addFlag(c_lflag.longValue(), lflag, LocalFlag.EXTPROC, EXTPROC); - addFlag(c_lflag.longValue(), lflag, LocalFlag.TOSTOP, TOSTOP); - addFlag(c_lflag.longValue(), lflag, LocalFlag.FLUSHO, FLUSHO); - addFlag(c_lflag.longValue(), lflag, LocalFlag.NOKERNINFO, NOKERNINFO); - addFlag(c_lflag.longValue(), lflag, LocalFlag.PENDIN, PENDIN); - addFlag(c_lflag.longValue(), lflag, LocalFlag.NOFLSH, NOFLSH); - // Control chars - EnumMap cc = attr.getControlChars(); - cc.put(ControlChar.VEOF, (int) c_cc[VEOF]); - cc.put(ControlChar.VEOL, (int) c_cc[VEOL]); - cc.put(ControlChar.VEOL2, (int) c_cc[VEOL2]); - cc.put(ControlChar.VERASE, (int) c_cc[VERASE]); - cc.put(ControlChar.VWERASE, (int) c_cc[VWERASE]); - cc.put(ControlChar.VKILL, (int) c_cc[VKILL]); - cc.put(ControlChar.VREPRINT, (int) c_cc[VREPRINT]); - cc.put(ControlChar.VINTR, (int) c_cc[VINTR]); - cc.put(ControlChar.VQUIT, (int) c_cc[VQUIT]); - cc.put(ControlChar.VSUSP, (int) c_cc[VSUSP]); - cc.put(ControlChar.VDSUSP, (int) c_cc[VDSUSP]); - cc.put(ControlChar.VSTART, (int) c_cc[VSTART]); - cc.put(ControlChar.VSTOP, (int) c_cc[VSTOP]); - cc.put(ControlChar.VLNEXT, (int) c_cc[VLNEXT]); - cc.put(ControlChar.VDISCARD, (int) c_cc[VDISCARD]); - cc.put(ControlChar.VMIN, (int) c_cc[VMIN]); - cc.put(ControlChar.VTIME, (int) c_cc[VTIME]); - cc.put(ControlChar.VSTATUS, (int) c_cc[VSTATUS]); - // Return - return attr; - } - - private > void addFlag(long value, EnumSet flags, T flag, int v) { - if ((value & v) != 0) { - flags.add(flag); - } - } - } - - // CONSTANTS - - long TIOCGWINSZ = 0x40087468L; - long TIOCSWINSZ = 0x80087467L; - - int TCSANOW = 0x00000000; - - int VEOF = 0; - int VEOL = 1; - int VEOL2 = 2; - int VERASE = 3; - int VWERASE = 4; - int VKILL = 5; - int VREPRINT = 6; - int VINTR = 8; - int VQUIT = 9; - int VSUSP = 10; - int VDSUSP = 11; - int VSTART = 12; - int VSTOP = 13; - int VLNEXT = 14; - int VDISCARD = 15; - int VMIN = 16; - int VTIME = 17; - int VSTATUS = 18; - - int IGNBRK = 0x00000001; - int BRKINT = 0x00000002; - int IGNPAR = 0x00000004; - int PARMRK = 0x00000008; - int INPCK = 0x00000010; - int ISTRIP = 0x00000020; - int INLCR = 0x00000040; - int IGNCR = 0x00000080; - int ICRNL = 0x00000100; - int IXON = 0x00000200; - int IXOFF = 0x00000400; - int IXANY = 0x00000800; - int IMAXBEL = 0x00002000; - int IUTF8 = 0x00004000; - - int OPOST = 0x00000001; - int ONLCR = 0x00000002; - int OXTABS = 0x00000004; - int ONOEOT = 0x00000008; - int OCRNL = 0x00000010; - int ONOCR = 0x00000020; - int ONLRET = 0x00000040; - int OFILL = 0x00000080; - int NLDLY = 0x00000300; - int TABDLY = 0x00000c04; - int CRDLY = 0x00003000; - int FFDLY = 0x00004000; - int BSDLY = 0x00008000; - int VTDLY = 0x00010000; - int OFDEL = 0x00020000; - - int CIGNORE = 0x00000001; - int CS5 = 0x00000000; - int CS6 = 0x00000100; - int CS7 = 0x00000200; - int CS8 = 0x00000300; - int CSTOPB = 0x00000400; - int CREAD = 0x00000800; - int PARENB = 0x00001000; - int PARODD = 0x00002000; - int HUPCL = 0x00004000; - int CLOCAL = 0x00008000; - int CCTS_OFLOW = 0x00010000; - int CRTS_IFLOW = 0x00020000; - int CDTR_IFLOW = 0x00040000; - int CDSR_OFLOW = 0x00080000; - int CCAR_OFLOW = 0x00100000; - - int ECHOKE = 0x00000001; - int ECHOE = 0x00000002; - int ECHOK = 0x00000004; - int ECHO = 0x00000008; - int ECHONL = 0x00000010; - int ECHOPRT = 0x00000020; - int ECHOCTL = 0x00000040; - int ISIG = 0x00000080; - int ICANON = 0x00000100; - int ALTWERASE = 0x00000200; - int IEXTEN = 0x00000400; - int EXTPROC = 0x00000800; - int TOSTOP = 0x00400000; - int FLUSHO = 0x00800000; - int NOKERNINFO = 0x02000000; - int PENDIN = 0x20000000; - int NOFLSH = 0x80000000; - -} diff --git a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibraryImpl.java b/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibraryImpl.java deleted file mode 100644 index da3099bb98471..0000000000000 --- a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/CLibraryImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna.osx; - -import jdk.internal.org.jline.terminal.impl.jna.LastErrorException; - -public final class CLibraryImpl implements CLibrary { - - static { - System.loadLibrary("le"); - initIDs(); - } - - private static native void initIDs(); - - @Override - public native void tcgetattr(int fd, termios termios) throws LastErrorException; - - @Override - public native void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException; - - @Override - public void ioctl(int fd, NativeLong cmd, winsize data) throws LastErrorException { - if (cmd.longValue() == CLibrary.TIOCGWINSZ || cmd.longValue() == CLibrary.TIOCSWINSZ) { - ioctl0(fd, cmd.longValue(), data); - } else { - throw new UnsupportedOperationException("Command: " + cmd + ", not supported."); - } - } - - private native void ioctl0(int fd, long cmd, winsize data) throws LastErrorException; - - @Override - public native int isatty(int fd); - - @Override - public native void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException; - - @Override - public void openpty(int[] master, int[] slave, byte[] name, termios t, winsize s) throws LastErrorException { - throw new UnsupportedOperationException(); - } - -} diff --git a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/NativeLong.java b/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/NativeLong.java deleted file mode 100644 index 7d9ab39bc33ca..0000000000000 --- a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/NativeLong.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna.osx; - -class NativeLong { - - public long value; - - public NativeLong(long value) { - this.value = value; - } - - public void setValue(long value) { - this.value = value; - } - - public long longValue() { - return value; - } - -} diff --git a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/OsXNativePty.java b/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/OsXNativePty.java deleted file mode 100644 index 12aaff4f1f102..0000000000000 --- a/src/jdk.internal.le/macosx/classes/jdk/internal/org/jline/terminal/impl/jna/osx/OsXNativePty.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2002-2020, the original author or authors. - * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the documentation provided with this software. - * - * https://opensource.org/licenses/BSD-3-Clause - */ -package jdk.internal.org.jline.terminal.impl.jna.osx; - -import java.io.FileDescriptor; -import java.io.IOException; - -//import com.sun.jna.Native; -//import com.sun.jna.NativeLong; -//import com.sun.jna.Platform; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.impl.jna.JnaNativePty; -import jdk.internal.org.jline.terminal.spi.TerminalProvider; - -import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TCSANOW; -import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TIOCGWINSZ; -import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TIOCSWINSZ; -import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.termios; -import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.winsize; - -public class OsXNativePty extends JnaNativePty { - -// private static final CLibrary C_LIBRARY = Native.load(Platform.C_LIBRARY_NAME, CLibrary.class); - private static final CLibrary C_LIBRARY = new CLibraryImpl();//Native.load(Platform.C_LIBRARY_NAME, CLibrary.class); - - public static OsXNativePty current(TerminalProvider.Stream consoleStream) throws IOException { - switch (consoleStream) { - case Output: - return new OsXNativePty(-1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(0)); - case Error: - return new OsXNativePty(-1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(0)); - default: - throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream); - } - } - - public static OsXNativePty open(Attributes attr, Size size) throws IOException { - int[] master = new int[1]; - int[] slave = new int[1]; - byte[] buf = new byte[64]; - C_LIBRARY.openpty(master, slave, buf, - attr != null ? new termios(attr) : null, - size != null ? new winsize(size) : null); - int len = 0; - while (buf[len] != 0) { - len++; - } - String name = new String(buf, 0, len); - return new OsXNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name); - } - - public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) { - super(master, masterFD, slave, slaveFD, name); - } - - public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) { - super(master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name); - } - - @Override - public Attributes getAttr() throws IOException { - termios termios = new termios(); - C_LIBRARY.tcgetattr(getSlave(), termios); - return termios.toAttributes(); - } - - @Override - protected void doSetAttr(Attributes attr) throws IOException { - termios termios = new termios(attr); - C_LIBRARY.tcsetattr(getSlave(), TCSANOW, termios); - } - - @Override - public Size getSize() throws IOException { - winsize sz = new winsize(); - C_LIBRARY.ioctl(getSlave(), new NativeLong(TIOCGWINSZ), sz); - return sz.toSize(); - } - - @Override - public void setSize(Size size) throws IOException { - winsize sz = new winsize(size); - C_LIBRARY.ioctl(getSlave(), new NativeLong(TIOCSWINSZ), sz); - } - - public static int isatty(int fd) { - return C_LIBRARY.isatty(fd); - } - - public static String ttyname(int fd) { - byte[] buf = new byte[64]; - C_LIBRARY.ttyname_r(fd, buf, buf.length); - int len = 0; - while (buf[len] != 0) { - len++; - } - return new String(buf, 0, len); - } -} diff --git a/src/jdk.internal.le/macosx/native/lible/CLibrary.cpp b/src/jdk.internal.le/macosx/native/lible/CLibrary.cpp deleted file mode 100644 index 3bc481f4afaa5..0000000000000 --- a/src/jdk.internal.le/macosx/native/lible/CLibrary.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2023, 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. - */ - -#include "jni.h" -#include "jni_util.h" -#include "jvm.h" -#include "jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl.h" - -#include -#include -#include -#include -#include - -static jclass lastErrorExceptionClass; -static jmethodID lastErrorExceptionConstructor; - -static jclass termios_j; -static jfieldID c_iflag; -static jfieldID c_oflag; -static jfieldID c_cflag; -static jfieldID c_lflag; -static jfieldID c_cc; -static jfieldID c_ispeed; -static jfieldID c_ospeed; - -static jclass winsize_j; -static jfieldID ws_row; -static jfieldID ws_col; -static jfieldID ws_xpixel; -static jfieldID ws_ypixel; - -static jclass nativelong_j; -static jfieldID nativelong_value; - -static void throw_errno(JNIEnv *env); - -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_initIDs - (JNIEnv *env, jclass) { - jclass cls; - cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException"); - CHECK_NULL(cls); - lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls); - lastErrorExceptionConstructor = env->GetMethodID(lastErrorExceptionClass, "", "(J)V"); - CHECK_NULL(lastErrorExceptionConstructor); - - cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary$termios"); - CHECK_NULL(cls); - termios_j = (jclass) env->NewGlobalRef(cls); - CHECK_NULL(termios_j); - c_iflag = env->GetFieldID(termios_j, "c_iflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;"); - CHECK_NULL(c_iflag); - c_oflag = env->GetFieldID(termios_j, "c_oflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;"); - CHECK_NULL(c_oflag); - c_cflag = env->GetFieldID(termios_j, "c_cflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;"); - CHECK_NULL(c_cflag); - c_lflag = env->GetFieldID(termios_j, "c_lflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;"); - CHECK_NULL(c_lflag); - c_cc = env->GetFieldID(termios_j, "c_cc", "[B"); - CHECK_NULL(c_cc); - c_ispeed = env->GetFieldID(termios_j, "c_ispeed", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;"); - CHECK_NULL(c_ispeed); - c_ospeed = env->GetFieldID(termios_j, "c_ospeed", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;"); - CHECK_NULL(c_ospeed); - - cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary$winsize"); - CHECK_NULL(cls); - winsize_j = (jclass) env->NewGlobalRef(cls); - ws_row = env->GetFieldID(winsize_j, "ws_row", "S"); - CHECK_NULL(ws_row); - ws_col = env->GetFieldID(winsize_j, "ws_col", "S"); - CHECK_NULL(ws_col); - ws_xpixel= env->GetFieldID(winsize_j, "ws_xpixel", "S"); - CHECK_NULL(ws_xpixel); - ws_ypixel= env->GetFieldID(winsize_j, "ws_ypixel", "S"); - CHECK_NULL(ws_ypixel); - - nativelong_j = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/NativeLong"); - CHECK_NULL(nativelong_j); - nativelong_value = env->GetFieldID(nativelong_j, "value", "J"); - CHECK_NULL(nativelong_value); -} - -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_tcgetattr - (JNIEnv *env, jobject, jint fd, jobject result) { - termios data; - - if (tcgetattr(fd, &data) != 0) { - throw_errno(env); - return ; - } - - env->SetLongField(env->GetObjectField(result, c_iflag), nativelong_value, data.c_iflag); - env->SetLongField(env->GetObjectField(result, c_oflag), nativelong_value, data.c_oflag); - env->SetLongField(env->GetObjectField(result, c_cflag), nativelong_value, data.c_cflag); - env->SetLongField(env->GetObjectField(result, c_lflag), nativelong_value, data.c_lflag); - jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(result, c_cc); - env->SetByteArrayRegion(c_ccValue, 0, NCCS, (signed char *) data.c_cc); - env->SetLongField(env->GetObjectField(result, c_ispeed), nativelong_value, data.c_ispeed); - env->SetLongField(env->GetObjectField(result, c_ospeed), nativelong_value, data.c_ospeed); -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl - * Method: tcsetattr - * Signature: (IILjdk/internal/org/jline/terminal/impl/jna/osx/CLibrary/termios;)V - */ -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_tcsetattr - (JNIEnv *env, jobject, jint fd, jint cmd, jobject input) { - termios data; - - data.c_iflag = env->GetLongField(env->GetObjectField(input, c_iflag), nativelong_value); - data.c_oflag = env->GetLongField(env->GetObjectField(input, c_oflag), nativelong_value); - data.c_cflag = env->GetLongField(env->GetObjectField(input, c_cflag), nativelong_value); - data.c_lflag = env->GetLongField(env->GetObjectField(input, c_lflag), nativelong_value); - jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(input, c_cc); - env->GetByteArrayRegion(c_ccValue, 0, NCCS, (jbyte *) data.c_cc); - data.c_ispeed = env->GetLongField(env->GetObjectField(input, c_ispeed), nativelong_value); - data.c_ospeed = env->GetLongField(env->GetObjectField(input, c_ospeed), nativelong_value); - - if (tcsetattr(fd, cmd, &data) != 0) { - throw_errno(env); - } -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl - * Method: ioctl0 - * Signature: (IILjdk/internal/org/jline/terminal/impl/jna/osx/CLibrary/winsize;)V - */ -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_ioctl0 - (JNIEnv *env, jobject, jint fd, jlong cmd, jobject data) { - winsize ws; - - ws.ws_row = env->GetShortField(data, ws_row); - ws.ws_col = env->GetShortField(data, ws_col); - ws.ws_xpixel = env->GetShortField(data, ws_xpixel); - ws.ws_ypixel = env->GetShortField(data, ws_ypixel); - - if (ioctl(fd, cmd, &ws) != 0) { - throw_errno(env); - return ; - } - - env->SetShortField(data, ws_row, ws.ws_row); - env->SetShortField(data, ws_col, ws.ws_col); - env->SetShortField(data, ws_xpixel, ws.ws_xpixel); - env->SetShortField(data, ws_ypixel, ws.ws_ypixel); -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl - * Method: isatty - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_isatty - (JNIEnv *, jobject, jint fd) { - return isatty(fd); -} - -/* - * Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl - * Method: ttyname_r - * Signature: (I[BI)V - */ -JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_ttyname_1r - (JNIEnv *env, jobject, jint fd, jbyteArray buf, jint len) { - char *data = new char[len]; - int error = ttyname_r(fd, data, len); - - if (error != 0) { - delete[] data; - throw_errno(env); - return ; - } - - env->SetByteArrayRegion(buf, 0, len, (jbyte *) data); - delete[] data; -} - -/* - * Throws LastErrorException based on the errno: - */ -static void throw_errno(JNIEnv *env) { - jobject exc = env->NewObject(lastErrorExceptionClass, - lastErrorExceptionConstructor, - errno); - env->Throw((jthrowable) exc); -} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java index 46a45ae396d2b..74d3a46ecf2a7 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -66,7 +66,7 @@ public T readBinding(KeyMap keys, KeyMap local, boolean block) { T o = null; int[] remaining = new int[1]; boolean hasRead = false; - for (;;) { + for (; ; ) { if (local != null) { o = local.getBound(opBuffer, remaining); } @@ -78,8 +78,7 @@ public T readBinding(KeyMap keys, KeyMap local, boolean block) { if (remaining[0] >= 0) { runMacro(opBuffer.substring(opBuffer.length() - remaining[0])); opBuffer.setLength(opBuffer.length() - remaining[0]); - } - else { + } else { long ambiguousTimeout = keys.getAmbiguousTimeout(); if (ambiguousTimeout > 0 && peekCharacter(ambiguousTimeout) != NonBlockingReader.READ_EXPIRED) { o = null; @@ -234,5 +233,4 @@ public String getCurrentBuffer() { public String getLastBinding() { return lastBinding; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java index 43c3a1b4fd124..a8a90ea5e0dcf 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,8 +8,6 @@ */ package jdk.internal.org.jline.keymap; -import java.io.IOException; -import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -218,7 +216,6 @@ public static Collection range(String range) { return seqs; } - public static String esc() { return "\033"; } @@ -264,7 +261,6 @@ public static String key(Terminal terminal, Capability capability) { // Methods // - public T getUnicode() { return unicode; } @@ -306,9 +302,7 @@ private static void doGetBoundKeys(KeyMap keyMap, String prefix, Map) keyMap.mapping[c], - prefix + (char) (c), - bound); + doGetBoundKeys((KeyMap) keyMap.mapping[c], prefix + (char) (c), bound); } else if (keyMap.mapping[c] != null) { bound.put(prefix + (char) (c), (T) keyMap.mapping[c]); } @@ -456,5 +450,4 @@ private static void bind(KeyMap map, CharSequence keySeq, T function, boo } } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java index 0070b55c22df2..15e7a49a64318 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,9 +14,8 @@ * @see Macro * @see Reference * @see Widget - * @see jdk.internal.org.jline.keymap.KeyMap + * @see org.jline.keymap.KeyMap * * @author Guillaume Nodet */ -public interface Binding { -} +public interface Binding {} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java index c47746f566c39..8d65891d9d900 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -84,8 +84,8 @@ public interface Buffer { void copyFrom(Buffer buffer); - // JDK specific modification - default void zeroOut() { - throw new UnsupportedOperationException(); - } + /** + * Clear any internal buffer. + */ + void zeroOut(); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java index 0e95538492d40..e28e72ffb2322 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -47,7 +47,15 @@ public Candidate(String value) { * @param complete the complete flag * @param sort the sort flag */ - public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete, int sort) { + public Candidate( + String value, + String displ, + String group, + String descr, + String suffix, + String key, + boolean complete, + int sort) { this.value = Objects.requireNonNull(value); this.displ = Objects.requireNonNull(displ); this.group = group; @@ -69,7 +77,8 @@ public Candidate(String value, String displ, String group, String descr, String * @param key the key * @param complete the complete flag */ - public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) { + public Candidate( + String value, String displ, String group, String descr, String suffix, String key, boolean complete) { this(value, displ, group, descr, suffix, key, complete, 0); } @@ -159,11 +168,10 @@ public int sort() { return sort; } - @Override public int compareTo(Candidate o) { // If both candidates have same sort, use default behavior - if( sort == o.sort() ) { + if (sort == o.sort()) { return value.compareTo(o.value); } else { return Integer.compare(sort, o.sort()); @@ -180,7 +188,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(value); + return Objects.hashCode(value); } @Override diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java index b87db7afbf02c..7a5937460d87c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,8 +18,7 @@ * @author Guillaume Nodet * @since 2.3 */ -public interface Completer -{ +public interface Completer { /** * Populates candidates with a list of possible completions for the command line. * diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java index 52a36b838969e..93558001af16a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -10,7 +10,7 @@ /** * An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules - * of the {@link jdk.internal.org.jline.reader.Parser} that produced it, knows if and how a completion candidate + * of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion candidate * should be escaped/quoted. * * @author Eric Bottard @@ -22,5 +22,4 @@ public interface CompletingParsedLine extends ParsedLine { int rawWordCursor(); int rawWordLength(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java index 58117c8f21333..4a2334642cad5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -23,8 +23,13 @@ public interface CompletionMatcher { * @param errors number of errors accepted in matching * @param originalGroupName value of JLineReader variable original-group-name */ - void compile(Map options, boolean prefix, CompletingParsedLine line - , boolean caseInsensitive, int errors, String originalGroupName); + void compile( + Map options, + boolean prefix, + CompletingParsedLine line, + boolean caseInsensitive, + int errors, + String originalGroupName); /** * @@ -44,5 +49,4 @@ void compile(Map options, boolean prefix, Completing * @return a common prefix of matched candidates */ String getCommonPrefix(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java index 382db8bc49f2b..8a4f516174e17 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java @@ -1,20 +1,10 @@ /* - * 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 + * Copyright (c) 2023, the original author(s). * - * http://www.apache.org/licenses/LICENSE-2.0 + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. * - * 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. + * https://opensource.org/licenses/BSD-3-Clause */ package jdk.internal.org.jline.reader; @@ -45,7 +35,7 @@ public String getMissing() { return missing; } - public int getOpenBrackets(){ + public int getOpenBrackets() { return openBrackets; } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java index e99706ed5d5ac..b2fadd3bd5213 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -13,6 +13,8 @@ public interface Editor { public void open(List files) throws IOException; + public void run() throws IOException; + public void setRestricted(boolean restricted); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java index 9f70420d9dff0..1e50a7ea1ae55 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -17,8 +17,7 @@ public class EndOfFileException extends RuntimeException { private static final long serialVersionUID = 528485360925144689L; private String partialLine; - public EndOfFileException() { - } + public EndOfFileException() {} public EndOfFileException(String message) { super(message); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java index 0562e92ed9604..614c89b3e6100 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -13,5 +13,4 @@ public interface Expander { String expandHistory(History history, String line); String expandVar(String word); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java index 136fb20324b89..dad62551ee062 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java index 7a669edddb5a3..0cb46a1ee9dfc 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,8 +21,7 @@ * @author Jason Dillon * @since 2.3 */ -public interface History extends Iterable -{ +public interface History extends Iterable { /** * Initialize the history for the given reader. @@ -75,7 +74,6 @@ public interface History extends Iterable */ void purge() throws IOException; - int size(); default boolean isEmpty() { @@ -110,8 +108,7 @@ default boolean isPersistable(Entry entry) { // Entries // - interface Entry - { + interface Entry { int index(); Instant time(); @@ -132,14 +129,17 @@ default Iterator reverseIterator() { default Iterator reverseIterator(int index) { return new Iterator() { private final ListIterator it = iterator(index + 1); + @Override public boolean hasNext() { return it.hasPrevious(); } + @Override public Entry next() { return it.previous(); } + @Override public void remove() { it.remove(); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java index bc719e9b46a57..bc513f5f636a1 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2023, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,7 +21,7 @@ /** Read lines from the console, with input editing. * - *

Thread safety

+ *

Thread safety

* The LineReader implementations are not thread safe, * thus you should not attempt to use a single reader in several threads. * Any attempt to call one of the readLine call while one is @@ -31,7 +31,7 @@ * {@link #printAbove(String)} or {@link #printAbove(AttributedString)} at * any time to allow text to be printed above the current prompt. * - *

Prompt strings

+ *

Prompt strings

* It is traditional for an interactive console-based program * to print a short prompt string to signal that the user is expected * to type a command. JLine supports 3 kinds of prompt string: @@ -81,7 +81,6 @@ * * */ - public interface LineReader { /** @@ -284,6 +283,7 @@ public interface LineReader { String MAIN = "main"; String EMACS = "emacs"; String SAFE = ".safe"; + String DUMB = "dumb"; String MENU = "menu"; // @@ -301,6 +301,7 @@ public interface LineReader { * they are displayed in a list below the field to be completed */ String MENU_LIST_MAX = "menu-list-max"; + String DISABLE_HISTORY = "disable-history"; String DISABLE_COMPLETION = "disable-completion"; String EDITING_MODE = "editing-mode"; @@ -317,18 +318,23 @@ public interface LineReader { String ORIGINAL_GROUP_NAME = "ORIGINAL_GROUP_NAME"; /** Completion style for displaying groups name */ String COMPLETION_STYLE_GROUP = "COMPLETION_STYLE_GROUP"; + String COMPLETION_STYLE_LIST_GROUP = "COMPLETION_STYLE_LIST_GROUP"; /** Completion style for displaying the current selected item */ String COMPLETION_STYLE_SELECTION = "COMPLETION_STYLE_SELECTION"; + String COMPLETION_STYLE_LIST_SELECTION = "COMPLETION_STYLE_LIST_SELECTION"; /** Completion style for displaying the candidate description */ String COMPLETION_STYLE_DESCRIPTION = "COMPLETION_STYLE_DESCRIPTION"; + String COMPLETION_STYLE_LIST_DESCRIPTION = "COMPLETION_STYLE_LIST_DESCRIPTION"; /** Completion style for displaying the matching part of candidates */ String COMPLETION_STYLE_STARTING = "COMPLETION_STYLE_STARTING"; + String COMPLETION_STYLE_LIST_STARTING = "COMPLETION_STYLE_LIST_STARTING"; /** Completion style for displaying the list */ String COMPLETION_STYLE_BACKGROUND = "COMPLETION_STYLE_BACKGROUND"; + String COMPLETION_STYLE_LIST_BACKGROUND = "COMPLETION_STYLE_LIST_BACKGROUND"; /** * Set the template for prompts for secondary (continuation) lines. @@ -390,6 +396,26 @@ public interface LineReader { */ String SUGGESTIONS_MIN_BUFFER_SIZE = "suggestions-min-buffer-size"; + /** + * Max number of times a command can be repeated. + */ + String MAX_REPEAT_COUNT = "max-repeat-count"; + + /** + * Number of spaces to display a tabulation, the default is 4. + */ + String TAB_WIDTH = "tab-width"; + + /** + * Name of inputrc to read at line reader creation time. + */ + String INPUT_RC_FILE_NAME = "input-rc-file-name"; + + /** + * Prefix to automatically delegate variables to system properties + */ + String SYSTEM_PROPERTY_PREFIX = "system-property-prefix"; + Map> defaultKeyMaps(); enum Option { @@ -469,8 +495,7 @@ enum Option { EMPTY_WORD_OPTIONS(true), /** Disable the undo feature */ - DISABLE_UNDO - ; + DISABLE_UNDO; private final boolean def; @@ -611,7 +636,8 @@ enum SuggestionType { * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example) * @throws java.io.IOError in case of other i/o errors */ - String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException; + String readLine(String prompt, String rightPrompt, Character mask, String buffer) + throws UserInterruptException, EndOfFileException; /** * Read a line from the in {@link InputStream}, and return the line @@ -631,7 +657,8 @@ enum SuggestionType { * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example) * @throws java.io.IOError in case of other i/o errors */ - String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException; + String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) + throws UserInterruptException, EndOfFileException; /** * Prints a line above the prompt and redraw everything. @@ -702,7 +729,7 @@ enum SuggestionType { void runMacro(String macro); /** - * Read a mouse event when the {@link jdk.internal.org.jline.utils.InfoCmp.Capability#key_mouse} sequence + * Read a mouse event when the {@link org.jline.utils.InfoCmp.Capability#key_mouse} sequence * has just been read on the input stream. * Compared to {@link Terminal#readMouseEvent()}, this method takes into account keys * that have been pushed back using {@link #runMacro(String)}. @@ -751,8 +778,8 @@ enum SuggestionType { SuggestionType getAutosuggestion(); - // JDK specific modification - default void zeroOut() { - throw new UnsupportedOperationException(); - } + /** + * Clear any internal buffers. + */ + void zeroOut(); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java index 14d5a0e8b1c3a..942bba3605d52 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -38,8 +38,7 @@ public static LineReaderBuilder builder() { Expander expander; CompletionMatcher completionMatcher; - private LineReaderBuilder() { - } + private LineReaderBuilder() {} public LineReaderBuilder terminal(Terminal terminal) { this.terminal = terminal; @@ -88,8 +87,9 @@ public LineReaderBuilder parser(Parser parser) { try { if (!Boolean.getBoolean(LineReader.PROP_SUPPORT_PARSEDLINE) && !(parser.parse("", 0) instanceof CompletingParsedLine)) { - Log.warn("The Parser of class " + parser.getClass().getName() + " does not support the CompletingParsedLine interface. " + - "Completion with escaped or quoted words won't work correctly."); + Log.warn("The Parser of class " + parser.getClass().getName() + + " does not support the CompletingParsedLine interface. " + + "Completion with escaped or quoted words won't work correctly."); } } catch (Throwable t) { // Ignore @@ -153,5 +153,4 @@ public LineReader build() { } return reader; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java index e66efcc5f9281..b00769aff52f5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -35,7 +35,6 @@ public int hashCode() { @Override public String toString() { - return "Macro[" + - sequence + ']'; + return "Macro[" + sequence + ']'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java index 03501aaf07c6a..3b624e306f28a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -31,5 +31,4 @@ public interface MaskingCallback { * @return the modified line */ String history(String line); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java index 683c4b48d776e..3d87e6b80b2eb 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -64,5 +64,4 @@ public interface ParsedLine { * @return the cursor position within the line */ int cursor(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java index 1f7df67d5739b..5db53818f67db 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -35,7 +35,7 @@ default boolean validVariableName(String name) { default String getCommand(final String line) { String out; - Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)"); + Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)"); Matcher matcher = patternCommand.matcher(line); if (matcher.find()) { out = matcher.group(1); @@ -50,7 +50,7 @@ default String getCommand(final String line) { default String getVariable(final String line) { String out = null; - Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*"); + Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*"); Matcher matcher = patternCommand.matcher(line); if (matcher.find()) { out = matcher.group(1); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java index 63c9decd19444..e23988310a593 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java index f799a3da22070..2fb1aaa671b0a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -38,7 +38,6 @@ public int hashCode() { @Override public String toString() { - return "Reference[" + - name + ']'; + return "Reference[" + name + ']'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java index e46143e4c3998..eaf3e1d758064 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java @@ -1,20 +1,10 @@ /* - * 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 + * Copyright (c) 2023, the original author(s). * - * http://www.apache.org/licenses/LICENSE-2.0 + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. * - * 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. + * https://opensource.org/licenses/BSD-3-Clause */ package jdk.internal.org.jline.reader; diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java index b5510cab5c918..68bec8041faa5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,23 +14,19 @@ * interrupt character (ctrl-C). The partially entered line is * available via the {@link #getPartialLine()} method. */ -public class UserInterruptException - extends RuntimeException -{ +public class UserInterruptException extends RuntimeException { private static final long serialVersionUID = 6172232572140736750L; private final String partialLine; - public UserInterruptException(String partialLine) - { + public UserInterruptException(String partialLine) { this.partialLine = partialLine; } /** * @return the partially entered line when ctrl-C was pressed */ - public String getPartialLine() - { + public String getPartialLine() { return partialLine; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java index d5add7fb1a7df..ae831c5eaadc6 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,5 +15,4 @@ public interface Widget extends Binding { boolean apply(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java index d0c4c2cb7ae07..a6295dbb487f4 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -20,8 +20,7 @@ * @author Jason Dillon * @since 2.0 */ -public class BufferImpl implements Buffer -{ +public class BufferImpl implements Buffer { private int cursor = 0; private int cursorCol = -1; private int[] buffer; @@ -46,7 +45,7 @@ private BufferImpl(BufferImpl buffer) { this.g1 = buffer.g1; } - public BufferImpl copy () { + public BufferImpl copy() { return new BufferImpl(this); } @@ -107,7 +106,7 @@ private int adjust(int i) { * @param c the character to insert */ public void write(int c) { - write(new int[] { c }); + write(new int[] {c}); } /** @@ -121,7 +120,7 @@ public void write(int c, boolean overTyping) { if (overTyping) { delete(1); } - write(new int[] { c }); + write(new int[] {c}); } /** @@ -224,8 +223,7 @@ public int move(final int num) { if ((cursor + where) < 0) { where = -cursor; - } - else if ((cursor + where) > length()) { + } else if ((cursor + where) > length()) { where = length() - cursor; } @@ -371,7 +369,6 @@ private void moveGapToCursor() { } } - // JDK specific modification @Override public void zeroOut() { Arrays.fill(buffer, 0); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java index f829f13d51b2c..761ee1815c3d0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,26 +8,25 @@ */ package jdk.internal.org.jline.reader.impl; -import jdk.internal.org.jline.reader.Candidate; -import jdk.internal.org.jline.reader.CompletingParsedLine; -import jdk.internal.org.jline.reader.CompletionMatcher; -import jdk.internal.org.jline.reader.LineReader; -import jdk.internal.org.jline.utils.AttributedString; - import java.util.*; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; +import jdk.internal.org.jline.reader.Candidate; +import jdk.internal.org.jline.reader.CompletingParsedLine; +import jdk.internal.org.jline.reader.CompletionMatcher; +import jdk.internal.org.jline.reader.LineReader; +import jdk.internal.org.jline.utils.AttributedString; + public class CompletionMatcherImpl implements CompletionMatcher { protected Predicate exact; protected List>, Map>>> matchers; private Map> matching; private boolean caseInsensitive; - public CompletionMatcherImpl() { - } + public CompletionMatcherImpl() {} protected void reset(boolean caseInsensitive) { this.caseInsensitive = caseInsensitive; @@ -37,8 +36,13 @@ protected void reset(boolean caseInsensitive) { } @Override - public void compile(Map options, boolean prefix, CompletingParsedLine line - , boolean caseInsensitive, int errors, String originalGroupName) { + public void compile( + Map options, + boolean prefix, + CompletingParsedLine line, + boolean caseInsensitive, + int errors, + String originalGroupName) { reset(caseInsensitive); defaultMatchers(options, prefix, line, caseInsensitive, errors, originalGroupName); } @@ -47,15 +51,18 @@ public void compile(Map options, boolean prefix, Com public List matches(List candidates) { matching = Collections.emptyMap(); Map> sortedCandidates = sort(candidates); - for (Function>, - Map>> matcher : matchers) { + for (Function>, Map>> matcher : matchers) { matching = matcher.apply(sortedCandidates); if (!matching.isEmpty()) { break; } } - return !matching.isEmpty() ? matching.entrySet().stream().flatMap(e -> e.getValue().stream()).distinct().collect(Collectors.toList()) - : new ArrayList<>(); + return !matching.isEmpty() + ? matching.entrySet().stream() + .flatMap(e -> e.getValue().stream()) + .distinct() + .collect(Collectors.toList()) + : new ArrayList<>(); } @Override @@ -63,10 +70,12 @@ public Candidate exactMatch() { if (matching == null) { throw new IllegalStateException(); } - return matching.values().stream().flatMap(Collection::stream) + return matching.values().stream() + .flatMap(Collection::stream) .filter(Candidate::complete) .filter(c -> exact.test(c.value())) - .findFirst().orElse(null); + .findFirst() + .orElse(null); } @Override @@ -84,8 +93,13 @@ public String getCommonPrefix() { /** * Default JLine matchers */ - protected void defaultMatchers(Map options, boolean prefix, CompletingParsedLine line - , boolean caseInsensitive, int errors, String originalGroupName) { + protected void defaultMatchers( + Map options, + boolean prefix, + CompletingParsedLine line, + boolean caseInsensitive, + int errors, + String originalGroupName) { // Find matchers // TODO: glob completion String wd = line.word(); @@ -94,8 +108,7 @@ protected void defaultMatchers(Map options, boolean if (prefix) { matchers = new ArrayList<>(Arrays.asList( simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wp)), - simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp)) - )); + simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp)))); if (LineReader.Option.COMPLETE_MATCHER_TYPO.isSet(options)) { matchers.add(typoMatcher(wp, errors, caseInsensitive, originalGroupName)); } @@ -109,14 +122,14 @@ protected void defaultMatchers(Map options, boolean Pattern p1 = Pattern.compile(Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*"); Pattern p2 = Pattern.compile(".*" + Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*"); matchers = new ArrayList<>(Arrays.asList( - simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s).matches()), - simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s).matches()) - )); + simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s) + .matches()), + simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s) + .matches()))); } else { matchers = new ArrayList<>(Arrays.asList( simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wdi)), - simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi)) - )); + simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi)))); } if (LineReader.Option.COMPLETE_MATCHER_CAMELCASE.isSet(options)) { matchers.add(simpleMatcher(s -> camelMatch(wd, 0, s, 0))); @@ -128,18 +141,20 @@ protected void defaultMatchers(Map options, boolean } } - protected Function>, - Map>> simpleMatcher(Predicate predicate) { + protected Function>, Map>> simpleMatcher( + Predicate predicate) { return m -> m.entrySet().stream() .filter(e -> predicate.test(e.getKey())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } - protected Function>, - Map>> typoMatcher(String word, int errors, boolean caseInsensitive, String originalGroupName) { + protected Function>, Map>> typoMatcher( + String word, int errors, boolean caseInsensitive, String originalGroupName) { return m -> { Map> map = m.entrySet().stream() - .filter(e -> ReaderUtils.distance(word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey()) < errors) + .filter(e -> ReaderUtils.distance( + word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey()) + < errors) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); if (map.size() > 1) { map.computeIfAbsent(word, w -> new ArrayList<>()) @@ -178,7 +193,8 @@ private Map> sort(List candidates) { Map> sortedCandidates = new HashMap<>(); for (Candidate candidate : candidates) { sortedCandidates - .computeIfAbsent(AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>()) + .computeIfAbsent( + AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>()) .add(candidate); } return sortedCandidates; @@ -206,5 +222,4 @@ private String getCommonStart(String str1, String str2, boolean caseInsensitive) } return new String(s1, 0, len); } - -} \ No newline at end of file +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java index b534b96ff2f04..e5e7735a38479 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -32,27 +32,25 @@ public String expandHistory(History history, String line) { if (unicode > 0) { escaped = (--unicode >= 0); sb.append(c); - } - else if (escaped) { + } else if (escaped) { if (c == 'u') { unicode = 4; } else { escaped = false; } sb.append(c); - } - else if (c == '\'') { + } else if (c == '\'') { inQuote = !inQuote; sb.append(c); - } - else if (inQuote) { + } else if (inQuote) { sb.append(c); - } - else { + } else { switch (c) { case '\\': - // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character - // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character + // any '\!' should be considered an expansion escape, so skip expansion and strip the escape + // character + // a leading '\^' should be considered an expansion escape, so skip expansion and strip the + // escape character // otherwise, add the escape escaped = true; sb.append(c); @@ -91,7 +89,8 @@ else if (inQuote) { if (history.size() == 0) { throw new IllegalArgumentException("!$: event not found"); } - String previous = history.get(history.index() - 1).trim(); + String previous = + history.get(history.index() - 1).trim(); int lastSpace = previous.lastIndexOf(' '); if (lastSpace != -1) { rep = previous.substring(lastSpace + 1); @@ -128,14 +127,18 @@ else if (inQuote) { try { idx = Integer.parseInt(line.substring(i1, i)); } catch (NumberFormatException e) { - throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); + throw new IllegalArgumentException( + (neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); } if (neg && idx > 0 && idx <= history.size()) { rep = history.get(history.index() - idx); - } else if (!neg && idx > history.index() - history.size() && idx <= history.index()) { + } else if (!neg + && idx > history.index() - history.size() + && idx <= history.index()) { rep = history.get(idx - 1); } else { - throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); + throw new IllegalArgumentException( + (neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); } break; default: diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java index ac286ad734f26..55d39efde27da 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -10,9 +10,9 @@ import java.util.regex.Pattern; +import jdk.internal.org.jline.reader.Highlighter; import jdk.internal.org.jline.reader.LineReader; import jdk.internal.org.jline.reader.LineReader.RegionType; -import jdk.internal.org.jline.reader.Highlighter; import jdk.internal.org.jline.utils.AttributedString; import jdk.internal.org.jline.utils.AttributedStringBuilder; import jdk.internal.org.jline.utils.AttributedStyle; @@ -57,7 +57,8 @@ public AttributedString highlight(LineReader reader, String buffer) { while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') { negativeStart--; } - while (negativeEnd < reader.getBuffer().length() - 1 && reader.getBuffer().atChar(negativeEnd + 1) != '\n') { + while (negativeEnd < reader.getBuffer().length() - 1 + && reader.getBuffer().atChar(negativeEnd + 1) != '\n') { negativeEnd++; } } @@ -104,5 +105,4 @@ public AttributedString highlight(LineReader reader, String buffer) { } return sb.toAttributedString(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java index d9b3a9948d505..26cdf6abc51af 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,18 +21,18 @@ public class DefaultParser implements Parser { public enum Bracket { - ROUND, // () - CURLY, // {} - SQUARE, // [] - ANGLE // <> + ROUND, // () + CURLY, // {} + SQUARE, // [] + ANGLE // <> } public static class BlockCommentDelims { private final String start; private final String end; + public BlockCommentDelims(String start, String end) { - if (start == null || end == null - || start.isEmpty() || end.isEmpty() || start.equals(end)) { + if (start == null || end == null || start.isEmpty() || end.isEmpty() || start.equals(end)) { throw new IllegalArgumentException("Bad block comment delimiter!"); } this.start = start; @@ -185,22 +185,22 @@ public void setEofOnUnclosedBracket(Bracket... brackets) { int i = 0; for (Bracket b : bs) { switch (b) { - case ROUND: - openingBrackets[i] = '('; - closingBrackets[i] = ')'; - break; - case CURLY: - openingBrackets[i] = '{'; - closingBrackets[i] = '}'; - break; - case SQUARE: - openingBrackets[i] = '['; - closingBrackets[i] = ']'; - break; - case ANGLE: - openingBrackets[i] = '<'; - closingBrackets[i] = '>'; - break; + case ROUND: + openingBrackets[i] = '('; + closingBrackets[i] = ')'; + break; + case CURLY: + openingBrackets[i] = '{'; + closingBrackets[i] = '}'; + break; + case SQUARE: + openingBrackets[i] = '['; + closingBrackets[i] = ']'; + break; + case ANGLE: + openingBrackets[i] = '<'; + closingBrackets[i] = '>'; + break; } i++; } @@ -229,7 +229,6 @@ public boolean validVariableName(String name) { return name != null && regexVariable != null && name.matches(regexVariable); } - @Override public String getCommand(final String line) { String out = ""; @@ -296,7 +295,7 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex if (quoteStart < 0 && isQuoteChar(line, i) && !lineCommented && !blockCommented) { // Start a quote block quoteStart = i; - if (current.length()==0) { + if (current.length() == 0) { quotedWord = true; if (context == ParseContext.SPLIT_LINE) { current.append(line.charAt(i)); @@ -324,13 +323,15 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex } } else { // Delimiter - rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); + rawWordLength = handleDelimiterAndGetRawWordLength( + current, words, rawWordStart, rawWordCursor, rawWordLength, i); rawWordStart = i + 1; } } else { if (quoteStart < 0 && !blockCommented && (lineCommented || isLineCommentStarted(line, i))) { lineCommented = true; - } else if (quoteStart < 0 && !lineCommented + } else if (quoteStart < 0 + && !lineCommented && (blockCommented || isCommentDelim(line, i, blockCommentStart))) { if (blockCommented) { if (blockCommentEnd != null && isCommentDelim(line, i, blockCommentEnd)) { @@ -339,12 +340,12 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex } } else { blockCommented = true; - rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); + rawWordLength = handleDelimiterAndGetRawWordLength( + current, words, rawWordStart, rawWordCursor, rawWordLength, i); i += blockCommentStart == null ? 0 : blockCommentStart.length() - 1; rawWordStart = i + 1; } - } else if (quoteStart < 0 && !lineCommented - && isCommentDelim(line, i, blockCommentEnd)) { + } else if (quoteStart < 0 && !lineCommented && isCommentDelim(line, i, blockCommentEnd)) { current.append(line.charAt(i)); blockCommentInRightOrder = false; } else if (!isEscapeChar(line, i)) { @@ -377,16 +378,14 @@ && isCommentDelim(line, i, blockCommentEnd)) { throw new EOFError(-1, -1, "Escaped new line", "newline"); } if (eofOnUnclosedQuote && quoteStart >= 0) { - throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' - ? "quote" : "dquote"); + throw new EOFError( + -1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' ? "quote" : "dquote"); } if (blockCommented) { - throw new EOFError(-1, -1, "Missing closing block comment delimiter", - "add: " + blockCommentEnd); + throw new EOFError(-1, -1, "Missing closing block comment delimiter", "add: " + blockCommentEnd); } if (!blockCommentInRightOrder) { - throw new EOFError(-1, -1, "Missing opening block comment delimiter", - "missing: " + blockCommentStart); + throw new EOFError(-1, -1, "Missing opening block comment delimiter", "missing: " + blockCommentStart); } if (bracketChecker.isClosingBracketMissing() || bracketChecker.isOpeningBracketMissing()) { String message = null; @@ -398,8 +397,13 @@ && isCommentDelim(line, i, blockCommentEnd)) { message = "Missing opening bracket"; missing = "missing: " + bracketChecker.getMissingOpeningBracket(); } - throw new EOFError(-1, -1, message, missing, - bracketChecker.getOpenBrackets(), bracketChecker.getNextClosingBracket()); + throw new EOFError( + -1, + -1, + message, + missing, + bracketChecker.getOpenBrackets(), + bracketChecker.getNextClosingBracket()); } } @@ -420,7 +424,13 @@ public boolean isDelimiter(final CharSequence buffer, final int pos) { return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos); } - private int handleDelimiterAndGetRawWordLength(StringBuilder current, List words, int rawWordStart, int rawWordCursor, int rawWordLength, int pos) { + private int handleDelimiterAndGetRawWordLength( + StringBuilder current, + List words, + int rawWordStart, + int rawWordCursor, + int rawWordLength, + int pos) { if (current.length() > 0) { words.add(current.toString()); current.setLength(0); // reset the arg @@ -470,7 +480,7 @@ private boolean isCommentDelim(final CharSequence buffer, final int pos, final S public boolean isLineCommentStarted(final CharSequence buffer, final int pos) { if (lineCommentDelims != null) { - for (String comment: lineCommentDelims) { + for (String comment : lineCommentDelims) { if (isCommentDelim(buffer, pos, comment)) { return true; } @@ -584,8 +594,8 @@ public void check(final CharSequence buffer, final int pos) { } else { bid = bracketId(closingBrackets, buffer, pos); if (bid >= 0) { - if (!nested.isEmpty() && bid == nested.get(nested.size()-1)) { - nested.remove(nested.size()-1); + if (!nested.isEmpty() && bid == nested.get(nested.size() - 1)) { + nested.remove(nested.size() - 1); } else { missingOpeningBracket = bid; } @@ -634,7 +644,7 @@ public String getNextClosingBracket() { } private int bracketId(final char[] brackets, final CharSequence buffer, final int pos) { - for (int i=0; i < brackets.length; i++) { + for (int i = 0; i < brackets.length; i++) { if (buffer.charAt(pos) == brackets[i]) { return i; } @@ -648,8 +658,7 @@ private int bracketId(final char[] brackets, final CharSequence buffer, final in * * @author Marc Prud'hommeaux */ - public class ArgumentList implements ParsedLine, CompletingParsedLine - { + public class ArgumentList implements ParsedLine, CompletingParsedLine { private final String line; private final List words; @@ -667,11 +676,21 @@ public class ArgumentList implements ParsedLine, CompletingParsedLine private final int rawWordLength; @Deprecated - public ArgumentList(final String line, final List words, - final int wordIndex, final int wordCursor, - final int cursor) { - this(line, words, wordIndex, wordCursor, cursor, - null, wordCursor, words.get(wordIndex).length()); + public ArgumentList( + final String line, + final List words, + final int wordIndex, + final int wordCursor, + final int cursor) { + this( + line, + words, + wordIndex, + wordCursor, + cursor, + null, + wordCursor, + words.get(wordIndex).length()); } /** @@ -685,10 +704,15 @@ public ArgumentList(final String line, final List words, * @param rawWordCursor the cursor position inside the raw word (i.e. including quotes and escape characters) * @param rawWordLength the raw word length, including quotes and escape characters */ - public ArgumentList(final String line, final List words, - final int wordIndex, final int wordCursor, - final int cursor, final String openingQuote, - final int rawWordCursor, final int rawWordLength) { + public ArgumentList( + final String line, + final List words, + final int wordIndex, + final int wordCursor, + final int cursor, + final String openingQuote, + final int rawWordCursor, + final int rawWordLength) { this.line = line; this.words = Collections.unmodifiableList(Objects.requireNonNull(words)); this.wordIndex = wordIndex; @@ -732,8 +756,8 @@ public CharSequence escape(CharSequence candidate, boolean complete) { Predicate needToBeEscaped; String quote = openingQuote; boolean middleQuotes = false; - if (openingQuote==null) { - for (int i=0; i < sb.length(); i++) { + if (openingQuote == null) { + for (int i = 0; i < sb.length(); i++) { if (isQuoteChar(sb, i)) { middleQuotes = true; break; @@ -746,7 +770,8 @@ public CharSequence escape(CharSequence candidate, boolean complete) { // Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does. // Also, close the quote at the end if (openingQuote != null) { - needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote); + needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) + || String.valueOf(sb.charAt(i)).equals(openingQuote); } // Completion is protected by middle quotes: // Delimiters (spaces) don't need to be escaped, nor do quotes, but everything else does. @@ -756,8 +781,8 @@ else if (middleQuotes) { // No quote protection, need to escape everything: delimiter chars (spaces), quote chars // and escapes themselves else { - needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) - || isRawQuoteChar(sb.charAt(i)); + needToBeEscaped = i -> + isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i)); } for (int i = 0; i < sb.length(); i++) { if (needToBeEscaped.test(i)) { @@ -792,5 +817,4 @@ public int rawWordLength() { return rawWordLength; } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java new file mode 100644 index 0000000000000..0c3aee057a46d --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2002-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.reader.impl; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import jdk.internal.org.jline.reader.LineReader; +import jdk.internal.org.jline.reader.Macro; +import jdk.internal.org.jline.reader.Reference; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.utils.Log; + +public final class InputRC { + + public static void configure(LineReader reader, URL url) throws IOException { + try (InputStream is = url.openStream()) { + configure(reader, is); + } + } + + public static void configure(LineReader reader, InputStream is) throws IOException { + try (InputStreamReader r = new InputStreamReader(is)) { + configure(reader, r); + } + } + + public static void configure(LineReader reader, Reader r) throws IOException { + BufferedReader br; + if (r instanceof BufferedReader) { + br = (BufferedReader) r; + } else { + br = new BufferedReader(r); + } + + Terminal terminal = reader.getTerminal(); + + if (Terminal.TYPE_DUMB.equals(terminal.getType()) || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType())) { + reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "dumb"); + } else { + reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "emacs"); + } + + reader.setKeyMap(LineReader.MAIN); + new InputRC(reader).parse(br); + if ("vi".equals(reader.getVariable(LineReader.EDITING_MODE))) { + reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.VIINS)); + } else if ("emacs".equals(reader.getVariable(LineReader.EDITING_MODE))) { + reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.EMACS)); + } else if ("dumb".equals(reader.getVariable(LineReader.EDITING_MODE))) { + reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.DUMB)); + } + } + + private final LineReader reader; + + private InputRC(LineReader reader) { + this.reader = reader; + } + + private void parse(BufferedReader br) throws IOException, IllegalArgumentException { + String line; + boolean parsing = true; + List ifsStack = new ArrayList<>(); + while ((line = br.readLine()) != null) { + try { + line = line.trim(); + if (line.length() == 0) { + continue; + } + if (line.charAt(0) == '#') { + continue; + } + int i = 0; + if (line.charAt(i) == '$') { + String cmd; + String args; + ++i; + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + int s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + cmd = line.substring(s, i); + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + args = line.substring(s, i); + if ("if".equalsIgnoreCase(cmd)) { + ifsStack.add(parsing); + if (!parsing) { + continue; + } + if (args.startsWith("term=")) { + // TODO + } else if (args.startsWith("mode=")) { + String mode = (String) reader.getVariable(LineReader.EDITING_MODE); + parsing = args.substring("mode=".length()).equalsIgnoreCase(mode); + } else { + parsing = args.equalsIgnoreCase(reader.getAppName()); + } + } else if ("else".equalsIgnoreCase(cmd)) { + if (ifsStack.isEmpty()) { + throw new IllegalArgumentException("$else found without matching $if"); + } + boolean invert = true; + for (boolean b : ifsStack) { + if (!b) { + invert = false; + break; + } + } + if (invert) { + parsing = !parsing; + } + } else if ("endif".equalsIgnoreCase(cmd)) { + if (ifsStack.isEmpty()) { + throw new IllegalArgumentException("endif found without matching $if"); + } + parsing = ifsStack.remove(ifsStack.size() - 1); + } else if ("include".equalsIgnoreCase(cmd)) { + // TODO + } + continue; + } + if (!parsing) { + continue; + } + if (line.charAt(i++) == '"') { + boolean esc = false; + for (; ; i++) { + if (i >= line.length()) { + throw new IllegalArgumentException("Missing closing quote on line '" + line + "'"); + } + if (esc) { + esc = false; + } else if (line.charAt(i) == '\\') { + esc = true; + } else if (line.charAt(i) == '"') { + break; + } + } + } + while (i < line.length() && line.charAt(i) != ':' && line.charAt(i) != ' ' && line.charAt(i) != '\t') { + i++; + } + String keySeq = line.substring(0, i); + boolean equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '='; + i++; + if (equivalency) { + i++; + } + if (keySeq.equalsIgnoreCase("set")) { + String key; + String val; + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + int s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + key = line.substring(s, i); + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + val = line.substring(s, i); + setVar(reader, key, val); + } else { + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + int start = i; + if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) { + char delim = line.charAt(i++); + boolean esc = false; + for (; ; i++) { + if (i >= line.length()) { + break; + } + if (esc) { + esc = false; + } else if (line.charAt(i) == '\\') { + esc = true; + } else if (line.charAt(i) == delim) { + break; + } + } + } + for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++) + ; + String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length())); + if (keySeq.charAt(0) == '"') { + keySeq = translateQuoted(keySeq); + } else { + // Bind key name + String keyName = + keySeq.lastIndexOf('-') > 0 ? keySeq.substring(keySeq.lastIndexOf('-') + 1) : keySeq; + char key = getKeyFromName(keyName); + keyName = keySeq.toLowerCase(); + keySeq = ""; + if (keyName.contains("meta-") || keyName.contains("m-")) { + keySeq += "\u001b"; + } + if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) { + key = (char) (Character.toUpperCase(key) & 0x1f); + } + keySeq += key; + } + if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) { + reader.getKeys().bind(new Macro(translateQuoted(val)), keySeq); + } else { + reader.getKeys().bind(new Reference(val), keySeq); + } + } + } catch (IllegalArgumentException e) { + Log.warn("Unable to parse user configuration: ", e); + } + } + } + + private static String translateQuoted(String keySeq) { + int i; + String str = keySeq.substring(1, keySeq.length() - 1); + StringBuilder sb = new StringBuilder(); + for (i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c == '\\') { + boolean ctrl = str.regionMatches(i, "\\C-", 0, 3) || str.regionMatches(i, "\\M-\\C-", 0, 6); + boolean meta = str.regionMatches(i, "\\M-", 0, 3) || str.regionMatches(i, "\\C-\\M-", 0, 6); + i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0); + if (i >= str.length()) { + break; + } + c = str.charAt(i); + if (meta) { + sb.append("\u001b"); + } + if (ctrl) { + c = c == '?' ? 0x7f : (char) (Character.toUpperCase(c) & 0x1f); + } + if (!meta && !ctrl) { + switch (c) { + case 'a': + c = 0x07; + break; + case 'b': + c = '\b'; + break; + case 'd': + c = 0x7f; + break; + case 'e': + c = 0x1b; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = 0x0b; + break; + case '\\': + c = '\\'; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + c = 0; + for (int j = 0; j < 3; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 8); + if (k < 0) { + break; + } + c = (char) (c * 8 + k); + } + c &= 0xFF; + break; + case 'x': + i++; + c = 0; + for (int j = 0; j < 2; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 16); + if (k < 0) { + break; + } + c = (char) (c * 16 + k); + } + c &= 0xFF; + break; + case 'u': + i++; + c = 0; + for (int j = 0; j < 4; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 16); + if (k < 0) { + break; + } + c = (char) (c * 16 + k); + } + break; + } + } + sb.append(c); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + private static char getKeyFromName(String name) { + if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) { + return 0x7f; + } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) { + return '\033'; + } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) { + return '\n'; + } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) { + return '\r'; + } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) { + return ' '; + } else if ("Tab".equalsIgnoreCase(name)) { + return '\t'; + } else { + return name.charAt(0); + } + } + + static void setVar(LineReader reader, String key, String val) { + if (LineReader.KEYMAP.equalsIgnoreCase(key)) { + reader.setKeyMap(val); + return; + } + + for (LineReader.Option option : LineReader.Option.values()) { + if (option.name().toLowerCase(Locale.ENGLISH).replace('_', '-').equals(val)) { + if ("on".equalsIgnoreCase(val)) { + reader.setOpt(option); + } else if ("off".equalsIgnoreCase(val)) { + reader.unsetOpt(option); + } + return; + } + } + + reader.setVariable(key, val); + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java index f89ed35d04e0d..2510fd9e32035 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java index a41f7d19bf8b1..da69d08b23c8d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2022, the original author or authors. + * Copyright (c) 2002-2023, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,6 +18,9 @@ import java.io.InputStream; import java.io.InterruptedIOException; import java.lang.reflect.Constructor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.time.Instant; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -56,6 +59,7 @@ import static jdk.internal.org.jline.keymap.KeyMap.esc; import static jdk.internal.org.jline.keymap.KeyMap.range; import static jdk.internal.org.jline.keymap.KeyMap.translate; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; /** * A reader for terminal applications. It supports custom tab-completion, @@ -66,23 +70,27 @@ * @author Guillaume Nodet */ @SuppressWarnings("StatementWithEmptyBody") -public class LineReaderImpl implements LineReader, Flushable -{ +public class LineReaderImpl implements LineReader, Flushable { public static final char NULL_MASK = 0; + /** + * @deprecated use {@link #DEFAULT_TAB_WIDTH} and {@link #getTabWidth()} + */ + @Deprecated public static final int TAB_WIDTH = 4; + public static final int DEFAULT_TAB_WIDTH = 4; public static final String DEFAULT_WORDCHARS = "*?_-.[]~=/&;!#$%^(){}<>"; public static final String DEFAULT_REMOVE_SUFFIX_CHARS = " \t\n;&|"; public static final String DEFAULT_COMMENT_BEGIN = "#"; public static final String DEFAULT_SEARCH_TERMINATORS = "\033\012"; public static final String DEFAULT_BELL_STYLE = ""; - public static final int DEFAULT_LIST_MAX = 100; - public static final int DEFAULT_MENU_LIST_MAX = Integer.MAX_VALUE; - public static final int DEFAULT_ERRORS = 2; - public static final long DEFAULT_BLINK_MATCHING_PAREN = 500L; - public static final long DEFAULT_AMBIGUOUS_BINDING = 1000L; + public static final int DEFAULT_LIST_MAX = 100; + public static final int DEFAULT_MENU_LIST_MAX = Integer.MAX_VALUE; + public static final int DEFAULT_ERRORS = 2; + public static final long DEFAULT_BLINK_MATCHING_PAREN = 500L; + public static final long DEFAULT_AMBIGUOUS_BINDING = 1000L; public static final String DEFAULT_SECONDARY_PROMPT_PATTERN = "%M> "; public static final String DEFAULT_OTHERS_GROUP_NAME = "others"; public static final String DEFAULT_ORIGINAL_GROUP_NAME = "original"; @@ -96,9 +104,10 @@ public class LineReaderImpl implements LineReader, Flushable public static final String DEFAULT_COMPLETION_STYLE_LIST_GROUP = "fg:black,bold"; public static final String DEFAULT_COMPLETION_STYLE_LIST_SELECTION = DEFAULT_COMPLETION_STYLE_SELECTION; public static final String DEFAULT_COMPLETION_STYLE_LIST_BACKGROUND = "bg:bright-magenta"; - public static final int DEFAULT_INDENTATION = 0; - public static final int DEFAULT_FEATURES_MAX_BUFFER_SIZE = 1000; - public static final int DEFAULT_SUGGESTIONS_MIN_BUFFER_SIZE = 1; + public static final int DEFAULT_INDENTATION = 0; + public static final int DEFAULT_FEATURES_MAX_BUFFER_SIZE = 1000; + public static final int DEFAULT_SUGGESTIONS_MIN_BUFFER_SIZE = 1; + public static final String DEFAULT_SYSTEM_PROPERTY_PREFIX = "org.jline.reader.props."; private static final int MIN_ROWS = 3; @@ -109,6 +118,7 @@ public class LineReaderImpl implements LineReader, Flushable public static final String FOCUS_IN_SEQ = "\033[I"; public static final String FOCUS_OUT_SEQ = "\033[O"; + public static final int DEFAULT_MAX_REPEAT_COUNT = 9999; /** * Possible states in which the current readline operation may be in. @@ -197,27 +207,28 @@ protected enum BellType { protected int searchIndex = -1; protected boolean doAutosuggestion; - // Reading buffers protected final BindingReader bindingReader; - /** * VI character find */ protected int findChar; + protected int findDir; protected int findTailAdd; /** * VI history string search */ private int searchDir; + private String searchString; /** * Region state */ protected int regionMark; + protected RegionType regionActive; private boolean forceChar; @@ -232,7 +243,7 @@ protected enum BellType { protected KillRing killRing = new KillRing(); - protected UndoTree undo = new UndoTree<>(this::setBuffer); + protected UndoTree undo; protected boolean isUndo; /** @@ -242,7 +253,7 @@ protected enum BellType { /* * Current internal state of the line reader */ - protected State state = State.DONE; + protected State state = State.DONE; protected final AtomicBoolean startedReading = new AtomicBoolean(); protected boolean reading; @@ -278,7 +289,10 @@ protected enum BellType { */ protected List commandsBuffer = new ArrayList<>(); - int candidateStartPosition = 0; + protected int candidateStartPosition = 0; + + protected String alternateIn; + protected String alternateOut; public LineReaderImpl(Terminal terminal) throws IOException { this(terminal, terminal.getName(), null); @@ -288,6 +302,7 @@ public LineReaderImpl(Terminal terminal, String appName) throws IOException { this(terminal, appName, null); } + @SuppressWarnings("this-escape") public LineReaderImpl(Terminal terminal, String appName, Map variables) { Objects.requireNonNull(terminal, "terminal can not be null"); this.terminal = terminal; @@ -300,11 +315,40 @@ public LineReaderImpl(Terminal terminal, String appName, Map var } else { this.variables = new HashMap<>(); } + String prefix = getString(SYSTEM_PROPERTY_PREFIX, DEFAULT_SYSTEM_PROPERTY_PREFIX); + if (prefix != null) { + Properties sysProps = System.getProperties(); + for (String s : sysProps.stringPropertyNames()) { + if (s.startsWith(prefix)) { + String key = s.substring(prefix.length()); + InputRC.setVar(this, key, sysProps.getProperty(s)); + } + } + } + this.keyMaps = defaultKeyMaps(); + if (!Boolean.getBoolean(PROP_DISABLE_ALTERNATE_CHARSET)) { + this.alternateIn = Curses.tputs(terminal.getStringCapability(Capability.enter_alt_charset_mode)); + this.alternateOut = Curses.tputs(terminal.getStringCapability(Capability.exit_alt_charset_mode)); + } + undo = new UndoTree<>(this::setBuffer); builtinWidgets = builtinWidgets(); widgets = new HashMap<>(builtinWidgets); bindingReader = new BindingReader(terminal.reader()); + + String inputRc = getString(INPUT_RC_FILE_NAME, null); + if (inputRc != null) { + Path inputRcPath = Paths.get(inputRc); + if (Files.exists(inputRcPath)) { + try (InputStream is = Files.newInputStream(inputRcPath)) { + InputRC.configure(this, is); + } catch (Exception e) { + Log.debug("Error reading inputRc config file: ", inputRc, e); + } + } + } + doDisplay(); } @@ -489,7 +533,8 @@ public String readLine(String prompt, Character mask) throws UserInterruptExcept * @param buffer A string that will be set for editing. * @return A line that is read from the terminal, can never be null. */ - public String readLine(String prompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException { + public String readLine(String prompt, Character mask, String buffer) + throws UserInterruptException, EndOfFileException { return readLine(prompt, null, mask, buffer); } @@ -503,7 +548,8 @@ public String readLine(String prompt, Character mask, String buffer) throws User * @param buffer A string that will be set for editing. * @return A line that is read from the terminal, can never be null. */ - public String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException { + public String readLine(String prompt, String rightPrompt, Character mask, String buffer) + throws UserInterruptException, EndOfFileException { return readLine(prompt, rightPrompt, mask != null ? new SimpleMaskingCallback(mask) : null, buffer); } @@ -517,7 +563,8 @@ public String readLine(String prompt, String rightPrompt, Character mask, String * @param buffer A string that will be set for editing. * @return A line that is read from the terminal, can never be null. */ - public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException { + public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) + throws UserInterruptException, EndOfFileException { // prompt may be null // maskingCallback may be null // buffer may be null @@ -618,23 +665,14 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin // Move into application mode if (!dumb) { terminal.puts(Capability.keypad_xmit); - if (isSet(Option.AUTO_FRESH_LINE)) - callWidget(FRESH_LINE); - if (isSet(Option.MOUSE)) - terminal.trackMouse(Terminal.MouseTracking.Normal); - if (isSet(Option.BRACKETED_PASTE)) - terminal.writer().write(BRACKETED_PASTE_ON); - } else { - // For dumb terminals, we need to make sure that CR are ignored - Attributes attr = new Attributes(originalAttributes); - attr.setInputFlag(Attributes.InputFlag.IGNCR, true); - terminal.setAttributes(attr); + if (isSet(Option.AUTO_FRESH_LINE)) callWidget(FRESH_LINE); + if (isSet(Option.MOUSE)) terminal.trackMouse(Terminal.MouseTracking.Normal); + if (isSet(Option.BRACKETED_PASTE)) terminal.writer().write(BRACKETED_PASTE_ON); } callWidget(CALLBACK_INIT); - if (!isSet(Option.DISABLE_UNDO)) - undo.newState(buf.copy()); + if (!isSet(Option.DISABLE_UNDO)) undo.newState(buf.copy()); // Draw initial prompt redrawLine(); @@ -654,7 +692,8 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin throw new EndOfFileException().partialLine(buf.length() > 0 ? buf.toString() : null); } Log.trace("Binding: ", o); - if (buf.length() == 0 && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) { + if (buf.length() == 0 + && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) { throw new EndOfFileException(); } @@ -675,12 +714,17 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin try { lock.lock(); // Get executable widget - Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) ? buf.copy() : null; + Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) + ? buf.copy() + : null; Widget w = getWidget(o); if (!w.apply()) { beep(); } - if (!isSet(Option.DISABLE_UNDO) && !isUndo && copy != null && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) + if (!isSet(Option.DISABLE_UNDO) + && !isUndo + && copy != null + && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) && !copy.toString().equals(buf.toString())) { undo.newState(buf.copy()); } @@ -718,13 +762,18 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin } else { throw e; } - } - finally { + } finally { + AtomicBoolean interrupted = new AtomicBoolean(Thread.interrupted()); try { lock.lock(); this.reading = false; + Terminal.SignalHandler tmpHandler = terminal.handle(Signal.INT, s -> interrupted.set(true)); + if (previousIntrHandler == null) { + previousIntrHandler = tmpHandler; + } + cleanup(); if (originalAttributes != null) { terminal.setAttributes(originalAttributes); @@ -741,13 +790,15 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin } finally { lock.unlock(); startedReading.set(false); + if (interrupted.get()) { + Thread.currentThread().interrupt(); + } } } } private boolean isTerminalDumb() { - return Terminal.TYPE_DUMB.equals(terminal.getType()) - || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType()); + return Terminal.TYPE_DUMB.equals(terminal.getType()) || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType()); } private void doDisplay() { @@ -757,8 +808,7 @@ private void doDisplay() { display = new Display(terminal, false); display.resize(size.getRows(), size.getColumns()); - if (isSet(Option.DELAY_LINE_WRAP)) - display.setDelayLineWrap(true); + if (isSet(Option.DELAY_LINE_WRAP)) display.setDelayLineWrap(true); } @Override @@ -965,8 +1015,10 @@ public Binding readBinding(KeyMap keys, KeyMap local) { if (!YANK_POP.equals(ref) && !YANK.equals(ref)) { killRing.resetLastYank(); } - if (!KILL_LINE.equals(ref) && !KILL_WHOLE_LINE.equals(ref) - && !BACKWARD_KILL_WORD.equals(ref) && !KILL_WORD.equals(ref)) { + if (!KILL_LINE.equals(ref) + && !KILL_WHOLE_LINE.equals(ref) + && !BACKWARD_KILL_WORD.equals(ref) + && !KILL_WORD.equals(ref)) { killRing.resetLastKill(); } } @@ -1083,7 +1135,7 @@ public void editAndAddInBuffer(File file) throws Exception { if (isSet(Option.BRACKETED_PASTE)) { terminal.writer().write(BRACKETED_PASTE_OFF); } - Constructor ctor = Class.forName("jdk.internal.org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); + Constructor ctor = Class.forName("org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); Editor editor = (Editor) ctor.newInstance(terminal, new File(file.getParent())); editor.setRestricted(true); editor.open(Collections.singletonList(file.getName())); @@ -1097,6 +1149,10 @@ public void editAndAddInBuffer(File file) throws Exception { } } + protected int getTabWidth() { + return getInt(LineReader.TAB_WIDTH, DEFAULT_TAB_WIDTH); + } + // // Widget implementation // @@ -1137,26 +1193,27 @@ protected String finish(String str) { } // we only add it to the history if the buffer is not empty - if (historyLine != null && historyLine.length() > 0 ) { + if (historyLine != null && historyLine.length() > 0) { history.add(Instant.now(), historyLine); } return str; } - protected void handleSignal(Signal signal) { + protected synchronized void handleSignal(Signal signal) { doAutosuggestion = false; if (signal == Signal.WINCH) { + size.copy(terminal.getBufferSize()); + display.resize(size.getRows(), size.getColumns()); Status status = Status.getStatus(terminal, false); if (status != null) { - status.hardReset(); + status.resize(size); + status.reset(); } - size.copy(terminal.getBufferSize()); - display.resize(size.getRows(), size.getColumns()); - // restores prompt but also prevents scrolling in consoleZ, see #492 - // redrawLine(); + terminal.puts(Capability.carriage_return); + terminal.puts(Capability.clr_eos); + redrawLine(); redisplay(); - } - else if (signal == Signal.CONT) { + } else if (signal == Signal.CONT) { terminal.enterRawMode(); size.copy(terminal.getBufferSize()); display.resize(size.getRows(), size.getColumns()); @@ -1200,13 +1257,11 @@ protected Widget getWidget(Object binding) { // public void setPrompt(final String prompt) { - this.prompt = (prompt == null ? AttributedString.EMPTY - : expandPromptPattern(prompt, 0, "", 0)); + this.prompt = (prompt == null ? AttributedString.EMPTY : expandPromptPattern(prompt, 0, "", 0)); } public void setRightPrompt(final String rightPrompt) { - this.rightPrompt = (rightPrompt == null ? AttributedString.EMPTY - : expandPromptPattern(rightPrompt, 0, "", 0)); + this.rightPrompt = (rightPrompt == null ? AttributedString.EMPTY : expandPromptPattern(rightPrompt, 0, "", 0)); } protected void setBuffer(Buffer buffer) { @@ -1233,7 +1288,7 @@ protected void setBuffer(final String buffer) { * @param op The incoming operation to remap * @return The remaped operation */ - protected String viDeleteChangeYankToRemap (String op) { + protected String viDeleteChangeYankToRemap(String op) { switch (op) { case SEND_BREAK: case BACKWARD_CHAR: @@ -1292,7 +1347,6 @@ protected boolean isInViCmdMode() { return VICMD.equals(keyMap); } - // // Movement // @@ -1332,7 +1386,6 @@ protected boolean viBackwardChar() { return true; } - // // Word movement // @@ -1365,9 +1418,7 @@ protected boolean viForwardWord() { buf.move(1); } } else { - while (buf.cursor() < buf.length() - && !isViAlphaNum(buf.currChar()) - && !isWhitespace(buf.currChar())) { + while (buf.cursor() < buf.length() && !isViAlphaNum(buf.currChar()) && !isWhitespace(buf.currChar())) { buf.move(1); } } @@ -1375,9 +1426,7 @@ protected boolean viForwardWord() { return true; } int nl = buf.currChar() == '\n' ? 1 : 0; - while (buf.cursor() < buf.length() - && nl < 2 - && isWhitespace(buf.currChar())) { + while (buf.cursor() < buf.length() && nl < 2 && isWhitespace(buf.currChar())) { buf.move(1); nl += buf.currChar() == '\n' ? 1 : 0; } @@ -1397,9 +1446,7 @@ protected boolean viForwardBlankWord() { return true; } int nl = buf.currChar() == '\n' ? 1 : 0; - while (buf.cursor() < buf.length() - && nl < 2 - && isWhitespace(buf.currChar())) { + while (buf.cursor() < buf.length() && nl < 2 && isWhitespace(buf.currChar())) { buf.move(1); nl += buf.currChar() == '\n' ? 1 : 0; } @@ -1451,7 +1498,9 @@ protected boolean viForwardWordEnd() { } } else { buf.move(1); - while (buf.cursor() < buf.length() && !isViAlphaNum(buf.nextChar()) && !isWhitespace(buf.nextChar())) { + while (buf.cursor() < buf.length() + && !isViAlphaNum(buf.nextChar()) + && !isWhitespace(buf.nextChar())) { buf.move(1); } } @@ -1720,9 +1769,7 @@ protected boolean capitalizeWord() { buf.move(1); } while (buf.cursor() < buf.length() && isWord(buf.currChar())) { - buf.currChar(first - ? Character.toUpperCase(buf.currChar()) - : Character.toLowerCase(buf.currChar())); + buf.currChar(first ? Character.toUpperCase(buf.currChar()) : Character.toLowerCase(buf.currChar())); buf.move(1); first = false; } @@ -1810,7 +1857,8 @@ protected boolean transposeWords() { sta1--; } end1 = sta1; - while (end1 < lend && !isDelimiter(buf.atChar(++end1))); + while (end1 < lend && !isDelimiter(buf.atChar(++end1))) + ; if (neg) { end2 = sta1 - 1; while (end2 > lstart && isDelimiter(buf.atChar(end2 - 1))) { @@ -1819,9 +1867,11 @@ protected boolean transposeWords() { if (end2 < lstart) { // No word before, use the word after sta2 = end1; - while (isDelimiter(buf.atChar(++sta2))); + while (isDelimiter(buf.atChar(++sta2))) + ; end2 = sta2; - while (end2 < lend && !isDelimiter(buf.atChar(++end2))); + while (end2 < lend && !isDelimiter(buf.atChar(++end2))) + ; } else { sta2 = end2; while (sta2 > lstart && !isDelimiter(buf.atChar(sta2 - 1))) { @@ -1830,7 +1880,8 @@ protected boolean transposeWords() { } } else { sta2 = end1; - while (sta2 < lend && isDelimiter(buf.atChar(++sta2))); + while (sta2 < lend && isDelimiter(buf.atChar(++sta2))) + ; if (sta2 == lend) { // No word after, use the word before end2 = sta1; @@ -1843,19 +1894,24 @@ protected boolean transposeWords() { } } else { end2 = sta2; - while (end2 < lend && !isDelimiter(buf.atChar(++end2))) ; + while (end2 < lend && !isDelimiter(buf.atChar(++end2))) + ; } } if (sta1 < sta2) { - String res = buf.substring(0, sta1) + buf.substring(sta2, end2) - + buf.substring(end1, sta2) + buf.substring(sta1, end1) + String res = buf.substring(0, sta1) + + buf.substring(sta2, end2) + + buf.substring(end1, sta2) + + buf.substring(sta1, end1) + buf.substring(end2); buf.clear(); buf.write(res); buf.cursor(neg ? end1 : end2); } else { - String res = buf.substring(0, sta2) + buf.substring(sta1, end1) - + buf.substring(end2, sta1) + buf.substring(sta2, end2) + String res = buf.substring(0, sta2) + + buf.substring(sta1, end1) + + buf.substring(end2, sta1) + + buf.substring(sta2, end2) + buf.substring(end1); buf.clear(); buf.write(res); @@ -1988,11 +2044,11 @@ private boolean vifindchar(boolean repeat) { while (count-- > 0) { do { buf.move(findDir); - } while (buf.cursor() > 0 && buf.cursor() < buf.length() + } while (buf.cursor() > 0 + && buf.cursor() < buf.length() && buf.currChar() != findChar && buf.currChar() != '\n'); - if (buf.cursor() <= 0 || buf.cursor() >= buf.length() - || buf.currChar() == '\n') { + if (buf.cursor() <= 0 || buf.cursor() >= buf.length() || buf.currChar() == '\n') { buf.cursor(cursor); return false; } @@ -2211,18 +2267,17 @@ protected boolean undefinedKey() { * character or if there was no matching bracket. */ protected boolean doViMatchBracket() { - int pos = buf.cursor(); + int pos = buf.cursor(); if (pos == buf.length()) { return false; } - int type = getBracketType(buf.atChar(pos)); - int move = (type < 0) ? -1 : 1; - int count = 1; + int type = getBracketType(buf.atChar(pos)); + int move = (type < 0) ? -1 : 1; + int count = 1; - if (type == 0) - return false; + if (type == 0) return false; while (count > 0) { pos += move; @@ -2235,8 +2290,7 @@ protected boolean doViMatchBracket() { int curType = getBracketType(buf.atChar(pos)); if (curType == type) { ++count; - } - else if (curType == -type) { + } else if (curType == -type) { --count; } } @@ -2245,8 +2299,7 @@ else if (curType == -type) { * Slight adjustment for delete-to, yank-to, change-to to ensure * that the matching paren is consumed */ - if (move > 0 && isInViMoveOperation()) - ++pos; + if (move > 0 && isInViMoveOperation()) ++pos; buf.cursor(pos); return true; @@ -2259,14 +2312,20 @@ else if (curType == -type) { * @return 1 is square, 2 curly, 3 parent, or zero for none. The value * will be negated if it is the closing form of the bracket. */ - protected int getBracketType (int ch) { + protected int getBracketType(int ch) { switch (ch) { - case '[': return 1; - case ']': return -1; - case '{': return 2; - case '}': return -2; - case '(': return 3; - case ')': return -3; + case '[': + return 1; + case ']': + return -1; + case '{': + return 2; + case '}': + return -2; + case '(': + return 3; + case ')': + return -3; default: return 0; } @@ -2331,7 +2390,7 @@ protected boolean sendBreak() { buf.clear(); println(); redrawLine(); -// state = State.INTERRUPT; + // state = State.INTERRUPT; return false; } return true; @@ -2378,6 +2437,10 @@ protected boolean negArgument() { protected boolean digitArgument() { String s = getLastBinding(); repeatCount = (repeatCount * 10) + s.charAt(s.length() - 1) - '0'; + int maxRepeatCount = getInt(MAX_REPEAT_COUNT, DEFAULT_MAX_REPEAT_COUNT); + if (repeatCount > maxRepeatCount) { + throw new IllegalArgumentException("digit argument should be less than " + maxRepeatCount); + } isArgDigit = true; return true; } @@ -2438,10 +2501,12 @@ protected boolean viYankTo() { protected boolean viYankWholeLine() { int s, e; int p = buf.cursor(); - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; s = buf.cursor(); for (int i = 0; i < repeatCount; i++) { - while (buf.move(1) == 1 && buf.prevChar() != '\n') ; + while (buf.move(1) == 1 && buf.prevChar() != '\n') + ; } e = buf.cursor(); yankBuffer = buf.substring(s, e); @@ -2554,15 +2619,19 @@ protected boolean historyIncrementalSearchBackward() { return doSearchHistory(true); } - static class Pair { - final U u; final V v; + static class Pair { + final U u; + final V v; + public Pair(U u, V v) { this.u = u; this.v = v; } + public U getU() { return u; } + public V getV() { return v; } @@ -2575,7 +2644,8 @@ protected boolean doSearchHistory(boolean backward) { KeyMap terminators = new KeyMap<>(); getString(SEARCH_TERMINATORS, DEFAULT_SEARCH_TERMINATORS) - .codePoints().forEach(c -> bind(terminators, ACCEPT_LINE, new String(Character.toChars(c)))); + .codePoints() + .forEach(c -> bind(terminators, ACCEPT_LINE, new String(Character.toChars(c)))); Buffer originalBuffer = buf.copy(); searchIndex = -1; @@ -2583,8 +2653,8 @@ protected boolean doSearchHistory(boolean backward) { searchBackward = backward; searchFailing = false; post = () -> new AttributedString((searchFailing ? "failing" + " " : "") - + (searchBackward ? "bck-i-search" : "fwd-i-search") - + ": " + searchTerm + "_"); + + (searchBackward ? "bck-i-search" : "fwd-i-search") + + ": " + searchTerm + "_"); redisplay(); try { @@ -2630,8 +2700,9 @@ protected boolean doSearchHistory(boolean backward) { searchFailing = false; } else { boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE_SEARCH); - Pattern pat = Pattern.compile(pattern, caseInsensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE - : Pattern.UNICODE_CASE); + Pattern pat = Pattern.compile( + pattern, + caseInsensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE : Pattern.UNICODE_CASE); Pair pair = null; if (searchBackward) { boolean nextOnly = next; @@ -2641,7 +2712,11 @@ protected boolean doSearchHistory(boolean backward) { .orElse(null); if (pair == null) { pair = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(history.reverseIterator(searchIndex < 0 ? history.last() : searchIndex - 1), Spliterator.ORDERED), false) + Spliterators.spliteratorUnknownSize( + history.reverseIterator( + searchIndex < 0 ? history.last() : searchIndex - 1), + Spliterator.ORDERED), + false) .flatMap(e -> matches(pat, e.line(), e.index()).stream()) .findFirst() .orElse(null); @@ -2654,7 +2729,11 @@ protected boolean doSearchHistory(boolean backward) { .orElse(null); if (pair == null) { pair = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(history.iterator((searchIndex < 0 ? history.last() : searchIndex) + 1), Spliterator.ORDERED), false) + Spliterators.spliteratorUnknownSize( + history.iterator( + (searchIndex < 0 ? history.last() : searchIndex) + 1), + Spliterator.ORDERED), + false) .flatMap(e -> matches(pat, e.line(), e.index()).stream()) .findFirst() .orElse(null); @@ -2714,7 +2793,10 @@ private String doGetSearchPattern() { sb.append("\\E"); inQuote = false; } - sb.append("[").append(Character.toLowerCase(c)).append(Character.toUpperCase(c)).append("]"); + sb.append("[") + .append(Character.toLowerCase(c)) + .append(Character.toUpperCase(c)) + .append("]"); } else { if (!inQuote) { sb.append("\\Q"); @@ -2742,8 +2824,7 @@ private void pushBackBinding(boolean skip) { } protected boolean historySearchForward() { - if (historyBuffer == null || buf.length() == 0 - || !buf.toString().equals(history.current())) { + if (historyBuffer == null || buf.length() == 0 || !buf.toString().equals(history.current())) { historyBuffer = buf.copy(); searchBuffer = getFirstWord(); } @@ -2791,8 +2872,7 @@ private CharSequence getFirstWord() { } protected boolean historySearchBackward() { - if (historyBuffer == null || buf.length() == 0 - || !buf.toString().equals(history.current())) { + if (historyBuffer == null || buf.length() == 0 || !buf.toString().equals(history.current())) { historyBuffer = buf.copy(); searchBuffer = getFirstWord(); } @@ -2984,7 +3064,7 @@ protected boolean acceptLine() { } void indention(int nb, StringBuilder sb) { - int indent = getInt(INDENTATION, DEFAULT_INDENTATION)*nb; + int indent = getInt(INDENTATION, DEFAULT_INDENTATION) * nb; for (int i = 0; i < indent; i++) { sb.append(' '); } @@ -3017,7 +3097,6 @@ protected boolean overwriteMode() { return true; } - // // History Control // @@ -3108,13 +3187,11 @@ protected boolean downHistory() { } protected boolean viUpLineOrHistory() { - return upLine() - || upHistory() && viFirstNonBlank(); + return upLine() || upHistory() && viFirstNonBlank(); } protected boolean viDownLineOrHistory() { - return downLine() - || downHistory() && viFirstNonBlank(); + return downLine() || downHistory() && viFirstNonBlank(); } protected boolean upLine() { @@ -3175,8 +3252,7 @@ protected boolean viChangeWholeLine() { } protected boolean viChangeEol() { - return viChange(buf.cursor(), buf.length()) - && setKeyMap(VIINS); + return viChange(buf.cursor(), buf.length()) && setKeyMap(VIINS); } protected boolean viKillEol() { @@ -3199,7 +3275,8 @@ protected boolean quotedInsert() { protected boolean viJoin() { if (buf.down()) { - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; buf.backspace(); buf.write(' '); buf.move(-1); @@ -3253,14 +3330,16 @@ protected boolean viEndOfLine() { protected boolean beginningOfLine() { while (count-- > 0) { - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; } return true; } protected boolean endOfLine() { while (count-- > 0) { - while (buf.move(1) == 1 && buf.currChar() != '\n') ; + while (buf.move(1) == 1 && buf.currChar() != '\n') + ; } return true; } @@ -3384,7 +3463,7 @@ protected boolean doViDeleteOrChange(int startPos, int endPos, boolean isChange) // what is really happening is that if we are in "move-mode" then the // cursor can't be moved off the end of the line, but in "edit-mode" it // is ok, but I have no easy way of knowing which mode we are in. - if (! isChange && startPos > 0 && startPos == buf.length()) { + if (!isChange && startPos > 0 && startPos == buf.length()) { buf.move(-1); } return true; @@ -3424,14 +3503,16 @@ protected boolean viYankTo(int startPos, int endPos) { } protected boolean viOpenLineAbove() { - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; buf.write('\n'); buf.move(-1); return setKeyMap(VIINS); } protected boolean viOpenLineBelow() { - while (buf.move(1) == 1 && buf.currChar() != '\n') ; + while (buf.move(1) == 1 && buf.currChar() != '\n') + ; buf.write('\n'); return setKeyMap(VIINS); } @@ -3443,11 +3524,12 @@ protected boolean viOpenLineBelow() { */ protected boolean viPutAfter() { if (yankBuffer.indexOf('\n') >= 0) { - while (buf.move(1) == 1 && buf.currChar() != '\n'); + while (buf.move(1) == 1 && buf.currChar() != '\n') + ; buf.move(1); putString(yankBuffer); - buf.move(- yankBuffer.length()); - } else if (yankBuffer.length () != 0) { + buf.move(-yankBuffer.length()); + } else if (yankBuffer.length() != 0) { if (buf.cursor() < buf.length()) { buf.move(1); } @@ -3461,10 +3543,11 @@ protected boolean viPutAfter() { protected boolean viPutBefore() { if (yankBuffer.indexOf('\n') >= 0) { - while (buf.move(-1) == -1 && buf.prevChar() != '\n'); + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; putString(yankBuffer); - buf.move(- yankBuffer.length()); - } else if (yankBuffer.length () != 0) { + buf.move(-yankBuffer.length()); + } else if (yankBuffer.length() != 0) { if (buf.cursor() > 0) { buf.move(-1); } @@ -3681,7 +3764,7 @@ protected Map builtinWidgets() { addBuiltinWidget(widgets, MENU_EXPAND_OR_COMPLETE, this::menuExpandOrComplete); addBuiltinWidget(widgets, NEG_ARGUMENT, this::negArgument); addBuiltinWidget(widgets, OVERWRITE_MODE, this::overwriteMode); -// addBuiltinWidget(widgets, QUIT, this::quit); + // addBuiltinWidget(widgets, QUIT, this::quit); addBuiltinWidget(widgets, QUOTED_INSERT, this::quotedInsert); addBuiltinWidget(widgets, REDISPLAY, this::redisplay); addBuiltinWidget(widgets, REDRAW_LINE, this::redrawLine); @@ -3774,6 +3857,7 @@ private Widget namedWidget(String name, Widget widget) { public String toString() { return name; } + @Override public boolean apply() { return widget.apply(); @@ -3797,14 +3881,11 @@ protected void redisplay(boolean flush) { Status status = Status.getStatus(terminal, false); if (status != null) { - if (terminal.getType().startsWith(AbstractWindowsTerminal.TYPE_WINDOWS)) { - status.resize(); - } status.redraw(); } if (size.getRows() > 0 && size.getRows() < MIN_ROWS) { - AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); sb.append(prompt); concat(getHighlightedBuffer(buf.toString()).columnSplitLength(Integer.MAX_VALUE), sb); @@ -3877,14 +3958,15 @@ protected void redisplay(boolean flush) { int cursorNewLinesId = -1; int cursorColPos = -1; if (size.getColumns() > 0) { - AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); sb.append(prompt); String buffer = buf.upToCursor(); if (maskingCallback != null) { buffer = maskingCallback.display(buffer); } sb.append(insertSecondaryPrompts(new AttributedString(buffer), secondaryPrompts, false)); - List promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + List promptLines = + sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); if (!promptLines.isEmpty()) { cursorNewLinesId = promptLines.size() - 1; cursorColPos = promptLines.get(promptLines.size() - 1).columnLength(); @@ -3904,7 +3986,7 @@ protected void redisplay(boolean flush) { int lineId = newLines.size() - displaySize + 1; int endId = displaySize; int startId = 1; - if (lineId > cursorNewLinesId) { + if (lineId > cursorNewLinesId) { lineId = cursorNewLinesId; endId = displaySize - 1; startId = 0; @@ -3949,10 +4031,9 @@ private String matchPreviousCommand(String buffer) { } History history = getHistory(); StringBuilder sb = new StringBuilder(); - for (char c: buffer.replace("\\", "\\\\").toCharArray()) { - if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '*' - || c == '$' || c == '.' || c == '?' || c == '+' || c == '|' || c == '<' || c == '>' || c == '!' - || c == '-') { + for (char c : buffer.replace("\\", "\\\\").toCharArray()) { + if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '*' || c == '$' + || c == '.' || c == '?' || c == '+' || c == '|' || c == '<' || c == '>' || c == '!' || c == '-') { sb.append('\\'); } sb.append(c); @@ -3984,7 +4065,7 @@ public AttributedString getDisplayedBufferWithPrompts(List sec AttributedString attBuf = getHighlightedBuffer(buf.toString()); AttributedString tNewBuf = insertSecondaryPrompts(attBuf, secondaryPrompts); - AttributedStringBuilder full = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder full = new AttributedStringBuilder().tabs(getTabWidth()); full.append(prompt); full.append(tNewBuf); if (doAutosuggestion && !isTerminalDumb()) { @@ -4040,15 +4121,15 @@ private AttributedString getHighlightedBuffer(String buffer) { if (maskingCallback != null) { buffer = maskingCallback.display(buffer); } - if (highlighter != null && !isSet(Option.DISABLE_HIGHLIGHTER) + if (highlighter != null + && !isSet(Option.DISABLE_HIGHLIGHTER) && buffer.length() < getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE)) { return highlighter.highlight(this, buffer); } return new AttributedString(buffer); } - private AttributedString expandPromptPattern(String pattern, int padToWidth, - String message, int line) { + private AttributedString expandPromptPattern(String pattern, int padToWidth, String message, int line) { ArrayList parts = new ArrayList<>(); boolean isHidden = false; int padPartIndex = -1; @@ -4065,7 +4146,8 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, if (ch == '%' && i < plen) { int count = 0; boolean countSeen = false; - decode: while (true) { + decode: + while (true) { ch = pattern.charAt(i++); switch (ch) { case '{': @@ -4073,7 +4155,7 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, String str = sb.toString(); AttributedString astr; if (!isHidden) { - astr = AttributedString.fromAnsi(str); + astr = fromAnsi(str); cols += astr.columnLength(); } else { astr = new AttributedString(str, AttributedStyle.HIDDEN); @@ -4096,12 +4178,10 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, sb.append(getInt(LINE_OFFSET, 0) + line); break decode; case 'M': - if (message != null) - sb.append(message); + if (message != null) sb.append(message); break decode; case 'P': - if (countSeen && count >= 0) - padToWidth = count; + if (countSeen && count >= 0) padToWidth = count; if (i < plen) { padChar = pattern.charAt(i++); // FIXME check surrogate @@ -4140,25 +4220,28 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, break decode; } } - } else - sb.append(ch); + } else sb.append(ch); } if (padToWidth > cols && padToWidth > 0) { int padCharCols = WCWidth.wcwidth(padChar); int padCount = (padToWidth - cols) / padCharCols; sb = padPartString; - while (--padCount >= 0) - sb.insert(padPos, (char) padChar); // FIXME if wide - parts.set(padPartIndex, AttributedString.fromAnsi(sb.toString())); + while (--padCount >= 0) sb.insert(padPos, (char) padChar); // FIXME if wide + parts.set(padPartIndex, fromAnsi(sb.toString())); } return AttributedString.join(null, parts); } + private AttributedString fromAnsi(String str) { + return AttributedString.fromAnsi(str, Collections.singletonList(0), alternateIn, alternateOut); + } + private AttributedString insertSecondaryPrompts(AttributedString str, List prompts) { return insertSecondaryPrompts(str, prompts, true); } - private AttributedString insertSecondaryPrompts(AttributedString strAtt, List prompts, boolean computePrompts) { + private AttributedString insertSecondaryPrompts( + AttributedString strAtt, List prompts, boolean computePrompts) { Objects.requireNonNull(prompts); List lines = strAtt.columnSplitLength(Integer.MAX_VALUE); AttributedStringBuilder sb = new AttributedStringBuilder(); @@ -4171,7 +4254,9 @@ private AttributedString insertSecondaryPrompts(AttributedString strAtt, List size.getColumns() || prompt.contains('\n')) { - width = new TerminalLine(prompt.toString(), 0, size.getColumns()).getEndLine().length(); + width = new TerminalLine(prompt.toString(), 0, size.getColumns()) + .getEndLine() + .length(); } for (int line = 0; line < lines.size() - 1; line++) { AttributedString prompt; @@ -4227,11 +4312,9 @@ private AttributedString insertSecondaryPrompts(AttributedString strAtt, List 0 - && line.charAt(line.length() - 1) == '\n'; + boolean endsWithNl = line.length() > 0 && line.charAt(line.length() - 1) == '\n'; // columnLength counts -1 for the final newline; adjust for that - int nb = size.getColumns() - width - - (line.columnLength() + (endsWithNl ? 1 : 0)); + int nb = size.getColumns() - width - (line.columnLength() + (endsWithNl ? 1 : 0)); if (nb >= 3) { AttributedStringBuilder sb = new AttributedStringBuilder(size.getColumns()); sb.append(line, 0, endsWithNl ? line.length() - 1 : line.length()); @@ -4253,8 +4336,8 @@ private AttributedString addRightPrompt(AttributedString prompt, AttributedStrin protected boolean insertTab() { return isSet(Option.INSERT_TAB) - && getLastBinding().equals("\t") - && buf.toString().matches("(^|[\\s\\S]*\n)[\r\n\t ]*"); + && getLastBinding().equals("\t") + && buf.toString().matches("(^|[\\s\\S]*\n)[\r\n\t ]*"); } protected boolean expandHistory() { @@ -4465,7 +4548,8 @@ else if (isSet(Option.RECOGNIZE_EXACT)) { if (op != null) { String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS); String ref = op instanceof Reference ? ((Reference) op).name() : null; - if (SELF_INSERT.equals(ref) && chars.indexOf(getLastBinding().charAt(0)) >= 0 + if (SELF_INSERT.equals(ref) + && chars.indexOf(getLastBinding().charAt(0)) >= 0 || ACCEPT_LINE.equals(ref)) { buf.backspace(completion.suffix().length()); if (getLastBinding().charAt(0) != ' ') { @@ -4533,27 +4617,35 @@ protected static CompletingParsedLine wrap(ParsedLine line) { public String word() { return line.word(); } + public int wordCursor() { return line.wordCursor(); } + public int wordIndex() { return line.wordIndex(); } + public List words() { return line.words(); } + public String line() { return line.line(); } + public int cursor() { return line.cursor(); } + public CharSequence escape(CharSequence candidate, boolean complete) { return candidate; } + public int rawWordCursor() { return wordCursor(); } + public int rawWordLength() { return word().length(); } @@ -4564,8 +4656,7 @@ public int rawWordLength() { protected Comparator getCandidateComparator(boolean caseInsensitive, String word) { String wdi = caseInsensitive ? word.toLowerCase() : word; ToIntFunction wordDistance = w -> ReaderUtils.distance(wdi, caseInsensitive ? w.toLowerCase() : w); - return Comparator - .comparing(Candidate::value, Comparator.comparingInt(wordDistance)) + return Comparator.comparing(Candidate::value, Comparator.comparingInt(wordDistance)) .thenComparing(Comparator.naturalOrder()); } @@ -4577,9 +4668,10 @@ protected String getOriginalGroupName() { return getString(ORIGINAL_GROUP_NAME, DEFAULT_ORIGINAL_GROUP_NAME); } - protected Comparator getGroupComparator() { - return Comparator.comparingInt(s -> getOthersGroupName().equals(s) ? 1 : getOriginalGroupName().equals(s) ? -1 : 0) + return Comparator.comparingInt(s -> getOthersGroupName().equals(s) + ? 1 + : getOriginalGroupName().equals(s) ? -1 : 0) .thenComparing(String::toLowerCase, Comparator.naturalOrder()); } @@ -4600,11 +4692,9 @@ private void mergeCandidates(List possible) { // the same description candidates.sort(Comparator.comparing(Candidate::value)); Candidate first = candidates.get(0); - String disp = candidates.stream() - .map(Candidate::displ) - .collect(Collectors.joining(" ")); - possible.add(new Candidate(first.value(), disp, first.group(), - first.descr(), first.suffix(), null, first.complete())); + String disp = candidates.stream().map(Candidate::displ).collect(Collectors.joining(" ")); + possible.add(new Candidate( + first.value(), disp, first.group(), first.descr(), first.suffix(), null, first.complete())); } } } @@ -4636,8 +4726,10 @@ private int visibleDisplayRows() { } private int promptLines() { - AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); - return text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); + AttributedString text = + insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); + return text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) + .size(); } private class MenuSupport implements Supplier { @@ -4651,7 +4743,8 @@ private class MenuSupport implements Supplier { int columns; String completed; - public MenuSupport(List original, String completed, BiFunction escaper) { + public MenuSupport( + List original, String completed, BiFunction escaper) { this.possible = new ArrayList<>(); this.escaper = escaper; this.selection = -1; @@ -4714,7 +4807,7 @@ private void minor(int step) { if (selection - row + axis > options) { // selection is the last row/column // so there are fewer options than other rows - axis = options%axis; + axis = options % axis; } selection = selection - row + ((axis + row + step) % axis); update(); @@ -4772,7 +4865,9 @@ private void update() { AttributedString post = pr.post; if (post.length() > 0 && post.charAt(post.length() - 1) != '\n') { post = new AttributedStringBuilder(post.length() + 1) - .append(post).append("\n").toAttributedString(); + .append(post) + .append("\n") + .toAttributedString(); } List lines = post.columnSplitLength(size.getColumns(), true, display.delayLineWrap()); List sub = new ArrayList<>(lines.subList(topLine, topLine + displayed)); @@ -4785,7 +4880,8 @@ private void update() { .append(" of ") .append(Integer.toString(lines.size())) .append("\n") - .style(AttributedStyle.DEFAULT).toAttributedString()); + .style(AttributedStyle.DEFAULT) + .toAttributedString()); computed = AttributedString.join(AttributedString.EMPTY, sub); } else { computed = pr.post; @@ -4798,10 +4894,10 @@ private void update() { public AttributedString get() { return computed; } - } - protected boolean doMenu(List original, String completed, BiFunction escaper) { + protected boolean doMenu( + List original, String completed, BiFunction escaper) { // Reorder candidates according to display order final List possible = new ArrayList<>(); boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE); @@ -4854,7 +4950,7 @@ protected boolean doMenu(List original, String completed, BiFunction< if (completion.suffix() != null) { String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS); if (SELF_INSERT.equals(ref) - && chars.indexOf(getLastBinding().charAt(0)) >= 0 + && chars.indexOf(getLastBinding().charAt(0)) >= 0 || BACKWARD_DELETE_CHAR.equals(ref)) { buf.backspace(completion.suffix().length()); } @@ -4866,8 +4962,8 @@ && getLastBinding().charAt(0) != ' ' } if (!ACCEPT_LINE.equals(ref) && !(SELF_INSERT.equals(ref) - && completion.suffix() != null - && completion.suffix().startsWith(getLastBinding()))) { + && completion.suffix() != null + && completion.suffix().startsWith(getLastBinding()))) { pushBackBinding(true); } post = null; @@ -4888,29 +4984,40 @@ protected boolean clearChoices() { return doList(new ArrayList<>(), "", false, null, false); } - protected boolean doList(List possible - , String completed, boolean runLoop, BiFunction escaper) { + protected boolean doList( + List possible, + String completed, + boolean runLoop, + BiFunction escaper) { return doList(possible, completed, runLoop, escaper, false); } - protected boolean doList(List possible - , String completed - , boolean runLoop, BiFunction escaper, boolean forSuggestion) { + protected boolean doList( + List possible, + String completed, + boolean runLoop, + BiFunction escaper, + boolean forSuggestion) { // If we list only and if there's a big // number of items, we should ask the user // for confirmation, display the list // and redraw the line at the bottom mergeCandidates(possible); - AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); - int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); + AttributedString text = + insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); + int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) + .size(); PostResult postResult = computePost(possible, null, null, completed); int lines = postResult.lines; int listMax = getInt(LIST_MAX, DEFAULT_LIST_MAX); - if (listMax > 0 && possible.size() >= listMax - || lines >= size.getRows() - promptLines) { + int possibleSize = possible.size(); + if (possibleSize == 0 || size.getRows() == 0) { + return false; + } + if (listMax > 0 && possibleSize >= listMax || lines >= size.getRows() - promptLines) { if (!forSuggestion) { // prompt - post = () -> new AttributedString(getAppName() + ": do you wish to see all " + possible.size() + post = () -> new AttributedString(getAppName() + ": do you wish to see all " + possibleSize + " possibilities (" + lines + " lines)?"); redisplay(true); int c = readCharacter(); @@ -4930,8 +5037,7 @@ protected boolean doList(List possible String current = completed + sb.toString(); List cands; if (sb.length() > 0) { - completionMatcher.compile(options, false, new CompletingWord(current), caseInsensitive, 0 - , null); + completionMatcher.compile(options, false, new CompletingWord(current), caseInsensitive, 0, null); cands = completionMatcher.matches(possible).stream() .sorted(getCandidateComparator(caseInsensitive, current)) .collect(Collectors.toList()); @@ -4944,8 +5050,10 @@ protected boolean doList(List possible candidateStartPosition = candidateStartPosition(cands); } post = () -> { - AttributedString t = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); - int pl = t.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); + AttributedString t = insertSecondaryPrompts( + AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); + int pl = t.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) + .size(); PostResult pr = computePost(cands, null, null, current); if (pr.lines >= size.getRows() - pl) { post = null; @@ -4954,7 +5062,8 @@ protected boolean doList(List possible redisplay(false); buf.cursor(oldCursor); println(); - List ls = pr.post.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + List ls = + pr.post.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); Display d = new Display(terminal, false); d.resize(size.getRows(), size.getColumns()); d.update(ls, -1); @@ -5074,25 +5183,41 @@ public PostResult(AttributedString post, int lines, int selectedLine) { } } - protected PostResult computePost(List possible, Candidate selection, List ordered, String completed) { - return computePost(possible, selection, ordered, completed, display::wcwidth, size.getColumns(), isSet(Option.AUTO_GROUP), isSet(Option.GROUP), isSet(Option.LIST_ROWS_FIRST)); - } - - protected PostResult computePost(List possible, Candidate selection, List ordered, String completed, Function wcwidth, int width, boolean autoGroup, boolean groupName, boolean rowsFirst) { + protected PostResult computePost( + List possible, Candidate selection, List ordered, String completed) { + return computePost( + possible, + selection, + ordered, + completed, + display::wcwidth, + size.getColumns(), + isSet(Option.AUTO_GROUP), + isSet(Option.GROUP), + isSet(Option.LIST_ROWS_FIRST)); + } + + protected PostResult computePost( + List possible, + Candidate selection, + List ordered, + String completed, + Function wcwidth, + int width, + boolean autoGroup, + boolean groupName, + boolean rowsFirst) { List strings = new ArrayList<>(); - boolean customOrder = possible.stream().anyMatch(c -> c.sort() != 0); if (groupName) { Comparator groupComparator = getGroupComparator(); - Map> sorted; - sorted = groupComparator != null - ? new TreeMap<>(groupComparator) - : new LinkedHashMap<>(); + Map> sorted; + sorted = groupComparator != null ? new TreeMap<>(groupComparator) : new LinkedHashMap<>(); for (Candidate cand : possible) { String group = cand.group(); - sorted.computeIfAbsent(group != null ? group : "", s -> new LinkedHashMap<>()) - .put((customOrder ? cand.sort() : cand.value()), cand); + sorted.computeIfAbsent(group != null ? group : "", s -> new ArrayList<>()) + .add(cand); } - for (Map.Entry> entry : sorted.entrySet()) { + for (Map.Entry> entry : sorted.entrySet()) { String group = entry.getKey(); if (group.isEmpty() && sorted.size() > 1) { group = getOthersGroupName(); @@ -5100,27 +5225,30 @@ protected PostResult computePost(List possible, Candidate selection, if (!group.isEmpty() && autoGroup) { strings.add(group); } - strings.add(new ArrayList<>(entry.getValue().values())); + List candidates = entry.getValue(); + Collections.sort(candidates); + strings.add(candidates); if (ordered != null) { - ordered.addAll(entry.getValue().values()); + ordered.addAll(candidates); } } } else { Set groups = new LinkedHashSet<>(); - TreeMap sorted = new TreeMap<>(); + List sorted = new ArrayList<>(); for (Candidate cand : possible) { String group = cand.group(); if (group != null) { groups.add(group); } - sorted.put((customOrder ? cand.sort() : cand.value()), cand); + sorted.add(cand); } if (autoGroup) { strings.addAll(groups); } - strings.add(new ArrayList<>(sorted.values())); + Collections.sort(sorted); + strings.add(sorted); if (ordered != null) { - ordered.addAll(sorted.values()); + ordered.addAll(sorted); } } return toColumns(strings, selection, completed, wcwidth, width, rowsFirst); @@ -5163,12 +5291,15 @@ public String getEndLine() { } private int candidateStartPosition(List cands) { - List values = cands.stream().map(c -> AttributedString.stripAnsi(c.displ())) - .filter(c -> !c.matches("\\w+") && c.length() > 1).collect(Collectors.toList()); + List values = cands.stream() + .map(c -> AttributedString.stripAnsi(c.displ())) + .filter(c -> !c.matches("\\w+") && c.length() > 1) + .collect(Collectors.toList()); Set notDelimiters = new HashSet<>(); - values.forEach(v -> v.substring(0, v.length() - 1).chars() + values.forEach(v -> v.substring(0, v.length() - 1) + .chars() .filter(c -> !Character.isDigit(c) && !Character.isAlphabetic(c)) - .forEach(c -> notDelimiters.add(Character.toString((char)c)))); + .forEach(c -> notDelimiters.add(Character.toString((char) c)))); int width = size.getColumns(); int promptLength = prompt != null ? prompt.length() : 0; if (promptLength > 0) { @@ -5179,8 +5310,7 @@ private int candidateStartPosition(List cands) { int out = tl.getStartPos(); String buffer = tl.getEndLine(); for (int i = buffer.length(); i > 0; i--) { - if (buffer.substring(0, i).matches(".*\\W") - && !notDelimiters.contains(buffer.substring(i - 1, i))) { + if (buffer.substring(0, i).matches(".*\\W") && !notDelimiters.contains(buffer.substring(i - 1, i))) { out += i; break; } @@ -5189,7 +5319,13 @@ private int candidateStartPosition(List cands) { } @SuppressWarnings("unchecked") - protected PostResult toColumns(List items, Candidate selection, String completed, Function wcwidth, int width, boolean rowsFirst) { + protected PostResult toColumns( + List items, + Candidate selection, + String completed, + Function wcwidth, + int width, + boolean rowsFirst) { int[] out = new int[2]; // TODO: support Option.LIST_PACKED // Compute column width @@ -5199,8 +5335,7 @@ protected PostResult toColumns(List items, Candidate selection, String c if (item instanceof String) { int len = wcwidth.apply((String) item); maxWidth = Math.max(maxWidth, len); - } - else if (item instanceof List) { + } else if (item instanceof List) { for (Candidate cand : (List) item) { listSize++; int len = wcwidth.apply(cand.displ()); @@ -5218,7 +5353,10 @@ else if (item instanceof List) { AttributedStringBuilder sb = new AttributedStringBuilder(); if (listSize > 0) { if (isSet(Option.AUTO_MENU_LIST) - && listSize < Math.min(getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), visibleDisplayRows() - promptLines())) { + && listSize + < Math.min( + getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), + visibleDisplayRows() - promptLines())) { maxWidth = Math.max(maxWidth, MENU_LIST_WIDTH); sb.tabs(Math.max(Math.min(candidateStartPosition, width - maxWidth - 1), 1)); width = maxWidth + 2; @@ -5251,8 +5389,16 @@ else if (item instanceof List) { } @SuppressWarnings("unchecked") - protected void toColumns(Object items, int width, int maxWidth, AttributedStringBuilder sb, Candidate selection, String completed - , boolean rowsFirst, boolean doMenuList, int[] out) { + protected void toColumns( + Object items, + int width, + int maxWidth, + AttributedStringBuilder sb, + Candidate selection, + String completed, + boolean rowsFirst, + boolean doMenuList, + int[] out) { if (maxWidth <= 0 || width <= 0) { return; } @@ -5305,18 +5451,20 @@ else if (items instanceof List) { if (idx < candidates.size()) { Candidate cand = candidates.get(idx); boolean hasRightItem = j < columns - 1 && index.applyAsInt(i, j + 1) < candidates.size(); - AttributedString left = AttributedString.fromAnsi(cand.displ()); - AttributedString right = AttributedString.fromAnsi(cand.descr()); + AttributedString left = fromAnsi(cand.displ()); + AttributedString right = fromAnsi(cand.descr()); int lw = left.columnLength(); int rw = 0; if (right != null) { - int rem = maxWidth - (lw + MARGIN_BETWEEN_DISPLAY_AND_DESC - + DESC_PREFIX.length() + DESC_SUFFIX.length()); + int rem = maxWidth + - (lw + + MARGIN_BETWEEN_DISPLAY_AND_DESC + + DESC_PREFIX.length() + + DESC_SUFFIX.length()); rw = right.columnLength(); if (rw > rem) { right = AttributedStringBuilder.append( - right.columnSubSequence(0, rem - WCWidth.wcwidth('\u2026')), - "\u2026"); + right.columnSubSequence(0, rem - WCWidth.wcwidth('\u2026')), "\u2026"); rw = right.columnLength(); } right = AttributedStringBuilder.append(DESC_PREFIX, right, DESC_SUFFIX); @@ -5325,8 +5473,9 @@ else if (items instanceof List) { if (cand == selection) { out[1] = i; asb.style(getCompletionStyleSelection(doMenuList)); - if (left.toString().regionMatches( - isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { + if (left.toString() + .regionMatches( + isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { asb.append(left.toString(), 0, completed.length()); asb.append(left.toString(), completed.length(), left.length()); } else { @@ -5340,8 +5489,9 @@ else if (items instanceof List) { } asb.style(AttributedStyle.DEFAULT); } else { - if (left.toString().regionMatches( - isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { + if (left.toString() + .regionMatches( + isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { asb.style(getCompletionStyleStarting(doMenuList)); asb.append(left, 0, completed.length()); asb.style(AttributedStyle.DEFAULT); @@ -5447,7 +5597,7 @@ protected AttributedStyle getCompletionStyle(String name, String value) { } protected AttributedStyle buildStyle(String str) { - return AttributedString.fromAnsi("\u001b[" + str + "m ").styleAt(0); + return fromAnsi("\u001b[" + str + "m ").styleAt(0); } /** @@ -5477,14 +5627,14 @@ protected boolean moveHistory(final boolean next) { } if (next && !history.next()) { return false; - } - else if (!next && !history.previous()) { + } else if (!next && !history.previous()) { return false; } - setBuffer(modifiedHistory.containsKey(history.index()) - ? modifiedHistory.get(history.index()) - : history.current()); + setBuffer( + modifiedHistory.containsKey(history.index()) + ? modifiedHistory.get(history.index()) + : history.current()); return true; } @@ -5515,7 +5665,6 @@ void println() { redrawLine(); } - // // Actions // @@ -5725,8 +5874,7 @@ public boolean yankPop() { public boolean mouse() { MouseEvent event = readMouseEvent(); - if (event.getType() == MouseEvent.Type.Released - && event.getButton() == MouseEvent.Button.Button1) { + if (event.getType() == MouseEvent.Type.Released && event.getButton() == MouseEvent.Button.Button1) { StringBuilder tsb = new StringBuilder(); Cursor cursor = terminal.getCursorPosition(c -> tsb.append((char) c)); bindingReader.runMacro(tsb.toString()); @@ -5734,15 +5882,20 @@ public boolean mouse() { List secondaryPrompts = new ArrayList<>(); getDisplayedBufferWithPrompts(secondaryPrompts); - AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); sb.append(prompt); sb.append(insertSecondaryPrompts(new AttributedString(buf.upToCursor()), secondaryPrompts, false)); - List promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + List promptLines = + sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); int currentLine = promptLines.size() - 1; int wantedLine = Math.max(0, Math.min(currentLine + event.getY() - cursor.getY(), secondaryPrompts.size())); - int pl0 = currentLine == 0 ? prompt.columnLength() : secondaryPrompts.get(currentLine - 1).columnLength(); - int pl1 = wantedLine == 0 ? prompt.columnLength() : secondaryPrompts.get(wantedLine - 1).columnLength(); + int pl0 = currentLine == 0 + ? prompt.columnLength() + : secondaryPrompts.get(currentLine - 1).columnLength(); + int pl1 = wantedLine == 0 + ? prompt.columnLength() + : secondaryPrompts.get(wantedLine - 1).columnLength(); int adjust = pl1 - pl0; buf.moveXY(event.getX() - cursor.getX() - adjust, event.getY() - cursor.getY()); } @@ -5814,13 +5967,11 @@ public boolean beep() { bell_preference = BellType.VISIBLE; break; case "on": - bell_preference = getBoolean(PREFER_VISIBLE_BELL, false) - ? BellType.VISIBLE : BellType.AUDIBLE; + bell_preference = getBoolean(PREFER_VISIBLE_BELL, false) ? BellType.VISIBLE : BellType.AUDIBLE; break; } if (bell_preference == BellType.VISIBLE) { - if (terminal.puts(Capability.flash_screen) - || terminal.puts(Capability.bell)) { + if (terminal.puts(Capability.flash_screen) || terminal.puts(Capability.bell)) { flush(); } } else if (bell_preference == BellType.AUDIBLE) { @@ -5869,8 +6020,7 @@ protected boolean isAlpha(int c) { protected boolean isWord(int c) { String wordchars = getString(WORDCHARS, DEFAULT_WORDCHARS); - return Character.isLetterOrDigit(c) - || (c < 128 && wordchars.indexOf((char) c) >= 0); + return Character.isLetterOrDigit(c) || (c < 128 && wordchars.indexOf((char) c) >= 0); } String getString(String name, String def) { @@ -5899,6 +6049,8 @@ public Map> defaultKeyMaps() { keyMaps.put(VIOPP, viOpp()); keyMaps.put(VISUAL, visual()); keyMaps.put(SAFE, safe()); + keyMaps.put(DUMB, dumb()); + if (getBoolean(BIND_TTY_SPECIAL_CHARS, true)) { Attributes attr = terminal.getAttributes(); bindConsoleChars(keyMaps.get(EMACS), attr); @@ -5909,240 +6061,241 @@ public Map> defaultKeyMaps() { keyMap.setUnicode(new Reference(SELF_INSERT)); keyMap.setAmbiguousTimeout(getLong(AMBIGUOUS_BINDING, DEFAULT_AMBIGUOUS_BINDING)); } - // By default, link main to emacs - keyMaps.put(MAIN, keyMaps.get(EMACS)); + // By default, link main to emacs unless the temrinal is dumb + keyMaps.put(MAIN, keyMaps.get(isTerminalDumb() ? DUMB : EMACS)); + return keyMaps; } public KeyMap emacs() { KeyMap emacs = new KeyMap<>(); bindKeys(emacs); - bind(emacs, SET_MARK_COMMAND, ctrl('@')); - bind(emacs, BEGINNING_OF_LINE, ctrl('A')); - bind(emacs, BACKWARD_CHAR, ctrl('B')); - bind(emacs, DELETE_CHAR_OR_LIST, ctrl('D')); - bind(emacs, END_OF_LINE, ctrl('E')); - bind(emacs, FORWARD_CHAR, ctrl('F')); - bind(emacs, SEND_BREAK, ctrl('G')); - bind(emacs, BACKWARD_DELETE_CHAR, ctrl('H')); - bind(emacs, EXPAND_OR_COMPLETE, ctrl('I')); - bind(emacs, ACCEPT_LINE, ctrl('J')); - bind(emacs, KILL_LINE, ctrl('K')); - bind(emacs, CLEAR_SCREEN, ctrl('L')); - bind(emacs, ACCEPT_LINE, ctrl('M')); - bind(emacs, DOWN_LINE_OR_HISTORY, ctrl('N')); - bind(emacs, ACCEPT_LINE_AND_DOWN_HISTORY, ctrl('O')); - bind(emacs, UP_LINE_OR_HISTORY, ctrl('P')); - bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); - bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); - bind(emacs, TRANSPOSE_CHARS, ctrl('T')); - bind(emacs, KILL_WHOLE_LINE, ctrl('U')); - bind(emacs, QUOTED_INSERT, ctrl('V')); - bind(emacs, BACKWARD_KILL_WORD, ctrl('W')); - bind(emacs, YANK, ctrl('Y')); - bind(emacs, CHARACTER_SEARCH, ctrl(']')); - bind(emacs, UNDO, ctrl('_')); - bind(emacs, SELF_INSERT, range(" -~")); - bind(emacs, INSERT_CLOSE_PAREN, ")"); - bind(emacs, INSERT_CLOSE_SQUARE, "]"); - bind(emacs, INSERT_CLOSE_CURLY, "}"); - bind(emacs, BACKWARD_DELETE_CHAR, del()); - bind(emacs, VI_MATCH_BRACKET, translate("^X^B")); - bind(emacs, SEND_BREAK, translate("^X^G")); - bind(emacs, EDIT_AND_EXECUTE_COMMAND, translate("^X^E")); - bind(emacs, VI_FIND_NEXT_CHAR, translate("^X^F")); - bind(emacs, VI_JOIN, translate("^X^J")); - bind(emacs, KILL_BUFFER, translate("^X^K")); - bind(emacs, INFER_NEXT_HISTORY, translate("^X^N")); - bind(emacs, OVERWRITE_MODE, translate("^X^O")); - bind(emacs, REDO, translate("^X^R")); - bind(emacs, UNDO, translate("^X^U")); - bind(emacs, VI_CMD_MODE, translate("^X^V")); - bind(emacs, EXCHANGE_POINT_AND_MARK, translate("^X^X")); - bind(emacs, DO_LOWERCASE_VERSION, translate("^XA-^XZ")); - bind(emacs, WHAT_CURSOR_POSITION, translate("^X=")); - bind(emacs, KILL_LINE, translate("^X^?")); - bind(emacs, SEND_BREAK, alt(ctrl('G'))); - bind(emacs, BACKWARD_KILL_WORD, alt(ctrl('H'))); - bind(emacs, SELF_INSERT_UNMETA, alt(ctrl('M'))); - bind(emacs, COMPLETE_WORD, alt(esc())); - bind(emacs, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); - bind(emacs, COPY_PREV_WORD, alt(ctrl('_'))); - bind(emacs, SET_MARK_COMMAND, alt(' ')); - bind(emacs, NEG_ARGUMENT, alt('-')); - bind(emacs, DIGIT_ARGUMENT, range("\\E0-\\E9")); - bind(emacs, BEGINNING_OF_HISTORY, alt('<')); - bind(emacs, LIST_CHOICES, alt('=')); - bind(emacs, END_OF_HISTORY, alt('>')); - bind(emacs, LIST_CHOICES, alt('?')); - bind(emacs, DO_LOWERCASE_VERSION, range("^[A-^[Z")); - bind(emacs, ACCEPT_AND_HOLD, alt('a')); - bind(emacs, BACKWARD_WORD, alt('b')); - bind(emacs, CAPITALIZE_WORD, alt('c')); - bind(emacs, KILL_WORD, alt('d')); - bind(emacs, KILL_WORD, translate("^[[3;5~")); // ctrl-delete - bind(emacs, FORWARD_WORD, alt('f')); - bind(emacs, DOWN_CASE_WORD, alt('l')); - bind(emacs, HISTORY_SEARCH_FORWARD, alt('n')); - bind(emacs, HISTORY_SEARCH_BACKWARD, alt('p')); - bind(emacs, TRANSPOSE_WORDS, alt('t')); - bind(emacs, UP_CASE_WORD, alt('u')); - bind(emacs, YANK_POP, alt('y')); - bind(emacs, BACKWARD_KILL_WORD, alt(del())); + bind(emacs, SET_MARK_COMMAND, ctrl('@')); + bind(emacs, BEGINNING_OF_LINE, ctrl('A')); + bind(emacs, BACKWARD_CHAR, ctrl('B')); + bind(emacs, DELETE_CHAR_OR_LIST, ctrl('D')); + bind(emacs, END_OF_LINE, ctrl('E')); + bind(emacs, FORWARD_CHAR, ctrl('F')); + bind(emacs, SEND_BREAK, ctrl('G')); + bind(emacs, BACKWARD_DELETE_CHAR, ctrl('H')); + bind(emacs, EXPAND_OR_COMPLETE, ctrl('I')); + bind(emacs, ACCEPT_LINE, ctrl('J')); + bind(emacs, KILL_LINE, ctrl('K')); + bind(emacs, CLEAR_SCREEN, ctrl('L')); + bind(emacs, ACCEPT_LINE, ctrl('M')); + bind(emacs, DOWN_LINE_OR_HISTORY, ctrl('N')); + bind(emacs, ACCEPT_LINE_AND_DOWN_HISTORY, ctrl('O')); + bind(emacs, UP_LINE_OR_HISTORY, ctrl('P')); + bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); + bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); + bind(emacs, TRANSPOSE_CHARS, ctrl('T')); + bind(emacs, KILL_WHOLE_LINE, ctrl('U')); + bind(emacs, QUOTED_INSERT, ctrl('V')); + bind(emacs, BACKWARD_KILL_WORD, ctrl('W')); + bind(emacs, YANK, ctrl('Y')); + bind(emacs, CHARACTER_SEARCH, ctrl(']')); + bind(emacs, UNDO, ctrl('_')); + bind(emacs, SELF_INSERT, range(" -~")); + bind(emacs, INSERT_CLOSE_PAREN, ")"); + bind(emacs, INSERT_CLOSE_SQUARE, "]"); + bind(emacs, INSERT_CLOSE_CURLY, "}"); + bind(emacs, BACKWARD_DELETE_CHAR, del()); + bind(emacs, VI_MATCH_BRACKET, translate("^X^B")); + bind(emacs, SEND_BREAK, translate("^X^G")); + bind(emacs, EDIT_AND_EXECUTE_COMMAND, translate("^X^E")); + bind(emacs, VI_FIND_NEXT_CHAR, translate("^X^F")); + bind(emacs, VI_JOIN, translate("^X^J")); + bind(emacs, KILL_BUFFER, translate("^X^K")); + bind(emacs, INFER_NEXT_HISTORY, translate("^X^N")); + bind(emacs, OVERWRITE_MODE, translate("^X^O")); + bind(emacs, REDO, translate("^X^R")); + bind(emacs, UNDO, translate("^X^U")); + bind(emacs, VI_CMD_MODE, translate("^X^V")); + bind(emacs, EXCHANGE_POINT_AND_MARK, translate("^X^X")); + bind(emacs, DO_LOWERCASE_VERSION, translate("^XA-^XZ")); + bind(emacs, WHAT_CURSOR_POSITION, translate("^X=")); + bind(emacs, KILL_LINE, translate("^X^?")); + bind(emacs, SEND_BREAK, alt(ctrl('G'))); + bind(emacs, BACKWARD_KILL_WORD, alt(ctrl('H'))); + bind(emacs, SELF_INSERT_UNMETA, alt(ctrl('M'))); + bind(emacs, COMPLETE_WORD, alt(esc())); + bind(emacs, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); + bind(emacs, COPY_PREV_WORD, alt(ctrl('_'))); + bind(emacs, SET_MARK_COMMAND, alt(' ')); + bind(emacs, NEG_ARGUMENT, alt('-')); + bind(emacs, DIGIT_ARGUMENT, range("\\E0-\\E9")); + bind(emacs, BEGINNING_OF_HISTORY, alt('<')); + bind(emacs, LIST_CHOICES, alt('=')); + bind(emacs, END_OF_HISTORY, alt('>')); + bind(emacs, LIST_CHOICES, alt('?')); + bind(emacs, DO_LOWERCASE_VERSION, range("^[A-^[Z")); + bind(emacs, ACCEPT_AND_HOLD, alt('a')); + bind(emacs, BACKWARD_WORD, alt('b')); + bind(emacs, CAPITALIZE_WORD, alt('c')); + bind(emacs, KILL_WORD, alt('d')); + bind(emacs, KILL_WORD, translate("^[[3;5~")); // ctrl-delete + bind(emacs, FORWARD_WORD, alt('f')); + bind(emacs, DOWN_CASE_WORD, alt('l')); + bind(emacs, HISTORY_SEARCH_FORWARD, alt('n')); + bind(emacs, HISTORY_SEARCH_BACKWARD, alt('p')); + bind(emacs, TRANSPOSE_WORDS, alt('t')); + bind(emacs, UP_CASE_WORD, alt('u')); + bind(emacs, YANK_POP, alt('y')); + bind(emacs, BACKWARD_KILL_WORD, alt(del())); bindArrowKeys(emacs); - bind(emacs, FORWARD_WORD, translate("^[[1;5C")); // ctrl-left - bind(emacs, BACKWARD_WORD, translate("^[[1;5D")); // ctrl-right - bind(emacs, FORWARD_WORD, alt(key(Capability.key_right))); - bind(emacs, BACKWARD_WORD, alt(key(Capability.key_left))); - bind(emacs, FORWARD_WORD, alt(translate("^[[C"))); - bind(emacs, BACKWARD_WORD, alt(translate("^[[D"))); + bind(emacs, FORWARD_WORD, translate("^[[1;5C")); // ctrl-left + bind(emacs, BACKWARD_WORD, translate("^[[1;5D")); // ctrl-right + bind(emacs, FORWARD_WORD, alt(key(Capability.key_right))); + bind(emacs, BACKWARD_WORD, alt(key(Capability.key_left))); + bind(emacs, FORWARD_WORD, alt(translate("^[[C"))); + bind(emacs, BACKWARD_WORD, alt(translate("^[[D"))); return emacs; } public KeyMap viInsertion() { KeyMap viins = new KeyMap<>(); bindKeys(viins); - bind(viins, SELF_INSERT, range("^@-^_")); - bind(viins, LIST_CHOICES, ctrl('D')); - bind(viins, SEND_BREAK, ctrl('G')); - bind(viins, BACKWARD_DELETE_CHAR, ctrl('H')); - bind(viins, EXPAND_OR_COMPLETE, ctrl('I')); - bind(viins, ACCEPT_LINE, ctrl('J')); - bind(viins, CLEAR_SCREEN, ctrl('L')); - bind(viins, ACCEPT_LINE, ctrl('M')); - bind(viins, MENU_COMPLETE, ctrl('N')); - bind(viins, REVERSE_MENU_COMPLETE, ctrl('P')); - bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); - bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); - bind(viins, TRANSPOSE_CHARS, ctrl('T')); - bind(viins, KILL_WHOLE_LINE, ctrl('U')); - bind(viins, QUOTED_INSERT, ctrl('V')); - bind(viins, BACKWARD_KILL_WORD, ctrl('W')); - bind(viins, YANK, ctrl('Y')); - bind(viins, VI_CMD_MODE, ctrl('[')); - bind(viins, UNDO, ctrl('_')); - bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); - bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); - bind(viins, SELF_INSERT, range(" -~")); - bind(viins, INSERT_CLOSE_PAREN, ")"); - bind(viins, INSERT_CLOSE_SQUARE, "]"); - bind(viins, INSERT_CLOSE_CURLY, "}"); - bind(viins, BACKWARD_DELETE_CHAR, del()); + bind(viins, SELF_INSERT, range("^@-^_")); + bind(viins, LIST_CHOICES, ctrl('D')); + bind(viins, SEND_BREAK, ctrl('G')); + bind(viins, BACKWARD_DELETE_CHAR, ctrl('H')); + bind(viins, EXPAND_OR_COMPLETE, ctrl('I')); + bind(viins, ACCEPT_LINE, ctrl('J')); + bind(viins, CLEAR_SCREEN, ctrl('L')); + bind(viins, ACCEPT_LINE, ctrl('M')); + bind(viins, MENU_COMPLETE, ctrl('N')); + bind(viins, REVERSE_MENU_COMPLETE, ctrl('P')); + bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); + bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); + bind(viins, TRANSPOSE_CHARS, ctrl('T')); + bind(viins, KILL_WHOLE_LINE, ctrl('U')); + bind(viins, QUOTED_INSERT, ctrl('V')); + bind(viins, BACKWARD_KILL_WORD, ctrl('W')); + bind(viins, YANK, ctrl('Y')); + bind(viins, VI_CMD_MODE, ctrl('[')); + bind(viins, UNDO, ctrl('_')); + bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); + bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); + bind(viins, SELF_INSERT, range(" -~")); + bind(viins, INSERT_CLOSE_PAREN, ")"); + bind(viins, INSERT_CLOSE_SQUARE, "]"); + bind(viins, INSERT_CLOSE_CURLY, "}"); + bind(viins, BACKWARD_DELETE_CHAR, del()); bindArrowKeys(viins); return viins; } public KeyMap viCmd() { KeyMap vicmd = new KeyMap<>(); - bind(vicmd, LIST_CHOICES, ctrl('D')); - bind(vicmd, EMACS_EDITING_MODE, ctrl('E')); - bind(vicmd, SEND_BREAK, ctrl('G')); - bind(vicmd, VI_BACKWARD_CHAR, ctrl('H')); - bind(vicmd, ACCEPT_LINE, ctrl('J')); - bind(vicmd, KILL_LINE, ctrl('K')); - bind(vicmd, CLEAR_SCREEN, ctrl('L')); - bind(vicmd, ACCEPT_LINE, ctrl('M')); - bind(vicmd, VI_DOWN_LINE_OR_HISTORY, ctrl('N')); - bind(vicmd, VI_UP_LINE_OR_HISTORY, ctrl('P')); - bind(vicmd, QUOTED_INSERT, ctrl('Q')); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); - bind(vicmd, TRANSPOSE_CHARS, ctrl('T')); - bind(vicmd, KILL_WHOLE_LINE, ctrl('U')); - bind(vicmd, QUOTED_INSERT, ctrl('V')); - bind(vicmd, BACKWARD_KILL_WORD, ctrl('W')); - bind(vicmd, YANK, ctrl('Y')); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); - bind(vicmd, SEND_BREAK, alt(ctrl('G'))); - bind(vicmd, BACKWARD_KILL_WORD, alt(ctrl('H'))); - bind(vicmd, SELF_INSERT_UNMETA, alt(ctrl('M'))); - bind(vicmd, COMPLETE_WORD, alt(esc())); - bind(vicmd, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); - bind(vicmd, SET_MARK_COMMAND, alt(' ')); -// bind(vicmd, INSERT_COMMENT, alt('#')); -// bind(vicmd, INSERT_COMPLETIONS, alt('*')); - bind(vicmd, DIGIT_ARGUMENT, alt('-')); - bind(vicmd, BEGINNING_OF_HISTORY, alt('<')); - bind(vicmd, LIST_CHOICES, alt('=')); - bind(vicmd, END_OF_HISTORY, alt('>')); - bind(vicmd, LIST_CHOICES, alt('?')); - bind(vicmd, DO_LOWERCASE_VERSION, range("^[A-^[Z")); - bind(vicmd, BACKWARD_WORD, alt('b')); - bind(vicmd, CAPITALIZE_WORD, alt('c')); - bind(vicmd, KILL_WORD, alt('d')); - bind(vicmd, FORWARD_WORD, alt('f')); - bind(vicmd, DOWN_CASE_WORD, alt('l')); - bind(vicmd, HISTORY_SEARCH_FORWARD, alt('n')); - bind(vicmd, HISTORY_SEARCH_BACKWARD, alt('p')); - bind(vicmd, TRANSPOSE_WORDS, alt('t')); - bind(vicmd, UP_CASE_WORD, alt('u')); - bind(vicmd, YANK_POP, alt('y')); - bind(vicmd, BACKWARD_KILL_WORD, alt(del())); - - bind(vicmd, FORWARD_CHAR, " "); - bind(vicmd, VI_INSERT_COMMENT, "#"); - bind(vicmd, END_OF_LINE, "$"); - bind(vicmd, VI_MATCH_BRACKET, "%"); - bind(vicmd, VI_DOWN_LINE_OR_HISTORY, "+"); - bind(vicmd, VI_REV_REPEAT_FIND, ","); - bind(vicmd, VI_UP_LINE_OR_HISTORY, "-"); - bind(vicmd, VI_REPEAT_CHANGE, "."); - bind(vicmd, VI_HISTORY_SEARCH_BACKWARD, "/"); - bind(vicmd, VI_DIGIT_OR_BEGINNING_OF_LINE, "0"); - bind(vicmd, DIGIT_ARGUMENT, range("1-9")); - bind(vicmd, VI_REPEAT_FIND, ";"); - bind(vicmd, LIST_CHOICES, "="); - bind(vicmd, VI_HISTORY_SEARCH_FORWARD, "?"); - bind(vicmd, VI_ADD_EOL, "A"); - bind(vicmd, VI_BACKWARD_BLANK_WORD, "B"); - bind(vicmd, VI_CHANGE_EOL, "C"); - bind(vicmd, VI_KILL_EOL, "D"); - bind(vicmd, VI_FORWARD_BLANK_WORD_END, "E"); - bind(vicmd, VI_FIND_PREV_CHAR, "F"); - bind(vicmd, VI_FETCH_HISTORY, "G"); - bind(vicmd, VI_INSERT_BOL, "I"); - bind(vicmd, VI_JOIN, "J"); - bind(vicmd, VI_REV_REPEAT_SEARCH, "N"); - bind(vicmd, VI_OPEN_LINE_ABOVE, "O"); - bind(vicmd, VI_PUT_BEFORE, "P"); - bind(vicmd, VI_REPLACE, "R"); - bind(vicmd, VI_KILL_LINE, "S"); - bind(vicmd, VI_FIND_PREV_CHAR_SKIP, "T"); - bind(vicmd, REDO, "U"); - bind(vicmd, VISUAL_LINE_MODE, "V"); - bind(vicmd, VI_FORWARD_BLANK_WORD, "W"); - bind(vicmd, VI_BACKWARD_DELETE_CHAR, "X"); - bind(vicmd, VI_YANK_WHOLE_LINE, "Y"); - bind(vicmd, VI_FIRST_NON_BLANK, "^"); - bind(vicmd, VI_ADD_NEXT, "a"); - bind(vicmd, VI_BACKWARD_WORD, "b"); - bind(vicmd, VI_CHANGE, "c"); - bind(vicmd, VI_DELETE, "d"); - bind(vicmd, VI_FORWARD_WORD_END, "e"); - bind(vicmd, VI_FIND_NEXT_CHAR, "f"); - bind(vicmd, WHAT_CURSOR_POSITION, "ga"); - bind(vicmd, VI_BACKWARD_BLANK_WORD_END, "gE"); - bind(vicmd, VI_BACKWARD_WORD_END, "ge"); - bind(vicmd, VI_BACKWARD_CHAR, "h"); - bind(vicmd, VI_INSERT, "i"); - bind(vicmd, DOWN_LINE_OR_HISTORY, "j"); - bind(vicmd, UP_LINE_OR_HISTORY, "k"); - bind(vicmd, VI_FORWARD_CHAR, "l"); - bind(vicmd, VI_REPEAT_SEARCH, "n"); - bind(vicmd, VI_OPEN_LINE_BELOW, "o"); - bind(vicmd, VI_PUT_AFTER, "p"); - bind(vicmd, VI_REPLACE_CHARS, "r"); - bind(vicmd, VI_SUBSTITUTE, "s"); - bind(vicmd, VI_FIND_NEXT_CHAR_SKIP, "t"); - bind(vicmd, UNDO, "u"); - bind(vicmd, VISUAL_MODE, "v"); - bind(vicmd, VI_FORWARD_WORD, "w"); - bind(vicmd, VI_DELETE_CHAR, "x"); - bind(vicmd, VI_YANK, "y"); - bind(vicmd, VI_GOTO_COLUMN, "|"); - bind(vicmd, VI_SWAP_CASE, "~"); - bind(vicmd, VI_BACKWARD_CHAR, del()); + bind(vicmd, LIST_CHOICES, ctrl('D')); + bind(vicmd, EMACS_EDITING_MODE, ctrl('E')); + bind(vicmd, SEND_BREAK, ctrl('G')); + bind(vicmd, VI_BACKWARD_CHAR, ctrl('H')); + bind(vicmd, ACCEPT_LINE, ctrl('J')); + bind(vicmd, KILL_LINE, ctrl('K')); + bind(vicmd, CLEAR_SCREEN, ctrl('L')); + bind(vicmd, ACCEPT_LINE, ctrl('M')); + bind(vicmd, VI_DOWN_LINE_OR_HISTORY, ctrl('N')); + bind(vicmd, VI_UP_LINE_OR_HISTORY, ctrl('P')); + bind(vicmd, QUOTED_INSERT, ctrl('Q')); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); + bind(vicmd, TRANSPOSE_CHARS, ctrl('T')); + bind(vicmd, KILL_WHOLE_LINE, ctrl('U')); + bind(vicmd, QUOTED_INSERT, ctrl('V')); + bind(vicmd, BACKWARD_KILL_WORD, ctrl('W')); + bind(vicmd, YANK, ctrl('Y')); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); + bind(vicmd, SEND_BREAK, alt(ctrl('G'))); + bind(vicmd, BACKWARD_KILL_WORD, alt(ctrl('H'))); + bind(vicmd, SELF_INSERT_UNMETA, alt(ctrl('M'))); + bind(vicmd, COMPLETE_WORD, alt(esc())); + bind(vicmd, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); + bind(vicmd, SET_MARK_COMMAND, alt(' ')); + // bind(vicmd, INSERT_COMMENT, alt('#')); + // bind(vicmd, INSERT_COMPLETIONS, alt('*')); + bind(vicmd, DIGIT_ARGUMENT, alt('-')); + bind(vicmd, BEGINNING_OF_HISTORY, alt('<')); + bind(vicmd, LIST_CHOICES, alt('=')); + bind(vicmd, END_OF_HISTORY, alt('>')); + bind(vicmd, LIST_CHOICES, alt('?')); + bind(vicmd, DO_LOWERCASE_VERSION, range("^[A-^[Z")); + bind(vicmd, BACKWARD_WORD, alt('b')); + bind(vicmd, CAPITALIZE_WORD, alt('c')); + bind(vicmd, KILL_WORD, alt('d')); + bind(vicmd, FORWARD_WORD, alt('f')); + bind(vicmd, DOWN_CASE_WORD, alt('l')); + bind(vicmd, HISTORY_SEARCH_FORWARD, alt('n')); + bind(vicmd, HISTORY_SEARCH_BACKWARD, alt('p')); + bind(vicmd, TRANSPOSE_WORDS, alt('t')); + bind(vicmd, UP_CASE_WORD, alt('u')); + bind(vicmd, YANK_POP, alt('y')); + bind(vicmd, BACKWARD_KILL_WORD, alt(del())); + + bind(vicmd, FORWARD_CHAR, " "); + bind(vicmd, VI_INSERT_COMMENT, "#"); + bind(vicmd, END_OF_LINE, "$"); + bind(vicmd, VI_MATCH_BRACKET, "%"); + bind(vicmd, VI_DOWN_LINE_OR_HISTORY, "+"); + bind(vicmd, VI_REV_REPEAT_FIND, ","); + bind(vicmd, VI_UP_LINE_OR_HISTORY, "-"); + bind(vicmd, VI_REPEAT_CHANGE, "."); + bind(vicmd, VI_HISTORY_SEARCH_BACKWARD, "/"); + bind(vicmd, VI_DIGIT_OR_BEGINNING_OF_LINE, "0"); + bind(vicmd, DIGIT_ARGUMENT, range("1-9")); + bind(vicmd, VI_REPEAT_FIND, ";"); + bind(vicmd, LIST_CHOICES, "="); + bind(vicmd, VI_HISTORY_SEARCH_FORWARD, "?"); + bind(vicmd, VI_ADD_EOL, "A"); + bind(vicmd, VI_BACKWARD_BLANK_WORD, "B"); + bind(vicmd, VI_CHANGE_EOL, "C"); + bind(vicmd, VI_KILL_EOL, "D"); + bind(vicmd, VI_FORWARD_BLANK_WORD_END, "E"); + bind(vicmd, VI_FIND_PREV_CHAR, "F"); + bind(vicmd, VI_FETCH_HISTORY, "G"); + bind(vicmd, VI_INSERT_BOL, "I"); + bind(vicmd, VI_JOIN, "J"); + bind(vicmd, VI_REV_REPEAT_SEARCH, "N"); + bind(vicmd, VI_OPEN_LINE_ABOVE, "O"); + bind(vicmd, VI_PUT_BEFORE, "P"); + bind(vicmd, VI_REPLACE, "R"); + bind(vicmd, VI_KILL_LINE, "S"); + bind(vicmd, VI_FIND_PREV_CHAR_SKIP, "T"); + bind(vicmd, REDO, "U"); + bind(vicmd, VISUAL_LINE_MODE, "V"); + bind(vicmd, VI_FORWARD_BLANK_WORD, "W"); + bind(vicmd, VI_BACKWARD_DELETE_CHAR, "X"); + bind(vicmd, VI_YANK_WHOLE_LINE, "Y"); + bind(vicmd, VI_FIRST_NON_BLANK, "^"); + bind(vicmd, VI_ADD_NEXT, "a"); + bind(vicmd, VI_BACKWARD_WORD, "b"); + bind(vicmd, VI_CHANGE, "c"); + bind(vicmd, VI_DELETE, "d"); + bind(vicmd, VI_FORWARD_WORD_END, "e"); + bind(vicmd, VI_FIND_NEXT_CHAR, "f"); + bind(vicmd, WHAT_CURSOR_POSITION, "ga"); + bind(vicmd, VI_BACKWARD_BLANK_WORD_END, "gE"); + bind(vicmd, VI_BACKWARD_WORD_END, "ge"); + bind(vicmd, VI_BACKWARD_CHAR, "h"); + bind(vicmd, VI_INSERT, "i"); + bind(vicmd, DOWN_LINE_OR_HISTORY, "j"); + bind(vicmd, UP_LINE_OR_HISTORY, "k"); + bind(vicmd, VI_FORWARD_CHAR, "l"); + bind(vicmd, VI_REPEAT_SEARCH, "n"); + bind(vicmd, VI_OPEN_LINE_BELOW, "o"); + bind(vicmd, VI_PUT_AFTER, "p"); + bind(vicmd, VI_REPLACE_CHARS, "r"); + bind(vicmd, VI_SUBSTITUTE, "s"); + bind(vicmd, VI_FIND_NEXT_CHAR_SKIP, "t"); + bind(vicmd, UNDO, "u"); + bind(vicmd, VISUAL_MODE, "v"); + bind(vicmd, VI_FORWARD_WORD, "w"); + bind(vicmd, VI_DELETE_CHAR, "x"); + bind(vicmd, VI_YANK, "y"); + bind(vicmd, VI_GOTO_COLUMN, "|"); + bind(vicmd, VI_SWAP_CASE, "~"); + bind(vicmd, VI_BACKWARD_CHAR, del()); bindArrowKeys(vicmd); return vicmd; @@ -6150,38 +6303,46 @@ public KeyMap viCmd() { public KeyMap menu() { KeyMap menu = new KeyMap<>(); - bind(menu, MENU_COMPLETE, "\t"); - bind(menu, REVERSE_MENU_COMPLETE, key(Capability.back_tab)); - bind(menu, ACCEPT_LINE, "\r", "\n"); + bind(menu, MENU_COMPLETE, "\t"); + bind(menu, REVERSE_MENU_COMPLETE, key(Capability.back_tab)); + bind(menu, ACCEPT_LINE, "\r", "\n"); bindArrowKeys(menu); return menu; } public KeyMap safe() { KeyMap safe = new KeyMap<>(); - bind(safe, SELF_INSERT, range("^@-^?")); - bind(safe, ACCEPT_LINE, "\r", "\n"); - bind(safe, SEND_BREAK, ctrl('G')); + bind(safe, SELF_INSERT, range("^@-^?")); + bind(safe, ACCEPT_LINE, "\r", "\n"); + bind(safe, SEND_BREAK, ctrl('G')); return safe; } + public KeyMap dumb() { + KeyMap dumb = new KeyMap<>(); + bind(dumb, SELF_INSERT, range("^@-^?")); + bind(dumb, ACCEPT_LINE, "\r", "\n"); + bind(dumb, BEEP, ctrl('G')); + return dumb; + } + public KeyMap visual() { KeyMap visual = new KeyMap<>(); - bind(visual, UP_LINE, key(Capability.key_up), "k"); - bind(visual, DOWN_LINE, key(Capability.key_down), "j"); - bind(visual, this::deactivateRegion, esc()); - bind(visual, EXCHANGE_POINT_AND_MARK, "o"); - bind(visual, PUT_REPLACE_SELECTION, "p"); - bind(visual, VI_DELETE, "x"); - bind(visual, VI_OPER_SWAP_CASE, "~"); + bind(visual, UP_LINE, key(Capability.key_up), "k"); + bind(visual, DOWN_LINE, key(Capability.key_down), "j"); + bind(visual, this::deactivateRegion, esc()); + bind(visual, EXCHANGE_POINT_AND_MARK, "o"); + bind(visual, PUT_REPLACE_SELECTION, "p"); + bind(visual, VI_DELETE, "x"); + bind(visual, VI_OPER_SWAP_CASE, "~"); return visual; } public KeyMap viOpp() { KeyMap viOpp = new KeyMap<>(); - bind(viOpp, UP_LINE, key(Capability.key_up), "k"); - bind(viOpp, DOWN_LINE, key(Capability.key_down), "j"); - bind(viOpp, VI_CMD_MODE, esc()); + bind(viOpp, UP_LINE, key(Capability.key_up), "k"); + bind(viOpp, DOWN_LINE, key(Capability.key_down), "j"); + bind(viOpp, VI_CMD_MODE, esc()); return viOpp; } @@ -6210,19 +6371,19 @@ private void bindKeys(KeyMap emacs) { } private void bindArrowKeys(KeyMap map) { - bind(map, UP_LINE_OR_SEARCH, key(Capability.key_up)); - bind(map, DOWN_LINE_OR_SEARCH, key(Capability.key_down)); - bind(map, BACKWARD_CHAR, key(Capability.key_left)); - bind(map, FORWARD_CHAR, key(Capability.key_right)); - bind(map, BEGINNING_OF_LINE, key(Capability.key_home)); - bind(map, END_OF_LINE, key(Capability.key_end)); - bind(map, DELETE_CHAR, key(Capability.key_dc)); - bind(map, KILL_WHOLE_LINE, key(Capability.key_dl)); - bind(map, OVERWRITE_MODE, key(Capability.key_ic)); - bind(map, MOUSE, key(Capability.key_mouse)); - bind(map, BEGIN_PASTE, BRACKETED_PASTE_BEGIN); - bind(map, FOCUS_IN, FOCUS_IN_SEQ); - bind(map, FOCUS_OUT, FOCUS_OUT_SEQ); + bind(map, UP_LINE_OR_SEARCH, key(Capability.key_up)); + bind(map, DOWN_LINE_OR_SEARCH, key(Capability.key_down)); + bind(map, BACKWARD_CHAR, key(Capability.key_left)); + bind(map, FORWARD_CHAR, key(Capability.key_right)); + bind(map, BEGINNING_OF_LINE, key(Capability.key_home)); + bind(map, END_OF_LINE, key(Capability.key_end)); + bind(map, DELETE_CHAR, key(Capability.key_dc)); + bind(map, KILL_WHOLE_LINE, key(Capability.key_dl)); + bind(map, OVERWRITE_MODE, key(Capability.key_ic)); + bind(map, MOUSE, key(Capability.key_mouse)); + bind(map, BEGIN_PASTE, BRACKETED_PASTE_BEGIN); + bind(map, FOCUS_IN, FOCUS_IN_SEQ); + bind(map, FOCUS_OUT, FOCUS_OUT_SEQ); } /** @@ -6231,14 +6392,10 @@ private void bindArrowKeys(KeyMap map) { */ private void bindConsoleChars(KeyMap keyMap, Attributes attr) { if (attr != null) { - rebind(keyMap, BACKWARD_DELETE_CHAR, - del(), (char) attr.getControlChar(ControlChar.VERASE)); - rebind(keyMap, BACKWARD_KILL_WORD, - ctrl('W'), (char) attr.getControlChar(ControlChar.VWERASE)); - rebind(keyMap, KILL_WHOLE_LINE, - ctrl('U'), (char) attr.getControlChar(ControlChar.VKILL)); - rebind(keyMap, QUOTED_INSERT, - ctrl('V'), (char) attr.getControlChar(ControlChar.VLNEXT)); + rebind(keyMap, BACKWARD_DELETE_CHAR, del(), (char) attr.getControlChar(ControlChar.VERASE)); + rebind(keyMap, BACKWARD_KILL_WORD, ctrl('W'), (char) attr.getControlChar(ControlChar.VWERASE)); + rebind(keyMap, KILL_WHOLE_LINE, ctrl('U'), (char) attr.getControlChar(ControlChar.VKILL)); + rebind(keyMap, QUOTED_INSERT, ctrl('V'), (char) attr.getControlChar(ControlChar.VLNEXT)); } } @@ -6250,7 +6407,6 @@ private void rebind(KeyMap keyMap, String operation, String prevBinding } } - // JDK specific modification @Override public void zeroOut() { buf.zeroOut(); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java index 0ae9475bd57bd..cdc60dccccfaf 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -13,7 +13,7 @@ public class ReaderUtils { - private ReaderUtils() { } + private ReaderUtils() {} public static boolean isSet(LineReader reader, LineReader.Option option) { return reader != null && reader.isSet(option); @@ -30,8 +30,7 @@ public static boolean getBoolean(LineReader reader, String name, boolean def) { return (Boolean) v; } else if (v != null) { String s = v.toString(); - return s.isEmpty() || s.equalsIgnoreCase("on") - || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true"); + return s.isEmpty() || s.equalsIgnoreCase("on") || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true"); } return def; } @@ -77,5 +76,4 @@ public static int distance(String word, String cand) { return Levenshtein.distance(word, cand); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java index fd6c2663c057e..423497f3dc44a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,10 +8,10 @@ */ package jdk.internal.org.jline.reader.impl; -import jdk.internal.org.jline.reader.MaskingCallback; - import java.util.Objects; +import jdk.internal.org.jline.reader.MaskingCallback; + /** * Simple {@link MaskingCallback} that will replace all the characters in the line with the given mask. * If the given mask is equal to {@link LineReaderImpl#NULL_MASK} then the line will be replaced with an empty String. @@ -29,7 +29,7 @@ public String display(String line) { return ""; } else { StringBuilder sb = new StringBuilder(line.length()); - for (int i = line.length(); i-- > 0;) { + for (int i = line.length(); i-- > 0; ) { sb.append((char) mask); } return sb.toString(); @@ -40,5 +40,4 @@ public String display(String line) { public String history(String line) { return null; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java index 0a467f9d7bac7..3b193f9eb65ea 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -20,6 +20,7 @@ public class UndoTree { private final Node parent; private Node current; + @SuppressWarnings("this-escape") public UndoTree(Consumer s) { state = s; parent = new Node(null); @@ -71,5 +72,4 @@ public Node(T s) { state = s; } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java index e8e41088c598e..145823c53cede 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -24,9 +24,7 @@ * @author Jason Dillon * @since 2.3 */ -public class AggregateCompleter - implements Completer -{ +public class AggregateCompleter implements Completer { private final Collection completers; /** @@ -78,9 +76,6 @@ public void complete(LineReader reader, final ParsedLine line, final ListJason Dillon * @since 2.3 */ -public class ArgumentCompleter implements Completer -{ +public class ArgumentCompleter implements Completer { private final List completers = new ArrayList<>(); private boolean strict = true; @@ -108,12 +107,12 @@ public void complete(LineReader reader, ParsedLine line, final List c // if we are beyond the end of the completers, just use the last one if (line.wordIndex() >= completers.size()) { completer = completers.get(completers.size() - 1); - } - else { + } else { completer = completers.get(line.wordIndex()); } - // ensure that all the previous completers are successful before allowing this completer to pass (only if strict). + // ensure that all the previous completers are successful before allowing this completer to pass (only if + // strict). for (int i = strictCommand ? 0 : 1; isStrict() && (i < line.wordIndex()); i++) { int idx = i >= completers.size() ? (completers.size() - 1) : i; if (idx == 0 && !strictCommand) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java index 6a18d3cfd93a0..a701f2e3560bc 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -19,8 +19,7 @@ * @author Jason Dillon * @since 2.3 */ -public class EnumCompleter extends StringsCompleter -{ +public class EnumCompleter extends StringsCompleter { public EnumCompleter(Class> source) { Objects.requireNonNull(source); for (Enum n : source.getEnumConstants()) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java index 3d173f72ec7e5..32bf6e3493e6a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -9,6 +9,7 @@ package jdk.internal.org.jline.reader.impl.completer; import java.io.IOException; +import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -41,11 +42,10 @@ * @author Marc Prud'hommeaux * @author Jason Dillon * @since 2.3 - * @deprecated use jdk.internal.org.jline.builtins.Completers$FileNameCompleter instead + * @deprecated use org.jline.builtins.Completers$FileNameCompleter instead */ @Deprecated -public class FileNameCompleter implements Completer -{ +public class FileNameCompleter implements Completer { public void complete(LineReader reader, ParsedLine commandLine, final List candidates) { assert commandLine != null; @@ -72,20 +72,21 @@ public void complete(LineReader reader, ParsedLine commandLine, final List { + try (DirectoryStream directoryStream = Files.newDirectoryStream(current, this::accept)) { + directoryStream.forEach(p -> { String value = curBuf + p.getFileName().toString(); if (Files.isDirectory(p)) { candidates.add(new Candidate( value + (reader.isSet(Option.AUTO_PARAM_SLASH) ? sep : ""), getDisplay(reader.getTerminal(), p), - null, null, + null, + null, reader.isSet(Option.AUTO_REMOVE_SLASH) ? sep : null, null, false)); } else { - candidates.add(new Candidate(value, getDisplay(reader.getTerminal(), p), - null, null, null, null, true)); + candidates.add( + new Candidate(value, getDisplay(reader.getTerminal(), p), null, null, null, null, true)); } }); } catch (IOException e) { @@ -125,5 +126,4 @@ protected String getDisplay(Terminal terminal, Path p) { } return name; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java index f3efefdc92919..21ce836a32f4e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,11 +22,8 @@ * @author Jason Dillon * @since 2.3 */ -public final class NullCompleter - implements Completer -{ +public final class NullCompleter implements Completer { public static final NullCompleter INSTANCE = new NullCompleter(); - public void complete(LineReader reader, final ParsedLine line, final List candidates) { - } + public void complete(LineReader reader, final ParsedLine line, final List candidates) {} } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java index 8baac657b93d9..c791ef68e72a4 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -27,8 +27,7 @@ * @author Jason Dillon * @since 2.3 */ -public class StringsCompleter implements Completer -{ +public class StringsCompleter implements Completer { protected Collection candidates; protected Supplier> stringsSupplier; @@ -54,7 +53,7 @@ public StringsCompleter(Iterable strings) { } } - public StringsCompleter(Candidate ... candidates) { + public StringsCompleter(Candidate... candidates) { this(Arrays.asList(candidates)); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java index a17a356bf0e5d..2fe6f8df49213 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,8 +22,8 @@ * @author Matti Rinta-Nikkola */ public class SystemCompleter implements Completer { - private Map> completers = new HashMap<>(); - private Map aliasCommand = new HashMap<>(); + private Map> completers = new HashMap<>(); + private Map aliasCommand = new HashMap<>(); private StringsCompleter commands; private boolean compiled = false; @@ -44,9 +44,9 @@ public void complete(LineReader reader, ParsedLine commandLine, List commands.complete(reader, commandLine, candidates); } else if (reader.getParser().validVariableName(buffer.substring(0, eq))) { String curBuf = buffer.substring(0, eq + 1); - for (String c: completers.keySet()) { - candidates.add(new Candidate(AttributedString.stripAnsi(curBuf+c) - , c, null, null, null, null, true)); + for (String c : completers.keySet()) { + candidates.add( + new Candidate(AttributedString.stripAnsi(curBuf + c), c, null, null, null, null, true)); } } } else { @@ -81,7 +81,7 @@ public void add(String command, List completers) { } public void add(List commands, Completer completer) { - for (String c: commands) { + for (String c : commands) { add(c, completer); } } @@ -104,22 +104,22 @@ public void add(SystemCompleter other) { if (other.isCompiled()) { throw new IllegalStateException(); } - for (Map.Entry> entry: other.getCompleters().entrySet()) { - for (Completer c: entry.getValue()) { + for (Map.Entry> entry : other.getCompleters().entrySet()) { + for (Completer c : entry.getValue()) { add(entry.getKey(), c); } } addAliases(other.getAliases()); } - public void addAliases(Map aliasCommand) { + public void addAliases(Map aliasCommand) { if (compiled) { throw new IllegalStateException(); } this.aliasCommand.putAll(aliasCommand); } - private Map getAliases() { + private Map getAliases() { return aliasCommand; } @@ -128,7 +128,7 @@ public void compile() { return; } Map> compiledCompleters = new HashMap<>(); - for (Map.Entry> entry: completers.entrySet()) { + for (Map.Entry> entry : completers.entrySet()) { if (entry.getValue().size() == 1) { compiledCompleters.put(entry.getKey(), entry.getValue()); } else { @@ -143,8 +143,7 @@ public void compile() { compiled = true; } - public Map> getCompleters() { + public Map> getCompleters() { return completers; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java index cdd1bc520ddd8..c696b33ba9e5b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -41,9 +41,9 @@ public class DefaultHistory implements History { private int offset = 0; private int index = 0; - public DefaultHistory() { - } + public DefaultHistory() {} + @SuppressWarnings("this-escape") public DefaultHistory(LineReader reader) { attach(reader); } @@ -67,8 +67,7 @@ public void attach(LineReader reader) { this.reader = reader; try { load(); - } - catch (IllegalArgumentException | IOException e) { + } catch (IllegalArgumentException | IOException e) { Log.warn("Failed to load history", e); } } @@ -117,13 +116,13 @@ public void read(Path file, boolean checkDuplicates) throws IOException { } } - private String doHistoryFileDataKey (Path path){ + private String doHistoryFileDataKey(Path path) { return path != null ? path.toAbsolutePath().toString() : null; } private HistoryFileData getHistoryFileData(Path path) { String key = doHistoryFileDataKey(path); - if (!historyFiles.containsKey(key)){ + if (!historyFiles.containsKey(key)) { historyFiles.put(key, new HistoryFileData()); } return historyFiles.get(key); @@ -133,7 +132,7 @@ private void setHistoryFileData(Path path, HistoryFileData historyFileData) { historyFiles.put(doHistoryFileDataKey(path), historyFileData); } - private boolean isLineReaderHistory (Path path) throws IOException { + private boolean isLineReaderHistory(Path path) throws IOException { Path lrp = getPath(); if (lrp == null) { return path == null; @@ -141,23 +140,23 @@ private boolean isLineReaderHistory (Path path) throws IOException { return Files.isSameFile(lrp, path); } - private void setLastLoaded(Path path, int lastloaded){ + private void setLastLoaded(Path path, int lastloaded) { getHistoryFileData(path).setLastLoaded(lastloaded); } - private void setEntriesInFile(Path path, int entriesInFile){ + private void setEntriesInFile(Path path, int entriesInFile) { getHistoryFileData(path).setEntriesInFile(entriesInFile); } - private void incEntriesInFile(Path path, int amount){ + private void incEntriesInFile(Path path, int amount) { getHistoryFileData(path).incEntriesInFile(amount); } - private int getLastLoaded(Path path){ + private int getLastLoaded(Path path) { return getHistoryFileData(path).getLastLoaded(); } - private int getEntriesInFile(Path path){ + private int getEntriesInFile(Path path) { return getHistoryFileData(path).getEntriesInFile(); } @@ -168,9 +167,8 @@ protected void addHistoryLine(Path path, String line) { protected void addHistoryLine(Path path, String line, boolean checkDuplicates) { if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) { int idx = line.indexOf(':'); - final String badHistoryFileSyntax = "Bad history file syntax! " + - "The history file `" + path + "` may be an older history: " + - "please remove it or use a different history file."; + final String badHistoryFileSyntax = "Bad history file syntax! " + "The history file `" + path + + "` may be an older history: " + "please remove it or use a different history file."; if (idx < 0) { throw new IllegalArgumentException(badHistoryFileSyntax); } @@ -183,8 +181,7 @@ protected void addHistoryLine(Path path, String line, boolean checkDuplicates) { String unescaped = unescape(line.substring(idx + 1)); internalAdd(time, unescaped, checkDuplicates); - } - else { + } else { internalAdd(Instant.now(), unescape(line), checkDuplicates); } } @@ -210,8 +207,7 @@ public void write(Path file, boolean incremental) throws IOException { @Override public void append(Path file, boolean incremental) throws IOException { - internalWrite(file != null ? file : getPath(), - incremental ? getLastLoaded(file) : 0); + internalWrite(file != null ? file : getPath(), incremental ? getLastLoaded(file) : 0); } @Override @@ -227,8 +223,11 @@ private void internalWrite(Path path, int from) throws IOException { Files.createDirectories(parent); } // Append new items to the history file - try (BufferedWriter writer = Files.newBufferedWriter(path.toAbsolutePath(), - StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) { + try (BufferedWriter writer = Files.newBufferedWriter( + path.toAbsolutePath(), + StandardOpenOption.WRITE, + StandardOpenOption.APPEND, + StandardOpenOption.CREATE)) { for (Entry entry : items.subList(from, items.size())) { if (isPersistable(entry)) { writer.append(format(entry)); @@ -248,18 +247,23 @@ protected void trimHistory(Path path, int max) throws IOException { Log.trace("Trimming history path: ", path); // Load all history entries LinkedList allItems = new LinkedList<>(); - try (BufferedReader reader = Files.newBufferedReader(path)) { - reader.lines().forEach(l -> { - int idx = l.indexOf(':'); - Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); - String line = unescape(l.substring(idx + 1)); - allItems.add(createEntry(allItems.size(), time, line)); + try (BufferedReader historyFileReader = Files.newBufferedReader(path)) { + historyFileReader.lines().forEach(l -> { + if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) { + int idx = l.indexOf(':'); + Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); + String line = unescape(l.substring(idx + 1)); + allItems.add(createEntry(allItems.size(), time, line)); + } else { + allItems.add(createEntry(allItems.size(), Instant.now(), unescape(l))); + } }); } // Remove duplicates List trimmedItems = doTrimHistory(allItems, max); // Write history - Path temp = Files.createTempFile(path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp"); + Path temp = Files.createTempFile( + path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp"); try (BufferedWriter writer = Files.newBufferedWriter(temp, StandardOpenOption.WRITE)) { for (Entry entry : trimmedItems) { writer.append(format(entry)); @@ -351,7 +355,7 @@ private String format(Entry entry) { public String get(final int index) { int idx = index - offset; if (idx >= items.size() || idx < 0) { - throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx +", Size:" + items.size()); + throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx + ", Size:" + items.size()); } return items.get(idx).line(); } @@ -382,8 +386,7 @@ public void add(Instant time, String line) { if (isSet(reader, LineReader.Option.HISTORY_INCREMENTAL)) { try { save(); - } - catch (IOException e) { + } catch (IOException e) { Log.warn("Failed to save history", e); } } @@ -417,7 +420,7 @@ protected void internalAdd(Instant time, String line) { protected void internalAdd(Instant time, String line, boolean checkDuplicates) { Entry entry = new EntryImpl(offset + items.size(), time, line); if (checkDuplicates) { - for (Entry e: items) { + for (Entry e : items) { if (e.line().trim().equals(line.trim())) { return; } @@ -430,7 +433,7 @@ protected void internalAdd(Instant time, String line, boolean checkDuplicates) { private void maybeResize() { while (size() > getInt(reader, LineReader.HISTORY_SIZE, DEFAULT_HISTORY_SIZE)) { items.removeFirst(); - for (HistoryFileData hfd: historyFiles.values()) { + for (HistoryFileData hfd : historyFiles.values()) { hfd.decLastLoaded(); } offset++; @@ -633,8 +636,7 @@ private static class HistoryFileData { private int lastLoaded = 0; private int entriesInFile = 0; - public HistoryFileData() { - } + public HistoryFileData() {} public HistoryFileData(int lastLoaded, int entriesInFile) { this.lastLoaded = lastLoaded; @@ -667,8 +669,5 @@ public void setEntriesInFile(int entriesInFile) { public void incEntriesInFile(int amount) { entriesInFile = entriesInFile + amount; } - } - } - diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java index b1bab287e79be..04959488cf158 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -43,63 +43,65 @@ public enum ControlChar { * Input flags - software input processing */ public enum InputFlag { - IGNBRK, /* ignore BREAK condition */ - BRKINT, /* map BREAK to SIGINTR */ - IGNPAR, /* ignore (discard) parity errors */ - PARMRK, /* mark parity and framing errors */ - INPCK, /* enable checking of parity errors */ - ISTRIP, /* strip 8th bit off chars */ - INLCR, /* map NL into CR */ - IGNCR, /* ignore CR */ - ICRNL, /* map CR to NL (ala CRMOD) */ - IXON, /* enable output flow control */ - IXOFF, /* enable input flow control */ - IXANY, /* any char will restart after stop */ - IMAXBEL, /* ring bell on input queue full */ - IUTF8 /* maintain state for UTF-8 VERASE */ + IGNBRK, /* ignore BREAK condition */ + BRKINT, /* map BREAK to SIGINTR */ + IGNPAR, /* ignore (discard) parity errors */ + PARMRK, /* mark parity and framing errors */ + INPCK, /* enable checking of parity errors */ + ISTRIP, /* strip 8th bit off chars */ + INLCR, /* map NL into CR */ + IGNCR, /* ignore CR */ + ICRNL, /* map CR to NL (ala CRMOD) */ + IXON, /* enable output flow control */ + IXOFF, /* enable input flow control */ + IXANY, /* any char will restart after stop */ + IMAXBEL, /* ring bell on input queue full */ + IUTF8, /* maintain state for UTF-8 VERASE */ + + INORMEOL /* normalize end-of-line */ } /* * Output flags - software output processing */ public enum OutputFlag { - OPOST, /* enable following output processing */ - ONLCR, /* map NL to CR-NL (ala CRMOD) */ - OXTABS, /* expand tabs to spaces */ - ONOEOT, /* discard EOT's (^D) on output) */ - OCRNL, /* map CR to NL on output */ - ONOCR, /* no CR output at column 0 */ - ONLRET, /* NL performs CR function */ - OFILL, /* use fill characters for delay */ - NLDLY, /* \n delay */ - TABDLY, /* horizontal tab delay */ - CRDLY, /* \r delay */ - FFDLY, /* form feed delay */ - BSDLY, /* \b delay */ - VTDLY, /* vertical tab delay */ - OFDEL /* fill is DEL, else NUL */ + OPOST, /* enable following output processing */ + ONLCR, /* map NL to CR-NL (ala CRMOD) */ + OXTABS, /* expand tabs to spaces */ + ONOEOT, /* discard EOT's (^D) on output) */ + OCRNL, /* map CR to NL on output */ + ONOCR, /* no CR output at column 0 */ + ONLRET, /* NL performs CR function */ + OFILL, /* use fill characters for delay */ + NLDLY, /* \n delay */ + TABDLY, /* horizontal tab delay */ + CRDLY, /* \r delay */ + FFDLY, /* form feed delay */ + BSDLY, /* \b delay */ + VTDLY, /* vertical tab delay */ + OFDEL /* fill is DEL, else NUL */ } /* * Control flags - hardware control of terminal */ public enum ControlFlag { - CIGNORE, /* ignore control flags */ - CS5, /* 5 bits (pseudo) */ - CS6, /* 6 bits */ - CS7, /* 7 bits */ - CS8, /* 8 bits */ - CSTOPB, /* send 2 stop bits */ - CREAD, /* enable receiver */ - PARENB, /* parity enable */ - PARODD, /* odd parity, else even */ - HUPCL, /* hang up on last close */ - CLOCAL, /* ignore modem status lines */ - CCTS_OFLOW, /* CTS flow control of output */ - CRTS_IFLOW, /* RTS flow control of input */ - CDTR_IFLOW, /* DTR flow control of input */ - CDSR_OFLOW, /* DSR flow control of output */ - CCAR_OFLOW /* DCD flow control of output */ + CIGNORE, /* ignore control flags */ + CS5, /* 5 bits (pseudo) */ + CS6, /* 6 bits */ + CS7, /* 7 bits */ + CS8, /* 8 bits */ + CSTOPB, /* send 2 stop bits */ + CREAD, /* enable receiver */ + PARENB, /* parity enable */ + PARODD, /* odd parity, else even */ + HUPCL, /* hang up on last close */ + CLOCAL, /* ignore modem status lines */ + CCTS_OFLOW, /* CTS flow control of output */ + CRTS_IFLOW, /* RTS flow control of input */ + CDTR_IFLOW, /* DTR flow control of input */ + CDSR_OFLOW, /* DSR flow control of output */ + CCAR_OFLOW /* DCD flow control of output */ } /* @@ -110,23 +112,23 @@ public enum ControlFlag { * input flag. */ public enum LocalFlag { - ECHOKE, /* visual erase for line kill */ - ECHOE, /* visually erase chars */ - ECHOK, /* echo NL after line kill */ - ECHO, /* enable echoing */ - ECHONL, /* echo NL even if ECHO is off */ - ECHOPRT, /* visual erase mode for hardcopy */ - ECHOCTL, /* echo control chars as ^(Char) */ - ISIG, /* enable signals INTR, QUIT, [D]SUSP */ - ICANON, /* canonicalize input lines */ - ALTWERASE, /* use alternate WERASE algorithm */ - IEXTEN, /* enable DISCARD and LNEXT */ - EXTPROC, /* external processing */ - TOSTOP, /* stop background jobs from output */ - FLUSHO, /* output being flushed (state) */ - NOKERNINFO, /* no kernel output from VSTATUS */ - PENDIN, /* XXX retype pending input (state) */ - NOFLSH /* don't flush after interrupt */ + ECHOKE, /* visual erase for line kill */ + ECHOE, /* visually erase chars */ + ECHOK, /* echo NL after line kill */ + ECHO, /* enable echoing */ + ECHONL, /* echo NL even if ECHO is off */ + ECHOPRT, /* visual erase mode for hardcopy */ + ECHOCTL, /* echo control chars as ^(Char) */ + ISIG, /* enable signals INTR, QUIT, [D]SUSP */ + ICANON, /* canonicalize input lines */ + ALTWERASE, /* use alternate WERASE algorithm */ + IEXTEN, /* enable DISCARD and LNEXT */ + EXTPROC, /* external processing */ + TOSTOP, /* stop background jobs from output */ + FLUSHO, /* output being flushed (state) */ + NOKERNINFO, /* no kernel output from VSTATUS */ + PENDIN, /* XXX retype pending input (state) */ + NOFLSH /* don't flush after interrupt */ } final EnumSet iflag = EnumSet.noneOf(InputFlag.class); @@ -135,9 +137,9 @@ public enum LocalFlag { final EnumSet lflag = EnumSet.noneOf(LocalFlag.class); final EnumMap cchars = new EnumMap<>(ControlChar.class); - public Attributes() { - } + public Attributes() {} + @SuppressWarnings("this-escape") public Attributes(Attributes attr) { copy(attr); } @@ -310,13 +312,12 @@ public void copy(Attributes attributes) { @Override public String toString() { - return "Attributes[" + - "lflags: " + append(lflag) + ", " + - "iflags: " + append(iflag) + ", " + - "oflags: " + append(oflag) + ", " + - "cflags: " + append(cflag) + ", " + - "cchars: " + append(EnumSet.allOf(ControlChar.class), this::display) + - "]"; + return "Attributes[" + "lflags: " + + append(lflag) + ", " + "iflags: " + + append(iflag) + ", " + "oflags: " + + append(oflag) + ", " + "cflags: " + + append(cflag) + ", " + "cchars: " + + append(EnumSet.allOf(ControlChar.class), this::display) + "]"; } private String display(ControlChar c) { @@ -345,5 +346,4 @@ private > String append(EnumSet set) { private > String append(EnumSet set, Function toString) { return set.stream().map(toString).collect(Collectors.joining(" ")); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java index c561349cb0ff0..9bc3d902849ed 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java index df59e3f41b250..059b43c51ae07 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -71,12 +71,11 @@ public int getY() { @Override public String toString() { - return "MouseEvent[" + - "type=" + type + - ", button=" + button + - ", modifiers=" + modifiers + - ", x=" + x + - ", y=" + y + - ']'; + return "MouseEvent[" + "type=" + + type + ", button=" + + button + ", modifiers=" + + modifiers + ", x=" + + x + ", y=" + + y + ']'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java index 29870ad626cd5..fde3bf35959ed 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -13,9 +13,9 @@ public class Size { private int rows; private int cols; - public Size() { - } + public Size() {} + @SuppressWarnings("this-escape") public Size(int columns, int rows) { this(); setColumns(columns); @@ -50,7 +50,7 @@ public void setRows(int rows) { * @return the cursor position */ public int cursorPos(int row, int col) { - return row * (cols+1) + col; + return row * (cols + 1) + col; } public void copy(Size size) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java index 38ffb029f604a..054915e133d2a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -34,6 +34,7 @@ public interface Terminal extends Closeable, Flushable { * Type used for dumb terminals. */ String TYPE_DUMB = "dumb"; + String TYPE_DUMB_COLOR = "dumb-color"; String getName(); @@ -42,6 +43,9 @@ public interface Terminal extends Closeable, Flushable { // Signal support // + /** + * Types of signals. + */ enum Signal { INT, QUIT, @@ -51,16 +55,55 @@ enum Signal { WINCH } + /** + * The SignalHandler defines the interface used to trap signals and perform specific behaviors. + * @see Terminal.Signal + * @see Terminal#handle(Signal, SignalHandler) + */ interface SignalHandler { + /** + * The {@code SIG_DFL} value can be used to specify that the JVM default behavior + * should be used to handle this signal. + */ SignalHandler SIG_DFL = NativeSignalHandler.SIG_DFL; + + /** + * The {@code SIG_IGN} value can be used to ignore this signal and not perform + * any special processing. + */ SignalHandler SIG_IGN = NativeSignalHandler.SIG_IGN; + /** + * Handle the signal. + * @param signal the signal + */ void handle(Signal signal); } + /** + * Registers a handler for the given {@link Signal}. + *

+ * Note that the JVM does not easily allow catching the {@link Signal#QUIT} signal, which causes a thread dump + * to be displayed. This signal is mainly used when connecting through an SSH socket to a virtual terminal. + * + * @param signal the signal to register a handler for + * @param handler the handler + * @return the previous signal handler + */ SignalHandler handle(Signal signal, SignalHandler handler); + /** + * Raise the specific signal. + * This is not method usually called by non system terminals. + * When accessing a terminal through a SSH or Telnet connection, signals may be + * conveyed by the protocol and thus need to be raised when reaching the terminal code. + * The terminals do that automatically when the terminal input stream has a character + * mapped to {@link Attributes.ControlChar#VINTR}, {@link Attributes.ControlChar#VQUIT}, + * or {@link Attributes.ControlChar#VSUSP}. + * + * @param signal the signal to raise + */ void raise(Signal signal); // @@ -180,8 +223,21 @@ interface SignalHandler { boolean echo(boolean echo); + /** + * Returns the terminal attributes. + * The returned object can be safely modified + * further used in a call to {@link #setAttributes(Attributes)}. + * + * @return the terminal attributes. + */ Attributes getAttributes(); + /** + * Set the terminal attributes. + * The terminal will perform a copy of the given attributes. + * + * @param attr the new attributes + */ void setAttributes(Attributes attr); /** @@ -334,5 +390,4 @@ enum MouseTracking { * Color support */ ColorPalette getPalette(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java index 014ad78b794d7..3b02ec2d8d8ac 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,9 +8,6 @@ */ package jdk.internal.org.jline.terminal; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -19,11 +16,16 @@ import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.ServiceLoader; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.stream.Collectors; @@ -31,8 +33,10 @@ import jdk.internal.org.jline.terminal.impl.AbstractPosixTerminal; import jdk.internal.org.jline.terminal.impl.AbstractTerminal; -import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; import jdk.internal.org.jline.terminal.impl.DumbTerminal; +import jdk.internal.org.jline.terminal.impl.DumbTerminalProvider; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalExt; import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.Log; import jdk.internal.org.jline.utils.OSUtils; @@ -49,16 +53,30 @@ public final class TerminalBuilder { public static final String PROP_ENCODING = "org.jline.terminal.encoding"; public static final String PROP_CODEPAGE = "org.jline.terminal.codepage"; public static final String PROP_TYPE = "org.jline.terminal.type"; - public static final String PROP_JNA = "org.jline.terminal.jna"; - public static final String PROP_JANSI = "org.jline.terminal.jansi"; - public static final String PROP_EXEC = "org.jline.terminal.exec"; - public static final String PROP_DUMB = "org.jline.terminal.dumb"; + public static final String PROP_PROVIDER = "org.jline.terminal.provider"; + public static final String PROP_PROVIDERS = "org.jline.terminal.providers"; + public static final String PROP_PROVIDER_FFM = "ffm"; + public static final String PROP_PROVIDER_JNI = "jni"; + public static final String PROP_PROVIDER_JANSI = "jansi"; + public static final String PROP_PROVIDER_JNA = "jna"; + public static final String PROP_PROVIDER_EXEC = "exec"; + public static final String PROP_PROVIDER_DUMB = "dumb"; + public static final String PROP_PROVIDERS_DEFAULT = String.join( + ",", PROP_PROVIDER_FFM, PROP_PROVIDER_JNI, PROP_PROVIDER_JANSI, PROP_PROVIDER_JNA, PROP_PROVIDER_EXEC); + public static final String PROP_FFM = "org.jline.terminal." + PROP_PROVIDER_FFM; + public static final String PROP_JNI = "org.jline.terminal." + PROP_PROVIDER_JNI; + public static final String PROP_JANSI = "org.jline.terminal." + PROP_PROVIDER_JANSI; + public static final String PROP_JNA = "org.jline.terminal." + PROP_PROVIDER_JNA; + public static final String PROP_EXEC = "org.jline.terminal." + PROP_PROVIDER_EXEC; + public static final String PROP_DUMB = "org.jline.terminal." + PROP_PROVIDER_DUMB; public static final String PROP_DUMB_COLOR = "org.jline.terminal.dumb.color"; public static final String PROP_OUTPUT = "org.jline.terminal.output"; public static final String PROP_OUTPUT_OUT = "out"; public static final String PROP_OUTPUT_ERR = "err"; public static final String PROP_OUTPUT_OUT_ERR = "out-err"; public static final String PROP_OUTPUT_ERR_OUT = "err-out"; + public static final String PROP_OUTPUT_FORCED_OUT = "forced-out"; + public static final String PROP_OUTPUT_FORCED_ERR = "forced-err"; // // Other system properties controlling various jline parts @@ -68,6 +86,32 @@ public final class TerminalBuilder { public static final String PROP_COLOR_DISTANCE = "org.jline.utils.colorDistance"; public static final String PROP_DISABLE_ALTERNATE_CHARSET = "org.jline.utils.disableAlternateCharset"; + // + // System properties controlling how FileDescriptor are create. + // The value can be a comma separated list of defined mechanisms. + // + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE = "org.jline.terminal.pty.fileDescriptorCreationMode"; + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE = "native"; + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION = "reflection"; + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT = + String.join(",", PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION, PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE); + + // + // System properties controlling how RedirectPipe are created. + // The value can be a comma separated list of defined mechanisms. + // + public static final String PROP_REDIRECT_PIPE_CREATION_MODE = "org.jline.terminal.exec.redirectPipeCreationMode"; + public static final String PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE = "native"; + public static final String PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION = "reflection"; + public static final String PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT = + String.join(",", PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION, PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE); + + public static final Set DEPRECATED_PROVIDERS = + Collections.unmodifiableSet(new HashSet<>(Arrays.asList(PROP_PROVIDER_JNA, PROP_PROVIDER_JANSI))); + + public static final String PROP_DISABLE_DEPRECATED_PROVIDER_WARNING = + "org.jline.terminal.disableDeprecatedProviderWarning"; + // // Terminal output control // @@ -75,7 +119,9 @@ public enum SystemOutput { SysOut, SysErr, SysOutOrSysErr, - SysErrOrSysOut + SysErrOrSysOut, + ForcedSysOut, + ForcedSysErr } /** @@ -115,20 +161,23 @@ public static TerminalBuilder builder() { private int codepage; private Boolean system; private SystemOutput systemOutput; + private String provider; + private String providers; private Boolean jna; private Boolean jansi; + private Boolean jni; private Boolean exec; + private Boolean ffm; private Boolean dumb; private Boolean color; private Attributes attributes; private Size size; - private boolean nativeSignals = false; + private boolean nativeSignals = true; private Function inputStreamWrapper = in -> in; private Terminal.SignalHandler signalHandler = Terminal.SignalHandler.SIG_DFL; private boolean paused = false; - private TerminalBuilder() { - } + private TerminalBuilder() {} public TerminalBuilder name(String name) { this.name = name; @@ -160,6 +209,16 @@ public TerminalBuilder systemOutput(SystemOutput systemOutput) { return this; } + public TerminalBuilder provider(String provider) { + this.provider = provider; + return this; + } + + public TerminalBuilder providers(String providers) { + this.providers = providers; + return this; + } + public TerminalBuilder jna(boolean jna) { this.jna = jna; return this; @@ -170,11 +229,21 @@ public TerminalBuilder jansi(boolean jansi) { return this; } + public TerminalBuilder jni(boolean jni) { + this.jni = jni; + return this; + } + public TerminalBuilder exec(boolean exec) { this.exec = exec; return this; } + public TerminalBuilder ffm(boolean ffm) { + this.ffm = ffm; + return this; + } + public TerminalBuilder dumb(boolean dumb) { this.dumb = dumb; return this; @@ -280,6 +349,12 @@ public TerminalBuilder nativeSignals(boolean nativeSignals) { return this; } + /** + * Determines the default value for signal handlers. + * All signals will be mapped to the given handler. + * @param signalHandler the default signal handler + * @return The builder + */ public TerminalBuilder signalHandler(Terminal.SignalHandler signalHandler) { this.signalHandler = signalHandler; return this; @@ -305,6 +380,11 @@ public TerminalBuilder paused(boolean paused) { return this; } + /** + * Builds the terminal. + * @return the newly created terminal, never {@code null} + * @throws IOException if an error occurs + */ public Terminal build() throws IOException { Terminal override = TERMINAL_OVERRIDE.get(); Terminal terminal = override != null ? override : doBuild(); @@ -313,7 +393,8 @@ public Terminal build() throws IOException { } Log.debug(() -> "Using terminal " + terminal.getClass().getSimpleName()); if (terminal instanceof AbstractPosixTerminal) { - Log.debug(() -> "Using pty " + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName()); + Log.debug(() -> "Using pty " + + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName()); } return terminal; } @@ -323,144 +404,76 @@ private Terminal doBuild() throws IOException { if (name == null) { name = "JLine terminal"; } - Charset encoding = this.encoding; - if (encoding == null) { - String charsetName = System.getProperty(PROP_ENCODING); - if (charsetName != null && Charset.isSupported(charsetName)) { - encoding = Charset.forName(charsetName); - } - } - if (encoding == null) { - int codepage = this.codepage; - if (codepage <= 0) { - String str = System.getProperty(PROP_CODEPAGE); - if (str != null) { - codepage = Integer.parseInt(str); - } - } - if (codepage >= 0) { - encoding = getCodepageCharset(codepage); - } else { - encoding = StandardCharsets.UTF_8; - } - } - String type = this.type; - if (type == null) { - type = System.getProperty(PROP_TYPE); - } - if (type == null) { - type = System.getenv("TERM"); - } - Boolean jna = this.jna; - if (jna == null) { - jna = getBoolean(PROP_JNA, true); - } - Boolean jansi = this.jansi; - if (jansi == null) { - jansi = getBoolean(PROP_JANSI, true); - } - Boolean exec = this.exec; - if (exec == null) { - exec = getBoolean(PROP_EXEC, true); + Charset encoding = computeEncoding(); + String type = computeType(); + + String provider = this.provider; + if (provider == null) { + provider = System.getProperty(PROP_PROVIDER, null); } + + boolean forceDumb = + (DumbTerminal.TYPE_DUMB.equals(type) || type != null && type.startsWith(DumbTerminal.TYPE_DUMB_COLOR)) + || (provider != null && provider.equals(PROP_PROVIDER_DUMB)); Boolean dumb = this.dumb; if (dumb == null) { dumb = getBoolean(PROP_DUMB, null); } IllegalStateException exception = new IllegalStateException("Unable to create a terminal"); - List providers = new ArrayList<>(); - if (jna) { - try { - TerminalProvider provider = TerminalProvider.load("jna"); - providers.add(provider); - } catch (Throwable t) { - Log.debug("Unable to load JNA support: ", t); - exception.addSuppressed(t); - } - } - if (jansi) { - try { - TerminalProvider provider = TerminalProvider.load("jansi"); - providers.add(provider); - } catch (Throwable t) { - Log.debug("Unable to load JANSI support: ", t); - exception.addSuppressed(t); - } - } - if (exec) - { - try { - TerminalProvider provider = TerminalProvider.load("exec"); - providers.add(provider); - } catch (Throwable t) { - Log.debug("Unable to load EXEC support: ", t); - exception.addSuppressed(t); - } - } - + List providers = getProviders(provider, exception); Terminal terminal = null; if ((system != null && system) || (system == null && in == null && out == null)) { - if (system != null && ((in != null && !in.equals(System.in)) || - (out != null && !out.equals(System.out) && !out.equals(System.err)))) { + if (system != null + && ((in != null && !in.equals(System.in)) + || (out != null && !out.equals(System.out) && !out.equals(System.err)))) { throw new IllegalArgumentException("Cannot create a system terminal using non System streams"); } if (attributes != null || size != null) { Log.warn("Attributes and size fields are ignored when creating a system terminal"); } - if (out != null) { - if (out.equals(System.out)) { - systemOutput = SystemOutput.SysOut; - } else if (out.equals(System.err)) { - systemOutput = SystemOutput.SysErr; - } - } - if (systemOutput == null) { - String str = System.getProperty(PROP_OUTPUT); - if (str != null) { - switch (str.trim().toLowerCase(Locale.ROOT)) { - case PROP_OUTPUT_OUT: systemOutput = SystemOutput.SysOut; break; - case PROP_OUTPUT_ERR: systemOutput = SystemOutput.SysErr; break; - case PROP_OUTPUT_OUT_ERR: systemOutput = SystemOutput.SysOutOrSysErr; break; - case PROP_OUTPUT_ERR_OUT: systemOutput = SystemOutput.SysErrOrSysOut; break; - default: - Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: " - + String.join(", ", PROP_OUTPUT_OUT, PROP_OUTPUT_ERR, PROP_OUTPUT_OUT_ERR,PROP_OUTPUT_ERR_OUT) - + "."); - } - } - } - if (systemOutput == null) { - systemOutput = SystemOutput.SysOutOrSysErr; - } - Map system = Stream.of(TerminalProvider.Stream.values()) - .collect(Collectors.toMap(stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream)))); - TerminalProvider.Stream console = select(system, systemOutput); + SystemOutput systemOutput = computeSystemOutput(); + Map system = Stream.of(SystemStream.values()) + .collect(Collectors.toMap( + stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream)))); + SystemStream systemStream = select(system, systemOutput); - if (system.get(TerminalProvider.Stream.Input) && console != null) { + if (!forceDumb && system.get(SystemStream.Input) && systemStream != null) { if (attributes != null || size != null) { Log.warn("Attributes and size fields are ignored when creating a system terminal"); } boolean ansiPassThrough = OSUtils.IS_CONEMU; // Cygwin defaults to XTERM, but actually supports 256 colors, // so if the value comes from the environment, change it to xterm-256color - if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) && "xterm".equals(type) - && this.type == null && System.getProperty(PROP_TYPE) == null) { + if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) + && "xterm".equals(type) + && this.type == null + && System.getProperty(PROP_TYPE) == null) { type = "xterm-256color"; } - for ( TerminalProvider provider : providers) { + for (TerminalProvider prov : providers) { if (terminal == null) { try { - terminal = provider.sysTerminal(name, type, ansiPassThrough, encoding, - nativeSignals, signalHandler, paused, console, inputStreamWrapper); + terminal = prov.sysTerminal( + name, + type, + ansiPassThrough, + encoding, + nativeSignals, + signalHandler, + paused, + systemStream, + inputStreamWrapper); } catch (Throwable t) { - Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); + Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t); exception.addSuppressed(t); } } } - if (terminal == null && OSUtils.IS_WINDOWS && !jna && !jansi && (dumb == null || !dumb)) { - throw new IllegalStateException("Unable to create a system terminal. On windows, either " - + "JNA or JANSI library is required. Make sure to add one of those in the classpath."); + if (terminal == null && OSUtils.IS_WINDOWS && providers.isEmpty() && (dumb == null || !dumb)) { + throw new IllegalStateException( + "Unable to create a system terminal. On Windows, either JLine's native libraries, JNA " + + "or Jansi library is required. Make sure to add one of those in the classpath.", + exception); } } if (terminal instanceof AbstractTerminal) { @@ -468,55 +481,42 @@ private Terminal doBuild() throws IOException { if (SYSTEM_TERMINAL.compareAndSet(null, t)) { t.setOnClose(() -> SYSTEM_TERMINAL.compareAndSet(t, null)); } else { - exception.addSuppressed(new IllegalStateException("A system terminal is already running. " + - "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " + - "or that previously created system Terminals have been correctly closed.")); + exception.addSuppressed(new IllegalStateException("A system terminal is already running. " + + "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " + + "or that previously created system Terminals have been correctly closed.")); terminal.close(); terminal = null; } } - if (terminal == null && (dumb == null || dumb)) { - // forced colored dumb terminal - Boolean color = this.color; - if (color == null) { - color = getBoolean(PROP_DUMB_COLOR, false); - // detect emacs using the env variable - if (!color) { - String emacs = System.getenv("INSIDE_EMACS"); - color = emacs != null && emacs.contains("comint"); - } - // detect Intellij Idea - if (!color) { - String command = getParentProcessCommand(); - color = command != null && command.contains("idea"); - } - if (!color) { - color = system.get(TerminalProvider.Stream.Output) && System.getenv("TERM") != null; - } - if (!color && dumb == null) { - if (Log.isDebugEnabled()) { - Log.warn("input is tty: {}", system.get(TerminalProvider.Stream.Input)); - Log.warn("output is tty: {}", system.get(TerminalProvider.Stream.Output)); - Log.warn("error is tty: {}", system.get(TerminalProvider.Stream.Error)); - Log.warn("Creating a dumb terminal", exception); - } else { - Log.warn("Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)"); - } + if (terminal == null && (forceDumb || dumb == null || dumb)) { + if (!forceDumb && dumb == null) { + if (Log.isDebugEnabled()) { + Log.warn("input is tty: " + system.get(SystemStream.Input)); + Log.warn("output is tty: " + system.get(SystemStream.Output)); + Log.warn("error is tty: " + system.get(SystemStream.Error)); + Log.warn("Creating a dumb terminal", exception); + } else { + Log.warn( + "Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)"); } } - terminal = new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB, - new FileInputStream(FileDescriptor.in), - //JDK change: always write into stdout: - new FileOutputStream(FileDescriptor.out), - encoding, signalHandler); + type = getDumbTerminalType(dumb, systemStream); + terminal = new DumbTerminalProvider() + .sysTerminal(name, type, false, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); + if (OSUtils.IS_WINDOWS) { + Attributes attr = terminal.getAttributes(); + attr.setInputFlag(Attributes.InputFlag.IGNCR, true); + terminal.setAttributes(attr); + } } } else { - for ( TerminalProvider provider : providers) { + for (TerminalProvider prov : providers) { if (terminal == null) { try { - terminal = provider.newTerminal(name, type, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused, attributes, size); + terminal = prov.newTerminal( + name, type, in, out, encoding, signalHandler, paused, attributes, size); } catch (Throwable t) { - Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); + Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t); exception.addSuppressed(t); } } @@ -525,25 +525,220 @@ private Terminal doBuild() throws IOException { if (terminal == null) { throw exception; } + if (terminal instanceof TerminalExt) { + TerminalExt te = (TerminalExt) terminal; + if (DEPRECATED_PROVIDERS.contains(te.getProvider().name()) + && !getBoolean(PROP_DISABLE_DEPRECATED_PROVIDER_WARNING, false)) { + Log.warn("The terminal provider " + te.getProvider().name() + + " has been deprecated, check your configuration. This warning can be disabled by setting the system property " + + PROP_DISABLE_DEPRECATED_PROVIDER_WARNING + " to true."); + } + } return terminal; } - private TerminalProvider.Stream select(Map system, SystemOutput systemOutput) { + private String getDumbTerminalType(Boolean dumb, SystemStream systemStream) { + // forced colored dumb terminal + Boolean color = this.color; + if (color == null) { + color = getBoolean(PROP_DUMB_COLOR, null); + } + if (dumb == null) { + // detect emacs using the env variable + if (color == null) { + String emacs = System.getenv("INSIDE_EMACS"); + if (emacs != null && emacs.contains("comint")) { + color = true; + } + } + // detect Intellij Idea + if (color == null) { + // using the env variable on windows + String ideHome = System.getenv("IDE_HOME"); + if (ideHome != null) { + color = true; + } else { + // using the parent process command on unix/mac + String command = getParentProcessCommand(); + if (command != null && command.endsWith("/idea")) { + color = true; + } + } + } + if (color == null) { + color = systemStream != null && System.getenv("TERM") != null; + } + } else { + if (color == null) { + color = false; + } + } + return color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB; + } + + public SystemOutput computeSystemOutput() { + SystemOutput systemOutput = null; + if (out != null) { + if (out.equals(System.out)) { + systemOutput = SystemOutput.SysOut; + } else if (out.equals(System.err)) { + systemOutput = SystemOutput.SysErr; + } + } + if (systemOutput == null) { + systemOutput = this.systemOutput; + } + if (systemOutput == null) { + String str = System.getProperty(PROP_OUTPUT); + if (str != null) { + switch (str.trim().toLowerCase(Locale.ROOT)) { + case PROP_OUTPUT_OUT: + systemOutput = SystemOutput.SysOut; + break; + case PROP_OUTPUT_ERR: + systemOutput = SystemOutput.SysErr; + break; + case PROP_OUTPUT_OUT_ERR: + systemOutput = SystemOutput.SysOutOrSysErr; + break; + case PROP_OUTPUT_ERR_OUT: + systemOutput = SystemOutput.SysErrOrSysOut; + break; + case PROP_OUTPUT_FORCED_OUT: + systemOutput = SystemOutput.ForcedSysOut; + break; + case PROP_OUTPUT_FORCED_ERR: + systemOutput = SystemOutput.ForcedSysErr; + break; + default: + Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: " + + String.join( + ", ", + PROP_OUTPUT_OUT, + PROP_OUTPUT_ERR, + PROP_OUTPUT_OUT_ERR, + PROP_OUTPUT_ERR_OUT) + + "."); + } + } + } + if (systemOutput == null) { + systemOutput = SystemOutput.SysOutOrSysErr; + } + return systemOutput; + } + + public String computeType() { + String type = this.type; + if (type == null) { + type = System.getProperty(PROP_TYPE); + } + if (type == null) { + type = System.getenv("TERM"); + } + return type; + } + + public Charset computeEncoding() { + Charset encoding = this.encoding; + if (encoding == null) { + String charsetName = System.getProperty(PROP_ENCODING); + if (charsetName != null && Charset.isSupported(charsetName)) { + encoding = Charset.forName(charsetName); + } + } + if (encoding == null) { + int codepage = this.codepage; + if (codepage <= 0) { + String str = System.getProperty(PROP_CODEPAGE); + if (str != null) { + codepage = Integer.parseInt(str); + } + } + if (codepage >= 0) { + encoding = getCodepageCharset(codepage); + } else { + encoding = StandardCharsets.UTF_8; + } + } + return encoding; + } + + /** + * Get the list of available terminal providers. + * This list is sorted according to the {@link #PROP_PROVIDERS} system property. + * @param provider if not {@code null}, only this provider will be checked + * @param exception if a provider throws an exception, it will be added to this exception as a suppressed exception + * @return a list of terminal providers + */ + public List getProviders(String provider, IllegalStateException exception) { + List providers = new ArrayList<>(); + // Check ffm provider + checkProvider(provider, exception, providers, ffm, PROP_FFM, PROP_PROVIDER_FFM); + // Check jni provider + checkProvider(provider, exception, providers, jni, PROP_JNI, PROP_PROVIDER_JNI); + // Check jansi provider + checkProvider(provider, exception, providers, jansi, PROP_JANSI, PROP_PROVIDER_JANSI); + // Check jna provider + checkProvider(provider, exception, providers, jna, PROP_JNA, PROP_PROVIDER_JNA); + // Check exec provider + checkProvider(provider, exception, providers, exec, PROP_EXEC, PROP_PROVIDER_EXEC); + // Order providers + List order = Arrays.asList( + (this.providers != null ? this.providers : System.getProperty(PROP_PROVIDERS, PROP_PROVIDERS_DEFAULT)) + .split(",")); + providers.sort(Comparator.comparing(l -> { + int idx = order.indexOf(l.name()); + return idx >= 0 ? idx : Integer.MAX_VALUE; + })); + String names = providers.stream().map(TerminalProvider::name).collect(Collectors.joining(", ")); + Log.debug("Available providers: " + names); + return providers; + } + + private void checkProvider( + String provider, + IllegalStateException exception, + List providers, + Boolean load, + String property, + String name) { + Boolean doLoad = provider != null ? (Boolean) name.equals(provider) : load; + if (doLoad == null) { + doLoad = getBoolean(property, true); + } + if (doLoad) { + try { + TerminalProvider prov = TerminalProvider.load(name); + prov.isSystemStream(SystemStream.Output); + providers.add(prov); + } catch (Throwable t) { + Log.debug("Unable to load " + name + " provider: ", t); + exception.addSuppressed(t); + } + } + } + + private SystemStream select(Map system, SystemOutput systemOutput) { switch (systemOutput) { case SysOut: - return select(system, TerminalProvider.Stream.Output); + return select(system, SystemStream.Output); case SysErr: - return select(system, TerminalProvider.Stream.Error); + return select(system, SystemStream.Error); case SysOutOrSysErr: - return select(system, TerminalProvider.Stream.Output, TerminalProvider.Stream.Error); + return select(system, SystemStream.Output, SystemStream.Error); case SysErrOrSysOut: - return select(system, TerminalProvider.Stream.Error, TerminalProvider.Stream.Output); + return select(system, SystemStream.Error, SystemStream.Output); + case ForcedSysOut: + return SystemStream.Output; + case ForcedSysErr: + return SystemStream.Error; } return null; } - private static TerminalProvider.Stream select(Map system, TerminalProvider.Stream... streams) { - for (TerminalProvider.Stream s : streams) { + private static SystemStream select(Map system, SystemStream... streams) { + for (SystemStream s : streams) { if (system.get(s)) { return s; } @@ -558,7 +753,9 @@ private static String getParentProcessCommand() { Object parent = ((Optional) phClass.getMethod("parent").invoke(current)).orElse(null); Method infoMethod = phClass.getMethod("info"); Object info = infoMethod.invoke(parent); - Object command = ((Optional) infoMethod.getReturnType().getMethod("command").invoke(info)).orElse(null); + Object command = ((Optional) + infoMethod.getReturnType().getMethod("command").invoke(info)) + .orElse(null); return (String) command; } catch (Throwable t) { return null; @@ -583,7 +780,7 @@ private static S load(Class clazz) { private static final int UTF8_CODE_PAGE = 65001; private static Charset getCodepageCharset(int codepage) { - //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html + // http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html if (codepage == UTF8_CODE_PAGE) { return StandardCharsets.UTF_8; } @@ -630,5 +827,4 @@ private static Charset getCodepageCharset(int codepage) { public static void setTerminalOverride(final Terminal terminal) { TERMINAL_OVERRIDE.set(terminal); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java index b5f55b80f1e31..5d000d070837b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,6 +18,8 @@ import jdk.internal.org.jline.terminal.Cursor; import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; public abstract class AbstractPosixTerminal extends AbstractTerminal { @@ -28,7 +30,8 @@ public AbstractPosixTerminal(String name, String type, Pty pty) throws IOExcepti this(name, type, pty, null, SignalHandler.SIG_DFL); } - public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) throws IOException { + public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) + throws IOException { super(name, type, encoding, signalHandler); Objects.requireNonNull(pty); this.pty = pty; @@ -82,4 +85,13 @@ public Cursor getCursorPosition(IntConsumer discarded) { return CursorSupport.getCursorPosition(this, discarded); } + @Override + public TerminalProvider getProvider() { + return getPty().getProvider(); + } + + @Override + public SystemStream getSystemStream() { + return getPty().getSystemStream(); + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java index 0feab84fc7e99..3fbe63f3c5d6b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,20 +8,39 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.spi.Pty; -import jdk.internal.org.jline.utils.NonBlockingInputStream; - +import java.io.FileDescriptor; +import java.io.FilterInputStream; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; +import java.lang.reflect.Field; + +//import jdk.internal.org.jline.nativ.JLineLibrary; +//import jdk.internal.org.jline.nativ.JLineNativeLoader; +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.utils.NonBlockingInputStream; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION; import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_NON_BLOCKING_READS; public abstract class AbstractPty implements Pty { + protected final TerminalProvider provider; + protected final SystemStream systemStream; private Attributes current; + private boolean skipNextLf; + + public AbstractPty(TerminalProvider provider, SystemStream systemStream) { + this.provider = provider; + this.systemStream = systemStream; + } @Override public void setAttr(Attributes attr) throws IOException { @@ -32,10 +51,32 @@ public void setAttr(Attributes attr) throws IOException { @Override public InputStream getSlaveInput() throws IOException { InputStream si = doGetSlaveInput(); + InputStream nsi = new FilterInputStream(si) { + @Override + public int read() throws IOException { + for (; ; ) { + int c = super.read(); + if (current.getInputFlag(Attributes.InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + continue; + } + } else { + skipNextLf = false; + } + } + return c; + } + } + }; if (Boolean.parseBoolean(System.getProperty(PROP_NON_BLOCKING_READS, "true"))) { - return new PtyInputStream(si); + return new PtyInputStream(nsi); } else { - return si; + return nsi; } } @@ -49,6 +90,16 @@ protected void checkInterrupted() throws InterruptedIOException { } } + @Override + public TerminalProvider getProvider() { + return provider; + } + + @Override + public SystemStream getSystemStream() { + return systemStream; + } + class PtyInputStream extends NonBlockingInputStream { final InputStream in; int c = 0; @@ -102,4 +153,103 @@ private void setNonBlocking() { } } + private static FileDescriptorCreator fileDescriptorCreator; + + protected static FileDescriptor newDescriptor(int fd) { + if (fileDescriptorCreator == null) { + String str = + System.getProperty(PROP_FILE_DESCRIPTOR_CREATION_MODE, PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT); + String[] modes = str.split(","); + IllegalStateException ise = new IllegalStateException("Unable to create FileDescriptor"); + for (String mode : modes) { + try { + switch (mode) { + case PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE: + fileDescriptorCreator = null;//new NativeFileDescriptorCreator(); + break; + case PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION: + fileDescriptorCreator = new ReflectionFileDescriptorCreator(); + break; + } + } catch (Throwable t) { + // ignore + ise.addSuppressed(t); + } + if (fileDescriptorCreator != null) { + break; + } + } + if (fileDescriptorCreator == null) { + throw ise; + } + } + return fileDescriptorCreator.newDescriptor(fd); + } + + interface FileDescriptorCreator { + FileDescriptor newDescriptor(int fd); + } + + /* + * Class that could be used on OpenJDK 17. However, it requires the following JVM option + * --add-exports java.base/jdk.internal.access=ALL-UNNAMED + * so the benefit does not seem important enough to warrant the problems caused + * by access the jdk.internal.access package at compile time, which itself requires + * custom compiler options and a different maven module, or at least a different compile + * phase with a JDK 17 compiler. + * So, just keep the ReflectionFileDescriptorCreator for now. + * + static class Jdk17FileDescriptorCreator implements FileDescriptorCreator { + private final jdk.internal.access.JavaIOFileDescriptorAccess fdAccess; + Jdk17FileDescriptorCreator() { + fdAccess = jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess(); + } + + @Override + public FileDescriptor newDescriptor(int fd) { + FileDescriptor descriptor = new FileDescriptor(); + fdAccess.set(descriptor, fd); + return descriptor; + } + } + */ + + /** + * Reflection based file descriptor creator. + * This requires the following option + * --add-opens java.base/java.io=ALL-UNNAMED + */ + static class ReflectionFileDescriptorCreator implements FileDescriptorCreator { + private final Field fileDescriptorField; + + ReflectionFileDescriptorCreator() throws Exception { + Field field = FileDescriptor.class.getDeclaredField("fd"); + field.setAccessible(true); + fileDescriptorField = field; + } + + @Override + public FileDescriptor newDescriptor(int fd) { + FileDescriptor descriptor = new FileDescriptor(); + try { + fileDescriptorField.set(descriptor, fd); + } catch (IllegalAccessException e) { + // This should not happen as the field has been set accessible + throw new IllegalStateException(e); + } + return descriptor; + } + } + +// static class NativeFileDescriptorCreator implements FileDescriptorCreator { +// NativeFileDescriptorCreator() { +// // Force load the library +// JLineNativeLoader.initialize(); +// } +// +// @Override +// public FileDescriptor newDescriptor(int fd) { +// return JLineLibrary.newFileDescriptor(fd); +// } +// } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java index 8a464a6726565..2608e2e5f37c5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -27,7 +27,7 @@ import jdk.internal.org.jline.terminal.Attributes.LocalFlag; import jdk.internal.org.jline.terminal.Cursor; import jdk.internal.org.jline.terminal.MouseEvent; -import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.spi.TerminalExt; import jdk.internal.org.jline.utils.ColorPalette; import jdk.internal.org.jline.utils.Curses; import jdk.internal.org.jline.utils.InfoCmp; @@ -35,7 +35,7 @@ import jdk.internal.org.jline.utils.Log; import jdk.internal.org.jline.utils.Status; -public abstract class AbstractTerminal implements Terminal { +public abstract class AbstractTerminal implements TerminalExt { protected final String name; protected final String type; @@ -44,7 +44,7 @@ public abstract class AbstractTerminal implements Terminal { protected final Set bools = new HashSet<>(); protected final Map ints = new HashMap<>(); protected final Map strings = new HashMap<>(); - protected final ColorPalette palette = new ColorPalette(this); + protected final ColorPalette palette; protected Status status; protected Runnable onClose; @@ -52,10 +52,13 @@ public AbstractTerminal(String name, String type) throws IOException { this(name, type, null, SignalHandler.SIG_DFL); } - public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) throws IOException { + @SuppressWarnings("this-escape") + public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) + throws IOException { this.name = name; this.type = type != null ? type : "ansi"; this.encoding = encoding != null ? encoding : System.out.charset(); + this.palette = new ColorPalette(this); for (Signal signal : Signal.values()) { handlers.put(signal, signalHandler); } @@ -85,12 +88,13 @@ public SignalHandler handle(Signal signal, SignalHandler handler) { public void raise(Signal signal) { Objects.requireNonNull(signal); SignalHandler handler = handlers.get(signal); - if (handler != SignalHandler.SIG_DFL && handler != SignalHandler.SIG_IGN) { + if (handler == SignalHandler.SIG_DFL) { + if (status != null && signal == Signal.WINCH) { + status.resize(); + } + } else if (handler != SignalHandler.SIG_IGN) { handler.handle(signal); } - if (status != null && signal == Signal.WINCH) { - status.resize(); - } } public final void close() throws IOException { @@ -105,8 +109,7 @@ public final void close() throws IOException { protected void doClose() throws IOException { if (status != null) { - status.update(null); - flush(); + status.close(); } } @@ -126,7 +129,7 @@ protected void echoSignal(Signal signal) { if (cc != null) { int vcc = getAttributes().getControlChar(cc); if (vcc > 0 && vcc < 32) { - writer().write(new char[]{'^', (char) (vcc + '@')}, 0, 2); + writer().write(new char[] {'^', (char) (vcc + '@')}, 0, 2); } } } @@ -217,8 +220,7 @@ public Cursor getCursorPosition(IntConsumer discarded) { } private MouseEvent lastMouseEvent = new MouseEvent( - MouseEvent.Type.Moved, MouseEvent.Button.NoButton, - EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0); + MouseEvent.Type.Moved, MouseEvent.Button.NoButton, EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0); @Override public boolean hasMouseSupport() { @@ -268,16 +270,13 @@ public boolean canPauseResume() { } @Override - public void pause() { - } + public void pause() {} @Override - public void pause(boolean wait) throws InterruptedException { - } + public void pause(boolean wait) throws InterruptedException {} @Override - public void resume() { - } + public void resume() {} @Override public boolean paused() { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java index 0c36902a1a772..301b89eb7963f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -29,11 +29,8 @@ public void write(char[] cbuf, int off, int len) throws IOException { } @Override - public void flush() { - } + public void flush() {} @Override - public void close() { - } - + public void close() {} } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java index 57cfb5d50b431..03c42fb19f7de 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2023, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,8 +8,20 @@ */ package jdk.internal.org.jline.terminal.impl; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.Curses; import jdk.internal.org.jline.utils.InfoCmp; import jdk.internal.org.jline.utils.Log; @@ -21,17 +33,6 @@ import jdk.internal.org.jline.utils.Signals; import jdk.internal.org.jline.utils.WriterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.Writer; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - /** * The AbstractWindowsTerminal is used as the base class for windows terminal. * Due to windows limitations, mostly the missing support for ansi sequences, @@ -44,7 +45,7 @@ * the writer() becomes the primary output, while the output() is bridged * to the writer() using a WriterOutputStream wrapper. */ -public abstract class AbstractWindowsTerminal extends AbstractTerminal { +public abstract class AbstractWindowsTerminal extends AbstractTerminal { public static final String TYPE_WINDOWS = "windows"; public static final String TYPE_WINDOWS_256_COLOR = "windows-256color"; @@ -56,12 +57,13 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { private static final int UTF8_CODE_PAGE = 65001; protected static final int ENABLE_PROCESSED_INPUT = 0x0001; - protected static final int ENABLE_LINE_INPUT = 0x0002; - protected static final int ENABLE_ECHO_INPUT = 0x0004; - protected static final int ENABLE_WINDOW_INPUT = 0x0008; - protected static final int ENABLE_MOUSE_INPUT = 0x0010; - protected static final int ENABLE_INSERT_MODE = 0x0020; + protected static final int ENABLE_LINE_INPUT = 0x0002; + protected static final int ENABLE_ECHO_INPUT = 0x0004; + protected static final int ENABLE_WINDOW_INPUT = 0x0008; + protected static final int ENABLE_MOUSE_INPUT = 0x0010; + protected static final int ENABLE_INSERT_MODE = 0x0020; protected static final int ENABLE_QUICK_EDIT_MODE = 0x0040; + protected static final int ENABLE_EXTENDED_FLAGS = 0x0080; protected final Writer slaveInputPipe; protected final InputStream input; @@ -71,7 +73,12 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { protected final Map nativeHandlers = new HashMap<>(); protected final ShutdownHooks.Task closer; protected final Attributes attributes = new Attributes(); - protected final int originalConsoleMode; + protected final Console inConsole; + protected final Console outConsole; + protected final int originalInConsoleMode; + protected final int originalOutConsoleMode; + private final TerminalProvider provider; + private final SystemStream systemStream; protected final Object lock = new Object(); protected boolean paused = true; @@ -80,21 +87,42 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { protected MouseTracking tracking = MouseTracking.Off; protected boolean focusTracking = false; private volatile boolean closing; - - public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, Function inputStreamWrapper) throws IOException { + protected boolean skipNextLf; + + @SuppressWarnings("this-escape") + public AbstractWindowsTerminal( + TerminalProvider provider, + SystemStream systemStream, + Writer writer, + String name, + String type, + Charset encoding, + boolean nativeSignals, + SignalHandler signalHandler, + Console inConsole, + int inConsoleMode, + Console outConsole, + int outConsoleMode, + Function inputStreamWrapper) + throws IOException { super(name, type, encoding, signalHandler); + this.provider = provider; + this.systemStream = systemStream; NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader(); this.slaveInputPipe = reader.getWriter(); this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding())); this.reader = NonBlocking.nonBlocking(name, input, encoding()); this.writer = new PrintWriter(writer); this.output = new WriterOutputStream(writer, encoding()); + this.inConsole = inConsole; + this.outConsole = outConsole; parseInfoCmp(); // Attributes - originalConsoleMode = getConsoleMode(); + this.originalInConsoleMode = inConsoleMode; + this.originalOutConsoleMode = outConsoleMode; attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true); attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C')); - attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D')); + attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D')); attributes.setControlChar(Attributes.ControlChar.VSUSP, ctrl('Z')); // Handle signals if (nativeSignals) { @@ -148,7 +176,7 @@ public OutputStream output() { } public Attributes getAttributes() { - int mode = getConsoleMode(); + int mode = getConsoleMode(inConsole); if ((mode & ENABLE_ECHO_INPUT) != 0) { attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true); } @@ -173,8 +201,11 @@ protected void updateConsoleMode() { } if (tracking != MouseTracking.Off) { mode |= ENABLE_MOUSE_INPUT; + // mouse events not send with quick edit mode + // to disable ENABLE_QUICK_EDIT_MODE just set extended flag + mode |= ENABLE_EXTENDED_FLAGS; } - setConsoleMode(mode); + setConsoleMode(inConsole, mode); } protected int ctrl(char key) { @@ -197,23 +228,26 @@ protected void doClose() throws IOException { } reader.close(); writer.close(); - setConsoleMode(originalConsoleMode); + setConsoleMode(inConsole, originalInConsoleMode); + setConsoleMode(outConsole, originalOutConsoleMode); } static final int SHIFT_FLAG = 0x01; - static final int ALT_FLAG = 0x02; - static final int CTRL_FLAG = 0x04; - - static final int RIGHT_ALT_PRESSED = 0x0001; - static final int LEFT_ALT_PRESSED = 0x0002; - static final int RIGHT_CTRL_PRESSED = 0x0004; - static final int LEFT_CTRL_PRESSED = 0x0008; - static final int SHIFT_PRESSED = 0x0010; - static final int NUMLOCK_ON = 0x0020; - static final int SCROLLLOCK_ON = 0x0040; - static final int CAPSLOCK_ON = 0x0080; - - protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) throws IOException { + static final int ALT_FLAG = 0x02; + static final int CTRL_FLAG = 0x04; + + static final int RIGHT_ALT_PRESSED = 0x0001; + static final int LEFT_ALT_PRESSED = 0x0002; + static final int RIGHT_CTRL_PRESSED = 0x0004; + static final int LEFT_CTRL_PRESSED = 0x0008; + static final int SHIFT_PRESSED = 0x0010; + static final int NUMLOCK_ON = 0x0020; + static final int SCROLLLOCK_ON = 0x0040; + static final int CAPSLOCK_ON = 0x0080; + + protected void processKeyEvent( + final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) + throws IOException { final boolean isCtrl = (controlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) > 0; final boolean isAlt = (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) > 0; final boolean isShift = (controlKeyState & SHIFT_PRESSED) > 0; @@ -222,11 +256,13 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed, // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors if (ch != 0 - && (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED)) - == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { + && (controlKeyState + & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) + == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { processInputChar(ch); } else { - final String keySeq = getEscapeSequence(virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0)); + final String keySeq = getEscapeSequence( + virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0)); if (keySeq != null) { for (char c : keySeq.toCharArray()) { processInputChar(c); @@ -240,7 +276,7 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo * 4). Ctrl + Space(0x20) : uchar=0x20 * 5). Ctrl + : uchar=0 * 6). Ctrl + Alt + : uchar=0 - */ + */ if (ch > 0) { if (isAlt) { processInputChar('\033'); @@ -254,10 +290,10 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo } else { processInputChar(ch); } - } else if (isCtrl) { //Handles the ctrl key events(uchar=0) + } else if (isCtrl) { // Handles the ctrl key events(uchar=0) if (virtualKeyCode >= 'A' && virtualKeyCode <= 'Z') { ch = (char) (virtualKeyCode - 0x40); - } else if (virtualKeyCode == 191) { //? + } else if (virtualKeyCode == 191) { // ? ch = 127; } if (ch > 0) { @@ -275,7 +311,7 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo else { // support ALT+NumPad input method if (virtualKeyCode == 0x12 /*VK_MENU ALT key*/ && ch > 0) { - processInputChar(ch); // no such combination in Windows + processInputChar(ch); // no such combination in Windows } } } @@ -468,7 +504,19 @@ public void processInputChar(char c) throws IOException { raise(Signal.INFO); } } - if (c == '\r') { + if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + return; + } + } else { + skipNextLf = false; + } + } else if (c == '\r') { if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) { return; } @@ -478,10 +526,10 @@ public void processInputChar(char c) throws IOException { } else if (c == '\n' && attributes.getInputFlag(Attributes.InputFlag.INLCR)) { c = '\r'; } -// if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) { -// processOutputByte(c); -// masterOutput.flush(); -// } + // if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) { + // processOutputByte(c); + // masterOutput.flush(); + // } slaveInputPipe.write(c); } @@ -492,9 +540,9 @@ public boolean trackMouse(MouseTracking tracking) { return true; } - protected abstract int getConsoleMode(); + protected abstract int getConsoleMode(Console console); - protected abstract void setConsoleMode(int mode); + protected abstract void setConsoleMode(Console console, int mode); /** * Read a single input event from the input buffer and process it. @@ -504,5 +552,13 @@ public boolean trackMouse(MouseTracking tracking) { */ protected abstract boolean processConsoleInput() throws IOException; -} + @Override + public TerminalProvider getProvider() { + return provider; + } + @Override + public SystemStream getSystemStream() { + return systemStream; + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java index ef22cd0a7d877..14253d8c1d19a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,17 +8,17 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.Cursor; -import jdk.internal.org.jline.terminal.Terminal; -import jdk.internal.org.jline.utils.Curses; -import jdk.internal.org.jline.utils.InfoCmp; - import java.io.IOError; import java.io.IOException; import java.util.function.IntConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jdk.internal.org.jline.terminal.Cursor; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.utils.Curses; +import jdk.internal.org.jline.utils.InfoCmp; + public class CursorSupport { public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) { @@ -105,5 +105,4 @@ public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) throw new IOError(e); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java index dfa784c29f30c..dc54ea2157d8d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, the original author or authors. + * Copyright (c) 2022, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -17,6 +17,7 @@ import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.spi.SystemStream; import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.OSUtils; @@ -26,7 +27,7 @@ public static void main(String[] args) { diag(System.out); } - static void diag(PrintStream out) { + public static void diag(PrintStream out) { out.println("System properties"); out.println("================="); out.println("os.name = " + System.getProperty("os.name")); @@ -50,6 +51,17 @@ static void diag(PrintStream out) { out.println("IS_OSX = " + OSUtils.IS_OSX); out.println(); + // FFM + out.println("FFM Support"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("ffm"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("FFM support not available: " + t); + } + out.println(); + out.println("JnaSupport"); out.println("================="); try { @@ -60,13 +72,23 @@ static void diag(PrintStream out) { } out.println(); - out.println("JansiSupport"); + out.println("Jansi2Support"); out.println("================="); try { TerminalProvider provider = TerminalProvider.load("jansi"); testProvider(out, provider); } catch (Throwable t) { - out.println("Jansi support not available: " + t); + out.println("Jansi 2 support not available: " + t); + } + out.println(); + + out.println("JniSupport"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("jni"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("JNI support not available: " + t); } out.println(); @@ -83,32 +105,45 @@ static void diag(PrintStream out) { private static void testProvider(PrintStream out, TerminalProvider provider) { try { - out.println("StdIn stream = " + provider.isSystemStream(TerminalProvider.Stream.Input)); - out.println("StdOut stream = " + provider.isSystemStream(TerminalProvider.Stream.Output)); - out.println("StdErr stream = " + provider.isSystemStream(TerminalProvider.Stream.Error)); + out.println("StdIn stream = " + provider.isSystemStream(SystemStream.Input)); + out.println("StdOut stream = " + provider.isSystemStream(SystemStream.Output)); + out.println("StdErr stream = " + provider.isSystemStream(SystemStream.Error)); } catch (Throwable t2) { out.println("Unable to check stream: " + t2); } try { - out.println("StdIn stream name = " + provider.systemStreamName(TerminalProvider.Stream.Input)); - out.println("StdOut stream name = " + provider.systemStreamName(TerminalProvider.Stream.Output)); - out.println("StdErr stream name = " + provider.systemStreamName(TerminalProvider.Stream.Error)); + out.println("StdIn stream name = " + provider.systemStreamName(SystemStream.Input)); + out.println("StdOut stream name = " + provider.systemStreamName(SystemStream.Output)); + out.println("StdErr stream name = " + provider.systemStreamName(SystemStream.Error)); } catch (Throwable t2) { out.println("Unable to check stream names: " + t2); } - try (Terminal terminal = provider.sysTerminal("diag", "xterm", false, StandardCharsets.UTF_8, - false, Terminal.SignalHandler.SIG_DFL, false, TerminalProvider.Stream.Output, input -> input) ) { + try (Terminal terminal = provider.sysTerminal( + "diag", + "xterm", + false, + StandardCharsets.UTF_8, + false, + Terminal.SignalHandler.SIG_DFL, + false, + SystemStream.Output, + input -> input)) { if (terminal != null) { Attributes attr = terminal.enterRawMode(); try { out.println("Terminal size: " + terminal.getSize()); - ForkJoinTask t = new ForkJoinPool(1).submit(() -> terminal.reader().read(1) ); + ForkJoinTask t = + new ForkJoinPool(1).submit(() -> terminal.reader().read(1)); int r = t.get(1000, TimeUnit.MILLISECONDS); StringBuilder sb = new StringBuilder(); sb.append("The terminal seems to work: "); sb.append("terminal ").append(terminal.getClass().getName()); if (terminal instanceof AbstractPosixTerminal) { - sb.append(" with pty ").append(((AbstractPosixTerminal) terminal).getPty().getClass().getName()); + sb.append(" with pty ") + .append(((AbstractPosixTerminal) terminal) + .getPty() + .getClass() + .getName()); } out.println(sb); } catch (Throwable t3) { @@ -129,5 +164,4 @@ private static void testProvider(PrintStream out, TerminalProvider provider) { static S load(Class clazz) { return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java index 0b8cb57cbbf24..2922132c1bfad 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,38 +14,58 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.Charset; +import java.util.function.Function; import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Attributes.ControlChar; import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.utils.NonBlockingInputStream; import jdk.internal.org.jline.utils.NonBlockingReader; public class DumbTerminal extends AbstractTerminal { + private final TerminalProvider provider; + private final SystemStream systemStream; private final NonBlockingInputStream input; private final OutputStream output; private final NonBlockingReader reader; private final PrintWriter writer; private final Attributes attributes; private final Size size; + private boolean skipNextLf; - public DumbTerminal(InputStream in, OutputStream out) throws IOException { - this(TYPE_DUMB, TYPE_DUMB, in, out, null); + public DumbTerminal(InputStream in, OutputStream out, Function inputStreamWrapper) throws IOException { + this(TYPE_DUMB, TYPE_DUMB, in, out, null, inputStreamWrapper); } - public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding) throws IOException { - this(name, type, in, out, encoding, SignalHandler.SIG_DFL); + public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, Function inputStreamWrapper) + throws IOException { + this(null, null, name, type, in, out, encoding, SignalHandler.SIG_DFL, inputStreamWrapper); } - public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException { + @SuppressWarnings("this-escape") + public DumbTerminal( + TerminalProvider provider, + SystemStream systemStream, + String name, + String type, + InputStream in, + OutputStream out, + Charset encoding, + SignalHandler signalHandler, + Function inputStreamWrapper) + throws IOException { super(name, type, encoding, signalHandler); - NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), in); + this.provider = provider; + this.systemStream = systemStream; + NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(in)); this.input = new NonBlockingInputStream() { @Override public int read(long timeout, boolean isPeek) throws IOException { - for (;;) { + for (; ; ) { int c = nbis.read(timeout, isPeek); if (attributes.getLocalFlag(Attributes.LocalFlag.ISIG)) { if (c == attributes.getControlChar(ControlChar.VINTR)) { @@ -62,7 +82,19 @@ public int read(long timeout, boolean isPeek) throws IOException { continue; } } - if (c == '\r') { + if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + continue; + } + } else { + skipNextLf = false; + } + } else if (c == '\r') { if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) { continue; } @@ -80,10 +112,10 @@ public int read(long timeout, boolean isPeek) throws IOException { this.reader = NonBlocking.nonBlocking(getName(), input, encoding()); this.writer = new PrintWriter(new OutputStreamWriter(output, encoding())); this.attributes = new Attributes(); - this.attributes.setControlChar(ControlChar.VERASE, (char) 127); + this.attributes.setControlChar(ControlChar.VERASE, (char) 127); this.attributes.setControlChar(ControlChar.VWERASE, (char) 23); - this.attributes.setControlChar(ControlChar.VKILL, (char) 21); - this.attributes.setControlChar(ControlChar.VLNEXT, (char) 22); + this.attributes.setControlChar(ControlChar.VKILL, (char) 21); + this.attributes.setControlChar(ControlChar.VLNEXT, (char) 22); this.size = new Size(); parseInfoCmp(); } @@ -107,9 +139,7 @@ public OutputStream output() { } public Attributes getAttributes() { - Attributes attr = new Attributes(); - attr.copy(attributes); - return attr; + return new Attributes(attributes); } public void setAttributes(Attributes attr) { @@ -126,4 +156,13 @@ public void setSize(Size sz) { size.copy(sz); } + @Override + public TerminalProvider getProvider() { + return provider; + } + + @Override + public SystemStream getSystemStream() { + return systemStream; + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java new file mode 100644 index 0000000000000..8ff9735306598 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.function.Function; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.TerminalBuilder; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; + +public class DumbTerminalProvider implements TerminalProvider { + + @Override + public String name() { + return TerminalBuilder.PROP_PROVIDER_DUMB; + } + + @Override + public Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { + return new DumbTerminal( + this, + systemStream, + name, + type, + new FileInputStream(FileDescriptor.in), + new FileOutputStream(systemStream == SystemStream.Error ? FileDescriptor.err : FileDescriptor.out), + encoding, + signalHandler, + inputStreamWrapper); + } + + @Override + public Terminal newTerminal( + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSystemStream(SystemStream stream) { + return false; + } + + @Override + public String systemStreamName(SystemStream stream) { + return null; + } + + @Override + public int systemStreamWidth(SystemStream stream) { + return 0; + } + + @Override + public String toString() { + return "TerminalProvider[" + name() + "]"; + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java index 2814b52c7ccd3..5033fd61279f2 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,10 +8,6 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Cursor; -import jdk.internal.org.jline.terminal.Size; - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -19,6 +15,11 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.IntConsumer; +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Cursor; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; + /** * Console implementation with embedded line disciplined. * @@ -32,45 +33,59 @@ */ public class ExternalTerminal extends LineDisciplineTerminal { + private final TerminalProvider provider; protected final AtomicBoolean closed = new AtomicBoolean(); protected final InputStream masterInput; protected final Object lock = new Object(); protected boolean paused = true; protected Thread pumpThread; - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding) throws IOException { - this(name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL); + public ExternalTerminal( + String name, String type, InputStream masterInput, OutputStream masterOutput, Charset encoding) + throws IOException { + this(null, name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL); } - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler) throws IOException { - this(name, type, masterInput, masterOutput, encoding, signalHandler, false); + public ExternalTerminal( + TerminalProvider provider, + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + SignalHandler signalHandler) + throws IOException { + this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, false); } - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler, - boolean paused) throws IOException { - this(name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null); + public ExternalTerminal( + TerminalProvider provider, + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + SignalHandler signalHandler, + boolean paused) + throws IOException { + this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null); } - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler, - boolean paused, - Attributes attributes, - Size size) throws IOException { + @SuppressWarnings("this-escape") + public ExternalTerminal( + TerminalProvider provider, + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { super(name, type, masterOutput, encoding, signalHandler); + this.provider = provider; this.masterInput = masterInput; if (attributes != null) { setAttributes(attributes); @@ -171,4 +186,8 @@ public Cursor getCursorPosition(IntConsumer discarded) { return CursorSupport.getCursorPosition(this, discarded); } + @Override + public TerminalProvider getProvider() { + return provider; + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java index 0f290379bbf50..4e7a396bbc304 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,6 +14,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.Charset; +import java.util.EnumSet; import java.util.Objects; import jdk.internal.org.jline.terminal.Attributes; @@ -23,6 +24,8 @@ import jdk.internal.org.jline.terminal.Attributes.OutputFlag; import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.utils.NonBlockingPumpInputStream; import jdk.internal.org.jline.utils.NonBlockingReader; @@ -45,21 +48,6 @@ */ public class LineDisciplineTerminal extends AbstractTerminal { - private static final String DEFAULT_TERMINAL_ATTRIBUTES = - "speed 9600 baud; 24 rows; 80 columns;\n" + - "lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl\n" + - "\t-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo\n" + - "\t-extproc\n" + - "iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8\n" + - "\t-ignbrk brkint -inpck -ignpar -parmrk\n" + - "oflags: opost onlcr -oxtabs -onocr -onlret\n" + - "cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow\n" + - "\t-dtrflow -mdmbuf\n" + - "cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = ;\n" + - "\teol2 = ; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;\n" + - "\tmin = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T;\n" + - "\tstop = ^S; susp = ^Z; time = 0; werase = ^W;\n"; - private static final int PIPE_SIZE = 1024; /* @@ -84,20 +72,20 @@ public class LineDisciplineTerminal extends AbstractTerminal { * Console data */ protected final Attributes attributes; + protected final Size size; - public LineDisciplineTerminal(String name, - String type, - OutputStream masterOutput, - Charset encoding) throws IOException { + protected boolean skipNextLf; + + public LineDisciplineTerminal(String name, String type, OutputStream masterOutput, Charset encoding) + throws IOException { this(name, type, masterOutput, encoding, SignalHandler.SIG_DFL); } - public LineDisciplineTerminal(String name, - String type, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler) throws IOException { + @SuppressWarnings("this-escape") + public LineDisciplineTerminal( + String name, String type, OutputStream masterOutput, Charset encoding, SignalHandler signalHandler) + throws IOException { super(name, type, encoding, signalHandler); NonBlockingPumpInputStream input = NonBlocking.nonBlockingPumpInputStream(PIPE_SIZE); this.slaveInputPipe = input.getOutputStream(); @@ -106,11 +94,66 @@ public LineDisciplineTerminal(String name, this.slaveOutput = new FilteringOutputStream(); this.slaveWriter = new PrintWriter(new OutputStreamWriter(slaveOutput, encoding())); this.masterOutput = masterOutput; - this.attributes = ExecPty.doGetAttr(DEFAULT_TERMINAL_ATTRIBUTES); + this.attributes = getDefaultTerminalAttributes(); this.size = new Size(160, 50); parseInfoCmp(); } + private static Attributes getDefaultTerminalAttributes() { + // speed 9600 baud; 24 rows; 80 columns; + // lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl + // -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo + // -extproc + // iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8 + // -ignbrk brkint -inpck -ignpar -parmrk + // oflags: opost onlcr -oxtabs -onocr -onlret + // cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow + // -dtrflow -mdmbuf + // cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = ; + // eol2 = ; erase = ^?; intr = ^C; kill = ^U; lnext = ^V; + // min = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T; + // stop = ^S; susp = ^Z; time = 0; werase = ^W; + Attributes attr = new Attributes(); + attr.setLocalFlags(EnumSet.of( + LocalFlag.ICANON, + LocalFlag.ISIG, + LocalFlag.IEXTEN, + LocalFlag.ECHO, + LocalFlag.ECHOE, + LocalFlag.ECHOKE, + LocalFlag.ECHOCTL, + LocalFlag.PENDIN)); + attr.setInputFlags(EnumSet.of( + InputFlag.ICRNL, + InputFlag.IXON, + InputFlag.IXANY, + InputFlag.IMAXBEL, + InputFlag.IUTF8, + InputFlag.BRKINT)); + attr.setOutputFlags(EnumSet.of(OutputFlag.OPOST, OutputFlag.ONLCR)); + attr.setControlChar(ControlChar.VDISCARD, ctrl('O')); + attr.setControlChar(ControlChar.VDSUSP, ctrl('Y')); + attr.setControlChar(ControlChar.VEOF, ctrl('D')); + attr.setControlChar(ControlChar.VERASE, ctrl('?')); + attr.setControlChar(ControlChar.VINTR, ctrl('C')); + attr.setControlChar(ControlChar.VKILL, ctrl('U')); + attr.setControlChar(ControlChar.VLNEXT, ctrl('V')); + attr.setControlChar(ControlChar.VMIN, 1); + attr.setControlChar(ControlChar.VQUIT, ctrl('\\')); + attr.setControlChar(ControlChar.VREPRINT, ctrl('R')); + attr.setControlChar(ControlChar.VSTART, ctrl('Q')); + attr.setControlChar(ControlChar.VSTATUS, ctrl('T')); + attr.setControlChar(ControlChar.VSTOP, ctrl('S')); + attr.setControlChar(ControlChar.VSUSP, ctrl('Z')); + attr.setControlChar(ControlChar.VTIME, 0); + attr.setControlChar(ControlChar.VWERASE, ctrl('W')); + return attr; + } + + private static int ctrl(char c) { + return c == '?' ? 177 : c - 64; + } + public NonBlockingReader reader() { return slaveReader; } @@ -130,9 +173,7 @@ public OutputStream output() { } public Attributes getAttributes() { - Attributes attr = new Attributes(); - attr.copy(attributes); - return attr; + return new Attributes(attributes); } public void setAttributes(Attributes attr) { @@ -149,9 +190,9 @@ public void setSize(Size sz) { size.copy(sz); } - @Override + @Override public void raise(Signal signal) { - Objects.requireNonNull(signal); + Objects.requireNonNull(signal); // Do not call clear() atm as this can cause // deadlock between reading / writing threads // TODO: any way to fix that ? @@ -214,7 +255,19 @@ protected boolean doProcessInputByte(int c) throws IOException { raise(Signal.INFO); } } - if (c == '\r') { + if (attributes.getInputFlag(InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + return false; + } + } else { + skipNextLf = false; + } + } else if (c == '\r') { if (attributes.getInputFlag(InputFlag.IGNCR)) { return false; } @@ -273,6 +326,16 @@ protected void doClose() throws IOException { } } + @Override + public TerminalProvider getProvider() { + return null; + } + + @Override + public SystemStream getSystemStream() { + return null; + } + private class FilteringOutputStream extends OutputStream { @Override public void write(int b) throws IOException { @@ -284,13 +347,12 @@ public void write(int b) throws IOException { public void write(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); - } else if ((off < 0) || (off > b.length) || (len < 0) || - ((off + len) > b.length) || ((off + len) < 0)) { + } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } - for (int i = 0 ; i < len ; i++) { + for (int i = 0; i < len; i++) { processOutputByte(b[off + i]); } flush(); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java index 89ae6e5b74a57..eef25c90d8f1c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,11 +8,6 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.MouseEvent; -import jdk.internal.org.jline.terminal.Terminal; -import jdk.internal.org.jline.utils.InfoCmp; -import jdk.internal.org.jline.utils.InputStreamReader; - import java.io.EOFException; import java.io.IOError; import java.io.IOException; @@ -20,6 +15,11 @@ import java.util.EnumSet; import java.util.function.IntSupplier; +import jdk.internal.org.jline.terminal.MouseEvent; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.utils.InfoCmp; +import jdk.internal.org.jline.utils.InputStreamReader; + public class MouseSupport { public static boolean hasMouseSupport(Terminal terminal) { @@ -78,7 +78,8 @@ public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) { case 0: button = MouseEvent.Button.Button1; if (last.getButton() == button - && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { + && (last.getType() == MouseEvent.Type.Pressed + || last.getType() == MouseEvent.Type.Dragged)) { type = MouseEvent.Type.Dragged; } else { type = MouseEvent.Type.Pressed; @@ -87,7 +88,8 @@ public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) { case 1: button = MouseEvent.Button.Button2; if (last.getButton() == button - && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { + && (last.getType() == MouseEvent.Type.Pressed + || last.getType() == MouseEvent.Type.Dragged)) { type = MouseEvent.Type.Dragged; } else { type = MouseEvent.Type.Pressed; @@ -96,7 +98,8 @@ public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) { case 2: button = MouseEvent.Button.Button3; if (last.getButton() == button - && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { + && (last.getType() == MouseEvent.Type.Pressed + || last.getType() == MouseEvent.Type.Dragged)) { type = MouseEvent.Type.Dragged; } else { type = MouseEvent.Type.Pressed; @@ -134,5 +137,4 @@ private static int readExt(Terminal terminal) { throw new IOError(e); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java index 00c584c6cb931..bba177794a5e0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -17,8 +17,7 @@ public final class NativeSignalHandler implements SignalHandler { public static final NativeSignalHandler SIG_IGN = new NativeSignalHandler(); - private NativeSignalHandler() { - } + private NativeSignalHandler() {} public void handle(Signal signal) { throw new UnsupportedOperationException(); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java index f85e3fe0b0c8b..d34103e4d5e1d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -38,15 +38,34 @@ public class PosixPtyTerminal extends AbstractPosixTerminal { private Thread outputPumpThread; private boolean paused = true; - public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) throws IOException { + public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) + throws IOException { this(name, type, pty, in, out, encoding, SignalHandler.SIG_DFL); } - public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException { + public PosixPtyTerminal( + String name, + String type, + Pty pty, + InputStream in, + OutputStream out, + Charset encoding, + SignalHandler signalHandler) + throws IOException { this(name, type, pty, in, out, encoding, signalHandler, false); } - public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler, boolean paused) throws IOException { + @SuppressWarnings("this-escape") + public PosixPtyTerminal( + String name, + String type, + Pty pty, + InputStream in, + OutputStream out, + Charset encoding, + SignalHandler signalHandler, + boolean paused) + throws IOException { super(name, type, pty, encoding, signalHandler); this.in = Objects.requireNonNull(in); this.out = Objects.requireNonNull(out); @@ -113,7 +132,7 @@ public void pause(boolean wait) throws InterruptedException { if (p1 != null) { p1.join(); } - if (p2 !=null) { + if (p2 != null) { p2.join(); } } @@ -167,7 +186,7 @@ public void close() throws IOException { private void pumpIn() { try { - for (;;) { + for (; ; ) { synchronized (lock) { if (paused) { inputPumpThread = null; @@ -193,7 +212,7 @@ private void pumpIn() { private void pumpOut() { try { - for (;;) { + for (; ; ) { synchronized (lock) { if (paused) { outputPumpThread = null; @@ -221,5 +240,4 @@ private void pumpOut() { // Ignore } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java index a55f3d4a748c7..135ed0bb0c04b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,8 +18,9 @@ import java.util.Map; import java.util.function.Function; -import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.utils.FastBufferedOutputStream; +import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.utils.NonBlockingInputStream; import jdk.internal.org.jline.utils.NonBlockingReader; import jdk.internal.org.jline.utils.ShutdownHooks; @@ -35,12 +36,14 @@ public class PosixSysTerminal extends AbstractPosixTerminal { protected final Map nativeHandlers = new HashMap<>(); protected final Task closer; - public PosixSysTerminal(String name, String type, Pty pty, Charset encoding, - boolean nativeSignals, SignalHandler signalHandler, - Function inputStreamWrapper) throws IOException { + @SuppressWarnings("this-escape") + public PosixSysTerminal( + String name, String type, Pty pty, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, + Function inputStreamWrapper) + throws IOException { super(name, type, pty, encoding, signalHandler); this.input = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(pty.getSlaveInput())); - this.output = pty.getSlaveOutput(); + this.output = new FastBufferedOutputStream(pty.getSlaveOutput()); this.reader = NonBlocking.nonBlocking(getName(), input, encoding()); this.writer = new PrintWriter(new OutputStreamWriter(output, encoding())); parseInfoCmp(); @@ -98,5 +101,4 @@ protected void doClose() throws IOException { // Do not call reader.close() reader.shutdown(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java similarity index 71% rename from src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java rename to src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java index 5377b4acdb8a2..c0a35cbd6a219 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java @@ -1,18 +1,18 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. * * https://opensource.org/licenses/BSD-3-Clause */ -package jdk.internal.org.jline.terminal.impl; +package jdk.internal.org.jline.terminal.impl.exec; +import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.FileDescriptor; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -26,8 +26,10 @@ import jdk.internal.org.jline.terminal.Attributes.LocalFlag; import jdk.internal.org.jline.terminal.Attributes.OutputFlag; import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.terminal.impl.AbstractPty; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.OSUtils; import static jdk.internal.org.jline.utils.ExecHelper.exec; @@ -35,28 +37,26 @@ public class ExecPty extends AbstractPty implements Pty { private final String name; - private final TerminalProvider.Stream console; - public static Pty current(TerminalProvider.Stream console) throws IOException { + public static Pty current(TerminalProvider provider, SystemStream systemStream) throws IOException { try { String result = exec(true, OSUtils.TTY_COMMAND); - if (console != TerminalProvider.Stream.Output && console != TerminalProvider.Stream.Error) { - throw new IllegalArgumentException("console should be Output or Error: " + console); + if (systemStream != SystemStream.Output && systemStream != SystemStream.Error) { + throw new IllegalArgumentException("systemStream should be Output or Error: " + systemStream); } - return new ExecPty(result.trim(), console); + return new ExecPty(provider, systemStream, result.trim()); } catch (IOException e) { throw new IOException("Not a tty", e); } } - protected ExecPty(String name, TerminalProvider.Stream console) { + protected ExecPty(TerminalProvider provider, SystemStream systemStream, String name) { + super(provider, systemStream); this.name = name; - this.console = console; } @Override - public void close() throws IOException { - } + public void close() throws IOException {} public String getName() { return name; @@ -74,18 +74,16 @@ public OutputStream getMasterOutput() { @Override protected InputStream doGetSlaveInput() throws IOException { - return console != null - ? new FileInputStream(FileDescriptor.in) - : new FileInputStream(getName()); + return systemStream != null ? new FileInputStream(FileDescriptor.in) : new FileInputStream(getName()); } @Override public OutputStream getSlaveOutput() throws IOException { - return console == TerminalProvider.Stream.Output + return systemStream == SystemStream.Output ? new FileOutputStream(FileDescriptor.out) - : console == TerminalProvider.Stream.Error - ? new FileOutputStream(FileDescriptor.err) - : new FileOutputStream(getName()); + : systemStream == SystemStream.Error + ? new FileOutputStream(FileDescriptor.err) + : new FileOutputStream(getName()); } @Override @@ -99,18 +97,30 @@ protected void doSetAttr(Attributes attr) throws IOException { List commands = getFlagsToSet(attr, getAttr()); if (!commands.isEmpty()) { commands.add(0, OSUtils.STTY_COMMAND); - if (console == null) { + if (systemStream == null) { commands.add(1, OSUtils.STTY_F_OPTION); commands.add(2, getName()); } - exec(console != null, commands.toArray(new String[0])); + try { + exec(systemStream != null, commands.toArray(new String[0])); + } catch (IOException e) { + // Handle partial failures with GNU stty, see #97 + if (e.toString().contains("unable to perform all requested operations")) { + commands = getFlagsToSet(attr, getAttr()); + if (!commands.isEmpty()) { + throw new IOException("Could not set the following flags: " + String.join(", ", commands), e); + } + } else { + throw e; + } + } } } protected List getFlagsToSet(Attributes attr, Attributes current) { List commands = new ArrayList<>(); for (InputFlag flag : InputFlag.values()) { - if (attr.getInputFlag(flag) != current.getInputFlag(flag)) { + if (attr.getInputFlag(flag) != current.getInputFlag(flag) && flag != InputFlag.INORMEOL) { commands.add((attr.getInputFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase()); } } @@ -137,11 +147,9 @@ protected List getFlagsToSet(Attributes attr, Attributes current) { commands.add(cchar.name().toLowerCase().substring(1)); if (cchar == ControlChar.VMIN || cchar == ControlChar.VTIME) { commands.add(Integer.toString(v)); - } - else if (v == 0) { + } else if (v == 0) { commands.add(undef); - } - else { + } else { if (v >= 128) { v -= 128; str += "M-"; @@ -165,12 +173,12 @@ public Size getSize() throws IOException { } protected String doGetConfig() throws IOException { - return console != null - ? exec(true, OSUtils.STTY_COMMAND, "-a") + return systemStream != null + ? exec(true, OSUtils.STTY_COMMAND, "-a") : exec(false, OSUtils.STTY_COMMAND, OSUtils.STTY_F_OPTION, getName(), "-a"); } - static Attributes doGetAttr(String cfg) throws IOException { + public static Attributes doGetAttr(String cfg) throws IOException { Attributes attributes = new Attributes(); for (InputFlag flag : InputFlag.values()) { Boolean value = doGetFlag(cfg, flag); @@ -201,16 +209,19 @@ static Attributes doGetAttr(String cfg) throws IOException { if ("reprint".endsWith(name)) { name = "(?:reprint|rprnt)"; } - Matcher matcher = Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg); + Matcher matcher = + Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg); if (matcher.find()) { - attributes.setControlChar(cchar, parseControlChar(matcher.group(1).toUpperCase())); + attributes.setControlChar( + cchar, parseControlChar(matcher.group(1).toUpperCase())); } } return attributes; } private static Boolean doGetFlag(String cfg, Enum flag) { - Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)").matcher(cfg); + Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)") + .matcher(cfg); return matcher.find() ? !matcher.group(1).startsWith("-") : null; } @@ -259,9 +270,7 @@ static Size doGetSize(String cfg) throws IOException { static int doGetInt(String name, String cfg) throws IOException { String[] patterns = new String[] { - "\\b([0-9]+)\\s+" + name + "\\b", - "\\b" + name + "\\s+([0-9]+)\\b", - "\\b" + name + "\\s*=\\s*([0-9]+)\\b" + "\\b([0-9]+)\\s+" + name + "\\b", "\\b" + name + "\\s+([0-9]+)\\b", "\\b" + name + "\\s*=\\s*([0-9]+)\\b" }; for (String pattern : patterns) { Matcher matcher = Pattern.compile(pattern).matcher(cfg); @@ -274,23 +283,29 @@ static int doGetInt(String name, String cfg) throws IOException { @Override public void setSize(Size size) throws IOException { - if (console != null) { - exec(true, - OSUtils.STTY_COMMAND, - "columns", Integer.toString(size.getColumns()), - "rows", Integer.toString(size.getRows())); + if (systemStream != null) { + exec( + true, + OSUtils.STTY_COMMAND, + "columns", + Integer.toString(size.getColumns()), + "rows", + Integer.toString(size.getRows())); } else { - exec(false, - OSUtils.STTY_COMMAND, - OSUtils.STTY_F_OPTION, getName(), - "columns", Integer.toString(size.getColumns()), - "rows", Integer.toString(size.getRows())); + exec( + false, + OSUtils.STTY_COMMAND, + OSUtils.STTY_F_OPTION, + getName(), + "columns", + Integer.toString(size.getColumns()), + "rows", + Integer.toString(size.getRows())); } } @Override public String toString() { - return "ExecPty[" + getName() + (console != null ? ", system]" : "]"); + return "ExecPty[" + getName() + (systemStream != null ? ", system]" : "]"); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java index 8bdeede2e1b3a..418d3452d4a6c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, the original author or authors. + * Copyright (c) 2022, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -17,117 +17,249 @@ import java.nio.charset.Charset; import java.util.function.Function; +//import jdk.internal.org.jline.nativ.JLineLibrary; +//import jdk.internal.org.jline.nativ.JLineNativeLoader; import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.Terminal; -import jdk.internal.org.jline.terminal.impl.ExecPty; +import jdk.internal.org.jline.terminal.TerminalBuilder; import jdk.internal.org.jline.terminal.impl.ExternalTerminal; import jdk.internal.org.jline.terminal.impl.PosixSysTerminal; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.ExecHelper; +import jdk.internal.org.jline.utils.Log; import jdk.internal.org.jline.utils.OSUtils; -public class ExecTerminalProvider implements TerminalProvider -{ +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION; + +public class ExecTerminalProvider implements TerminalProvider { + + private static boolean warned; public String name() { - return "exec"; + return TerminalBuilder.PROP_PROVIDER_EXEC; } - public Pty current(Stream consoleStream) throws IOException { - return ExecPty.current(consoleStream); + public Pty current(SystemStream systemStream) throws IOException { + return ExecPty.current(this, systemStream); } @Override - public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, - boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper) throws IOException { + public Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { if (OSUtils.IS_WINDOWS) { - return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); + return winSysTerminal( + name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); } else { - return posixSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); + return posixSysTerminal( + name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); } } - public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, - boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper ) throws IOException { + public Terminal winSysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { - Pty pty = current(consoleStream); + Pty pty = current(systemStream); return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); } else { return null; } } - public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, - boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper) throws IOException { - Pty pty = current(consoleStream); + public Terminal posixSysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { + Pty pty = current(systemStream); return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); } @Override - public Terminal newTerminal(String name, String type, InputStream in, OutputStream out, - Charset encoding, Terminal.SignalHandler signalHandler, boolean paused, - Attributes attributes, Size size) throws IOException - { - return new ExternalTerminal(name, type, in, out, encoding, signalHandler, paused, attributes, size); + public Terminal newTerminal( + String name, + String type, + InputStream in, + OutputStream out, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { + return new ExternalTerminal(this, name, type, in, out, encoding, signalHandler, paused, attributes, size); } @Override - public boolean isSystemStream(Stream stream) { + public boolean isSystemStream(SystemStream stream) { try { - return isWindowsSystemStream(stream) || isPosixSystemStream(stream); + return isPosixSystemStream(stream) || isWindowsSystemStream(stream); } catch (Throwable t) { return false; } } - public boolean isWindowsSystemStream(Stream stream) { - return systemStreamName( stream ) != null; + public boolean isWindowsSystemStream(SystemStream stream) { + return systemStreamName(stream) != null; } - public boolean isPosixSystemStream(Stream stream) { + public boolean isPosixSystemStream(SystemStream stream) { try { Process p = new ProcessBuilder(OSUtils.TEST_COMMAND, "-t", Integer.toString(stream.ordinal())) - .inheritIO().start(); + .inheritIO() + .start(); return p.waitFor() == 0; } catch (Throwable t) { + Log.debug("ExecTerminalProvider failed 'test -t' for " + stream, t); // ignore } return false; } @Override - public String systemStreamName(Stream stream) { + public String systemStreamName(SystemStream stream) { try { - ProcessBuilder.Redirect input = stream == Stream.Input - ? ProcessBuilder.Redirect.INHERIT - : getRedirect(stream == Stream.Output ? FileDescriptor.out : FileDescriptor.err); - Process p = new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start(); + ProcessBuilder.Redirect input = stream == SystemStream.Input + ? ProcessBuilder.Redirect.INHERIT + : newDescriptor(stream == SystemStream.Output ? FileDescriptor.out : FileDescriptor.err); + Process p = + new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start(); String result = ExecHelper.waitAndCapture(p); if (p.exitValue() == 0) { return result.trim(); } } catch (Throwable t) { + if ("java.lang.reflect.InaccessibleObjectException" + .equals(t.getClass().getName()) + && !warned) { + Log.warn( + "The ExecTerminalProvider requires the JVM options: '--add-opens java.base/java.lang=ALL-UNNAMED'"); + warned = true; + } // ignore } return null; } - private ProcessBuilder.Redirect getRedirect(FileDescriptor fd) throws ReflectiveOperationException { - // This is not really allowed, but this is the only way to redirect the output or error stream - // to the input. This is definitely not something you'd usually want to do, but in the case of - // the `tty` utility, it provides a way to get - Class rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl"); - Constructor cns = rpi.getDeclaredConstructor(); - cns.setAccessible(true); - ProcessBuilder.Redirect input = (ProcessBuilder.Redirect) cns.newInstance(); - Field f = rpi.getDeclaredField("fd"); - f.setAccessible(true); - f.set(input, fd); - return input; + @Override + public int systemStreamWidth(SystemStream stream) { + try (ExecPty pty = new ExecPty(this, stream, null)) { + return pty.getSize().getColumns(); + } catch (Throwable t) { + return -1; + } + } + + private static RedirectPipeCreator redirectPipeCreator; + + protected static ProcessBuilder.Redirect newDescriptor(FileDescriptor fd) { + if (redirectPipeCreator == null) { + String str = System.getProperty(PROP_REDIRECT_PIPE_CREATION_MODE, PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT); + String[] modes = str.split(","); + IllegalStateException ise = new IllegalStateException("Unable to create RedirectPipe"); + for (String mode : modes) { + try { + switch (mode) { + case PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE: + redirectPipeCreator = null;//new NativeRedirectPipeCreator(); + break; + case PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION: + redirectPipeCreator = new ReflectionRedirectPipeCreator(); + break; + } + } catch (Throwable t) { + // ignore + ise.addSuppressed(t); + } + if (redirectPipeCreator != null) { + break; + } + } + if (redirectPipeCreator == null) { + throw ise; + } + } + return redirectPipeCreator.newRedirectPipe(fd); + } + + interface RedirectPipeCreator { + ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd); + } + + /** + * Reflection based file descriptor creator. + * This requires the following option + * --add-opens java.base/java.lang=ALL-UNNAMED + */ + static class ReflectionRedirectPipeCreator implements RedirectPipeCreator { + private final Constructor constructor; + private final Field fdField; + + @SuppressWarnings("unchecked") + ReflectionRedirectPipeCreator() throws Exception { + Class rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl"); + constructor = (Constructor) rpi.getDeclaredConstructor(); + constructor.setAccessible(true); + fdField = rpi.getDeclaredField("fd"); + fdField.setAccessible(true); + } + + @Override + public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) { + try { + ProcessBuilder.Redirect input = constructor.newInstance(); + fdField.set(input, fd); + return input; + } catch (ReflectiveOperationException e) { + // This should not happen as the field has been set accessible + throw new IllegalStateException(e); + } + } + } + +// static class NativeRedirectPipeCreator implements RedirectPipeCreator { +// public NativeRedirectPipeCreator() { +// // Force load the library +// JLineNativeLoader.initialize(); +// } +// +// @Override +// public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) { +// return JLineLibrary.newRedirectPipe(fd); +// } +// } + + @Override + public String toString() { + return "TerminalProvider[" + name() + "]"; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/CLibrary.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/CLibrary.java new file mode 100644 index 0000000000000..453ce290d3ce8 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/CLibrary.java @@ -0,0 +1,1170 @@ +/* + * Copyright (c) 2022-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.ffm; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.foreign.*; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.Optional; +//import java.util.logging.Level; +//import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.utils.OSUtils; + +@SuppressWarnings("restricted") +class CLibrary { + +// private static final Logger logger = Logger.getLogger("org.jline"); + + // Window sizes. + // @see IOCTL_TTY(2) man-page + static class winsize { + static final GroupLayout LAYOUT; + private static final VarHandle ws_col; + private static final VarHandle ws_row; + + static { + LAYOUT = MemoryLayout.structLayout( + ValueLayout.JAVA_SHORT.withName("ws_row"), + ValueLayout.JAVA_SHORT.withName("ws_col"), + ValueLayout.JAVA_SHORT, + ValueLayout.JAVA_SHORT); + ws_row = FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("ws_row")); + ws_col = FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("ws_col")); + } + + private final java.lang.foreign.MemorySegment seg; + + winsize() { + seg = java.lang.foreign.Arena.ofAuto().allocate(LAYOUT); + } + + winsize(short ws_col, short ws_row) { + this(); + ws_col(ws_col); + ws_row(ws_row); + } + + java.lang.foreign.MemorySegment segment() { + return seg; + } + + short ws_col() { + return (short) ws_col.get(seg); + } + + void ws_col(short col) { + ws_col.set(seg, col); + } + + short ws_row() { + return (short) ws_row.get(seg); + } + + void ws_row(short row) { + ws_row.set(seg, row); + } + } + + // termios structure for termios functions, describing a general terminal interface that is + // provided to control asynchronous communications ports + // @see TERMIOS(3) man-page + static class termios { + static final GroupLayout LAYOUT; + private static final VarHandle c_iflag; + private static final VarHandle c_oflag; + private static final VarHandle c_cflag; + private static final VarHandle c_lflag; + private static final long c_cc_offset; + private static final VarHandle c_ispeed; + private static final VarHandle c_ospeed; + + static { + if (OSUtils.IS_OSX) { + LAYOUT = MemoryLayout.structLayout( + ValueLayout.JAVA_LONG.withName("c_iflag"), + ValueLayout.JAVA_LONG.withName("c_oflag"), + ValueLayout.JAVA_LONG.withName("c_cflag"), + ValueLayout.JAVA_LONG.withName("c_lflag"), + MemoryLayout.sequenceLayout(32, ValueLayout.JAVA_BYTE).withName("c_cc"), + ValueLayout.JAVA_LONG.withName("c_ispeed"), + ValueLayout.JAVA_LONG.withName("c_ospeed")); + } else if (OSUtils.IS_LINUX) { + LAYOUT = MemoryLayout.structLayout( + ValueLayout.JAVA_INT.withName("c_iflag"), + ValueLayout.JAVA_INT.withName("c_oflag"), + ValueLayout.JAVA_INT.withName("c_cflag"), + ValueLayout.JAVA_INT.withName("c_lflag"), + ValueLayout.JAVA_BYTE.withName("c_line"), + MemoryLayout.sequenceLayout(32, ValueLayout.JAVA_BYTE).withName("c_cc"), + MemoryLayout.paddingLayout(3), + ValueLayout.JAVA_INT.withName("c_ispeed"), + ValueLayout.JAVA_INT.withName("c_ospeed")); + } else { + throw new IllegalStateException("Unsupported system!"); + } + c_iflag = adjust2LinuxHandle( + FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("c_iflag"))); + c_oflag = adjust2LinuxHandle( + FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("c_oflag"))); + c_cflag = adjust2LinuxHandle( + FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("c_cflag"))); + c_lflag = adjust2LinuxHandle( + FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("c_lflag"))); + c_cc_offset = LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("c_cc")); + c_ispeed = adjust2LinuxHandle( + FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("c_ispeed"))); + c_ospeed = adjust2LinuxHandle( + FfmTerminalProvider.lookupVarHandle(LAYOUT, MemoryLayout.PathElement.groupElement("c_ospeed"))); + } + + private static VarHandle adjust2LinuxHandle(VarHandle v) { + if (OSUtils.IS_LINUX) { + MethodHandle id = MethodHandles.identity(int.class); + v = MethodHandles.filterValue( + v, + MethodHandles.explicitCastArguments(id, MethodType.methodType(int.class, long.class)), + MethodHandles.explicitCastArguments(id, MethodType.methodType(long.class, int.class))); + } + + return v; + } + + private final java.lang.foreign.MemorySegment seg; + + termios() { + seg = java.lang.foreign.Arena.ofAuto().allocate(LAYOUT); + } + + termios(Attributes t) { + this(); + // Input flags + long c_iflag = 0; + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNPAR), IGNPAR, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.PARMRK), PARMRK, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INPCK), INPCK, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ISTRIP), ISTRIP, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INLCR), INLCR, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNCR), IGNCR, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ICRNL), ICRNL, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXON), IXON, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXOFF), IXOFF, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXANY), IXANY, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IMAXBEL), IMAXBEL, c_iflag); + c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IUTF8), IUTF8, c_iflag); + c_iflag(c_iflag); + // Output flags + long c_oflag = 0; + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OPOST), OPOST, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLCR), ONLCR, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OXTABS), OXTABS, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOEOT), ONOEOT, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OCRNL), OCRNL, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOCR), ONOCR, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLRET), ONLRET, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFILL), OFILL, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.NLDLY), NLDLY, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.TABDLY), TABDLY, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.CRDLY), CRDLY, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.FFDLY), FFDLY, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.BSDLY), BSDLY, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.VTDLY), VTDLY, c_oflag); + c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFDEL), OFDEL, c_oflag); + c_oflag(c_oflag); + // Control flags + long c_cflag = 0; + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CIGNORE), CIGNORE, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS5), CS5, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS6), CS6, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS7), CS7, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS8), CS8, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CSTOPB), CSTOPB, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CREAD), CREAD, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARENB), PARENB, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARODD), PARODD, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.HUPCL), HUPCL, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CLOCAL), CLOCAL, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCTS_OFLOW), CCTS_OFLOW, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CRTS_IFLOW), CRTS_IFLOW, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDTR_IFLOW), CDTR_IFLOW, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDSR_OFLOW), CDSR_OFLOW, c_cflag); + c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCAR_OFLOW), CCAR_OFLOW, c_cflag); + c_cflag(c_cflag); + // Local flags + long c_lflag = 0; + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOKE), ECHOKE, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOE), ECHOE, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOK), ECHOK, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHO), ECHO, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHONL), ECHONL, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOPRT), ECHOPRT, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOCTL), ECHOCTL, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ISIG), ISIG, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ICANON), ICANON, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ALTWERASE), ALTWERASE, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.IEXTEN), IEXTEN, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.EXTPROC), EXTPROC, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.TOSTOP), TOSTOP, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.FLUSHO), FLUSHO, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOKERNINFO), NOKERNINFO, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.PENDIN), PENDIN, c_lflag); + c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOFLSH), NOFLSH, c_lflag); + c_lflag(c_lflag); + // Control chars + byte[] c_cc = new byte[20]; + c_cc[VEOF] = (byte) t.getControlChar(Attributes.ControlChar.VEOF); + c_cc[VEOL] = (byte) t.getControlChar(Attributes.ControlChar.VEOL); + c_cc[VEOL2] = (byte) t.getControlChar(Attributes.ControlChar.VEOL2); + c_cc[VERASE] = (byte) t.getControlChar(Attributes.ControlChar.VERASE); + c_cc[VWERASE] = (byte) t.getControlChar(Attributes.ControlChar.VWERASE); + c_cc[VKILL] = (byte) t.getControlChar(Attributes.ControlChar.VKILL); + c_cc[VREPRINT] = (byte) t.getControlChar(Attributes.ControlChar.VREPRINT); + c_cc[VINTR] = (byte) t.getControlChar(Attributes.ControlChar.VINTR); + c_cc[VQUIT] = (byte) t.getControlChar(Attributes.ControlChar.VQUIT); + c_cc[VSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VSUSP); + if (VDSUSP != (-1)) { + c_cc[VDSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VDSUSP); + } + c_cc[VSTART] = (byte) t.getControlChar(Attributes.ControlChar.VSTART); + c_cc[VSTOP] = (byte) t.getControlChar(Attributes.ControlChar.VSTOP); + c_cc[VLNEXT] = (byte) t.getControlChar(Attributes.ControlChar.VLNEXT); + c_cc[VDISCARD] = (byte) t.getControlChar(Attributes.ControlChar.VDISCARD); + c_cc[VMIN] = (byte) t.getControlChar(Attributes.ControlChar.VMIN); + c_cc[VTIME] = (byte) t.getControlChar(Attributes.ControlChar.VTIME); + if (VSTATUS != (-1)) { + c_cc[VSTATUS] = (byte) t.getControlChar(Attributes.ControlChar.VSTATUS); + } + c_cc().copyFrom(java.lang.foreign.MemorySegment.ofArray(c_cc)); + } + + java.lang.foreign.MemorySegment segment() { + return seg; + } + + long c_iflag() { + return (long) c_iflag.get(seg); + } + + void c_iflag(long f) { + c_iflag.set(seg, f); + } + + long c_oflag() { + return (long) c_oflag.get(seg); + } + + void c_oflag(long f) { + c_oflag.set(seg, f); + } + + long c_cflag() { + return (long) c_cflag.get(seg); + } + + void c_cflag(long f) { + c_cflag.set(seg, f); + } + + long c_lflag() { + return (long) c_lflag.get(seg); + } + + void c_lflag(long f) { + c_lflag.set(seg, f); + } + + java.lang.foreign.MemorySegment c_cc() { + return seg.asSlice(c_cc_offset, 20); + } + + long c_ispeed() { + return (long) c_ispeed.get(seg); + } + + void c_ispeed(long f) { + c_ispeed.set(seg, f); + } + + long c_ospeed() { + return (long) c_ospeed.get(seg); + } + + void c_ospeed(long f) { + c_ospeed.set(seg, f); + } + + private static long setFlag(boolean flag, long value, long org) { + return flag ? org | value : org; + } + + private static > void addFlag(long value, EnumSet flags, T flag, int v) { + if ((value & v) != 0) { + flags.add(flag); + } + } + + public Attributes asAttributes() { + Attributes attr = new Attributes(); + // Input flags + long c_iflag = c_iflag(); + EnumSet iflag = attr.getInputFlags(); + addFlag(c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(c_iflag, iflag, Attributes.InputFlag.BRKINT, BRKINT); + addFlag(c_iflag, iflag, Attributes.InputFlag.IGNPAR, IGNPAR); + addFlag(c_iflag, iflag, Attributes.InputFlag.PARMRK, PARMRK); + addFlag(c_iflag, iflag, Attributes.InputFlag.INPCK, INPCK); + addFlag(c_iflag, iflag, Attributes.InputFlag.ISTRIP, ISTRIP); + addFlag(c_iflag, iflag, Attributes.InputFlag.INLCR, INLCR); + addFlag(c_iflag, iflag, Attributes.InputFlag.IGNCR, IGNCR); + addFlag(c_iflag, iflag, Attributes.InputFlag.ICRNL, ICRNL); + addFlag(c_iflag, iflag, Attributes.InputFlag.IXON, IXON); + addFlag(c_iflag, iflag, Attributes.InputFlag.IXOFF, IXOFF); + addFlag(c_iflag, iflag, Attributes.InputFlag.IXANY, IXANY); + addFlag(c_iflag, iflag, Attributes.InputFlag.IMAXBEL, IMAXBEL); + addFlag(c_iflag, iflag, Attributes.InputFlag.IUTF8, IUTF8); + // Output flags + long c_oflag = c_oflag(); + EnumSet oflag = attr.getOutputFlags(); + addFlag(c_oflag, oflag, Attributes.OutputFlag.OPOST, OPOST); + addFlag(c_oflag, oflag, Attributes.OutputFlag.ONLCR, ONLCR); + addFlag(c_oflag, oflag, Attributes.OutputFlag.OXTABS, OXTABS); + addFlag(c_oflag, oflag, Attributes.OutputFlag.ONOEOT, ONOEOT); + addFlag(c_oflag, oflag, Attributes.OutputFlag.OCRNL, OCRNL); + addFlag(c_oflag, oflag, Attributes.OutputFlag.ONOCR, ONOCR); + addFlag(c_oflag, oflag, Attributes.OutputFlag.ONLRET, ONLRET); + addFlag(c_oflag, oflag, Attributes.OutputFlag.OFILL, OFILL); + addFlag(c_oflag, oflag, Attributes.OutputFlag.NLDLY, NLDLY); + addFlag(c_oflag, oflag, Attributes.OutputFlag.TABDLY, TABDLY); + addFlag(c_oflag, oflag, Attributes.OutputFlag.CRDLY, CRDLY); + addFlag(c_oflag, oflag, Attributes.OutputFlag.FFDLY, FFDLY); + addFlag(c_oflag, oflag, Attributes.OutputFlag.BSDLY, BSDLY); + addFlag(c_oflag, oflag, Attributes.OutputFlag.VTDLY, VTDLY); + addFlag(c_oflag, oflag, Attributes.OutputFlag.OFDEL, OFDEL); + // Control flags + long c_cflag = c_cflag(); + EnumSet cflag = attr.getControlFlags(); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CIGNORE, CIGNORE); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CS5, CS5); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CS6, CS6); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CS7, CS7); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CS8, CS8); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CSTOPB, CSTOPB); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CREAD, CREAD); + addFlag(c_cflag, cflag, Attributes.ControlFlag.PARENB, PARENB); + addFlag(c_cflag, cflag, Attributes.ControlFlag.PARODD, PARODD); + addFlag(c_cflag, cflag, Attributes.ControlFlag.HUPCL, HUPCL); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CLOCAL, CLOCAL); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CCTS_OFLOW, CCTS_OFLOW); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CRTS_IFLOW, CRTS_IFLOW); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CDSR_OFLOW, CDSR_OFLOW); + addFlag(c_cflag, cflag, Attributes.ControlFlag.CCAR_OFLOW, CCAR_OFLOW); + // Local flags + long c_lflag = c_lflag(); + EnumSet lflag = attr.getLocalFlags(); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ECHOKE, ECHOKE); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ECHOE, ECHOE); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ECHOK, ECHOK); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ECHO, ECHO); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ECHONL, ECHONL); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ECHOPRT, ECHOPRT); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ECHOCTL, ECHOCTL); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ISIG, ISIG); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ICANON, ICANON); + addFlag(c_lflag, lflag, Attributes.LocalFlag.ALTWERASE, ALTWERASE); + addFlag(c_lflag, lflag, Attributes.LocalFlag.IEXTEN, IEXTEN); + addFlag(c_lflag, lflag, Attributes.LocalFlag.EXTPROC, EXTPROC); + addFlag(c_lflag, lflag, Attributes.LocalFlag.TOSTOP, TOSTOP); + addFlag(c_lflag, lflag, Attributes.LocalFlag.FLUSHO, FLUSHO); + addFlag(c_lflag, lflag, Attributes.LocalFlag.NOKERNINFO, NOKERNINFO); + addFlag(c_lflag, lflag, Attributes.LocalFlag.PENDIN, PENDIN); + addFlag(c_lflag, lflag, Attributes.LocalFlag.NOFLSH, NOFLSH); + // Control chars + byte[] c_cc = c_cc().toArray(ValueLayout.JAVA_BYTE); + EnumMap cc = attr.getControlChars(); + cc.put(Attributes.ControlChar.VEOF, (int) c_cc[VEOF]); + cc.put(Attributes.ControlChar.VEOL, (int) c_cc[VEOL]); + cc.put(Attributes.ControlChar.VEOL2, (int) c_cc[VEOL2]); + cc.put(Attributes.ControlChar.VERASE, (int) c_cc[VERASE]); + cc.put(Attributes.ControlChar.VWERASE, (int) c_cc[VWERASE]); + cc.put(Attributes.ControlChar.VKILL, (int) c_cc[VKILL]); + cc.put(Attributes.ControlChar.VREPRINT, (int) c_cc[VREPRINT]); + cc.put(Attributes.ControlChar.VINTR, (int) c_cc[VINTR]); + cc.put(Attributes.ControlChar.VQUIT, (int) c_cc[VQUIT]); + cc.put(Attributes.ControlChar.VSUSP, (int) c_cc[VSUSP]); + if (VDSUSP != (-1)) { + cc.put(Attributes.ControlChar.VDSUSP, (int) c_cc[VDSUSP]); + } + cc.put(Attributes.ControlChar.VSTART, (int) c_cc[VSTART]); + cc.put(Attributes.ControlChar.VSTOP, (int) c_cc[VSTOP]); + cc.put(Attributes.ControlChar.VLNEXT, (int) c_cc[VLNEXT]); + cc.put(Attributes.ControlChar.VDISCARD, (int) c_cc[VDISCARD]); + cc.put(Attributes.ControlChar.VMIN, (int) c_cc[VMIN]); + cc.put(Attributes.ControlChar.VTIME, (int) c_cc[VTIME]); + if (VSTATUS != (-1)) { + cc.put(Attributes.ControlChar.VSTATUS, (int) c_cc[VSTATUS]); + } + // Return + return attr; + } + } + + static MethodHandle ioctl; + static MethodHandle isatty; + static MethodHandle openpty; + static MethodHandle tcsetattr; + static MethodHandle tcgetattr; + static MethodHandle ttyname_r; + static LinkageError openptyError; + + static { + // methods + Linker linker = Linker.nativeLinker(); + SymbolLookup lookup = SymbolLookup.loaderLookup().or(linker.defaultLookup()); + // https://man7.org/linux/man-pages/man2/ioctl.2.html + ioctl = linker.downcallHandle( + lookup.find("ioctl").get(), + FunctionDescriptor.of( + ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.ADDRESS), + Linker.Option.firstVariadicArg(2)); + // https://www.man7.org/linux/man-pages/man3/isatty.3.html + isatty = linker.downcallHandle( + lookup.find("isatty").get(), FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT)); + // https://man7.org/linux/man-pages/man3/tcsetattr.3p.html + tcsetattr = linker.downcallHandle( + lookup.find("tcsetattr").get(), + FunctionDescriptor.of( + ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.ADDRESS)); + // https://man7.org/linux/man-pages/man3/tcgetattr.3p.html + tcgetattr = linker.downcallHandle( + lookup.find("tcgetattr").get(), + FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.ADDRESS)); + // https://man7.org/linux/man-pages/man3/ttyname.3.html + ttyname_r = linker.downcallHandle( + lookup.find("ttyname_r").get(), + FunctionDescriptor.of( + ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_LONG)); + // https://man7.org/linux/man-pages/man3/openpty.3.html + LinkageError error = null; + Optional openPtyAddr = lookup.find("openpty"); + if (openPtyAddr.isPresent()) { + openpty = linker.downcallHandle( + openPtyAddr.get(), + FunctionDescriptor.of( + ValueLayout.JAVA_INT, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS, + ValueLayout.ADDRESS)); + openptyError = null; + } else { + openpty = null; + openptyError = error; + } + } + + private static String readFully(InputStream in) throws IOException { + int readLen = 0; + ByteArrayOutputStream b = new ByteArrayOutputStream(); + byte[] buf = new byte[32]; + while ((readLen = in.read(buf, 0, buf.length)) >= 0) { + b.write(buf, 0, readLen); + } + return b.toString(); + } + + static Size getTerminalSize(int fd) { + try { + winsize ws = new winsize(); + int res = (int) ioctl.invoke(fd, (long) TIOCGWINSZ, ws.segment()); + return new Size(ws.ws_col(), ws.ws_row()); + } catch (Throwable e) { + throw new RuntimeException("Unable to call ioctl(TIOCGWINSZ)", e); + } + } + + static void setTerminalSize(int fd, Size size) { + try { + winsize ws = new winsize(); + ws.ws_row((short) size.getRows()); + ws.ws_col((short) size.getColumns()); + int res = (int) ioctl.invoke(fd, TIOCSWINSZ, ws.segment()); + } catch (Throwable e) { + throw new RuntimeException("Unable to call ioctl(TIOCSWINSZ)", e); + } + } + + static Attributes getAttributes(int fd) { + try { + termios t = new termios(); + int res = (int) tcgetattr.invoke(fd, t.segment()); + return t.asAttributes(); + } catch (Throwable e) { + throw new RuntimeException("Unable to call tcgetattr()", e); + } + } + + static void setAttributes(int fd, Attributes attr) { + try { + termios t = new termios(attr); + int res = (int) tcsetattr.invoke(fd, TCSANOW, t.segment()); + } catch (Throwable e) { + throw new RuntimeException("Unable to call tcsetattr()", e); + } + } + + static boolean isTty(int fd) { + try { + return (int) isatty.invoke(fd) == 1; + } catch (Throwable e) { + throw new RuntimeException("Unable to call isatty()", e); + } + } + + static String ttyName(int fd) { + try { + java.lang.foreign.MemorySegment buf = + java.lang.foreign.Arena.ofAuto().allocate(64); + int res = (int) ttyname_r.invoke(fd, buf, buf.byteSize()); + byte[] data = buf.toArray(ValueLayout.JAVA_BYTE); + int len = 0; + while (data[len] != 0) { + len++; + } + return new String(data, 0, len); + } catch (Throwable e) { + throw new RuntimeException("Unable to call ttyname_r()", e); + } + } + + static Pty openpty(TerminalProvider provider, Attributes attr, Size size) { + if (openptyError != null) { + throw openptyError; + } + try { + java.lang.foreign.MemorySegment buf = + java.lang.foreign.Arena.ofAuto().allocate(64); + java.lang.foreign.MemorySegment master = + java.lang.foreign.Arena.ofAuto().allocate(ValueLayout.JAVA_INT); + java.lang.foreign.MemorySegment slave = + java.lang.foreign.Arena.ofAuto().allocate(ValueLayout.JAVA_INT); + int res = (int) openpty.invoke( + master, + slave, + buf, + attr != null ? new termios(attr).segment() : java.lang.foreign.MemorySegment.NULL, + size != null + ? new winsize((short) size.getRows(), (short) size.getColumns()).segment() + : java.lang.foreign.MemorySegment.NULL); + byte[] str = buf.toArray(ValueLayout.JAVA_BYTE); + int len = 0; + while (str[len] != 0) { + len++; + } + String device = new String(str, 0, len); + return new FfmNativePty( + provider, null, master.get(ValueLayout.JAVA_INT, 0), slave.get(ValueLayout.JAVA_INT, 0), device); + } catch (Throwable e) { + throw new RuntimeException("Unable to call openpty()", e); + } + } + + // CONSTANTS + + private static final int TIOCGWINSZ; + private static final int TIOCSWINSZ; + + private static final int TCSANOW; + private static int TCSADRAIN; + private static int TCSAFLUSH; + + private static final int VEOF; + private static final int VEOL; + private static final int VEOL2; + private static final int VERASE; + private static final int VWERASE; + private static final int VKILL; + private static final int VREPRINT; + private static final int VERASE2; + private static final int VINTR; + private static final int VQUIT; + private static final int VSUSP; + private static final int VDSUSP; + private static final int VSTART; + private static final int VSTOP; + private static final int VLNEXT; + private static final int VDISCARD; + private static final int VMIN; + private static final int VSWTC; + private static final int VTIME; + private static final int VSTATUS; + + private static final int IGNBRK; + private static final int BRKINT; + private static final int IGNPAR; + private static final int PARMRK; + private static final int INPCK; + private static final int ISTRIP; + private static final int INLCR; + private static final int IGNCR; + private static final int ICRNL; + private static int IUCLC; + private static final int IXON; + private static final int IXOFF; + private static final int IXANY; + private static final int IMAXBEL; + private static int IUTF8; + + private static final int OPOST; + private static int OLCUC; + private static final int ONLCR; + private static int OXTABS; + private static int NLDLY; + private static int NL0; + private static int NL1; + private static final int TABDLY; + private static int TAB0; + private static int TAB1; + private static int TAB2; + private static int TAB3; + private static int CRDLY; + private static int CR0; + private static int CR1; + private static int CR2; + private static int CR3; + private static int FFDLY; + private static int FF0; + private static int FF1; + private static int XTABS; + private static int BSDLY; + private static int BS0; + private static int BS1; + private static int VTDLY; + private static int VT0; + private static int VT1; + private static int CBAUD; + private static int B0; + private static int B50; + private static int B75; + private static int B110; + private static int B134; + private static int B150; + private static int B200; + private static int B300; + private static int B600; + private static int B1200; + private static int B1800; + private static int B2400; + private static int B4800; + private static int B9600; + private static int B19200; + private static int B38400; + private static int EXTA; + private static int EXTB; + private static int OFDEL; + private static int ONOEOT; + private static final int OCRNL; + private static int ONOCR; + private static final int ONLRET; + private static int OFILL; + + private static int CIGNORE; + private static int CSIZE; + private static final int CS5; + private static final int CS6; + private static final int CS7; + private static final int CS8; + private static final int CSTOPB; + private static final int CREAD; + private static final int PARENB; + private static final int PARODD; + private static final int HUPCL; + private static final int CLOCAL; + private static int CCTS_OFLOW; + private static int CRTS_IFLOW; + private static int CDTR_IFLOW; + private static int CDSR_OFLOW; + private static int CCAR_OFLOW; + + private static final int ECHOKE; + private static final int ECHOE; + private static final int ECHOK; + private static final int ECHO; + private static final int ECHONL; + private static final int ECHOPRT; + private static final int ECHOCTL; + private static final int ISIG; + private static final int ICANON; + private static int XCASE; + private static int ALTWERASE; + private static final int IEXTEN; + private static final int EXTPROC; + private static final int TOSTOP; + private static final int FLUSHO; + private static int NOKERNINFO; + private static final int PENDIN; + private static final int NOFLSH; + + static { + String osName = System.getProperty("os.name"); + if (osName.startsWith("Linux")) { + String arch = System.getProperty("os.arch"); + boolean isMipsPpcOrSparc = arch.equals("mips") + || arch.equals("mips64") + || arch.equals("mipsel") + || arch.equals("mips64el") + || arch.startsWith("ppc") + || arch.startsWith("sparc"); + TIOCGWINSZ = isMipsPpcOrSparc ? 0x40087468 : 0x00005413; + TIOCSWINSZ = isMipsPpcOrSparc ? 0x80087467 : 0x00005414; + + TCSANOW = 0x0; + TCSADRAIN = 0x1; + TCSAFLUSH = 0x2; + + VINTR = 0; + VQUIT = 1; + VERASE = 2; + VKILL = 3; + VEOF = 4; + VTIME = 5; + VMIN = 6; + VSWTC = 7; + VSTART = 8; + VSTOP = 9; + VSUSP = 10; + VEOL = 11; + VREPRINT = 12; + VDISCARD = 13; + VWERASE = 14; + VLNEXT = 15; + VEOL2 = 16; + VERASE2 = -1; + VDSUSP = -1; + VSTATUS = -1; + + IGNBRK = 0x0000001; + BRKINT = 0x0000002; + IGNPAR = 0x0000004; + PARMRK = 0x0000008; + INPCK = 0x0000010; + ISTRIP = 0x0000020; + INLCR = 0x0000040; + IGNCR = 0x0000080; + ICRNL = 0x0000100; + IUCLC = 0x0000200; + IXON = 0x0000400; + IXANY = 0x0000800; + IXOFF = 0x0001000; + IMAXBEL = 0x0002000; + IUTF8 = 0x0004000; + + OPOST = 0x0000001; + OLCUC = 0x0000002; + ONLCR = 0x0000004; + OCRNL = 0x0000008; + ONOCR = 0x0000010; + ONLRET = 0x0000020; + OFILL = 0x0000040; + OFDEL = 0x0000080; + NLDLY = 0x0000100; + NL0 = 0x0000000; + NL1 = 0x0000100; + CRDLY = 0x0000600; + CR0 = 0x0000000; + CR1 = 0x0000200; + CR2 = 0x0000400; + CR3 = 0x0000600; + TABDLY = 0x0001800; + TAB0 = 0x0000000; + TAB1 = 0x0000800; + TAB2 = 0x0001000; + TAB3 = 0x0001800; + XTABS = 0x0001800; + BSDLY = 0x0002000; + BS0 = 0x0000000; + BS1 = 0x0002000; + VTDLY = 0x0004000; + VT0 = 0x0000000; + VT1 = 0x0004000; + FFDLY = 0x0008000; + FF0 = 0x0000000; + FF1 = 0x0008000; + + CBAUD = 0x000100f; + B0 = 0x0000000; + B50 = 0x0000001; + B75 = 0x0000002; + B110 = 0x0000003; + B134 = 0x0000004; + B150 = 0x0000005; + B200 = 0x0000006; + B300 = 0x0000007; + B600 = 0x0000008; + B1200 = 0x0000009; + B1800 = 0x000000a; + B2400 = 0x000000b; + B4800 = 0x000000c; + B9600 = 0x000000d; + B19200 = 0x000000e; + B38400 = 0x000000f; + EXTA = B19200; + EXTB = B38400; + CSIZE = 0x0000030; + CS5 = 0x0000000; + CS6 = 0x0000010; + CS7 = 0x0000020; + CS8 = 0x0000030; + CSTOPB = 0x0000040; + CREAD = 0x0000080; + PARENB = 0x0000100; + PARODD = 0x0000200; + HUPCL = 0x0000400; + CLOCAL = 0x0000800; + + ISIG = 0x0000001; + ICANON = 0x0000002; + XCASE = 0x0000004; + ECHO = 0x0000008; + ECHOE = 0x0000010; + ECHOK = 0x0000020; + ECHONL = 0x0000040; + NOFLSH = 0x0000080; + TOSTOP = 0x0000100; + ECHOCTL = 0x0000200; + ECHOPRT = 0x0000400; + ECHOKE = 0x0000800; + FLUSHO = 0x0001000; + PENDIN = 0x0002000; + IEXTEN = 0x0008000; + EXTPROC = 0x0010000; + } else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) { + int _TIOC = ('T' << 8); + TIOCGWINSZ = (_TIOC | 104); + TIOCSWINSZ = (_TIOC | 103); + + TCSANOW = 0x0; + TCSADRAIN = 0x1; + TCSAFLUSH = 0x2; + + VINTR = 0; + VQUIT = 1; + VERASE = 2; + VKILL = 3; + VEOF = 4; + VTIME = 5; + VMIN = 6; + VSWTC = 7; + VSTART = 8; + VSTOP = 9; + VSUSP = 10; + VEOL = 11; + VREPRINT = 12; + VDISCARD = 13; + VWERASE = 14; + VLNEXT = 15; + VEOL2 = 16; + VERASE2 = -1; + VDSUSP = -1; + VSTATUS = -1; + + IGNBRK = 0x0000001; + BRKINT = 0x0000002; + IGNPAR = 0x0000004; + PARMRK = 0x0000010; + INPCK = 0x0000020; + ISTRIP = 0x0000040; + INLCR = 0x0000100; + IGNCR = 0x0000200; + ICRNL = 0x0000400; + IUCLC = 0x0001000; + IXON = 0x0002000; + IXANY = 0x0004000; + IXOFF = 0x0010000; + IMAXBEL = 0x0020000; + IUTF8 = 0x0040000; + + OPOST = 0x0000001; + OLCUC = 0x0000002; + ONLCR = 0x0000004; + OCRNL = 0x0000010; + ONOCR = 0x0000020; + ONLRET = 0x0000040; + OFILL = 0x0000100; + OFDEL = 0x0000200; + NLDLY = 0x0000400; + NL0 = 0x0000000; + NL1 = 0x0000400; + CRDLY = 0x0003000; + CR0 = 0x0000000; + CR1 = 0x0001000; + CR2 = 0x0002000; + CR3 = 0x0003000; + TABDLY = 0x0014000; + TAB0 = 0x0000000; + TAB1 = 0x0004000; + TAB2 = 0x0010000; + TAB3 = 0x0014000; + XTABS = 0x0014000; + BSDLY = 0x0020000; + BS0 = 0x0000000; + BS1 = 0x0020000; + VTDLY = 0x0040000; + VT0 = 0x0000000; + VT1 = 0x0040000; + FFDLY = 0x0100000; + FF0 = 0x0000000; + FF1 = 0x0100000; + + CBAUD = 0x0010017; + B0 = 0x0000000; + B50 = 0x0000001; + B75 = 0x0000002; + B110 = 0x0000003; + B134 = 0x0000004; + B150 = 0x0000005; + B200 = 0x0000006; + B300 = 0x0000007; + B600 = 0x0000010; + B1200 = 0x0000011; + B1800 = 0x0000012; + B2400 = 0x0000013; + B4800 = 0x0000014; + B9600 = 0x0000015; + B19200 = 0x0000016; + B38400 = 0x0000017; + EXTA = 0xB19200; + EXTB = 0xB38400; + CSIZE = 0x0000060; + CS5 = 0x0000000; + CS6 = 0x0000020; + CS7 = 0x0000040; + CS8 = 0x0000060; + CSTOPB = 0x0000100; + CREAD = 0x0000200; + PARENB = 0x0000400; + PARODD = 0x0001000; + HUPCL = 0x0002000; + CLOCAL = 0x0004000; + + ISIG = 0x0000001; + ICANON = 0x0000002; + XCASE = 0x0000004; + ECHO = 0x0000010; + ECHOE = 0x0000020; + ECHOK = 0x0000040; + ECHONL = 0x0000100; + NOFLSH = 0x0000200; + TOSTOP = 0x0000400; + ECHOCTL = 0x0001000; + ECHOPRT = 0x0002000; + ECHOKE = 0x0004000; + FLUSHO = 0x0010000; + PENDIN = 0x0040000; + IEXTEN = 0x0100000; + EXTPROC = 0x0200000; + } else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) { + TIOCGWINSZ = 0x40087468; + TIOCSWINSZ = 0x80087467; + + TCSANOW = 0x00000000; + + VEOF = 0; + VEOL = 1; + VEOL2 = 2; + VERASE = 3; + VWERASE = 4; + VKILL = 5; + VREPRINT = 6; + VINTR = 8; + VQUIT = 9; + VSUSP = 10; + VDSUSP = 11; + VSTART = 12; + VSTOP = 13; + VLNEXT = 14; + VDISCARD = 15; + VMIN = 16; + VTIME = 17; + VSTATUS = 18; + VERASE2 = -1; + VSWTC = -1; + + IGNBRK = 0x00000001; + BRKINT = 0x00000002; + IGNPAR = 0x00000004; + PARMRK = 0x00000008; + INPCK = 0x00000010; + ISTRIP = 0x00000020; + INLCR = 0x00000040; + IGNCR = 0x00000080; + ICRNL = 0x00000100; + IXON = 0x00000200; + IXOFF = 0x00000400; + IXANY = 0x00000800; + IMAXBEL = 0x00002000; + IUTF8 = 0x00004000; + + OPOST = 0x00000001; + ONLCR = 0x00000002; + OXTABS = 0x00000004; + ONOEOT = 0x00000008; + OCRNL = 0x00000010; + ONOCR = 0x00000020; + ONLRET = 0x00000040; + OFILL = 0x00000080; + NLDLY = 0x00000300; + TABDLY = 0x00000c04; + CRDLY = 0x00003000; + FFDLY = 0x00004000; + BSDLY = 0x00008000; + VTDLY = 0x00010000; + OFDEL = 0x00020000; + + CIGNORE = 0x00000001; + CS5 = 0x00000000; + CS6 = 0x00000100; + CS7 = 0x00000200; + CS8 = 0x00000300; + CSTOPB = 0x00000400; + CREAD = 0x00000800; + PARENB = 0x00001000; + PARODD = 0x00002000; + HUPCL = 0x00004000; + CLOCAL = 0x00008000; + CCTS_OFLOW = 0x00010000; + CRTS_IFLOW = 0x00020000; + CDTR_IFLOW = 0x00040000; + CDSR_OFLOW = 0x00080000; + CCAR_OFLOW = 0x00100000; + + ECHOKE = 0x00000001; + ECHOE = 0x00000002; + ECHOK = 0x00000004; + ECHO = 0x00000008; + ECHONL = 0x00000010; + ECHOPRT = 0x00000020; + ECHOCTL = 0x00000040; + ISIG = 0x00000080; + ICANON = 0x00000100; + ALTWERASE = 0x00000200; + IEXTEN = 0x00000400; + EXTPROC = 0x00000800; + TOSTOP = 0x00400000; + FLUSHO = 0x00800000; + NOKERNINFO = 0x02000000; + PENDIN = 0x20000000; + NOFLSH = 0x80000000; + } else if (osName.startsWith("FreeBSD")) { + TIOCGWINSZ = 0x40087468; + TIOCSWINSZ = 0x80087467; + + TCSANOW = 0x0; + TCSADRAIN = 0x1; + TCSAFLUSH = 0x2; + + VEOF = 0; + VEOL = 1; + VEOL2 = 2; + VERASE = 3; + VWERASE = 4; + VKILL = 5; + VREPRINT = 6; + VERASE2 = 7; + VINTR = 8; + VQUIT = 9; + VSUSP = 10; + VDSUSP = 11; + VSTART = 12; + VSTOP = 13; + VLNEXT = 14; + VDISCARD = 15; + VMIN = 16; + VTIME = 17; + VSTATUS = 18; + VSWTC = -1; + + IGNBRK = 0x0000001; + BRKINT = 0x0000002; + IGNPAR = 0x0000004; + PARMRK = 0x0000008; + INPCK = 0x0000010; + ISTRIP = 0x0000020; + INLCR = 0x0000040; + IGNCR = 0x0000080; + ICRNL = 0x0000100; + IXON = 0x0000200; + IXOFF = 0x0000400; + IXANY = 0x0000800; + IMAXBEL = 0x0002000; + + OPOST = 0x0000001; + ONLCR = 0x0000002; + TABDLY = 0x0000004; + TAB0 = 0x0000000; + TAB3 = 0x0000004; + ONOEOT = 0x0000008; + OCRNL = 0x0000010; + ONLRET = 0x0000040; + + CIGNORE = 0x0000001; + CSIZE = 0x0000300; + CS5 = 0x0000000; + CS6 = 0x0000100; + CS7 = 0x0000200; + CS8 = 0x0000300; + CSTOPB = 0x0000400; + CREAD = 0x0000800; + PARENB = 0x0001000; + PARODD = 0x0002000; + HUPCL = 0x0004000; + CLOCAL = 0x0008000; + + ECHOKE = 0x0000001; + ECHOE = 0x0000002; + ECHOK = 0x0000004; + ECHO = 0x0000008; + ECHONL = 0x0000010; + ECHOPRT = 0x0000020; + ECHOCTL = 0x0000040; + ISIG = 0x0000080; + ICANON = 0x0000100; + ALTWERASE = 0x000200; + IEXTEN = 0x0000400; + EXTPROC = 0x0000800; + TOSTOP = 0x0400000; + FLUSHO = 0x0800000; + PENDIN = 0x2000000; + NOFLSH = 0x8000000; + } else { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmNativePty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmNativePty.java new file mode 100644 index 0000000000000..1f8b668115aae --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmNativePty.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2022-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.ffm; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.impl.AbstractPty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; + +class FfmNativePty extends AbstractPty { + private final int master; + private final int slave; + private final int slaveOut; + private final String name; + private final FileDescriptor masterFD; + private final FileDescriptor slaveFD; + private final FileDescriptor slaveOutFD; + + public FfmNativePty(TerminalProvider provider, SystemStream systemStream, int master, int slave, String name) { + this( + provider, + systemStream, + master, + newDescriptor(master), + slave, + newDescriptor(slave), + slave, + newDescriptor(slave), + name); + } + + public FfmNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + int slaveOut, + FileDescriptor slaveOutFD, + String name) { + super(provider, systemStream); + this.master = master; + this.slave = slave; + this.slaveOut = slaveOut; + this.name = name; + this.masterFD = masterFD; + this.slaveFD = slaveFD; + this.slaveOutFD = slaveOutFD; + } + + @Override + public void close() throws IOException { + if (master > 0) { + getMasterInput().close(); + } + if (slave > 0) { + getSlaveInput().close(); + } + } + + public int getMaster() { + return master; + } + + public int getSlave() { + return slave; + } + + public int getSlaveOut() { + return slaveOut; + } + + public String getName() { + return name; + } + + public FileDescriptor getMasterFD() { + return masterFD; + } + + public FileDescriptor getSlaveFD() { + return slaveFD; + } + + public FileDescriptor getSlaveOutFD() { + return slaveOutFD; + } + + public InputStream getMasterInput() { + return new FileInputStream(getMasterFD()); + } + + public OutputStream getMasterOutput() { + return new FileOutputStream(getMasterFD()); + } + + protected InputStream doGetSlaveInput() { + return new FileInputStream(getSlaveFD()); + } + + public OutputStream getSlaveOutput() { + return new FileOutputStream(getSlaveOutFD()); + } + + @Override + public Attributes getAttr() throws IOException { + return CLibrary.getAttributes(slave); + } + + @Override + protected void doSetAttr(Attributes attr) throws IOException { + CLibrary.setAttributes(slave, attr); + } + + @Override + public Size getSize() throws IOException { + return CLibrary.getTerminalSize(slave); + } + + @Override + public void setSize(Size size) throws IOException { + CLibrary.setTerminalSize(slave, size); + } + + @Override + public String toString() { + return "FfmNativePty[" + getName() + "]"; + } + + public static boolean isPosixSystemStream(SystemStream stream) { + switch (stream) { + case Input: + return CLibrary.isTty(0); + case Output: + return CLibrary.isTty(1); + case Error: + return CLibrary.isTty(2); + default: + throw new IllegalArgumentException(); + } + } + + public static String posixSystemStreamName(SystemStream stream) { + switch (stream) { + case Input: + return CLibrary.ttyName(0); + case Output: + return CLibrary.ttyName(1); + case Error: + return CLibrary.ttyName(2); + default: + throw new IllegalArgumentException(); + } + } + + public static int systemStreamWidth(SystemStream systemStream) { + int fd = systemStream == SystemStream.Output ? 1 : 2; + return CLibrary.getTerminalSize(fd).getColumns(); + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmTerminalProvider.java new file mode 100644 index 0000000000000..76f07926b125b --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/FfmTerminalProvider.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.ffm; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.nio.charset.Charset; +import java.util.function.Function; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.TerminalBuilder; +import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal; +import jdk.internal.org.jline.terminal.impl.PosixSysTerminal; +import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.utils.OSUtils; + +public class FfmTerminalProvider implements TerminalProvider { + + public FfmTerminalProvider() { + if (!FfmTerminalProvider.class.getModule().isNativeAccessEnabled()) { + throw new UnsupportedOperationException( + "Native access is not enabled for the current module: " + FfmTerminalProvider.class.getModule()); + } + } + + @Override + public String name() { + return TerminalBuilder.PROP_PROVIDER_FFM; + } + + @Override + public Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { + if (OSUtils.IS_WINDOWS) { + return NativeWinSysTerminal.createTerminal( + this, systemStream, name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, inputStreamWrapper); + } else { + Pty pty = new FfmNativePty( + this, + systemStream, + -1, + null, + 0, + FileDescriptor.in, + systemStream == SystemStream.Output ? 1 : 2, + systemStream == SystemStream.Output ? FileDescriptor.out : FileDescriptor.err, + CLibrary.ttyName(0)); + return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); + } + } + + @Override + public Terminal newTerminal( + String name, + String type, + InputStream in, + OutputStream out, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { + Pty pty = CLibrary.openpty(this, attributes, size); + return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused); + } + + @Override + public boolean isSystemStream(SystemStream stream) { + if (OSUtils.IS_WINDOWS) { + return isWindowsSystemStream(stream); + } else { + return isPosixSystemStream(stream); + } + } + + public boolean isWindowsSystemStream(SystemStream stream) { + return NativeWinSysTerminal.isWindowsSystemStream(stream); + } + + public boolean isPosixSystemStream(SystemStream stream) { + return FfmNativePty.isPosixSystemStream(stream); + } + + @Override + public String systemStreamName(SystemStream stream) { + return FfmNativePty.posixSystemStreamName(stream); + } + + @Override + public int systemStreamWidth(SystemStream stream) { + return FfmNativePty.systemStreamWidth(stream); + } + + @Override + public String toString() { + return "TerminalProvider[" + name() + "]"; + } + + static VarHandle lookupVarHandle(MemoryLayout layout, PathElement... element) { + VarHandle h = layout.varHandle(element); + + // the last parameter of the VarHandle is additional offset, hardcode zero: + h = MethodHandles.insertCoordinates(h, h.coordinateTypes().size() - 1, 0L); + + return h; + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/Kernel32.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/Kernel32.java new file mode 100644 index 0000000000000..0c485819f57dc --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/Kernel32.java @@ -0,0 +1,927 @@ +/* + * Copyright (c) 2009-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.ffm; + +import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +@SuppressWarnings({"unused", "restricted"}) +final class Kernel32 { + + public static final int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; + + public static final int INVALID_HANDLE_VALUE = -1; + public static final int STD_INPUT_HANDLE = -10; + public static final int STD_OUTPUT_HANDLE = -11; + public static final int STD_ERROR_HANDLE = -12; + + public static final int ENABLE_PROCESSED_INPUT = 0x0001; + public static final int ENABLE_LINE_INPUT = 0x0002; + public static final int ENABLE_ECHO_INPUT = 0x0004; + public static final int ENABLE_WINDOW_INPUT = 0x0008; + public static final int ENABLE_MOUSE_INPUT = 0x0010; + public static final int ENABLE_INSERT_MODE = 0x0020; + public static final int ENABLE_QUICK_EDIT_MODE = 0x0040; + public static final int ENABLE_EXTENDED_FLAGS = 0x0080; + + public static final int RIGHT_ALT_PRESSED = 0x0001; + public static final int LEFT_ALT_PRESSED = 0x0002; + public static final int RIGHT_CTRL_PRESSED = 0x0004; + public static final int LEFT_CTRL_PRESSED = 0x0008; + public static final int SHIFT_PRESSED = 0x0010; + + public static final int FOREGROUND_BLUE = 0x0001; + public static final int FOREGROUND_GREEN = 0x0002; + public static final int FOREGROUND_RED = 0x0004; + public static final int FOREGROUND_INTENSITY = 0x0008; + public static final int BACKGROUND_BLUE = 0x0010; + public static final int BACKGROUND_GREEN = 0x0020; + public static final int BACKGROUND_RED = 0x0040; + public static final int BACKGROUND_INTENSITY = 0x0080; + + // Button state + public static final int FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001; + public static final int RIGHTMOST_BUTTON_PRESSED = 0x0002; + public static final int FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004; + public static final int FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008; + public static final int FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010; + + // Event flags + public static final int MOUSE_MOVED = 0x0001; + public static final int DOUBLE_CLICK = 0x0002; + public static final int MOUSE_WHEELED = 0x0004; + public static final int MOUSE_HWHEELED = 0x0008; + + // Event types + public static final short KEY_EVENT = 0x0001; + public static final short MOUSE_EVENT = 0x0002; + public static final short WINDOW_BUFFER_SIZE_EVENT = 0x0004; + public static final short MENU_EVENT = 0x0008; + public static final short FOCUS_EVENT = 0x0010; + + public static int WaitForSingleObject(java.lang.foreign.MemorySegment hHandle, int dwMilliseconds) { + MethodHandle mh$ = requireNonNull(WaitForSingleObject$MH, "WaitForSingleObject"); + try { + return (int) mh$.invokeExact(hHandle, dwMilliseconds); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static java.lang.foreign.MemorySegment GetStdHandle(int nStdHandle) { + MethodHandle mh$ = requireNonNull(GetStdHandle$MH, "GetStdHandle"); + try { + return (java.lang.foreign.MemorySegment) mh$.invokeExact(nStdHandle); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int FormatMessageW( + int dwFlags, + java.lang.foreign.MemorySegment lpSource, + int dwMessageId, + int dwLanguageId, + java.lang.foreign.MemorySegment lpBuffer, + int nSize, + java.lang.foreign.MemorySegment Arguments) { + MethodHandle mh$ = requireNonNull(FormatMessageW$MH, "FormatMessageW"); + try { + return (int) mh$.invokeExact(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int SetConsoleTextAttribute(java.lang.foreign.MemorySegment hConsoleOutput, short wAttributes) { + MethodHandle mh$ = requireNonNull(SetConsoleTextAttribute$MH, "SetConsoleTextAttribute"); + try { + return (int) mh$.invokeExact(hConsoleOutput, wAttributes); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int SetConsoleMode(java.lang.foreign.MemorySegment hConsoleHandle, int dwMode) { + MethodHandle mh$ = requireNonNull(SetConsoleMode$MH, "SetConsoleMode"); + try { + return (int) mh$.invokeExact(hConsoleHandle, dwMode); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int GetConsoleMode( + java.lang.foreign.MemorySegment hConsoleHandle, java.lang.foreign.MemorySegment lpMode) { + MethodHandle mh$ = requireNonNull(GetConsoleMode$MH, "GetConsoleMode"); + try { + return (int) mh$.invokeExact(hConsoleHandle, lpMode); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int SetConsoleTitleW(java.lang.foreign.MemorySegment lpConsoleTitle) { + MethodHandle mh$ = requireNonNull(SetConsoleTitleW$MH, "SetConsoleTitleW"); + try { + return (int) mh$.invokeExact(lpConsoleTitle); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int SetConsoleCursorPosition(java.lang.foreign.MemorySegment hConsoleOutput, COORD dwCursorPosition) { + MethodHandle mh$ = requireNonNull(SetConsoleCursorPosition$MH, "SetConsoleCursorPosition"); + try { + return (int) mh$.invokeExact(hConsoleOutput, dwCursorPosition.seg); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int FillConsoleOutputCharacterW( + java.lang.foreign.MemorySegment hConsoleOutput, + char cCharacter, + int nLength, + COORD dwWriteCoord, + java.lang.foreign.MemorySegment lpNumberOfCharsWritten) { + MethodHandle mh$ = requireNonNull(FillConsoleOutputCharacterW$MH, "FillConsoleOutputCharacterW"); + try { + return (int) mh$.invokeExact(hConsoleOutput, cCharacter, nLength, dwWriteCoord.seg, lpNumberOfCharsWritten); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int FillConsoleOutputAttribute( + java.lang.foreign.MemorySegment hConsoleOutput, + short wAttribute, + int nLength, + COORD dwWriteCoord, + java.lang.foreign.MemorySegment lpNumberOfAttrsWritten) { + MethodHandle mh$ = requireNonNull(FillConsoleOutputAttribute$MH, "FillConsoleOutputAttribute"); + try { + return (int) mh$.invokeExact(hConsoleOutput, wAttribute, nLength, dwWriteCoord.seg, lpNumberOfAttrsWritten); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int WriteConsoleW( + java.lang.foreign.MemorySegment hConsoleOutput, + java.lang.foreign.MemorySegment lpBuffer, + int nNumberOfCharsToWrite, + java.lang.foreign.MemorySegment lpNumberOfCharsWritten, + java.lang.foreign.MemorySegment lpReserved) { + MethodHandle mh$ = requireNonNull(WriteConsoleW$MH, "WriteConsoleW"); + try { + return (int) mh$.invokeExact( + hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int ReadConsoleInputW( + java.lang.foreign.MemorySegment hConsoleInput, + java.lang.foreign.MemorySegment lpBuffer, + int nLength, + java.lang.foreign.MemorySegment lpNumberOfEventsRead) { + MethodHandle mh$ = requireNonNull(ReadConsoleInputW$MH, "ReadConsoleInputW"); + try { + return (int) mh$.invokeExact(hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int PeekConsoleInputW( + java.lang.foreign.MemorySegment hConsoleInput, + java.lang.foreign.MemorySegment lpBuffer, + int nLength, + java.lang.foreign.MemorySegment lpNumberOfEventsRead) { + MethodHandle mh$ = requireNonNull(PeekConsoleInputW$MH, "PeekConsoleInputW"); + try { + return (int) mh$.invokeExact(hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int GetConsoleScreenBufferInfo( + java.lang.foreign.MemorySegment hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo) { + MethodHandle mh$ = requireNonNull(GetConsoleScreenBufferInfo$MH, "GetConsoleScreenBufferInfo"); + try { + return (int) mh$.invokeExact(hConsoleOutput, lpConsoleScreenBufferInfo.seg); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int ScrollConsoleScreenBuffer( + java.lang.foreign.MemorySegment hConsoleOutput, + SMALL_RECT lpScrollRectangle, + SMALL_RECT lpClipRectangle, + COORD dwDestinationOrigin, + CHAR_INFO lpFill) { + MethodHandle mh$ = requireNonNull(ScrollConsoleScreenBufferW$MH, "ScrollConsoleScreenBuffer"); + try { + return (int) + mh$.invokeExact(hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int GetLastError() { + MethodHandle mh$ = requireNonNull(GetLastError$MH, "GetLastError"); + try { + return (int) mh$.invokeExact(); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static int GetFileType(java.lang.foreign.MemorySegment hFile) { + MethodHandle mh$ = requireNonNull(GetFileType$MH, "GetFileType"); + try { + return (int) mh$.invokeExact(hFile); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static java.lang.foreign.MemorySegment _get_osfhandle(int fd) { + MethodHandle mh$ = requireNonNull(_get_osfhandle$MH, "_get_osfhandle"); + try { + return (java.lang.foreign.MemorySegment) mh$.invokeExact(fd); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + public static INPUT_RECORD[] readConsoleInputHelper(java.lang.foreign.MemorySegment handle, int count, boolean peek) + throws IOException { + return readConsoleInputHelper(java.lang.foreign.Arena.ofAuto(), handle, count, peek); + } + + public static INPUT_RECORD[] readConsoleInputHelper( + java.lang.foreign.Arena arena, java.lang.foreign.MemorySegment handle, int count, boolean peek) + throws IOException { + java.lang.foreign.MemorySegment inputRecordPtr = arena.allocate(INPUT_RECORD.LAYOUT, count); + java.lang.foreign.MemorySegment length = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT, 1); + int res = peek + ? PeekConsoleInputW(handle, inputRecordPtr, count, length) + : ReadConsoleInputW(handle, inputRecordPtr, count, length); + if (res == 0) { + throw new IOException("ReadConsoleInputW failed: " + getLastErrorMessage()); + } + int len = length.get(java.lang.foreign.ValueLayout.JAVA_INT, 0); + return inputRecordPtr + .elements(INPUT_RECORD.LAYOUT) + .map(INPUT_RECORD::new) + .limit(len) + .toArray(INPUT_RECORD[]::new); + } + + public static String getLastErrorMessage() { + int errorCode = GetLastError(); + return getErrorMessage(errorCode); + } + + public static String getErrorMessage(int errorCode) { + int bufferSize = 160; + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + java.lang.foreign.MemorySegment data = arena.allocate(bufferSize); + FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM, + java.lang.foreign.MemorySegment.NULL, + errorCode, + 0, + data, + bufferSize, + java.lang.foreign.MemorySegment.NULL); + return new String(data.toArray(java.lang.foreign.ValueLayout.JAVA_BYTE), StandardCharsets.UTF_16LE).trim(); + } + } + + private static final java.lang.foreign.SymbolLookup SYMBOL_LOOKUP; + + static { + System.loadLibrary("msvcrt"); + System.loadLibrary("Kernel32"); + SYMBOL_LOOKUP = java.lang.foreign.SymbolLookup.loaderLookup(); + } + + static MethodHandle downcallHandle(String name, java.lang.foreign.FunctionDescriptor fdesc) { + return SYMBOL_LOOKUP + .find(name) + .map(addr -> java.lang.foreign.Linker.nativeLinker().downcallHandle(addr, fdesc)) + .orElse(null); + } + + static final java.lang.foreign.ValueLayout.OfBoolean C_BOOL$LAYOUT = java.lang.foreign.ValueLayout.JAVA_BOOLEAN; + static final java.lang.foreign.ValueLayout.OfByte C_CHAR$LAYOUT = java.lang.foreign.ValueLayout.JAVA_BYTE; + static final java.lang.foreign.ValueLayout.OfChar C_WCHAR$LAYOUT = java.lang.foreign.ValueLayout.JAVA_CHAR; + static final java.lang.foreign.ValueLayout.OfShort C_SHORT$LAYOUT = java.lang.foreign.ValueLayout.JAVA_SHORT; + static final java.lang.foreign.ValueLayout.OfShort C_WORD$LAYOUT = java.lang.foreign.ValueLayout.JAVA_SHORT; + static final java.lang.foreign.ValueLayout.OfInt C_DWORD$LAYOUT = java.lang.foreign.ValueLayout.JAVA_INT; + static final java.lang.foreign.ValueLayout.OfInt C_INT$LAYOUT = java.lang.foreign.ValueLayout.JAVA_INT; + static final java.lang.foreign.ValueLayout.OfLong C_LONG$LAYOUT = java.lang.foreign.ValueLayout.JAVA_LONG; + static final java.lang.foreign.ValueLayout.OfLong C_LONG_LONG$LAYOUT = java.lang.foreign.ValueLayout.JAVA_LONG; + static final java.lang.foreign.ValueLayout.OfFloat C_FLOAT$LAYOUT = java.lang.foreign.ValueLayout.JAVA_FLOAT; + static final java.lang.foreign.ValueLayout.OfDouble C_DOUBLE$LAYOUT = java.lang.foreign.ValueLayout.JAVA_DOUBLE; + static final java.lang.foreign.AddressLayout C_POINTER$LAYOUT = java.lang.foreign.ValueLayout.ADDRESS; + + static final MethodHandle WaitForSingleObject$MH = downcallHandle( + "WaitForSingleObject", + java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT)); + static final MethodHandle GetStdHandle$MH = + downcallHandle("GetStdHandle", java.lang.foreign.FunctionDescriptor.of(C_POINTER$LAYOUT, C_INT$LAYOUT)); + static final MethodHandle FormatMessageW$MH = downcallHandle( + "FormatMessageW", + java.lang.foreign.FunctionDescriptor.of( + C_INT$LAYOUT, + C_INT$LAYOUT, + C_POINTER$LAYOUT, + C_INT$LAYOUT, + C_INT$LAYOUT, + C_POINTER$LAYOUT, + C_INT$LAYOUT, + C_POINTER$LAYOUT)); + static final MethodHandle SetConsoleTextAttribute$MH = downcallHandle( + "SetConsoleTextAttribute", + java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_SHORT$LAYOUT)); + static final MethodHandle SetConsoleMode$MH = downcallHandle( + "SetConsoleMode", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT)); + static final MethodHandle GetConsoleMode$MH = downcallHandle( + "GetConsoleMode", + java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT)); + + static final MethodHandle SetConsoleTitleW$MH = + downcallHandle("SetConsoleTitleW", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT)); + static final MethodHandle SetConsoleCursorPosition$MH = downcallHandle( + "SetConsoleCursorPosition", + java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, COORD.LAYOUT)); + static final MethodHandle FillConsoleOutputCharacterW$MH = downcallHandle( + "FillConsoleOutputCharacterW", + java.lang.foreign.FunctionDescriptor.of( + C_INT$LAYOUT, C_POINTER$LAYOUT, C_WCHAR$LAYOUT, C_INT$LAYOUT, COORD.LAYOUT, C_POINTER$LAYOUT)); + static final MethodHandle FillConsoleOutputAttribute$MH = downcallHandle( + "FillConsoleOutputAttribute", + java.lang.foreign.FunctionDescriptor.of( + C_INT$LAYOUT, C_POINTER$LAYOUT, C_SHORT$LAYOUT, C_INT$LAYOUT, COORD.LAYOUT, C_POINTER$LAYOUT)); + static final MethodHandle WriteConsoleW$MH = downcallHandle( + "WriteConsoleW", + java.lang.foreign.FunctionDescriptor.of( + C_INT$LAYOUT, + C_POINTER$LAYOUT, + C_POINTER$LAYOUT, + C_INT$LAYOUT, + C_POINTER$LAYOUT, + C_POINTER$LAYOUT)); + + static final MethodHandle ReadConsoleInputW$MH = downcallHandle( + "ReadConsoleInputW", + java.lang.foreign.FunctionDescriptor.of( + C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT, C_POINTER$LAYOUT)); + static final MethodHandle PeekConsoleInputW$MH = downcallHandle( + "PeekConsoleInputW", + java.lang.foreign.FunctionDescriptor.of( + C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT, C_POINTER$LAYOUT)); + + static final MethodHandle GetConsoleScreenBufferInfo$MH = downcallHandle( + "GetConsoleScreenBufferInfo", + java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT)); + + static final MethodHandle ScrollConsoleScreenBufferW$MH = downcallHandle( + "ScrollConsoleScreenBufferW", + java.lang.foreign.FunctionDescriptor.of( + C_INT$LAYOUT, + C_POINTER$LAYOUT, + C_POINTER$LAYOUT, + C_POINTER$LAYOUT, + COORD.LAYOUT, + C_POINTER$LAYOUT)); + static final MethodHandle GetLastError$MH = + downcallHandle("GetLastError", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT)); + static final MethodHandle GetFileType$MH = + downcallHandle("GetFileType", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT)); + static final MethodHandle _get_osfhandle$MH = + downcallHandle("_get_osfhandle", java.lang.foreign.FunctionDescriptor.of(C_POINTER$LAYOUT, C_INT$LAYOUT)); + + public static final class INPUT_RECORD { + static final java.lang.foreign.MemoryLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout( + java.lang.foreign.ValueLayout.JAVA_SHORT.withName("EventType"), + java.lang.foreign.ValueLayout.JAVA_SHORT, // padding + java.lang.foreign.MemoryLayout.unionLayout( + KEY_EVENT_RECORD.LAYOUT.withName("KeyEvent"), + MOUSE_EVENT_RECORD.LAYOUT.withName("MouseEvent"), + WINDOW_BUFFER_SIZE_RECORD.LAYOUT.withName("WindowBufferSizeEvent"), + MENU_EVENT_RECORD.LAYOUT.withName("MenuEvent"), + FOCUS_EVENT_RECORD.LAYOUT.withName("FocusEvent")) + .withName("Event")); + static final VarHandle EventType$VH = varHandle(LAYOUT, "EventType"); + static final long Event$OFFSET = byteOffset(LAYOUT, "Event"); + + private final java.lang.foreign.MemorySegment seg; + + public INPUT_RECORD() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public INPUT_RECORD(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public INPUT_RECORD(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public short eventType() { + return (short) EventType$VH.get(seg); + } + + public KEY_EVENT_RECORD keyEvent() { + return new KEY_EVENT_RECORD(seg, Event$OFFSET); + } + + public MOUSE_EVENT_RECORD mouseEvent() { + return new MOUSE_EVENT_RECORD(seg, Event$OFFSET); + } + + public FOCUS_EVENT_RECORD focusEvent() { + return new FOCUS_EVENT_RECORD(seg, Event$OFFSET); + } + } + + public static final class MENU_EVENT_RECORD { + + static final java.lang.foreign.GroupLayout LAYOUT = + java.lang.foreign.MemoryLayout.structLayout(C_DWORD$LAYOUT.withName("dwCommandId")); + static final VarHandle COMMAND_ID = varHandle(LAYOUT, "dwCommandId"); + + private final java.lang.foreign.MemorySegment seg; + + public MENU_EVENT_RECORD() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public MENU_EVENT_RECORD(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public MENU_EVENT_RECORD(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public int commandId() { + return (int) MENU_EVENT_RECORD.COMMAND_ID.get(seg); + } + + public void commandId(int commandId) { + MENU_EVENT_RECORD.COMMAND_ID.set(seg, commandId); + } + } + + public static final class FOCUS_EVENT_RECORD { + + static final java.lang.foreign.GroupLayout LAYOUT = + java.lang.foreign.MemoryLayout.structLayout(C_INT$LAYOUT.withName("bSetFocus")); + static final VarHandle SET_FOCUS = varHandle(LAYOUT, "bSetFocus"); + + private final java.lang.foreign.MemorySegment seg; + + public FOCUS_EVENT_RECORD() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public FOCUS_EVENT_RECORD(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public FOCUS_EVENT_RECORD(java.lang.foreign.MemorySegment seg) { + this.seg = Objects.requireNonNull(seg); + } + + public FOCUS_EVENT_RECORD(java.lang.foreign.MemorySegment seg, long offset) { + this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize()); + } + + public boolean setFocus() { + return ((int) FOCUS_EVENT_RECORD.SET_FOCUS.get(seg) != 0); + } + + public void setFocus(boolean setFocus) { + FOCUS_EVENT_RECORD.SET_FOCUS.set(seg, setFocus ? 1 : 0); + } + } + + public static final class WINDOW_BUFFER_SIZE_RECORD { + + static final java.lang.foreign.GroupLayout LAYOUT = + java.lang.foreign.MemoryLayout.structLayout(COORD.LAYOUT.withName("size")); + static final long SIZE_OFFSET = byteOffset(LAYOUT, "size"); + + private final java.lang.foreign.MemorySegment seg; + + public WINDOW_BUFFER_SIZE_RECORD() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public WINDOW_BUFFER_SIZE_RECORD(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public WINDOW_BUFFER_SIZE_RECORD(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public COORD size() { + return new COORD(seg, SIZE_OFFSET); + } + + public String toString() { + return "WINDOW_BUFFER_SIZE_RECORD{size=" + this.size() + '}'; + } + } + + public static final class MOUSE_EVENT_RECORD { + + static final java.lang.foreign.MemoryLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout( + COORD.LAYOUT.withName("dwMousePosition"), + C_DWORD$LAYOUT.withName("dwButtonState"), + C_DWORD$LAYOUT.withName("dwControlKeyState"), + C_DWORD$LAYOUT.withName("dwEventFlags")); + static final long MOUSE_POSITION_OFFSET = byteOffset(LAYOUT, "dwMousePosition"); + static final VarHandle BUTTON_STATE = varHandle(LAYOUT, "dwButtonState"); + static final VarHandle CONTROL_KEY_STATE = varHandle(LAYOUT, "dwControlKeyState"); + static final VarHandle EVENT_FLAGS = varHandle(LAYOUT, "dwEventFlags"); + + private final java.lang.foreign.MemorySegment seg; + + public MOUSE_EVENT_RECORD() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public MOUSE_EVENT_RECORD(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public MOUSE_EVENT_RECORD(java.lang.foreign.MemorySegment seg) { + this.seg = Objects.requireNonNull(seg); + } + + public MOUSE_EVENT_RECORD(java.lang.foreign.MemorySegment seg, long offset) { + this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize()); + } + + public COORD mousePosition() { + return new COORD(seg, MOUSE_POSITION_OFFSET); + } + + public int buttonState() { + return (int) BUTTON_STATE.get(seg); + } + + public int controlKeyState() { + return (int) CONTROL_KEY_STATE.get(seg); + } + + public int eventFlags() { + return (int) EVENT_FLAGS.get(seg); + } + + public String toString() { + return "MOUSE_EVENT_RECORD{mousePosition=" + mousePosition() + ", buttonState=" + buttonState() + + ", controlKeyState=" + controlKeyState() + ", eventFlags=" + eventFlags() + '}'; + } + } + + public static final class KEY_EVENT_RECORD { + + static final java.lang.foreign.MemoryLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout( + java.lang.foreign.ValueLayout.JAVA_INT.withName("bKeyDown"), + java.lang.foreign.ValueLayout.JAVA_SHORT.withName("wRepeatCount"), + java.lang.foreign.ValueLayout.JAVA_SHORT.withName("wVirtualKeyCode"), + java.lang.foreign.ValueLayout.JAVA_SHORT.withName("wVirtualScanCode"), + java.lang.foreign.MemoryLayout.unionLayout( + java.lang.foreign.ValueLayout.JAVA_CHAR.withName("UnicodeChar"), + java.lang.foreign.ValueLayout.JAVA_BYTE.withName("AsciiChar")) + .withName("uChar"), + java.lang.foreign.ValueLayout.JAVA_INT.withName("dwControlKeyState")); + static final VarHandle bKeyDown$VH = varHandle(LAYOUT, "bKeyDown"); + static final VarHandle wRepeatCount$VH = varHandle(LAYOUT, "wRepeatCount"); + static final VarHandle wVirtualKeyCode$VH = varHandle(LAYOUT, "wVirtualKeyCode"); + static final VarHandle wVirtualScanCode$VH = varHandle(LAYOUT, "wVirtualScanCode"); + static final VarHandle UnicodeChar$VH = varHandle(LAYOUT, "uChar", "UnicodeChar"); + static final VarHandle AsciiChar$VH = varHandle(LAYOUT, "uChar", "AsciiChar"); + static final VarHandle dwControlKeyState$VH = varHandle(LAYOUT, "dwControlKeyState"); + + final java.lang.foreign.MemorySegment seg; + + public KEY_EVENT_RECORD() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public KEY_EVENT_RECORD(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public KEY_EVENT_RECORD(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public KEY_EVENT_RECORD(java.lang.foreign.MemorySegment seg, long offset) { + this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize()); + } + + public boolean keyDown() { + return ((int) bKeyDown$VH.get(seg)) != 0; + } + + public int repeatCount() { + return (int) wRepeatCount$VH.get(seg); + } + + public short keyCode() { + return (short) wVirtualKeyCode$VH.get(seg); + } + + public short scanCode() { + return (short) wVirtualScanCode$VH.get(seg); + } + + public char uchar() { + return (char) UnicodeChar$VH.get(seg); + } + + public int controlKeyState() { + return (int) dwControlKeyState$VH.get(seg); + } + + public String toString() { + return "KEY_EVENT_RECORD{keyDown=" + this.keyDown() + ", repeatCount=" + this.repeatCount() + ", keyCode=" + + this.keyCode() + ", scanCode=" + this.scanCode() + ", uchar=" + this.uchar() + + ", controlKeyState=" + + this.controlKeyState() + '}'; + } + } + + public static final class CHAR_INFO { + + static final java.lang.foreign.GroupLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout( + java.lang.foreign.MemoryLayout.unionLayout( + C_WCHAR$LAYOUT.withName("UnicodeChar"), C_CHAR$LAYOUT.withName("AsciiChar")) + .withName("Char"), + C_WORD$LAYOUT.withName("Attributes")); + static final VarHandle UnicodeChar$VH = varHandle(LAYOUT, "Char", "UnicodeChar"); + static final VarHandle Attributes$VH = varHandle(LAYOUT, "Attributes"); + + final java.lang.foreign.MemorySegment seg; + + public CHAR_INFO() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public CHAR_INFO(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public CHAR_INFO(java.lang.foreign.Arena arena, char c, short a) { + this(arena); + UnicodeChar$VH.set(seg, c); + Attributes$VH.set(seg, a); + } + + public CHAR_INFO(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public char unicodeChar() { + return (char) UnicodeChar$VH.get(seg); + } + } + + public static final class CONSOLE_SCREEN_BUFFER_INFO { + static final java.lang.foreign.GroupLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout( + COORD.LAYOUT.withName("dwSize"), + COORD.LAYOUT.withName("dwCursorPosition"), + C_WORD$LAYOUT.withName("wAttributes"), + SMALL_RECT.LAYOUT.withName("srWindow"), + COORD.LAYOUT.withName("dwMaximumWindowSize")); + static final long dwSize$OFFSET = byteOffset(LAYOUT, "dwSize"); + static final long dwCursorPosition$OFFSET = byteOffset(LAYOUT, "dwCursorPosition"); + static final VarHandle wAttributes$VH = varHandle(LAYOUT, "wAttributes"); + static final long srWindow$OFFSET = byteOffset(LAYOUT, "srWindow"); + + private final java.lang.foreign.MemorySegment seg; + + public CONSOLE_SCREEN_BUFFER_INFO() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public CONSOLE_SCREEN_BUFFER_INFO(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public CONSOLE_SCREEN_BUFFER_INFO(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public COORD size() { + return new COORD(seg, dwSize$OFFSET); + } + + public COORD cursorPosition() { + return new COORD(seg, dwCursorPosition$OFFSET); + } + + public short attributes() { + return (short) wAttributes$VH.get(seg); + } + + public SMALL_RECT window() { + return new SMALL_RECT(seg, srWindow$OFFSET); + } + + public int windowWidth() { + return this.window().width() + 1; + } + + public int windowHeight() { + return this.window().height() + 1; + } + + public void attributes(short attr) { + wAttributes$VH.set(seg, attr); + } + } + + public static final class COORD { + + static final java.lang.foreign.GroupLayout LAYOUT = + java.lang.foreign.MemoryLayout.structLayout(C_SHORT$LAYOUT.withName("x"), C_SHORT$LAYOUT.withName("y")); + static final VarHandle x$VH = varHandle(LAYOUT, "x"); + static final VarHandle y$VH = varHandle(LAYOUT, "y"); + + private final java.lang.foreign.MemorySegment seg; + + public COORD() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public COORD(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public COORD(java.lang.foreign.Arena arena, short x, short y) { + this(arena.allocate(LAYOUT)); + x(x); + y(y); + } + + public COORD(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public COORD(java.lang.foreign.MemorySegment seg, long offset) { + this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize()); + } + + public short x() { + return (short) COORD.x$VH.get(seg); + } + + public void x(short x) { + COORD.x$VH.set(seg, x); + } + + public short y() { + return (short) COORD.y$VH.get(seg); + } + + public void y(short y) { + COORD.y$VH.set(seg, y); + } + + public COORD copy(java.lang.foreign.Arena arena) { + return new COORD(arena.allocate(LAYOUT).copyFrom(seg)); + } + } + + public static final class SMALL_RECT { + + static final java.lang.foreign.GroupLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout( + C_SHORT$LAYOUT.withName("Left"), + C_SHORT$LAYOUT.withName("Top"), + C_SHORT$LAYOUT.withName("Right"), + C_SHORT$LAYOUT.withName("Bottom")); + static final VarHandle Left$VH = varHandle(LAYOUT, "Left"); + static final VarHandle Top$VH = varHandle(LAYOUT, "Top"); + static final VarHandle Right$VH = varHandle(LAYOUT, "Right"); + static final VarHandle Bottom$VH = varHandle(LAYOUT, "Bottom"); + + private final java.lang.foreign.MemorySegment seg; + + public SMALL_RECT() { + this(java.lang.foreign.Arena.ofAuto()); + } + + public SMALL_RECT(java.lang.foreign.Arena arena) { + this(arena.allocate(LAYOUT)); + } + + public SMALL_RECT(java.lang.foreign.Arena arena, SMALL_RECT rect) { + this(arena); + left(rect.left()); + right(rect.right()); + top(rect.top()); + bottom(rect.bottom()); + } + + public SMALL_RECT(java.lang.foreign.MemorySegment seg, long offset) { + this(seg.asSlice(offset, LAYOUT.byteSize())); + } + + public SMALL_RECT(java.lang.foreign.MemorySegment seg) { + this.seg = seg; + } + + public short left() { + return (short) Left$VH.get(seg); + } + + public short top() { + return (short) Top$VH.get(seg); + } + + public short right() { + return (short) Right$VH.get(seg); + } + + public short bottom() { + return (short) Bottom$VH.get(seg); + } + + public short width() { + return (short) (this.right() - this.left()); + } + + public short height() { + return (short) (this.bottom() - this.top()); + } + + public void left(short l) { + Left$VH.set(seg, l); + } + + public void top(short t) { + Top$VH.set(seg, t); + } + + public void right(short r) { + Right$VH.set(seg, r); + } + + public void bottom(short b) { + Bottom$VH.set(seg, b); + } + + public SMALL_RECT copy(java.lang.foreign.Arena arena) { + return new SMALL_RECT(arena.allocate(LAYOUT).copyFrom(seg)); + } + } + + static T requireNonNull(T obj, String symbolName) { + if (obj == null) { + throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); + } + return obj; + } + + static VarHandle varHandle(java.lang.foreign.MemoryLayout layout, String name) { + return FfmTerminalProvider.lookupVarHandle( + layout, java.lang.foreign.MemoryLayout.PathElement.groupElement(name)); + } + + static VarHandle varHandle(java.lang.foreign.MemoryLayout layout, String e1, String name) { + return FfmTerminalProvider.lookupVarHandle( + layout, + java.lang.foreign.MemoryLayout.PathElement.groupElement(e1), + java.lang.foreign.MemoryLayout.PathElement.groupElement(name)); + } + + static long byteOffset(java.lang.foreign.MemoryLayout layout, String name) { + return layout.byteOffset(java.lang.foreign.MemoryLayout.PathElement.groupElement(name)); + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinConsoleWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinConsoleWriter.java new file mode 100644 index 0000000000000..55a2ec650552a --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinConsoleWriter.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.ffm; + +import java.io.IOException; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; + +import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter; + +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetStdHandle; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_OUTPUT_HANDLE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.WriteConsoleW; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.getLastErrorMessage; + +class NativeWinConsoleWriter extends AbstractWindowsConsoleWriter { + + private final java.lang.foreign.MemorySegment console = GetStdHandle(STD_OUTPUT_HANDLE); + + @Override + protected void writeConsole(char[] text, int len) throws IOException { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + java.lang.foreign.MemorySegment txt = arena.allocateFrom(ValueLayout.JAVA_CHAR, text); + if (WriteConsoleW(console, txt, len, MemorySegment.NULL, MemorySegment.NULL) == 0) { + throw new IOException("Failed to write to console: " + getLastErrorMessage()); + } + } + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinSysTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinSysTerminal.java new file mode 100644 index 0000000000000..189fc2808d904 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/NativeWinSysTerminal.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2022-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.ffm; + +import java.io.BufferedWriter; +import java.io.IOError; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.function.Function; +import java.util.function.IntConsumer; + +import jdk.internal.org.jline.terminal.Cursor; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.utils.OSUtils; + +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.*; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetConsoleMode; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetConsoleScreenBufferInfo; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetStdHandle; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.INPUT_RECORD; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.INVALID_HANDLE_VALUE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.KEY_EVENT_RECORD; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.MOUSE_EVENT_RECORD; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_ERROR_HANDLE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_INPUT_HANDLE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_OUTPUT_HANDLE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleMode; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.WaitForSingleObject; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.getLastErrorMessage; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.readConsoleInputHelper; + +public class NativeWinSysTerminal extends AbstractWindowsTerminal { + + public static NativeWinSysTerminal createTerminal( + TerminalProvider provider, + SystemStream systemStream, + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + SignalHandler signalHandler, + boolean paused, + Function inputStreamWrapper) + throws IOException { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + // Get input console mode + java.lang.foreign.MemorySegment consoleIn = GetStdHandle(STD_INPUT_HANDLE); + java.lang.foreign.MemorySegment inMode = allocateInt(arena); + if (GetConsoleMode(consoleIn, inMode) == 0) { + throw new IOException("Failed to get console mode: " + getLastErrorMessage()); + } + // Get output console and mode + java.lang.foreign.MemorySegment console; + switch (systemStream) { + case Output: + console = GetStdHandle(STD_OUTPUT_HANDLE); + break; + case Error: + console = GetStdHandle(STD_ERROR_HANDLE); + break; + default: + throw new IllegalArgumentException("Unsupported stream for console: " + systemStream); + } + java.lang.foreign.MemorySegment outMode = allocateInt(arena); + if (GetConsoleMode(console, outMode) == 0) { + throw new IOException("Failed to get console mode: " + getLastErrorMessage()); + } + // Create writer + Writer writer; + if (ansiPassThrough) { + type = type != null ? type : OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS; + writer = new NativeWinConsoleWriter(); + } else { + int m = inMode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0); + if (enableVtp(console, m)) { + type = type != null ? type : TYPE_WINDOWS_VTP; + writer = new NativeWinConsoleWriter(); + } else if (OSUtils.IS_CONEMU) { + type = type != null ? type : TYPE_WINDOWS_CONEMU; + writer = new NativeWinConsoleWriter(); + } else { + type = type != null ? type : TYPE_WINDOWS; + writer = new WindowsAnsiWriter(new BufferedWriter(new NativeWinConsoleWriter())); + } + } + // Create terminal + NativeWinSysTerminal terminal = new NativeWinSysTerminal( + provider, + systemStream, + writer, + name, + type, + encoding, + nativeSignals, + signalHandler, + consoleIn, + inMode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0), + console, + outMode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0), + inputStreamWrapper); + // Start input pump thread + if (!paused) { + terminal.resume(); + } + return terminal; + } + } + + private static boolean enableVtp(java.lang.foreign.MemorySegment console, int m) { + return SetConsoleMode(console, m | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0; + } + + public static boolean isWindowsSystemStream(SystemStream stream) { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + java.lang.foreign.MemorySegment console; + java.lang.foreign.MemorySegment mode = allocateInt(arena); + switch (stream) { + case Input: + console = GetStdHandle(STD_INPUT_HANDLE); + break; + case Output: + console = GetStdHandle(STD_OUTPUT_HANDLE); + break; + case Error: + console = GetStdHandle(STD_ERROR_HANDLE); + break; + default: + return false; + } + return GetConsoleMode(console, mode) != 0; + } + } + + private static java.lang.foreign.MemorySegment allocateInt(java.lang.foreign.Arena arena) { + return arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT); + } + + NativeWinSysTerminal( + TerminalProvider provider, + SystemStream systemStream, + Writer writer, + String name, + String type, + Charset encoding, + boolean nativeSignals, + SignalHandler signalHandler, + java.lang.foreign.MemorySegment inConsole, + int inConsoleMode, + java.lang.foreign.MemorySegment outConsole, + int outConsoleMode, + Function inputStreamWrapper) + throws IOException { + super( + provider, + systemStream, + writer, + name, + type, + encoding, + nativeSignals, + signalHandler, + inConsole, + inConsoleMode, + outConsole, + outConsoleMode, + inputStreamWrapper); + } + + @Override + protected int getConsoleMode(java.lang.foreign.MemorySegment console) { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + java.lang.foreign.MemorySegment mode = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT); + if (GetConsoleMode(console, mode) == 0) { + return -1; + } + return mode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0); + } + } + + @Override + protected void setConsoleMode(java.lang.foreign.MemorySegment console, int mode) { + SetConsoleMode(console, mode); + } + + public Size getSize() { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(arena); + GetConsoleScreenBufferInfo(outConsole, info); + return new Size(info.windowWidth(), info.windowHeight()); + } + } + + @Override + public Size getBufferSize() { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(arena); + GetConsoleScreenBufferInfo(outConsole, info); + return new Size(info.size().x(), info.size().y()); + } + } + + protected boolean processConsoleInput() throws IOException { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + INPUT_RECORD[] events; + if (inConsole != null + && inConsole.address() != INVALID_HANDLE_VALUE + && WaitForSingleObject(inConsole, 100) == 0) { + events = readConsoleInputHelper(arena, inConsole, 1, false); + } else { + return false; + } + + boolean flush = false; + for (INPUT_RECORD event : events) { + int eventType = event.eventType(); + if (eventType == KEY_EVENT) { + KEY_EVENT_RECORD keyEvent = event.keyEvent(); + processKeyEvent( + keyEvent.keyDown(), keyEvent.keyCode(), keyEvent.uchar(), keyEvent.controlKeyState()); + flush = true; + } else if (eventType == WINDOW_BUFFER_SIZE_EVENT) { + raise(Signal.WINCH); + } else if (eventType == MOUSE_EVENT) { + processMouseEvent(event.mouseEvent()); + flush = true; + } else if (eventType == FOCUS_EVENT) { + processFocusEvent(event.focusEvent().setFocus()); + } + } + + return flush; + } + } + + private final char[] focus = new char[] {'\033', '[', ' '}; + + private void processFocusEvent(boolean hasFocus) throws IOException { + if (focusTracking) { + focus[2] = hasFocus ? 'I' : 'O'; + slaveInputPipe.write(focus); + } + } + + private final char[] mouse = new char[] {'\033', '[', 'M', ' ', ' ', ' '}; + + private void processMouseEvent(MOUSE_EVENT_RECORD mouseEvent) throws IOException { + int dwEventFlags = mouseEvent.eventFlags(); + int dwButtonState = mouseEvent.buttonState(); + if (tracking == MouseTracking.Off + || tracking == MouseTracking.Normal && dwEventFlags == MOUSE_MOVED + || tracking == MouseTracking.Button && dwEventFlags == MOUSE_MOVED && dwButtonState == 0) { + return; + } + int cb = 0; + dwEventFlags &= ~DOUBLE_CLICK; // Treat double-clicks as normal + if (dwEventFlags == MOUSE_WHEELED) { + cb |= 64; + if ((dwButtonState >> 16) < 0) { + cb |= 1; + } + } else if (dwEventFlags == MOUSE_HWHEELED) { + return; + } else if ((dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0) { + cb |= 0x00; + } else if ((dwButtonState & RIGHTMOST_BUTTON_PRESSED) != 0) { + cb |= 0x01; + } else if ((dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) != 0) { + cb |= 0x02; + } else { + cb |= 0x03; + } + int cx = mouseEvent.mousePosition().x(); + int cy = mouseEvent.mousePosition().y(); + mouse[3] = (char) (' ' + cb); + mouse[4] = (char) (' ' + cx + 1); + mouse[5] = (char) (' ' + cy + 1); + slaveInputPipe.write(mouse); + } + + @Override + public Cursor getCursorPosition(IntConsumer discarded) { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(arena); + if (GetConsoleScreenBufferInfo(outConsole, info) == 0) { + throw new IOError(new IOException("Could not get the cursor position: " + getLastErrorMessage())); + } + return new Cursor(info.cursorPosition().x(), info.cursorPosition().y()); + } + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/WindowsAnsiWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/WindowsAnsiWriter.java new file mode 100644 index 0000000000000..6330e975952ce --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ffm/WindowsAnsiWriter.java @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2022-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl.ffm; + +import java.io.IOException; +import java.io.Writer; + +import jdk.internal.org.jline.utils.AnsiWriter; +import jdk.internal.org.jline.utils.Colors; + +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_BLUE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_GREEN; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_INTENSITY; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_RED; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.CHAR_INFO; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.CONSOLE_SCREEN_BUFFER_INFO; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.COORD; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_BLUE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_GREEN; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_INTENSITY; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_RED; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FillConsoleOutputAttribute; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FillConsoleOutputCharacterW; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetConsoleScreenBufferInfo; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetStdHandle; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SMALL_RECT; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_OUTPUT_HANDLE; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.ScrollConsoleScreenBuffer; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleCursorPosition; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleTextAttribute; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleTitleW; +import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.getLastErrorMessage; + +class WindowsAnsiWriter extends AnsiWriter { + + private static final java.lang.foreign.MemorySegment console = GetStdHandle(STD_OUTPUT_HANDLE); + + private static final short FOREGROUND_BLACK = 0; + private static final short FOREGROUND_YELLOW = (short) (FOREGROUND_RED | FOREGROUND_GREEN); + private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE | FOREGROUND_RED); + private static final short FOREGROUND_CYAN = (short) (FOREGROUND_BLUE | FOREGROUND_GREEN); + private static final short FOREGROUND_WHITE = (short) (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + + private static final short BACKGROUND_BLACK = 0; + private static final short BACKGROUND_YELLOW = (short) (BACKGROUND_RED | BACKGROUND_GREEN); + private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE | BACKGROUND_RED); + private static final short BACKGROUND_CYAN = (short) (BACKGROUND_BLUE | BACKGROUND_GREEN); + private static final short BACKGROUND_WHITE = (short) (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); + + private static final short[] ANSI_FOREGROUND_COLOR_MAP = { + FOREGROUND_BLACK, + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_YELLOW, + FOREGROUND_BLUE, + FOREGROUND_MAGENTA, + FOREGROUND_CYAN, + FOREGROUND_WHITE, + }; + + private static final short[] ANSI_BACKGROUND_COLOR_MAP = { + BACKGROUND_BLACK, + BACKGROUND_RED, + BACKGROUND_GREEN, + BACKGROUND_YELLOW, + BACKGROUND_BLUE, + BACKGROUND_MAGENTA, + BACKGROUND_CYAN, + BACKGROUND_WHITE, + }; + + private final CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(java.lang.foreign.Arena.ofAuto()); + private final short originalColors; + + private boolean negative; + private boolean bold; + private boolean underline; + private short savedX = -1; + private short savedY = -1; + + public WindowsAnsiWriter(Writer out) throws IOException { + super(out); + getConsoleInfo(); + originalColors = info.attributes(); + } + + private void getConsoleInfo() throws IOException { + out.flush(); + if (GetConsoleScreenBufferInfo(console, info) == 0) { + throw new IOException("Could not get the screen info: " + getLastErrorMessage()); + } + if (negative) { + info.attributes(invertAttributeColors(info.attributes())); + } + } + + private void applyAttribute() throws IOException { + out.flush(); + short attributes = info.attributes(); + // bold is simulated by high foreground intensity + if (bold) { + attributes |= FOREGROUND_INTENSITY; + } + // underline is simulated by high foreground intensity + if (underline) { + attributes |= BACKGROUND_INTENSITY; + } + if (negative) { + attributes = invertAttributeColors(attributes); + } + if (SetConsoleTextAttribute(console, attributes) == 0) { + throw new IOException(getLastErrorMessage()); + } + } + + private short invertAttributeColors(short attributes) { + // Swap the the Foreground and Background bits. + int fg = 0x000F & attributes; + fg <<= 4; + int bg = 0X00F0 & attributes; + bg >>= 4; + attributes = (short) ((attributes & 0xFF00) | fg | bg); + return attributes; + } + + private void applyCursorPosition() throws IOException { + info.cursorPosition().x((short) + Math.max(0, Math.min(info.size().x() - 1, info.cursorPosition().x()))); + info.cursorPosition().y((short) + Math.max(0, Math.min(info.size().y() - 1, info.cursorPosition().y()))); + if (SetConsoleCursorPosition(console, info.cursorPosition()) == 0) { + throw new IOException(getLastErrorMessage()); + } + } + + @Override + protected void processEraseScreen(int eraseOption) throws IOException { + getConsoleInfo(); + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + java.lang.foreign.MemorySegment written = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT); + switch (eraseOption) { + case ERASE_SCREEN -> { + COORD topLeft = new COORD(arena, (short) 0, info.window().top()); + int screenLength = info.window().height() * info.size().x(); + FillConsoleOutputAttribute(console, originalColors, screenLength, topLeft, written); + FillConsoleOutputCharacterW(console, ' ', screenLength, topLeft, written); + } + case ERASE_SCREEN_TO_BEGINING -> { + COORD topLeft2 = new COORD(arena, (short) 0, info.window().top()); + int lengthToCursor = + (info.cursorPosition().y() - info.window().top()) + * info.size().x() + + info.cursorPosition().x(); + FillConsoleOutputAttribute(console, originalColors, lengthToCursor, topLeft2, written); + FillConsoleOutputCharacterW(console, ' ', lengthToCursor, topLeft2, written); + } + case ERASE_SCREEN_TO_END -> { + int lengthToEnd = + (info.window().bottom() - info.cursorPosition().y()) + * info.size().x() + + (info.size().x() - info.cursorPosition().x()); + FillConsoleOutputAttribute(console, originalColors, lengthToEnd, info.cursorPosition(), written); + FillConsoleOutputCharacterW(console, ' ', lengthToEnd, info.cursorPosition(), written); + } + default -> {} + } + } + } + + @Override + protected void processEraseLine(int eraseOption) throws IOException { + getConsoleInfo(); + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + java.lang.foreign.MemorySegment written = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT); + switch (eraseOption) { + case ERASE_LINE -> { + COORD leftColCurrRow = + new COORD(arena, (short) 0, info.cursorPosition().y()); + FillConsoleOutputAttribute( + console, originalColors, info.size().x(), leftColCurrRow, written); + FillConsoleOutputCharacterW(console, ' ', info.size().x(), leftColCurrRow, written); + } + case ERASE_LINE_TO_BEGINING -> { + COORD leftColCurrRow2 = + new COORD(arena, (short) 0, info.cursorPosition().y()); + FillConsoleOutputAttribute( + console, originalColors, info.cursorPosition().x(), leftColCurrRow2, written); + FillConsoleOutputCharacterW( + console, ' ', info.cursorPosition().x(), leftColCurrRow2, written); + } + case ERASE_LINE_TO_END -> { + int lengthToLastCol = + info.size().x() - info.cursorPosition().x(); + FillConsoleOutputAttribute( + console, originalColors, lengthToLastCol, info.cursorPosition(), written); + FillConsoleOutputCharacterW(console, ' ', lengthToLastCol, info.cursorPosition(), written); + } + default -> {} + } + } + } + + protected void processCursorUpLine(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition().x((short) 0); + info.cursorPosition().y((short) (info.cursorPosition().y() - count)); + applyCursorPosition(); + } + + protected void processCursorDownLine(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition().x((short) 0); + info.cursorPosition().y((short) (info.cursorPosition().y() + count)); + applyCursorPosition(); + } + + @Override + protected void processCursorLeft(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition().x((short) (info.cursorPosition().x() - count)); + applyCursorPosition(); + } + + @Override + protected void processCursorRight(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition().x((short) (info.cursorPosition().x() + count)); + applyCursorPosition(); + } + + @Override + protected void processCursorDown(int count) throws IOException { + getConsoleInfo(); + int nb = Math.max(0, info.cursorPosition().y() + count - info.size().y() + 1); + if (nb != count) { + info.cursorPosition().y((short) (info.cursorPosition().y() + count)); + applyCursorPosition(); + } + if (nb > 0) { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + SMALL_RECT scroll = new SMALL_RECT(arena, info.window()); + scroll.top((short) 0); + COORD org = new COORD(arena); + org.x((short) 0); + org.y((short) (-nb)); + CHAR_INFO info = new CHAR_INFO(arena, ' ', originalColors); + ScrollConsoleScreenBuffer(console, scroll, scroll, org, info); + } + } + } + + @Override + protected void processCursorUp(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition().y((short) (info.cursorPosition().y() - count)); + applyCursorPosition(); + } + + @Override + protected void processCursorTo(int row, int col) throws IOException { + getConsoleInfo(); + info.cursorPosition().y((short) (info.window().top() + row - 1)); + info.cursorPosition().x((short) (col - 1)); + applyCursorPosition(); + } + + @Override + protected void processCursorToColumn(int x) throws IOException { + getConsoleInfo(); + info.cursorPosition().x((short) (x - 1)); + applyCursorPosition(); + } + + @Override + protected void processSetForegroundColorExt(int paletteIndex) throws IOException { + int color = Colors.roundColor(paletteIndex, 16); + info.attributes((short) ((info.attributes() & ~0x0007) | ANSI_FOREGROUND_COLOR_MAP[color & 0x07])); + info.attributes( + (short) ((info.attributes() & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0))); + applyAttribute(); + } + + @Override + protected void processSetBackgroundColorExt(int paletteIndex) throws IOException { + int color = Colors.roundColor(paletteIndex, 16); + info.attributes((short) ((info.attributes() & ~0x0070) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07])); + info.attributes( + (short) ((info.attributes() & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0))); + applyAttribute(); + } + + @Override + protected void processDefaultTextColor() throws IOException { + info.attributes((short) ((info.attributes() & ~0x000F) | (originalColors & 0xF))); + info.attributes((short) (info.attributes() & ~FOREGROUND_INTENSITY)); + applyAttribute(); + } + + @Override + protected void processDefaultBackgroundColor() throws IOException { + info.attributes((short) ((info.attributes() & ~0x00F0) | (originalColors & 0xF0))); + info.attributes((short) (info.attributes() & ~BACKGROUND_INTENSITY)); + applyAttribute(); + } + + @Override + protected void processAttributeRest() throws IOException { + info.attributes((short) ((info.attributes() & ~0x00FF) | originalColors)); + this.negative = false; + this.bold = false; + this.underline = false; + applyAttribute(); + } + + @Override + protected void processSetAttribute(int attribute) throws IOException { + switch (attribute) { + case ATTRIBUTE_INTENSITY_BOLD -> { + bold = true; + applyAttribute(); + } + case ATTRIBUTE_INTENSITY_NORMAL -> { + bold = false; + applyAttribute(); + } + case ATTRIBUTE_UNDERLINE -> { + underline = true; + applyAttribute(); + } + case ATTRIBUTE_UNDERLINE_OFF -> { + underline = false; + applyAttribute(); + } + case ATTRIBUTE_NEGATIVE_ON -> { + negative = true; + applyAttribute(); + } + case ATTRIBUTE_NEGATIVE_OFF -> { + negative = false; + applyAttribute(); + } + default -> {} + } + } + + @Override + protected void processSaveCursorPosition() throws IOException { + getConsoleInfo(); + savedX = info.cursorPosition().x(); + savedY = info.cursorPosition().y(); + } + + @Override + protected void processRestoreCursorPosition() throws IOException { + // restore only if there was a save operation first + if (savedX != -1 && savedY != -1) { + out.flush(); + info.cursorPosition().x(savedX); + info.cursorPosition().y(savedY); + applyCursorPosition(); + } + } + + @Override + protected void processInsertLine(int optionInt) throws IOException { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + getConsoleInfo(); + SMALL_RECT scroll = info.window().copy(arena); + scroll.top(info.cursorPosition().y()); + COORD org = + new COORD(arena, (short) 0, (short) (info.cursorPosition().y() + optionInt)); + CHAR_INFO info = new CHAR_INFO(arena, ' ', originalColors); + if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) { + throw new IOException(getLastErrorMessage()); + } + } + } + + @Override + protected void processDeleteLine(int optionInt) throws IOException { + try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) { + getConsoleInfo(); + SMALL_RECT scroll = info.window().copy(arena); + scroll.top(info.cursorPosition().y()); + COORD org = + new COORD(arena, (short) 0, (short) (info.cursorPosition().y() - optionInt)); + CHAR_INFO info = new CHAR_INFO(arena, ' ', originalColors); + if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) { + throw new IOException(getLastErrorMessage()); + } + } + } + + @Override + protected void processChangeWindowTitle(String title) { + try (java.lang.foreign.Arena session = java.lang.foreign.Arena.ofConfined()) { + java.lang.foreign.MemorySegment str = session.allocateFrom(title); + SetConsoleTitleW(str); + } + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/jna/LastErrorException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/jna/LastErrorException.java deleted file mode 100644 index 63795664dfc62..0000000000000 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/jna/LastErrorException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018, 2023, 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. - */ -package jdk.internal.org.jline.terminal.impl.jna; - -@SuppressWarnings("serial") -public class LastErrorException extends RuntimeException{ - - public final long lastError; - - public LastErrorException(long lastError) { - this.lastError = lastError; - } - -} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java index b1e22056702ca..d72e0e669d102 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -34,4 +34,7 @@ public interface Pty extends Closeable { void setSize(Size size) throws IOException; + SystemStream getSystemStream(); + + TerminalProvider getProvider(); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java new file mode 100644 index 0000000000000..5f95024829556 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.spi; + +public enum SystemStream { + Input, + Output, + Error +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java new file mode 100644 index 0000000000000..00cfb2e9d475e --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.spi; + +import jdk.internal.org.jline.terminal.Terminal; + +/** + * The {@code TerminalExt} interface is implemented by {@code Terminal}s + * and provides access to the Terminal's internals. + */ +public interface TerminalExt extends Terminal { + + /** + * Returns the {@code TerminalProvider} that created this terminal + * or {@code null} if the terminal was created with no provider. + */ + TerminalProvider getProvider(); + + /** + * The underlying system stream, may be {@link SystemStream#Output}, + * {@link SystemStream#Error}, or {@code null} if this terminal is not bound + * to a system stream. + */ + SystemStream getSystemStream(); +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java index 69f353c571905..055bf224fc516 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, the original author or authors. + * Copyright (c) 2022, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -11,58 +11,60 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.URL; import java.nio.charset.Charset; import java.util.Properties; -import java.util.ServiceLoader; import java.util.function.Function; import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.Terminal; import jdk.internal.org.jline.terminal.impl.exec.ExecTerminalProvider; +import jdk.internal.org.jline.terminal.impl.ffm.FfmTerminalProvider; -public interface TerminalProvider -{ - - enum Stream { - Input, - Output, - Error - } +public interface TerminalProvider { String name(); - Terminal sysTerminal(String name, String type, boolean ansiPassThrough, - Charset encoding, boolean nativeSignals, - Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper) throws IOException; + Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException; + + Terminal newTerminal( + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException; - Terminal newTerminal(String name, String type, - InputStream masterInput, OutputStream masterOutput, - Charset encoding, Terminal.SignalHandler signalHandler, - boolean paused, Attributes attributes, Size size) throws IOException; + boolean isSystemStream(SystemStream stream); - boolean isSystemStream(Stream stream); + String systemStreamName(SystemStream stream); - String systemStreamName(Stream stream); + int systemStreamWidth(SystemStream stream); static TerminalProvider load(String name) throws IOException { switch (name) { case "exec": return new ExecTerminalProvider(); - case "jna": { - try { - return (TerminalProvider) Class.forName("jdk.internal.org.jline.terminal.impl.jna.JnaTerminalProvider").getConstructor().newInstance(); - } catch (ReflectiveOperationException t) { - throw new IOException(t); - } - } + case "ffm": return new FfmTerminalProvider(); } ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { cl = ClassLoader.getSystemClassLoader(); } - InputStream is = cl.getResourceAsStream( "META-INF/services/org/jline/terminal/provider/" + name); + InputStream is = cl.getResourceAsStream("META-INF/services/org/jline/terminal/provider/" + name); if (is != null) { Properties props = new Properties(); try { @@ -71,14 +73,13 @@ static TerminalProvider load(String name) throws IOException { if (className == null) { throw new IOException("No class defined in terminal provider file " + name); } - Class clazz = cl.loadClass( className ); + Class clazz = cl.loadClass(className); return (TerminalProvider) clazz.getConstructor().newInstance(); - } catch ( Exception e ) { - throw new IOException("Unable to load terminal provider " + name, e); + } catch (Exception e) { + throw new IOException("Unable to load terminal provider " + name + ": " + e.getMessage(), e); } } else { throw new IOException("Unable to find terminal provider " + name); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java index 081665a2d4693..32d8282d4c0b7 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java @@ -1,17 +1,10 @@ /* - * Copyright (C) 2009-2018 the original author(s). + * Copyright (c) 2009-2018, the original author(s). * - * Licensed 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 + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. * - * 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. + * https://opensource.org/licenses/BSD-3-Clause */ package jdk.internal.org.jline.utils; @@ -252,12 +245,10 @@ private void reset(boolean skipBuffer) throws IOException { * @throws IOException if no more non-null values left */ private int getNextOptionInt(Iterator optionsIterator) throws IOException { - for (;;) { - if (!optionsIterator.hasNext()) - throw new IllegalArgumentException(); + for (; ; ) { + if (!optionsIterator.hasNext()) throw new IllegalArgumentException(); Object arg = optionsIterator.next(); - if (arg != null) - return (Integer) arg; + if (arg != null) return (Integer) arg; } } @@ -346,27 +337,21 @@ private boolean processEscapeCommand(ArrayList options, int command) thr int g = getNextOptionInt(optionsIterator); int b = getNextOptionInt(optionsIterator); if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) { - if (value == 38) - processSetForegroundColorExt(r, g, b); - else - processSetBackgroundColorExt(r, g, b); + if (value == 38) processSetForegroundColorExt(r, g, b); + else processSetBackgroundColorExt(r, g, b); } else { throw new IllegalArgumentException(); } - } - else if (arg2or5 == 5) { + } else if (arg2or5 == 5) { // 256 color style like `esc[38;5;m` int paletteIndex = getNextOptionInt(optionsIterator); if (paletteIndex >= 0 && paletteIndex <= 255) { - if (value == 38) - processSetForegroundColorExt(paletteIndex); - else - processSetBackgroundColorExt(paletteIndex); + if (value == 38) processSetForegroundColorExt(paletteIndex); + else processSetBackgroundColorExt(paletteIndex); } else { throw new IllegalArgumentException(); } - } - else { + } else { throw new IllegalArgumentException(); } } else { @@ -449,47 +434,41 @@ private boolean processOperatingSystemCommand(ArrayList options) throws * Process CSI u ANSI code, corresponding to RCP \u2013 Restore Cursor Position * @throws IOException if an error occurs */ - protected void processRestoreCursorPosition() throws IOException { - } + protected void processRestoreCursorPosition() throws IOException {} /** * Process CSI s ANSI code, corresponding to SCP \u2013 Save Cursor Position * @throws IOException if an error occurs */ - protected void processSaveCursorPosition() throws IOException { - } + protected void processSaveCursorPosition() throws IOException {} /** * Process CSI s ANSI code, corresponding to IL \u2013 Insert Line * @param optionInt the option * @throws IOException if an error occurs */ - protected void processInsertLine(int optionInt) throws IOException { - } + protected void processInsertLine(int optionInt) throws IOException {} /** * Process CSI s ANSI code, corresponding to DL \u2013 Delete Line * @param optionInt the option * @throws IOException if an error occurs */ - protected void processDeleteLine(int optionInt) throws IOException { - } + protected void processDeleteLine(int optionInt) throws IOException {} /** * Process CSI n T ANSI code, corresponding to SD \u2013 Scroll Down * @param optionInt the option * @throws IOException if an error occurs */ - protected void processScrollDown(int optionInt) throws IOException { - } + protected void processScrollDown(int optionInt) throws IOException {} /** * Process CSI n U ANSI code, corresponding to SU \u2013 Scroll Up * @param optionInt the option * @throws IOException if an error occurs */ - protected void processScrollUp(int optionInt) throws IOException { - } + protected void processScrollUp(int optionInt) throws IOException {} protected static final int ERASE_SCREEN_TO_END = 0; protected static final int ERASE_SCREEN_TO_BEGINING = 1; @@ -500,8 +479,7 @@ protected void processScrollUp(int optionInt) throws IOException { * @param eraseOption the erase option * @throws IOException if an error occurs */ - protected void processEraseScreen(int eraseOption) throws IOException { - } + protected void processEraseScreen(int eraseOption) throws IOException {} protected static final int ERASE_LINE_TO_END = 0; protected static final int ERASE_LINE_TO_BEGINING = 1; @@ -512,25 +490,27 @@ protected void processEraseScreen(int eraseOption) throws IOException { * @param eraseOption the erase option * @throws IOException if an error occurs */ - protected void processEraseLine(int eraseOption) throws IOException { - } + protected void processEraseLine(int eraseOption) throws IOException {} + + protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold + protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported + protected static final int ATTRIBUTE_ITALIC = 3; // Italic; on not widely supported. Sometimes treated as inverse. + protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single + protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute + protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more + protected static final int ATTRIBUTE_NEGATIVE_ON = + 7; // Image; Negative inverse or reverse; swap foreground and background + protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on + protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported + protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint + protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None + protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off - protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold - protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported - protected static final int ATTRIBUTE_ITALIC = 3; // Italic; on not widely supported. Sometimes treated as inverse. - protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single - protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute - protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more - protected static final int ATTRIBUTE_NEGATIVE_ON = 7; // Image; Negative inverse or reverse; swap foreground and background - protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on - protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported - protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint - protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None - protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off @Deprecated protected static final int ATTRIBUTE_NEGATIVE_Off = 27; // Image; Positive + protected static final int ATTRIBUTE_NEGATIVE_OFF = 27; // Image; Positive - protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off + protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off /** * process SGR other than 0 (reset), 30-39 (foreground), @@ -546,8 +526,7 @@ protected void processEraseLine(int eraseOption) throws IOException { * @see #processDefaultTextColor() * @see #processDefaultBackgroundColor() */ - protected void processSetAttribute(int attribute) throws IOException { - } + protected void processSetAttribute(int attribute) throws IOException {} protected static final int BLACK = 0; protected static final int RED = 1; @@ -584,8 +563,7 @@ protected void processSetForegroundColor(int color, boolean bright) throws IOExc * @param paletteIndex the text color in the palette * @throws IOException if an error occurs */ - protected void processSetForegroundColorExt(int paletteIndex) throws IOException { - } + protected void processSetForegroundColorExt(int paletteIndex) throws IOException {} /** * process SGR 38 corresponding to extended set text color (foreground) @@ -625,8 +603,7 @@ protected void processSetBackgroundColor(int color, boolean bright) throws IOExc * @param paletteIndex the background color in the palette * @throws IOException if an error occurs */ - protected void processSetBackgroundColorExt(int paletteIndex) throws IOException { - } + protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {} /** * process SGR 48 corresponding to extended set background color @@ -644,22 +621,19 @@ protected void processSetBackgroundColorExt(int r, int g, int b) throws IOExcept * process SGR 39 corresponding to Default text color (foreground) * @throws IOException if an error occurs */ - protected void processDefaultTextColor() throws IOException { - } + protected void processDefaultTextColor() throws IOException {} /** * process SGR 49 corresponding to Default background color * @throws IOException if an error occurs */ - protected void processDefaultBackgroundColor() throws IOException { - } + protected void processDefaultBackgroundColor() throws IOException {} /** * process SGR 0 corresponding to Reset / Normal * @throws IOException if an error occurs */ - protected void processAttributeRest() throws IOException { - } + protected void processAttributeRest() throws IOException {} /** * process CSI n ; m H corresponding to CUP \u2013 Cursor Position or @@ -668,24 +642,21 @@ protected void processAttributeRest() throws IOException { * @param col the column * @throws IOException if an error occurs */ - protected void processCursorTo(int row, int col) throws IOException { - } + protected void processCursorTo(int row, int col) throws IOException {} /** * process CSI n G corresponding to CHA \u2013 Cursor Horizontal Absolute * @param x the column * @throws IOException if an error occurs */ - protected void processCursorToColumn(int x) throws IOException { - } + protected void processCursorToColumn(int x) throws IOException {} /** * process CSI n F corresponding to CPL \u2013 Cursor Previous Line * @param count line count * @throws IOException if an error occurs */ - protected void processCursorUpLine(int count) throws IOException { - } + protected void processCursorUpLine(int count) throws IOException {} /** * process CSI n E corresponding to CNL \u2013 Cursor Next Line @@ -704,8 +675,7 @@ protected void processCursorDownLine(int count) throws IOException { * @param count the count * @throws IOException if an error occurs */ - protected void processCursorLeft(int count) throws IOException { - } + protected void processCursorLeft(int count) throws IOException {} /** * process CSI n C corresponding to CUF \u2013 Cursor Forward @@ -724,19 +694,16 @@ protected void processCursorRight(int count) throws IOException { * @param count the count * @throws IOException if an error occurs */ - protected void processCursorDown(int count) throws IOException { - } + protected void processCursorDown(int count) throws IOException {} /** * process CSI n A corresponding to CUU \u2013 Cursor Up * @param count the count * @throws IOException if an error occurs */ - protected void processCursorUp(int count) throws IOException { - } + protected void processCursorUp(int count) throws IOException {} - protected void processUnknownExtension(ArrayList options, int command) { - } + protected void processUnknownExtension(ArrayList options, int command) {} /** * process OSC 0;text BEL corresponding to Change Window and Icon label @@ -751,23 +718,20 @@ protected void processChangeIconNameAndWindowTitle(String label) { * process OSC 1;text BEL corresponding to Change Icon label * @param name the icon name */ - protected void processChangeIconName(String name) { - } + protected void processChangeIconName(String name) {} /** * process OSC 2;text BEL corresponding to Change Window title * @param title the title */ - protected void processChangeWindowTitle(String title) { - } + protected void processChangeWindowTitle(String title) {} /** * Process unknown OSC command. * @param command the command * @param param the param */ - protected void processUnknownOperatingSystemCommand(int command, String param) { - } + protected void processUnknownOperatingSystemCommand(int command, String param) {} /** * Process character set sequence. @@ -781,17 +745,13 @@ private boolean processCharsetSelect(ArrayList options) throws IOExcepti return true; } - protected void processCharsetSelect(int set, char seq) { - } + protected void processCharsetSelect(int set, char seq) {} private int optionInt(ArrayList options, int index) { - if (options.size() <= index) - throw new IllegalArgumentException(); + if (options.size() <= index) throw new IllegalArgumentException(); Object value = options.get(index); - if (value == null) - throw new IllegalArgumentException(); - if (!value.getClass().equals(Integer.class)) - throw new IllegalArgumentException(); + if (value == null) throw new IllegalArgumentException(); + if (!value.getClass().equals(Integer.class)) throw new IllegalArgumentException(); return (Integer) value; } @@ -828,5 +788,4 @@ public void close() throws IOException { flush(); super.close(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java index ccb0aaf689b86..6386f5bba3901 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,6 +15,7 @@ import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; import jdk.internal.org.jline.utils.InfoCmp.Capability; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR; import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR_EXP; import static jdk.internal.org.jline.utils.AttributedStyle.FG_COLOR; @@ -30,12 +31,11 @@ import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND; import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_IND; import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_RGB; +import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN; import static jdk.internal.org.jline.utils.AttributedStyle.F_INVERSE; import static jdk.internal.org.jline.utils.AttributedStyle.F_ITALIC; import static jdk.internal.org.jline.utils.AttributedStyle.F_UNDERLINE; -import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN; import static jdk.internal.org.jline.utils.AttributedStyle.MASK; -import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; public abstract class AttributedCharSequence implements CharSequence { @@ -120,6 +120,7 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a char c = charAt(i); if (altIn != null && altOut != null) { char pc = c; + // @spotless:off switch (c) { case '\u2518': c = 'j'; break; case '\u2510': c = 'k'; break; @@ -133,15 +134,16 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a case '\u252C': c = 'w'; break; case '\u2502': c = 'x'; break; } + // @spotless:on boolean oldalt = alt; alt = c != pc; if (oldalt ^ alt) { sb.append(alt ? altIn : altOut); } } - long s = styleCodeAt(i) & ~F_HIDDEN; // The hidden flag does not change the ansi styles + long s = styleCodeAt(i) & ~F_HIDDEN; // The hidden flag does not change the ansi styles if (style != s) { - long d = (style ^ s) & MASK; + long d = (style ^ s) & MASK; long fg = (s & F_FOREGROUND) != 0 ? s & (FG_COLOR | F_FOREGROUND) : 0; long bg = (s & F_BACKGROUND) != 0 ? s & (BG_COLOR | F_BACKGROUND) : 0; if (s == 0) { @@ -172,16 +174,16 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a if (fg > 0) { int rounded = -1; if ((fg & F_FOREGROUND_RGB) != 0) { - int r = (int)(fg >> (FG_COLOR_EXP + 16)) & 0xFF; - int g = (int)(fg >> (FG_COLOR_EXP + 8)) & 0xFF; - int b = (int)(fg >> FG_COLOR_EXP) & 0xFF; + int r = (int) (fg >> (FG_COLOR_EXP + 16)) & 0xFF; + int g = (int) (fg >> (FG_COLOR_EXP + 8)) & 0xFF; + int b = (int) (fg >> FG_COLOR_EXP) & 0xFF; if (colors >= HIGH_COLORS) { first = attr(sb, "38;2;" + r + ";" + g + ";" + b, first); } else { rounded = palette.round(r, g, b); } } else if ((fg & F_FOREGROUND_IND) != 0) { - rounded = palette.round((int)(fg >> FG_COLOR_EXP) & 0xFF); + rounded = palette.round((int) (fg >> FG_COLOR_EXP) & 0xFF); } if (rounded >= 0) { if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) { @@ -211,16 +213,16 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a if (bg > 0) { int rounded = -1; if ((bg & F_BACKGROUND_RGB) != 0) { - int r = (int)(bg >> (BG_COLOR_EXP + 16)) & 0xFF; - int g = (int)(bg >> (BG_COLOR_EXP + 8)) & 0xFF; - int b = (int)(bg >> BG_COLOR_EXP) & 0xFF; + int r = (int) (bg >> (BG_COLOR_EXP + 16)) & 0xFF; + int g = (int) (bg >> (BG_COLOR_EXP + 8)) & 0xFF; + int b = (int) (bg >> BG_COLOR_EXP) & 0xFF; if (colors >= HIGH_COLORS) { first = attr(sb, "48;2;" + r + ";" + g + ";" + b, first); } else { rounded = palette.round(r, g, b); } } else if ((bg & F_BACKGROUND_IND) != 0) { - rounded = palette.round((int)(bg >> BG_COLOR_EXP) & 0xFF); + rounded = palette.round((int) (bg >> BG_COLOR_EXP) & 0xFF); } if (rounded >= 0) { if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) { @@ -243,8 +245,7 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a background = bg; } if ((d & (F_BOLD | F_FAINT)) != 0) { - if ( (d & F_BOLD) != 0 && (s & F_BOLD) == 0 - || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) { + if ((d & F_BOLD) != 0 && (s & F_BOLD) == 0 || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) { first = attr(sb, "22", first); } if ((d & F_BOLD) != 0 && (s & F_BOLD) != 0) { @@ -360,8 +361,7 @@ public int columnLength() { int len = length(); for (int cur = 0; cur < len; ) { int cp = codePointAt(cur); - if (!isHidden(cur)) - cols += WCWidth.wcwidth(cp); + if (!isHidden(cur)) cols += WCWidth.wcwidth(cp); cur += Character.charCount(cp); } return cols; @@ -382,8 +382,7 @@ public AttributedString columnSubSequence(int start, int stop) { int end = begin; while (end < this.length()) { int cp = codePointAt(end); - if (cp == '\n') - break; + if (cp == '\n') break; int w = isHidden(end) ? 0 : WCWidth.wcwidth(cp); if (col + w > stop) { break; @@ -407,7 +406,7 @@ public List columnSplitLength(int columns, boolean includeNewl int cp = codePointAt(cur); int w = isHidden(cur) ? 0 : WCWidth.wcwidth(cp); if (cp == '\n') { - strings.add(subSequence(beg, includeNewlines ? cur+1 : cur)); + strings.add(subSequence(beg, includeNewlines ? cur + 1 : cur)); beg = cur + 1; col = 0; } else if ((col += w) > columns) { @@ -429,5 +428,4 @@ public String toString() { public AttributedString toAttributedString() { return substring(0, length()); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java index 47492b72e7648..3c70a6d0e7bf4 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,6 +15,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import jdk.internal.org.jline.terminal.Terminal; + /** * Attributed string. * Instances of this class are immutables. @@ -103,11 +105,28 @@ public static AttributedString fromAnsi(String ansi, int tabs) { } public static AttributedString fromAnsi(String ansi, List tabs) { + return fromAnsi(ansi, tabs, null, null); + } + + public static AttributedString fromAnsi(String ansi, Terminal terminal) { + String alternateIn, alternateOut; + if (!DISABLE_ALTERNATE_CHARSET) { + alternateIn = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.enter_alt_charset_mode)); + alternateOut = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.exit_alt_charset_mode)); + } else { + alternateIn = null; + alternateOut = null; + } + return fromAnsi(ansi, Arrays.asList(0), alternateIn, alternateOut); + } + + public static AttributedString fromAnsi(String ansi, List tabs, String altIn, String altOut) { if (ansi == null) { return null; } return new AttributedStringBuilder(ansi.length()) .tabs(tabs) + .altCharset(altIn, altOut) .ansiAppend(ansi) .toAttributedString(); } @@ -116,9 +135,7 @@ public static String stripAnsi(String ansi) { if (ansi == null) { return null; } - return new AttributedStringBuilder(ansi.length()) - .ansiAppend(ansi) - .toString(); + return new AttributedStringBuilder(ansi.length()).ansiAppend(ansi).toString(); } @Override @@ -162,7 +179,7 @@ public AttributedString styleMatches(Pattern pattern, AttributedStyle style) { } result = matcher.find(); } while (result); - return new AttributedString(buffer, newstyle, start , end); + return new AttributedString(buffer, newstyle, start, end); } return this; } @@ -179,15 +196,16 @@ && arrEq(buffer, that.buffer, start, that.start, end - start) private boolean arrEq(char[] a1, char[] a2, int s1, int s2, int l) { for (int i = 0; i < l; i++) { - if (a1[s1+i] != a2[s2+i]) { + if (a1[s1 + i] != a2[s2 + i]) { return false; } } return true; } + private boolean arrEq(long[] a1, long[] a2, int s1, int s2, int l) { for (int i = 0; i < l; i++) { - if (a1[s1+i] != a2[s2+i]) { + if (a1[s1 + i] != a2[s2 + i]) { return false; } } @@ -221,5 +239,4 @@ public static AttributedString join(AttributedString delimiter, Iterable 0) { + append(s); + } + return this; + } + public AttributedStringBuilder append(CharSequence csq, AttributedStyle style) { return append(new AttributedString(csq, style)); } @@ -117,12 +125,12 @@ public AttributedStringBuilder style(AttributedStyle style) { return this; } - public AttributedStringBuilder style(Function style) { + public AttributedStringBuilder style(Function style) { current = style.apply(current); return this; } - public AttributedStringBuilder styled(Function style, CharSequence cs) { + public AttributedStringBuilder styled(Function style, CharSequence cs) { return styled(style, sb -> sb.append(cs)); } @@ -130,7 +138,8 @@ public AttributedStringBuilder styled(AttributedStyle style, CharSequence cs) { return styled(s -> style, sb -> sb.append(cs)); } - public AttributedStringBuilder styled(Function style, Consumer consumer) { + public AttributedStringBuilder styled( + Function style, Consumer consumer) { AttributedStyle prev = current; current = style.apply(prev); consumer.accept(this); @@ -338,23 +347,90 @@ public AttributedStringBuilder ansiAppend(String ansi) { // This is not a SGR code, so ignore ansiState = 0; } - } else if (c == '\t' && tabs.defined()) { - insertTab(current); } else { - ensureCapacity(length + 1); - buffer[length] = c; - style[length] = this.current.getStyle(); - if (c == '\n') { - lastLineLength = 0; + if (ansiState >= 1) { + ensureCapacity(length + 1); + buffer[length++] = 27; + if (ansiState >= 2) { + ensureCapacity(length + 1); + buffer[length++] = '['; + } + ansiState = 0; + } + if (c == '\t' && tabs.defined()) { + insertTab(current); } else { - lastLineLength++; + ensureCapacity(length + 1); + if (inAltCharset) { + switch (c) { + case 'j': + c = '\u2518'; + break; + case 'k': + c = '\u2510'; + break; + case 'l': + c = '\u250C'; + break; + case 'm': + c = '\u2514'; + break; + case 'n': + c = '\u253C'; + break; + case 'q': + c = '\u2500'; + break; + case 't': + c = '\u251C'; + break; + case 'u': + c = '\u2524'; + break; + case 'v': + c = '\u2534'; + break; + case 'w': + c = '\u252C'; + break; + case 'x': + c = '\u2502'; + break; + } + } + buffer[length] = c; + style[length] = this.current.getStyle(); + if (c == '\n') { + lastLineLength = 0; + } else { + lastLineLength++; + } + length++; + if (altIn != null && altOut != null) { + char[] alt = inAltCharset ? altOut : altIn; + if (equals(buffer, length - alt.length, alt, 0, alt.length)) { + inAltCharset = !inAltCharset; + length -= alt.length; + } + } } - length++; } } return this; } + private static boolean equals(char[] a, int aFromIndex, char[] b, int bFromIndex, int length) { + if (aFromIndex < 0 || bFromIndex < 0 || aFromIndex + length > a.length || bFromIndex + length > b.length) { + return false; + } + for (int i = 0; i < length; i++) { + if (a[aFromIndex + i] != b[bFromIndex + i]) { + return false; + } + } + return true; + } + protected void insertTab(AttributedStyle s) { int nb = tabs.spaces(lastLineLength); ensureCapacity(length + nb); @@ -393,6 +469,15 @@ public AttributedStringBuilder tabs(List tabs) { return this; } + public AttributedStringBuilder altCharset(String altIn, String altOut) { + if (length > 0) { + throw new IllegalStateException("Cannot change alternative charset after appending text"); + } + this.altIn = altIn != null ? altIn.toCharArray() : null; + this.altOut = altOut != null ? altOut.toCharArray() : null; + return this; + } + public AttributedStringBuilder styleMatches(Pattern pattern, AttributedStyle s) { Matcher matcher = pattern.matcher(this); while (matcher.find()) { @@ -416,7 +501,7 @@ public AttributedStringBuilder styleMatches(Pattern pattern, List tabs = new ArrayList<>(); private int lastStop = 0; private int lastSize = 0; @@ -428,7 +513,7 @@ public TabStops(int tabs) { public TabStops(List tabs) { this.tabs = tabs; int p = 0; - for (int s: tabs) { + for (int s : tabs) { if (s <= p) { continue; } @@ -447,7 +532,7 @@ int spaces(int lastLineLength) { if (lastLineLength >= lastStop) { out = lastSize - (lastLineLength - lastStop) % lastSize; } else { - for (int s: tabs) { + for (int s : tabs) { if (s > lastLineLength) { out = s - lastLineLength; break; @@ -456,7 +541,5 @@ int spaces(int lastLineLength) { } return out; } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java index 902e2e1f3b849..7845e99e0b0f9 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,39 +15,39 @@ */ public class AttributedStyle { - public static final int BLACK = 0; - public static final int RED = 1; - public static final int GREEN = 2; - public static final int YELLOW = 3; - public static final int BLUE = 4; - public static final int MAGENTA = 5; - public static final int CYAN = 6; - public static final int WHITE = 7; - - public static final int BRIGHT = 8; - - static final long F_BOLD = 0x00000001; - static final long F_FAINT = 0x00000002; - static final long F_ITALIC = 0x00000004; - static final long F_UNDERLINE = 0x00000008; - static final long F_BLINK = 0x00000010; - static final long F_INVERSE = 0x00000020; - static final long F_CONCEAL = 0x00000040; - static final long F_CROSSED_OUT = 0x00000080; - static final long F_FOREGROUND_IND = 0x00000100; - static final long F_FOREGROUND_RGB = 0x00000200; - static final long F_FOREGROUND = F_FOREGROUND_IND | F_FOREGROUND_RGB; - static final long F_BACKGROUND_IND = 0x00000400; - static final long F_BACKGROUND_RGB = 0x00000800; - static final long F_BACKGROUND = F_BACKGROUND_IND | F_BACKGROUND_RGB; - static final long F_HIDDEN = 0x00001000; - - static final long MASK = 0x00001FFF; - - static final int FG_COLOR_EXP = 15; - static final int BG_COLOR_EXP = 39; - static final long FG_COLOR = 0xFFFFFFL << FG_COLOR_EXP; - static final long BG_COLOR = 0xFFFFFFL << BG_COLOR_EXP; + public static final int BLACK = 0; + public static final int RED = 1; + public static final int GREEN = 2; + public static final int YELLOW = 3; + public static final int BLUE = 4; + public static final int MAGENTA = 5; + public static final int CYAN = 6; + public static final int WHITE = 7; + + public static final int BRIGHT = 8; + + static final long F_BOLD = 0x00000001; + static final long F_FAINT = 0x00000002; + static final long F_ITALIC = 0x00000004; + static final long F_UNDERLINE = 0x00000008; + static final long F_BLINK = 0x00000010; + static final long F_INVERSE = 0x00000020; + static final long F_CONCEAL = 0x00000040; + static final long F_CROSSED_OUT = 0x00000080; + static final long F_FOREGROUND_IND = 0x00000100; + static final long F_FOREGROUND_RGB = 0x00000200; + static final long F_FOREGROUND = F_FOREGROUND_IND | F_FOREGROUND_RGB; + static final long F_BACKGROUND_IND = 0x00000400; + static final long F_BACKGROUND_RGB = 0x00000800; + static final long F_BACKGROUND = F_BACKGROUND_IND | F_BACKGROUND_RGB; + static final long F_HIDDEN = 0x00001000; + + static final long MASK = 0x00001FFF; + + static final int FG_COLOR_EXP = 15; + static final int BG_COLOR_EXP = 39; + static final long FG_COLOR = 0xFFFFFFL << FG_COLOR_EXP; + static final long BG_COLOR = 0xFFFFFFL << BG_COLOR_EXP; public static final AttributedStyle DEFAULT = new AttributedStyle(); public static final AttributedStyle BOLD = DEFAULT.bold(); @@ -70,8 +70,9 @@ public AttributedStyle(AttributedStyle s) { public AttributedStyle(long style, long mask) { this.style = style; - this.mask = mask & MASK | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0) - | ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0); + this.mask = mask & MASK + | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0) + | ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0); } public AttributedStyle bold() { @@ -176,7 +177,9 @@ public AttributedStyle crossedOutDefault() { } public AttributedStyle foreground(int color) { - return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_IND); + return new AttributedStyle( + style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR), + mask | F_FOREGROUND_IND); } public AttributedStyle foreground(int r, int g, int b) { @@ -184,7 +187,9 @@ public AttributedStyle foreground(int r, int g, int b) { } public AttributedStyle foregroundRgb(int color) { - return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_RGB); + return new AttributedStyle( + style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR), + mask | F_FOREGROUND_RGB); } public AttributedStyle foregroundOff() { @@ -196,7 +201,9 @@ public AttributedStyle foregroundDefault() { } public AttributedStyle background(int color) { - return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_IND); + return new AttributedStyle( + style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR), + mask | F_BACKGROUND_IND); } public AttributedStyle background(int r, int g, int b) { @@ -204,7 +211,9 @@ public AttributedStyle background(int r, int g, int b) { } public AttributedStyle backgroundRgb(int color) { - return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_RGB); + return new AttributedStyle( + style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR), + mask | F_BACKGROUND_RGB); } public AttributedStyle backgroundOff() { @@ -249,7 +258,6 @@ public boolean equals(Object o) { AttributedStyle that = (AttributedStyle) o; if (style != that.style) return false; return mask == that.mask; - } @Override @@ -266,10 +274,6 @@ public String toAnsi() { @Override public String toString() { - return "AttributedStyle{" + - "style=" + style + - ", mask=" + mask + - ", ansi=" + toAnsi() + - '}'; + return "AttributedStyle{" + "style=" + style + ", mask=" + mask + ", ansi=" + toAnsi() + '}'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java index f2adb0878c718..a6f5bfb5b5463 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,8 +14,7 @@ public class ClosedException extends IOException { private static final long serialVersionUID = 3085420657077696L; - public ClosedException() { - } + public ClosedException() {} public ClosedException(String message) { super(message); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java index 6f55273a7b935..b4175fe13cec5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,7 +21,8 @@ */ public class ColorPalette { - public static final String XTERM_INITC = "\\E]4;%p1%d;rgb\\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\\E\\\\"; + public static final String XTERM_INITC = + "\\E]4;%p1%d;rgb\\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\\E\\\\"; public static final ColorPalette DEFAULT = new ColorPalette(); @@ -41,6 +42,7 @@ public ColorPalette(Terminal terminal) throws IOException { this(terminal, null); } + @SuppressWarnings("this-escape") public ColorPalette(Terminal terminal, String distance) throws IOException { this.terminal = terminal; this.distanceName = distance; @@ -245,10 +247,13 @@ private static int[] doLoad(Terminal terminal) throws IOException { if (rgb.size() != 3) { return null; } - double r = Integer.parseInt(rgb.get(0), 16) / ((1 << (4 * rgb.get(0).length())) - 1.0); - double g = Integer.parseInt(rgb.get(1), 16) / ((1 << (4 * rgb.get(1).length())) - 1.0); - double b = Integer.parseInt(rgb.get(2), 16) / ((1 << (4 * rgb.get(2).length())) - 1.0); - palette[idx] = (int)((Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255)); + double r = Integer.parseInt(rgb.get(0), 16) + / ((1 << (4 * rgb.get(0).length())) - 1.0); + double g = Integer.parseInt(rgb.get(1), 16) + / ((1 << (4 * rgb.get(1).length())) - 1.0); + double b = Integer.parseInt(rgb.get(2), 16) + / ((1 << (4 * rgb.get(2).length())) - 1.0); + palette[idx] = (int) ((Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255)); black &= palette[idx] == 0; } if (black) { @@ -256,7 +261,13 @@ private static int[] doLoad(Terminal terminal) throws IOException { } } int max = 256; - while (max > 0 && palette[--max] == 0); + while (max > 0 && palette[--max] == 0) + ; return Arrays.copyOfRange(palette, 0, max + 1); } + + @Override + public String toString() { + return "ColorPalette[" + "length=" + getLength() + ", " + "distance='" + getDist() + "\']"; + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java index dc452e103645f..d5e7644d3cb44 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,6 +21,8 @@ public class Colors { + // @spotless:off + /** * Default 256 colors palette */ @@ -111,24 +113,26 @@ public class Colors { 0x2e2e2e, 0x5c5c5c, 0x737373, 0x8b8b8b, 0xa2a2a2, 0xb9b9b9, 0xd0d0d0, 0xe7e7e7, }; + // @spotless:on + /** D50 illuminant for CAM color spaces */ - public static final double[] D50 = new double[] { 96.422f, 100.0f, 82.521f }; + public static final double[] D50 = new double[] {96.422f, 100.0f, 82.521f}; /** D65 illuminant for CAM color spaces */ - public static final double[] D65 = new double[] { 95.047, 100.0, 108.883 }; + public static final double[] D65 = new double[] {95.047, 100.0, 108.883}; /** Average surrounding for CAM color spaces */ - public static final double[] averageSurrounding = new double[] { 1.0, 0.690, 1.0 }; + public static final double[] averageSurrounding = new double[] {1.0, 0.690, 1.0}; /** Dim surrounding for CAM color spaces */ - public static final double[] dimSurrounding = new double[] { 0.9, 0.590, 0.9 }; + public static final double[] dimSurrounding = new double[] {0.9, 0.590, 0.9}; /** Dark surrounding for CAM color spaces */ - public static final double[] darkSurrounding = new double[] { 0.8, 0.525, 0.8 }; + public static final double[] darkSurrounding = new double[] {0.8, 0.525, 0.8}; /** sRGB encoding environment */ - public static final double[] sRGB_encoding_environment = vc(D50, 64.0, 64.0/5, dimSurrounding); + public static final double[] sRGB_encoding_environment = vc(D50, 64.0, 64.0 / 5, dimSurrounding); /** sRGB typical environment */ - public static final double[] sRGB_typical_environment = vc(D50, 200.0, 200.0/5, averageSurrounding); + public static final double[] sRGB_typical_environment = vc(D50, 200.0, 200.0 / 5, averageSurrounding); /** Adobe RGB environment */ - public static final double[] AdobeRGB_environment = vc(D65, 160.0, 160.0/5, averageSurrounding); + public static final double[] AdobeRGB_environment = vc(D65, 160.0, 160.0 / 5, averageSurrounding); private static int[] COLORS_256 = DEFAULT_COLORS_256; @@ -149,8 +153,9 @@ public static Integer rgbColor(String name) { if (COLOR_NAMES == null) { Map colors = new LinkedHashMap<>(); try (InputStream is = InfoCmp.class.getResourceAsStream("colors.txt"); - BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { - br.lines().map(String::trim) + BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + br.lines() + .map(String::trim) .filter(s -> !s.startsWith("#")) .filter(s -> !s.isEmpty()) .forEachOrdered(s -> { @@ -206,7 +211,7 @@ static Distance getDistance(String dist) { if (dist == null) { dist = System.getProperty(PROP_COLOR_DISTANCE, "cie76"); } - return doGetDistance(dist); + return new NamedDistance(dist, doGetDistance(dist)); } private static Distance doGetDistance(String dist) { @@ -216,7 +221,7 @@ private static Distance doGetDistance(String dist) { double[] c1 = rgb(p1); double[] c2 = rgb(p2); double rmean = (c1[0] + c2[0]) / 2.0; - double[] w = { 2.0 + rmean, 4.0, 3.0 - rmean }; + double[] w = {2.0 + rmean, 4.0, 3.0 - rmean}; return scalar(c1, c2, w); }; } @@ -228,7 +233,7 @@ private static Distance doGetDistance(String dist) { } if (dist.matches("lab\\(([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?)\\)")) { double[] w = getWeights(dist); - return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2), new double[] { w[0], w[1], w[1] }); + return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2), new double[] {w[0], w[1], w[1]}); } if (dist.equals("cie94")) { return (p1, p2) -> cie94(rgb2cielab(p1), rgb2cielab(p2)); @@ -251,7 +256,7 @@ private static Distance doGetDistance(String dist) { double[] c1 = camlab(p1, sRGB_typical_environment); double[] c2 = camlab(p2, sRGB_typical_environment); double[] w = getWeights(dist); - return scalar(c1, c2, new double[] { w[0], w[1], w[1] }); + return scalar(c1, c2, new double[] {w[0], w[1], w[1]}); }; } if (dist.matches("camlch")) { @@ -273,20 +278,37 @@ private static Distance doGetDistance(String dist) { } private static double[] getWeights(String dist) { - String[] weights = dist.substring(dist.indexOf('(') + 1, dist.length() - 1).split(","); + String[] weights = + dist.substring(dist.indexOf('(') + 1, dist.length() - 1).split(","); return Stream.of(weights).mapToDouble(Double::parseDouble).toArray(); } private static double scalar(double[] c1, double[] c2, double[] w) { - return sqr((c1[0] - c2[0]) * w[0]) - + sqr((c1[1] - c2[1]) * w[1]) - + sqr((c1[2] - c2[2]) * w[2]); + return sqr((c1[0] - c2[0]) * w[0]) + sqr((c1[1] - c2[1]) * w[1]) + sqr((c1[2] - c2[2]) * w[2]); } private static double scalar(double[] c1, double[] c2) { - return sqr(c1[0] - c2[0]) - + sqr(c1[1] - c2[1]) - + sqr(c1[2] - c2[2]); + return sqr(c1[0] - c2[0]) + sqr(c1[1] - c2[1]) + sqr(c1[2] - c2[2]); + } + + private static class NamedDistance implements Distance { + private final String name; + private final Distance delegate; + + public NamedDistance(String name, Distance delegate) { + this.name = name; + this.delegate = delegate; + } + + @Override + public double compute(int c1, int c2) { + return delegate.compute(c1, c2); + } + + @Override + public String toString() { + return name; + } } private static final int L = 0; @@ -325,7 +347,7 @@ private static double cie00(double[] lab1, double[] lab2) { double c_star_average_ab = (c_star_1_ab + c_star_2_ab) / 2.0; double c_star_average_ab_pot_3 = c_star_average_ab * c_star_average_ab * c_star_average_ab; double c_star_average_ab_pot_7 = c_star_average_ab_pot_3 * c_star_average_ab_pot_3 * c_star_average_ab; - double G = 0.5 * (1.0 - Math.sqrt(c_star_average_ab_pot_7 / (c_star_average_ab_pot_7 + 6103515625.0))); //25^7 + double G = 0.5 * (1.0 - Math.sqrt(c_star_average_ab_pot_7 / (c_star_average_ab_pot_7 + 6103515625.0))); // 25^7 double a1_prime = (1.0 + G) * lab1[A]; double a2_prime = (1.0 + G) * lab2[A]; double C_prime_1 = Math.sqrt(a1_prime * a1_prime + lab1[B] * lab1[B]); @@ -365,16 +387,18 @@ private static double cie00(double[] lab1, double[] lab2) { + 0.24 * Math.cos(Math.toRadians(h_prime_average * 2.0)) + 0.32 * Math.cos(Math.toRadians(h_prime_average * 3.0 + 6.0)) - 0.20 * Math.cos(Math.toRadians(h_prime_average * 4.0 - 63.0)); - double S_L = 1.0 + ((0.015 * L_prime_average_minus_50_square) / Math.sqrt(20.0 + L_prime_average_minus_50_square)); + double S_L = + 1.0 + ((0.015 * L_prime_average_minus_50_square) / Math.sqrt(20.0 + L_prime_average_minus_50_square)); double S_C = 1.0 + 0.045 * C_prime_average; double S_H = 1.0 + 0.015 * T * C_prime_average; double h_prime_average_minus_275_div_25 = (h_prime_average - 275.0) / (25.0); - double h_prime_average_minus_275_div_25_square = h_prime_average_minus_275_div_25 * h_prime_average_minus_275_div_25; + double h_prime_average_minus_275_div_25_square = + h_prime_average_minus_275_div_25 * h_prime_average_minus_275_div_25; double delta_theta = 30.0 * Math.exp(-h_prime_average_minus_275_div_25_square); double C_prime_average_pot_3 = C_prime_average * C_prime_average * C_prime_average; double C_prime_average_pot_7 = C_prime_average_pot_3 * C_prime_average_pot_3 * C_prime_average; - double R_C = 2.0 * Math.sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625.0)); //25^7 - double R_T = - Math.sin(Math.toRadians(2.0 * delta_theta)) * R_C; + double R_C = 2.0 * Math.sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625.0)); // 25^7 + double R_T = -Math.sin(Math.toRadians(2.0 * delta_theta)) * R_C; double dLKlsl = delta_L_prime / (kl * S_L); double dCkcsc = delta_C_prime / (kc * S_C); double dHkhsh = delta_H_prime / (kh * S_H); @@ -392,11 +416,11 @@ private static double[] jmh2ucs(double[] lch) { double sM = ((1.0 / 0.0228) * Math.log(1.0 + 0.0228 * lch[1])); double a = sM * Math.cos(Math.toRadians(lch[2])); double b = sM * Math.sin(Math.toRadians(lch[2])); - return new double[] {sJ, a, b }; + return new double[] {sJ, a, b}; } static double camlch(double[] c1, double[] c2) { - return camlch(c1, c2, new double[] { 1.0, 1.0, 1.0 }); + return camlch(c1, c2, new double[] {1.0, 1.0, 1.0}); } static double camlch(double[] c1, double[] c2, double[] w) { @@ -414,18 +438,16 @@ static double camlch(double[] c1, double[] c2, double[] w) { private static double hueDifference(double hue1, double hue2, double c) { double difference = (hue2 - hue1) % c; double ch = c / 2; - if (difference > ch) - difference -= c; - if (difference < -ch) - difference += c; + if (difference > ch) difference -= c; + if (difference < -ch) difference += c; return difference; } private static double[] rgb(int color) { int r = (color >> 16) & 0xFF; - int g = (color >> 8) & 0xFF; - int b = (color >> 0) & 0xFF; - return new double[] { r / 255.0, g / 255.0, b / 255.0 }; + int g = (color >> 8) & 0xFF; + int b = (color >> 0) & 0xFF; + return new double[] {r / 255.0, g / 255.0, b / 255.0}; } static double[] rgb2xyz(int color) { @@ -454,13 +476,13 @@ static double[] camlab(int color, double[] vc) { static double[] lch2lab(double[] lch) { double toRad = Math.PI / 180; - return new double[] { lch[0], lch[1] * Math.cos(lch[2] * toRad), lch[1] * Math.sin(lch[2] * toRad) }; + return new double[] {lch[0], lch[1] * Math.cos(lch[2] * toRad), lch[1] * Math.sin(lch[2] * toRad)}; } private static double[] xyz2camlch(double[] xyz, double[] vc) { double[] XYZ = new double[] {xyz[0] * 100.0, xyz[1] * 100.0, xyz[2] * 100.0}; double[] cam = forwardTransform(XYZ, vc); - return new double[] { cam[J], cam[M], cam[h] }; + return new double[] {cam[J], cam[M], cam[h]}; } /** Lightness */ @@ -478,12 +500,12 @@ private static double[] xyz2camlch(double[] xyz, double[] vc) { /** Hue */ public static final int h = 6; - /** CIECAM02 appearance correlates */ private static double[] forwardTransform(double[] XYZ, double[] vc) { // calculate sharpened cone response double[] RGB = forwardPreAdaptationConeResponse(XYZ); - // calculate corresponding (sharpened) cone response considering various luminance level and surround conditions in D + // calculate corresponding (sharpened) cone response considering various luminance level and surround conditions + // in D double[] RGB_c = forwardPostAdaptationConeResponse(RGB, vc); // calculate HPE equal area cone fundamentals double[] RGBPrime = CAT02toHPE(RGB_c); @@ -501,37 +523,40 @@ private static double[] forwardTransform(double[] XYZ, double[] vc) { // calculate eccentricity double e = ((12500.0 / 13.0) * vc[VC_N_C] * vc[VC_N_CB]) * (Math.cos(Math.toRadians(h) + 2.0) + 3.8); // get t - double t = e * Math.sqrt(Math.pow(a, 2.0) + Math.pow(b, 2.0)) / (RGBPrime_a[0] + RGBPrime_a[1] + 1.05 * RGBPrime_a[2]); + double t = e + * Math.sqrt(Math.pow(a, 2.0) + Math.pow(b, 2.0)) + / (RGBPrime_a[0] + RGBPrime_a[1] + 1.05 * RGBPrime_a[2]); // calculate brightness double Q = (4.0 / vc[VC_C]) * Math.sqrt(J / 100.0) * (vc[VC_A_W] + 4.0) * Math.pow(vc[VC_F_L], 0.25); // calculate the correlates of chroma, colorfulness, and saturation - double C = Math.signum(t) * Math.pow(Math.abs(t), 0.9) * Math.sqrt(J / 100.0) * Math.pow(1.64- Math.pow(0.29, vc[VC_N]), 0.73); + double C = Math.signum(t) + * Math.pow(Math.abs(t), 0.9) + * Math.sqrt(J / 100.0) + * Math.pow(1.64 - Math.pow(0.29, vc[VC_N]), 0.73); double M = C * Math.pow(vc[VC_F_L], 0.25); double s = 100.0 * Math.sqrt(M / Q); // calculate hue composition double H = calculateH(h); - return new double[] { J, Q, C, M, s, H, h }; + return new double[] {J, Q, C, M, s, H, h}; } private static double calculateH(double h) { - if (h < 20.14) - h = h + 360; + if (h < 20.14) h = h + 360; double i; - if (h >= 20.14 && h < 90.0) { // index i = 1 + if (h >= 20.14 && h < 90.0) { // index i = 1 i = (h - 20.14) / 0.8; return 100.0 * i / (i + (90 - h) / 0.7); } else if (h < 164.25) { // index i = 2 i = (h - 90) / 0.7; return 100.0 + 100.0 * i / (i + (164.25 - h) / 1); - } else if (h < 237.53) { // index i = 3 + } else if (h < 237.53) { // index i = 3 i = (h - 164.25) / 1.0; return 200.0 + 100.0 * i / (i + (237.53 - h) / 1.2); - } else if (h <= 380.14) { // index i = 4 + } else if (h <= 380.14) { // index i = 4 i = (h - 237.53) / 1.2; double H = 300.0 + 100.0 * i / (i + (380.14 - h) / 0.8); // don't use 400 if we can use 0 - if (H <= 400.0 && H >= 399.999) - H = 0; + if (H <= 400.0 && H >= 399.999) H = 0; return H; } else { throw new IllegalArgumentException("h outside assumed range 0..360: " + h); @@ -540,8 +565,8 @@ private static double calculateH(double h) { private static double[] forwardResponseCompression(double[] RGB, double[] vc) { double[] result = new double[3]; - for(int channel = 0; channel < RGB.length; channel++) { - if(RGB[channel] >= 0) { + for (int channel = 0; channel < RGB.length; channel++) { + if (RGB[channel] >= 0) { double n = Math.pow(vc[VC_F_L] * RGB[channel] / 100.0, 0.42); result[channel] = 400.0 * n / (n + 27.13) + 0.1; } else { @@ -553,22 +578,22 @@ private static double[] forwardResponseCompression(double[] RGB, double[] vc) { } private static double[] forwardPostAdaptationConeResponse(double[] RGB, double[] vc) { - return new double[] { vc[VC_D_RGB_R] * RGB[0], vc[VC_D_RGB_G] * RGB[1], vc[VC_D_RGB_B] * RGB[2] }; + return new double[] {vc[VC_D_RGB_R] * RGB[0], vc[VC_D_RGB_G] * RGB[1], vc[VC_D_RGB_B] * RGB[2]}; } public static double[] CAT02toHPE(double[] RGB) { double[] RGBPrime = new double[3]; - RGBPrime[0] = 0.7409792 * RGB[0] + 0.2180250 * RGB[1] + 0.0410058 * RGB[2]; - RGBPrime[1] = 0.2853532 * RGB[0] + 0.6242014 * RGB[1] + 0.0904454 * RGB[2]; + RGBPrime[0] = 0.7409792 * RGB[0] + 0.2180250 * RGB[1] + 0.0410058 * RGB[2]; + RGBPrime[1] = 0.2853532 * RGB[0] + 0.6242014 * RGB[1] + 0.0904454 * RGB[2]; RGBPrime[2] = -0.0096280 * RGB[0] - 0.0056980 * RGB[1] + 1.0153260 * RGB[2]; return RGBPrime; } private static double[] forwardPreAdaptationConeResponse(double[] XYZ) { double[] RGB = new double[3]; - RGB[0] = 0.7328 * XYZ[0] + 0.4296 * XYZ[1] - 0.1624 * XYZ[2]; + RGB[0] = 0.7328 * XYZ[0] + 0.4296 * XYZ[1] - 0.1624 * XYZ[2]; RGB[1] = -0.7036 * XYZ[0] + 1.6975 * XYZ[1] + 0.0061 * XYZ[2]; - RGB[2] = 0.0030 * XYZ[0] + 0.0136 * XYZ[1] + 0.9834 * XYZ[2]; + RGB[2] = 0.0030 * XYZ[0] + 0.0136 * XYZ[1] + 0.9834 * XYZ[2]; return RGB; } @@ -581,8 +606,8 @@ private static double[] forwardPreAdaptationConeResponse(double[] XYZ) { static final int VC_Z_W = 2; static final int VC_L_A = 3; static final int VC_Y_B = 4; - static final int VC_F = 5; - static final int VC_C = 6; + static final int VC_F = 5; + static final int VC_C = 6; static final int VC_N_C = 7; static final int VC_Z = 8; @@ -607,33 +632,33 @@ static double[] vc(double[] xyz_w, double L_A, double Y_b, double[] surrounding) vc[VC_N_C] = surrounding[SUR_N_C]; double[] RGB_w = forwardPreAdaptationConeResponse(xyz_w); - double D = Math.max(0.0, Math.min(1.0, vc[VC_F] * (1.0 - (1.0 / 3.6) * Math.pow(Math.E, (-L_A - 42.0) / 92.0)))); + double D = + Math.max(0.0, Math.min(1.0, vc[VC_F] * (1.0 - (1.0 / 3.6) * Math.pow(Math.E, (-L_A - 42.0) / 92.0)))); double Yw = xyz_w[1]; double[] RGB_c = new double[] { - (D * Yw / RGB_w[0]) + (1.0 - D), - (D * Yw / RGB_w[1]) + (1.0 - D), - (D * Yw / RGB_w[2]) + (1.0 - D), + (D * Yw / RGB_w[0]) + (1.0 - D), (D * Yw / RGB_w[1]) + (1.0 - D), (D * Yw / RGB_w[2]) + (1.0 - D), }; // calculate increase in brightness and colorfulness caused by brighter viewing environments double L_Ax5 = 5.0 * L_A; double k = 1.0 / (L_Ax5 + 1.0); double kpow4 = Math.pow(k, 4.0); - vc[VC_F_L] = 0.2 * kpow4 * (L_Ax5) + 0.1 * Math.pow(1.0 - kpow4, 2.0) * Math.pow(L_Ax5, 1.0/3.0); + vc[VC_F_L] = 0.2 * kpow4 * (L_Ax5) + 0.1 * Math.pow(1.0 - kpow4, 2.0) * Math.pow(L_Ax5, 1.0 / 3.0); // calculate response compression on J and C caused by background lightness. vc[VC_N] = Y_b / Yw; vc[VC_Z] = 1.48 + Math.sqrt(vc[VC_N]); vc[VC_N_BB] = 0.725 * Math.pow(1.0 / vc[VC_N], 0.2); - vc[VC_N_CB] = vc[VC_N_BB]; // chromatic contrast factors (calculate increase in J, Q, and C caused by dark backgrounds) + vc[VC_N_CB] = vc[ + VC_N_BB]; // chromatic contrast factors (calculate increase in J, Q, and C caused by dark backgrounds) // calculate achromatic response to white double[] RGB_wc = new double[] {RGB_c[0] * RGB_w[0], RGB_c[1] * RGB_w[1], RGB_c[2] * RGB_w[2]}; double[] RGBPrime_w = CAT02toHPE(RGB_wc); double[] RGBPrime_aw = new double[3]; - for(int channel = 0; channel < RGBPrime_w.length; channel++) { - if(RGBPrime_w[channel] >= 0) { + for (int channel = 0; channel < RGBPrime_w.length; channel++) { + if (RGBPrime_w[channel] >= 0) { double n = Math.pow(vc[VC_F_L] * RGBPrime_w[channel] / 100.0, 0.42); RGBPrime_aw[channel] = 400.0 * n / (n + 27.13) + 0.1; } else { @@ -660,7 +685,7 @@ private static double[] rgb2xyz(double[] rgb) { double x = vr * 0.4124564 + vg * 0.3575761 + vb * 0.1804375; double y = vr * 0.2126729 + vg * 0.7151522 + vb * 0.0721750; double z = vr * 0.0193339 + vg * 0.1191920 + vb * 0.9503041; - return new double[] { x, y, z }; + return new double[] {x, y, z}; } private static double pivotRgb(double n) { @@ -674,11 +699,12 @@ private static double[] xyz2lab(double[] xyz) { double l = 116.0 * fy - 16.0; double a = 500.0 * (fx - fy); double b = 200.0 * (fy - fz); - return new double[] { l, a, b }; + return new double[] {l, a, b}; } private static final double epsilon = 216.0 / 24389.0; private static final double kappa = 24389.0 / 27.0; + private static double pivotXyz(double n) { return n > epsilon ? Math.cbrt(n) : (kappa * n + 16) / 116; } @@ -686,5 +712,4 @@ private static double pivotXyz(double n) { private static double sqr(double n) { return n * n; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java index bdfd4c37bc2d8..b9ada27070577 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -29,8 +29,7 @@ public final class Curses { private static final int IFTE_THEN = 2; private static final int IFTE_ELSE = 3; - private Curses() { - } + private Curses() {} /** * Print the given terminal capabilities @@ -95,9 +94,9 @@ private static void doTputs(Appendable out, String str, Object... params) throws case 'n': out.append('\n'); break; -// case 'l': -// rawPrint('\l'); -// break; + // case 'l': + // rawPrint('\l'); + // break; case 'r': if (exec) { out.append('\r'); @@ -138,7 +137,7 @@ private static void doTputs(Appendable out, String str, Object... params) throws case '^': ch = str.charAt(index++); if (exec) { - out.append((char)(ch - '@')); + out.append((char) (ch - '@')); } break; case '%': @@ -195,7 +194,8 @@ private static void doTputs(Appendable out, String str, Object... params) throws break; case '{': int start = index; - while (str.charAt(index++) != '}') ; + while (str.charAt(index++) != '}') + ; if (exec) { int v = Integer.parseInt(str.substring(start, index - 1)); stack.push(v); @@ -364,10 +364,18 @@ private static void doTputs(Appendable out, String str, Object... params) throws int cnv; while ("-+# ".indexOf(ch) >= 0) { switch (ch) { - case '-': left = true; break; - case '+': plus = true; break; - case '#': alternate = true; break; - case ' ': space = true; break; + case '-': + left = true; + break; + case '+': + plus = true; + break; + case '#': + alternate = true; + break; + case ' ': + space = true; + break; } ch = str.charAt(index++); } @@ -473,5 +481,4 @@ private static int toInteger(Object pop) { return Integer.parseInt(pop.toString()); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java index 3852f572746ce..93b065395de77 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -25,7 +25,9 @@ public class DiffHelper { * which means: delete "Hello", add "Goodbye" and keep " world." */ public enum Operation { - DELETE, INSERT, EQUAL + DELETE, + INSERT, + EQUAL } /** @@ -86,16 +88,13 @@ public static List diff(AttributedString text1, AttributedString text2) { && text1.charAt(commonStart) == text2.charAt(commonStart) && text1.styleAt(commonStart).equals(text2.styleAt(commonStart))) { if (text1.isHidden(commonStart)) { - if (startHiddenRange < 0) - startHiddenRange = commonStart; - } else - startHiddenRange = -1; + if (startHiddenRange < 0) startHiddenRange = commonStart; + } else startHiddenRange = -1; commonStart++; } if (startHiddenRange >= 0 - && ((l1 > commonStart && text1.isHidden(commonStart)) - || (l2 > commonStart && text2.isHidden(commonStart)))) - commonStart = startHiddenRange; + && ((l1 > commonStart && text1.isHidden(commonStart)) + || (l2 > commonStart && text2.isHidden(commonStart)))) commonStart = startHiddenRange; startHiddenRange = -1; int commonEnd = 0; @@ -103,32 +102,24 @@ public static List diff(AttributedString text1, AttributedString text2) { && text1.charAt(l1 - commonEnd - 1) == text2.charAt(l2 - commonEnd - 1) && text1.styleAt(l1 - commonEnd - 1).equals(text2.styleAt(l2 - commonEnd - 1))) { if (text1.isHidden(l1 - commonEnd - 1)) { - if (startHiddenRange < 0) - startHiddenRange = commonEnd; - } else - startHiddenRange = -1; + if (startHiddenRange < 0) startHiddenRange = commonEnd; + } else startHiddenRange = -1; commonEnd++; } - if (startHiddenRange >= 0) - commonEnd = startHiddenRange; + if (startHiddenRange >= 0) commonEnd = startHiddenRange; LinkedList diffs = new LinkedList<>(); if (commonStart > 0) { - diffs.add(new Diff(DiffHelper.Operation.EQUAL, - text1.subSequence(0, commonStart))); + diffs.add(new Diff(DiffHelper.Operation.EQUAL, text1.subSequence(0, commonStart))); } if (l2 > commonStart + commonEnd) { - diffs.add(new Diff(DiffHelper.Operation.INSERT, - text2.subSequence(commonStart, l2 - commonEnd))); + diffs.add(new Diff(DiffHelper.Operation.INSERT, text2.subSequence(commonStart, l2 - commonEnd))); } if (l1 > commonStart + commonEnd) { - diffs.add(new Diff(DiffHelper.Operation.DELETE, - text1.subSequence(commonStart, l1 - commonEnd))); + diffs.add(new Diff(DiffHelper.Operation.DELETE, text1.subSequence(commonStart, l1 - commonEnd))); } if (commonEnd > 0) { - diffs.add(new Diff(DiffHelper.Operation.EQUAL, - text1.subSequence(l1 - commonEnd, l1))); + diffs.add(new Diff(DiffHelper.Operation.EQUAL, text1.subSequence(l1 - commonEnd, l1))); } return diffs; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java index aaeab9b71ffe9..557024a121ed2 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -37,8 +37,8 @@ public class Display { protected final boolean fullScreen; protected List oldLines = Collections.emptyList(); protected int cursorPos; - private int columns; - private int columns1; // columns+1 + protected int columns; + protected int columns1; // columns+1 protected int rows; protected boolean reset; protected boolean delayLineWrap; @@ -49,15 +49,15 @@ public class Display { protected final boolean delayedWrapAtEol; protected final boolean cursorDownIsNewLine; + @SuppressWarnings("this-escape") public Display(Terminal terminal, boolean fullscreen) { this.terminal = terminal; this.fullScreen = fullscreen; this.canScroll = can(Capability.insert_line, Capability.parm_insert_line) - && can(Capability.delete_line, Capability.parm_delete_line); + && can(Capability.delete_line, Capability.parm_delete_line); this.wrapAtEol = terminal.getBooleanCapability(Capability.auto_right_margin); - this.delayedWrapAtEol = this.wrapAtEol - && terminal.getBooleanCapability(Capability.eat_newline_glitch); + this.delayedWrapAtEol = this.wrapAtEol && terminal.getBooleanCapability(Capability.eat_newline_glitch); this.cursorDownIsNewLine = "\n".equals(Curses.tputs(terminal.getStringCapability(Capability.cursor_down))); } @@ -69,18 +69,22 @@ public Display(Terminal terminal, boolean fullscreen) { public boolean delayLineWrap() { return delayLineWrap; } - public void setDelayLineWrap(boolean v) { delayLineWrap = v; } + + public void setDelayLineWrap(boolean v) { + delayLineWrap = v; + } public void resize(int rows, int columns) { if (rows == 0 || columns == 0) { - columns = Integer.MAX_VALUE - 1; + columns = 1; rows = 1; } if (this.rows != rows || this.columns != columns) { this.rows = rows; this.columns = columns; this.columns1 = columns + 1; - oldLines = AttributedString.join(AttributedString.EMPTY, oldLines).columnSplitLength(columns, true, delayLineWrap()); + oldLines = AttributedString.join(AttributedString.EMPTY, oldLines) + .columnSplitLength(columns, true, delayLineWrap()); } } @@ -128,7 +132,8 @@ public void update(List newLines, int targetCursorPos, boolean // If dumb display, get rid of ansi sequences now Integer cols = terminal.getNumericCapability(Capability.max_colors); if (cols == null || cols < 8) { - newLines = newLines.stream().map(s -> new AttributedString(s.toString())) + newLines = newLines.stream() + .map(s -> new AttributedString(s.toString())) .collect(Collectors.toList()); } @@ -138,12 +143,13 @@ public void update(List newLines, int targetCursorPos, boolean int nbFooters = 0; // Find common headers and footers int l = newLines.size(); - while (nbHeaders < l - && Objects.equals(newLines.get(nbHeaders), oldLines.get(nbHeaders))) { + while (nbHeaders < l && Objects.equals(newLines.get(nbHeaders), oldLines.get(nbHeaders))) { nbHeaders++; } while (nbFooters < l - nbHeaders - 1 - && Objects.equals(newLines.get(newLines.size() - nbFooters - 1), oldLines.get(oldLines.size() - nbFooters - 1))) { + && Objects.equals( + newLines.get(newLines.size() - nbFooters - 1), + oldLines.get(oldLines.size() - nbFooters - 1))) { nbFooters++; } List o1 = newLines.subList(nbHeaders, newLines.size() - nbFooters); @@ -190,18 +196,14 @@ public void update(List newLines, int targetCursorPos, boolean int numLines = Math.min(rows, Math.max(oldLines.size(), newLines.size())); boolean wrapNeeded = false; while (lineIndex < numLines) { - AttributedString oldLine = - lineIndex < oldLines.size() ? oldLines.get(lineIndex) - : AttributedString.NEWLINE; - AttributedString newLine = - lineIndex < newLines.size() ? newLines.get(lineIndex) - : AttributedString.NEWLINE; + AttributedString oldLine = lineIndex < oldLines.size() ? oldLines.get(lineIndex) : AttributedString.NEWLINE; + AttributedString newLine = lineIndex < newLines.size() ? newLines.get(lineIndex) : AttributedString.NEWLINE; currentPos = lineIndex * columns1; int curCol = currentPos; int oldLength = oldLine.length(); int newLength = newLine.length(); - boolean oldNL = oldLength > 0 && oldLine.charAt(oldLength-1)=='\n'; - boolean newNL = newLength > 0 && newLine.charAt(newLength-1)=='\n'; + boolean oldNL = oldLength > 0 && oldLine.charAt(oldLength - 1) == '\n'; + boolean newNL = newLength > 0 && newLine.charAt(newLength - 1) == '\n'; if (oldNL) { oldLength--; oldLine = oldLine.substring(0, oldLength); @@ -210,9 +212,7 @@ public void update(List newLines, int targetCursorPos, boolean newLength--; newLine = newLine.substring(0, newLength); } - if (wrapNeeded - && lineIndex == (cursorPos + 1) / columns1 - && lineIndex < newLines.size()) { + if (wrapNeeded && lineIndex == (cursorPos + 1) / columns1 && lineIndex < newLines.size()) { // move from right margin to next line's left margin cursorPos++; if (newLength == 0 || newLine.isHidden(0)) { @@ -250,8 +250,7 @@ public void update(List newLines, int targetCursorPos, boolean } break; case INSERT: - if (i <= diffs.size() - 2 - && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { + if (i <= diffs.size() - 2 && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { cursorPos = moveVisualCursorTo(currentPos); if (insertChars(width)) { rawPrint(diff.text); @@ -282,8 +281,7 @@ public void update(List newLines, int targetCursorPos, boolean if (currentPos - curCol >= columns) { continue; } - if (i <= diffs.size() - 2 - && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { + if (i <= diffs.size() - 2 && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { if (currentPos + diffs.get(i + 1).text.columnLength() < columns) { moveVisualCursorTo(currentPos); if (deleteChars(width)) { @@ -305,25 +303,23 @@ public void update(List newLines, int targetCursorPos, boolean } } lineIndex++; - boolean newWrap = ! newNL && lineIndex < newLines.size(); - if (targetCursorPos + 1 == lineIndex * columns1 - && (newWrap || ! delayLineWrap)) - targetCursorPos++; + boolean newWrap = !newNL && lineIndex < newLines.size(); + if (targetCursorPos + 1 == lineIndex * columns1 && (newWrap || !delayLineWrap)) targetCursorPos++; boolean atRight = (cursorPos - curCol) % columns1 == columns; wrapNeeded = false; if (this.delayedWrapAtEol) { - boolean oldWrap = ! oldNL && lineIndex < oldLines.size(); - if (newWrap != oldWrap && ! (oldWrap && cleared)) { - moveVisualCursorTo(lineIndex*columns1-1, newLines); - if (newWrap) - wrapNeeded = true; - else - terminal.puts(Capability.clr_eol); + boolean oldWrap = !oldNL && lineIndex < oldLines.size(); + if (newWrap != oldWrap && !(oldWrap && cleared)) { + moveVisualCursorTo(lineIndex * columns1 - 1, newLines); + if (newWrap) wrapNeeded = true; + else terminal.puts(Capability.clr_eol); } } else if (atRight) { if (this.wrapAtEol) { - terminal.writer().write(" \b"); - cursorPos++; + if (!fullScreen || (fullScreen && lineIndex < numLines)) { + terminal.writer().write(" \b"); + cursorPos++; + } } else { terminal.puts(Capability.carriage_return); // CR / not newline. cursorPos = curCol; @@ -358,8 +354,7 @@ protected boolean deleteChars(int nb) { } protected boolean can(Capability single, Capability multi) { - return terminal.getStringCapability(single) != null - || terminal.getStringCapability(multi) != null; + return terminal.getStringCapability(single) != null || terminal.getStringCapability(multi) != null; } protected boolean perform(Capability single, Capability multi, int nb) { @@ -405,7 +400,7 @@ private static int[] longestCommon(List l1, List l1, List newLines) { + protected void moveVisualCursorTo(int targetPos, List newLines) { if (cursorPos != targetPos) { boolean atRight = (targetPos % columns1) == columns; moveVisualCursorTo(targetPos - (atRight ? 1 : 0)); @@ -422,12 +416,11 @@ protected void moveVisualCursorTo(int targetPos, // There is no portable way to move to the right margin // except by writing a character in the right-most column. int row = targetPos / columns1; - AttributedString lastChar = row >= newLines.size() ? AttributedString.EMPTY - : newLines.get(row).columnSubSequence(columns-1, columns); - if (lastChar.length() == 0) - rawPrint((int) ' '); - else - rawPrint(lastChar); + AttributedString lastChar = row >= newLines.size() + ? AttributedString.EMPTY + : newLines.get(row).columnSubSequence(columns - 1, columns); + if (lastChar.length() == 0) rawPrint((int) ' '); + else rawPrint(lastChar); cursorPos++; } } @@ -499,5 +492,4 @@ void rawPrint(AttributedString str) { public int wcwidth(String str) { return str != null ? AttributedString.fromAnsi(str).columnLength() : 0; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java index 9fce26fcf357d..5d3c235661b4c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,8 +22,7 @@ */ public final class ExecHelper { - private ExecHelper() { - } + private ExecHelper() {} public static String exec(boolean redirectInput, final String... cmd) throws IOException { Objects.requireNonNull(cmd); @@ -31,7 +30,7 @@ public static String exec(boolean redirectInput, final String... cmd) throws IOE Log.trace("Running: ", cmd); ProcessBuilder pb = new ProcessBuilder(cmd); if (OSUtils.IS_AIX) { - Map env = pb.environment(); + Map env = pb.environment(); env.put("PATH", "/opt/freeware/bin:" + env.get("PATH")); env.put("LANG", "C"); env.put("LC_ALL", "C"); @@ -90,4 +89,3 @@ private static void close(final Closeable... closeables) { } } } - diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java new file mode 100644 index 0000000000000..62c29c17f7816 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.utils; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * A simple buffering output stream with no synchronization. + */ +public class FastBufferedOutputStream extends FilterOutputStream { + + protected final byte[] buf = new byte[8192]; + protected int count; + + public FastBufferedOutputStream(OutputStream out) { + super(out); + } + + @Override + public void write(int b) throws IOException { + if (count >= buf.length) { + flushBuffer(); + } + buf[count++] = (byte) b; + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + if (len >= buf.length) { + flushBuffer(); + out.write(b, off, len); + return; + } + if (len > buf.length - count) { + flushBuffer(); + } + System.arraycopy(b, off, buf, count, len); + count += len; + } + + private void flushBuffer() throws IOException { + if (count > 0) { + out.write(buf, 0, count); + count = 0; + } + } + + @Override + public void flush() throws IOException { + flushBuffer(); + out.flush(); + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java index 23a7607148683..32cf3f56318ab 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -28,476 +28,474 @@ public final class InfoCmp { private static final Map CAPS = new HashMap<>(); - private InfoCmp() { - } + private InfoCmp() {} @SuppressWarnings("unused") public enum Capability { - - auto_left_margin, // auto_left_margin, bw, bw - auto_right_margin, // auto_right_margin, am, am - back_color_erase, // back_color_erase, bce, ut - can_change, // can_change, ccc, cc - ceol_standout_glitch, // ceol_standout_glitch, xhp, xs - col_addr_glitch, // col_addr_glitch, xhpa, YA - cpi_changes_res, // cpi_changes_res, cpix, YF - cr_cancels_micro_mode, // cr_cancels_micro_mode, crxm, YB - dest_tabs_magic_smso, // dest_tabs_magic_smso, xt, xt - eat_newline_glitch, // eat_newline_glitch, xenl, xn - erase_overstrike, // erase_overstrike, eo, eo - generic_type, // generic_type, gn, gn - hard_copy, // hard_copy, hc, hc - hard_cursor, // hard_cursor, chts, HC - has_meta_key, // has_meta_key, km, km - has_print_wheel, // has_print_wheel, daisy, YC - has_status_line, // has_status_line, hs, hs - hue_lightness_saturation, // hue_lightness_saturation, hls, hl - insert_null_glitch, // insert_null_glitch, in, in - lpi_changes_res, // lpi_changes_res, lpix, YG - memory_above, // memory_above, da, da - memory_below, // memory_below, db, db - move_insert_mode, // move_insert_mode, mir, mi - move_standout_mode, // move_standout_mode, msgr, ms - needs_xon_xoff, // needs_xon_xoff, nxon, nx - no_esc_ctlc, // no_esc_ctlc, xsb, xb - no_pad_char, // no_pad_char, npc, NP - non_dest_scroll_region, // non_dest_scroll_region, ndscr, ND - non_rev_rmcup, // non_rev_rmcup, nrrmc, NR - over_strike, // over_strike, os, os - prtr_silent, // prtr_silent, mc5i, 5i - row_addr_glitch, // row_addr_glitch, xvpa, YD - semi_auto_right_margin, // semi_auto_right_margin, sam, YE - status_line_esc_ok, // status_line_esc_ok, eslok, es - tilde_glitch, // tilde_glitch, hz, hz - transparent_underline, // transparent_underline, ul, ul - xon_xoff, // xon_xoff, xon, xo - columns, // columns, cols, co - init_tabs, // init_tabs, it, it - label_height, // label_height, lh, lh - label_width, // label_width, lw, lw - lines, // lines, lines, li - lines_of_memory, // lines_of_memory, lm, lm - magic_cookie_glitch, // magic_cookie_glitch, xmc, sg - max_attributes, // max_attributes, ma, ma - max_colors, // max_colors, colors, Co - max_pairs, // max_pairs, pairs, pa - maximum_windows, // maximum_windows, wnum, MW - no_color_video, // no_color_video, ncv, NC - num_labels, // num_labels, nlab, Nl - padding_baud_rate, // padding_baud_rate, pb, pb - virtual_terminal, // virtual_terminal, vt, vt - width_status_line, // width_status_line, wsl, ws - bit_image_entwining, // bit_image_entwining, bitwin, Yo - bit_image_type, // bit_image_type, bitype, Yp - buffer_capacity, // buffer_capacity, bufsz, Ya - buttons, // buttons, btns, BT - dot_horz_spacing, // dot_horz_spacing, spinh, Yc - dot_vert_spacing, // dot_vert_spacing, spinv, Yb - max_micro_address, // max_micro_address, maddr, Yd - max_micro_jump, // max_micro_jump, mjump, Ye - micro_col_size, // micro_col_size, mcs, Yf - micro_line_size, // micro_line_size, mls, Yg - number_of_pins, // number_of_pins, npins, Yh - output_res_char, // output_res_char, orc, Yi - output_res_horz_inch, // output_res_horz_inch, orhi, Yk - output_res_line, // output_res_line, orl, Yj - output_res_vert_inch, // output_res_vert_inch, orvi, Yl - print_rate, // print_rate, cps, Ym - wide_char_size, // wide_char_size, widcs, Yn - acs_chars, // acs_chars, acsc, ac - back_tab, // back_tab, cbt, bt - bell, // bell, bel, bl - carriage_return, // carriage_return, cr, cr - change_char_pitch, // change_char_pitch, cpi, ZA - change_line_pitch, // change_line_pitch, lpi, ZB - change_res_horz, // change_res_horz, chr, ZC - change_res_vert, // change_res_vert, cvr, ZD - change_scroll_region, // change_scroll_region, csr, cs - char_padding, // char_padding, rmp, rP - clear_all_tabs, // clear_all_tabs, tbc, ct - clear_margins, // clear_margins, mgc, MC - clear_screen, // clear_screen, clear, cl - clr_bol, // clr_bol, el1, cb - clr_eol, // clr_eol, el, ce - clr_eos, // clr_eos, ed, cd - column_address, // column_address, hpa, ch - command_character, // command_character, cmdch, CC - create_window, // create_window, cwin, CW - cursor_address, // cursor_address, cup, cm - cursor_down, // cursor_down, cud1, do - cursor_home, // cursor_home, home, ho - cursor_invisible, // cursor_invisible, civis, vi - cursor_left, // cursor_left, cub1, le - cursor_mem_address, // cursor_mem_address, mrcup, CM - cursor_normal, // cursor_normal, cnorm, ve - cursor_right, // cursor_right, cuf1, nd - cursor_to_ll, // cursor_to_ll, ll, ll - cursor_up, // cursor_up, cuu1, up - cursor_visible, // cursor_visible, cvvis, vs - define_char, // define_char, defc, ZE - delete_character, // delete_character, dch1, dc - delete_line, // delete_line, dl1, dl - dial_phone, // dial_phone, dial, DI - dis_status_line, // dis_status_line, dsl, ds - display_clock, // display_clock, dclk, DK - down_half_line, // down_half_line, hd, hd - ena_acs, // ena_acs, enacs, eA - enter_alt_charset_mode, // enter_alt_charset_mode, smacs, as - enter_am_mode, // enter_am_mode, smam, SA - enter_blink_mode, // enter_blink_mode, blink, mb - enter_bold_mode, // enter_bold_mode, bold, md - enter_ca_mode, // enter_ca_mode, smcup, ti - enter_delete_mode, // enter_delete_mode, smdc, dm - enter_dim_mode, // enter_dim_mode, dim, mh - enter_doublewide_mode, // enter_doublewide_mode, swidm, ZF - enter_draft_quality, // enter_draft_quality, sdrfq, ZG - enter_insert_mode, // enter_insert_mode, smir, im - enter_italics_mode, // enter_italics_mode, sitm, ZH - enter_leftward_mode, // enter_leftward_mode, slm, ZI - enter_micro_mode, // enter_micro_mode, smicm, ZJ - enter_near_letter_quality, // enter_near_letter_quality, snlq, ZK - enter_normal_quality, // enter_normal_quality, snrmq, ZL - enter_protected_mode, // enter_protected_mode, prot, mp - enter_reverse_mode, // enter_reverse_mode, rev, mr - enter_secure_mode, // enter_secure_mode, invis, mk - enter_shadow_mode, // enter_shadow_mode, sshm, ZM - enter_standout_mode, // enter_standout_mode, smso, so - enter_subscript_mode, // enter_subscript_mode, ssubm, ZN - enter_superscript_mode, // enter_superscript_mode, ssupm, ZO - enter_underline_mode, // enter_underline_mode, smul, us - enter_upward_mode, // enter_upward_mode, sum, ZP - enter_xon_mode, // enter_xon_mode, smxon, SX - erase_chars, // erase_chars, ech, ec - exit_alt_charset_mode, // exit_alt_charset_mode, rmacs, ae - exit_am_mode, // exit_am_mode, rmam, RA - exit_attribute_mode, // exit_attribute_mode, sgr0, me - exit_ca_mode, // exit_ca_mode, rmcup, te - exit_delete_mode, // exit_delete_mode, rmdc, ed - exit_doublewide_mode, // exit_doublewide_mode, rwidm, ZQ - exit_insert_mode, // exit_insert_mode, rmir, ei - exit_italics_mode, // exit_italics_mode, ritm, ZR - exit_leftward_mode, // exit_leftward_mode, rlm, ZS - exit_micro_mode, // exit_micro_mode, rmicm, ZT - exit_shadow_mode, // exit_shadow_mode, rshm, ZU - exit_standout_mode, // exit_standout_mode, rmso, se - exit_subscript_mode, // exit_subscript_mode, rsubm, ZV - exit_superscript_mode, // exit_superscript_mode, rsupm, ZW - exit_underline_mode, // exit_underline_mode, rmul, ue - exit_upward_mode, // exit_upward_mode, rum, ZX - exit_xon_mode, // exit_xon_mode, rmxon, RX - fixed_pause, // fixed_pause, pause, PA - flash_hook, // flash_hook, hook, fh - flash_screen, // flash_screen, flash, vb - form_feed, // form_feed, ff, ff - from_status_line, // from_status_line, fsl, fs - goto_window, // goto_window, wingo, WG - hangup, // hangup, hup, HU - init_1string, // init_1string, is1, i1 - init_2string, // init_2string, is2, is - init_3string, // init_3string, is3, i3 - init_file, // init_file, if, if - init_prog, // init_prog, iprog, iP - initialize_color, // initialize_color, initc, Ic - initialize_pair, // initialize_pair, initp, Ip - insert_character, // insert_character, ich1, ic - insert_line, // insert_line, il1, al - insert_padding, // insert_padding, ip, ip - key_a1, // key_a1, ka1, K1 - key_a3, // key_a3, ka3, K3 - key_b2, // key_b2, kb2, K2 - key_backspace, // key_backspace, kbs, kb - key_beg, // key_beg, kbeg, @1 - key_btab, // key_btab, kcbt, kB - key_c1, // key_c1, kc1, K4 - key_c3, // key_c3, kc3, K5 - key_cancel, // key_cancel, kcan, @2 - key_catab, // key_catab, ktbc, ka - key_clear, // key_clear, kclr, kC - key_close, // key_close, kclo, @3 - key_command, // key_command, kcmd, @4 - key_copy, // key_copy, kcpy, @5 - key_create, // key_create, kcrt, @6 - key_ctab, // key_ctab, kctab, kt - key_dc, // key_dc, kdch1, kD - key_dl, // key_dl, kdl1, kL - key_down, // key_down, kcud1, kd - key_eic, // key_eic, krmir, kM - key_end, // key_end, kend, @7 - key_enter, // key_enter, kent, @8 - key_eol, // key_eol, kel, kE - key_eos, // key_eos, ked, kS - key_exit, // key_exit, kext, @9 - key_f0, // key_f0, kf0, k0 - key_f1, // key_f1, kf1, k1 - key_f10, // key_f10, kf10, k; - key_f11, // key_f11, kf11, F1 - key_f12, // key_f12, kf12, F2 - key_f13, // key_f13, kf13, F3 - key_f14, // key_f14, kf14, F4 - key_f15, // key_f15, kf15, F5 - key_f16, // key_f16, kf16, F6 - key_f17, // key_f17, kf17, F7 - key_f18, // key_f18, kf18, F8 - key_f19, // key_f19, kf19, F9 - key_f2, // key_f2, kf2, k2 - key_f20, // key_f20, kf20, FA - key_f21, // key_f21, kf21, FB - key_f22, // key_f22, kf22, FC - key_f23, // key_f23, kf23, FD - key_f24, // key_f24, kf24, FE - key_f25, // key_f25, kf25, FF - key_f26, // key_f26, kf26, FG - key_f27, // key_f27, kf27, FH - key_f28, // key_f28, kf28, FI - key_f29, // key_f29, kf29, FJ - key_f3, // key_f3, kf3, k3 - key_f30, // key_f30, kf30, FK - key_f31, // key_f31, kf31, FL - key_f32, // key_f32, kf32, FM - key_f33, // key_f33, kf33, FN - key_f34, // key_f34, kf34, FO - key_f35, // key_f35, kf35, FP - key_f36, // key_f36, kf36, FQ - key_f37, // key_f37, kf37, FR - key_f38, // key_f38, kf38, FS - key_f39, // key_f39, kf39, FT - key_f4, // key_f4, kf4, k4 - key_f40, // key_f40, kf40, FU - key_f41, // key_f41, kf41, FV - key_f42, // key_f42, kf42, FW - key_f43, // key_f43, kf43, FX - key_f44, // key_f44, kf44, FY - key_f45, // key_f45, kf45, FZ - key_f46, // key_f46, kf46, Fa - key_f47, // key_f47, kf47, Fb - key_f48, // key_f48, kf48, Fc - key_f49, // key_f49, kf49, Fd - key_f5, // key_f5, kf5, k5 - key_f50, // key_f50, kf50, Fe - key_f51, // key_f51, kf51, Ff - key_f52, // key_f52, kf52, Fg - key_f53, // key_f53, kf53, Fh - key_f54, // key_f54, kf54, Fi - key_f55, // key_f55, kf55, Fj - key_f56, // key_f56, kf56, Fk - key_f57, // key_f57, kf57, Fl - key_f58, // key_f58, kf58, Fm - key_f59, // key_f59, kf59, Fn - key_f6, // key_f6, kf6, k6 - key_f60, // key_f60, kf60, Fo - key_f61, // key_f61, kf61, Fp - key_f62, // key_f62, kf62, Fq - key_f63, // key_f63, kf63, Fr - key_f7, // key_f7, kf7, k7 - key_f8, // key_f8, kf8, k8 - key_f9, // key_f9, kf9, k9 - key_find, // key_find, kfnd, @0 - key_help, // key_help, khlp, %1 - key_home, // key_home, khome, kh - key_ic, // key_ic, kich1, kI - key_il, // key_il, kil1, kA - key_left, // key_left, kcub1, kl - key_ll, // key_ll, kll, kH - key_mark, // key_mark, kmrk, %2 - key_message, // key_message, kmsg, %3 - key_move, // key_move, kmov, %4 - key_next, // key_next, knxt, %5 - key_npage, // key_npage, knp, kN - key_open, // key_open, kopn, %6 - key_options, // key_options, kopt, %7 - key_ppage, // key_ppage, kpp, kP - key_previous, // key_previous, kprv, %8 - key_print, // key_print, kprt, %9 - key_redo, // key_redo, krdo, %0 - key_reference, // key_reference, kref, &1 - key_refresh, // key_refresh, krfr, &2 - key_replace, // key_replace, krpl, &3 - key_restart, // key_restart, krst, &4 - key_resume, // key_resume, kres, &5 - key_right, // key_right, kcuf1, kr - key_save, // key_save, ksav, &6 - key_sbeg, // key_sbeg, kBEG, &9 - key_scancel, // key_scancel, kCAN, &0 - key_scommand, // key_scommand, kCMD, *1 - key_scopy, // key_scopy, kCPY, *2 - key_screate, // key_screate, kCRT, *3 - key_sdc, // key_sdc, kDC, *4 - key_sdl, // key_sdl, kDL, *5 - key_select, // key_select, kslt, *6 - key_send, // key_send, kEND, *7 - key_seol, // key_seol, kEOL, *8 - key_sexit, // key_sexit, kEXT, *9 - key_sf, // key_sf, kind, kF - key_sfind, // key_sfind, kFND, *0 - key_shelp, // key_shelp, kHLP, #1 - key_shome, // key_shome, kHOM, #2 - key_sic, // key_sic, kIC, #3 - key_sleft, // key_sleft, kLFT, #4 - key_smessage, // key_smessage, kMSG, %a - key_smove, // key_smove, kMOV, %b - key_snext, // key_snext, kNXT, %c - key_soptions, // key_soptions, kOPT, %d - key_sprevious, // key_sprevious, kPRV, %e - key_sprint, // key_sprint, kPRT, %f - key_sr, // key_sr, kri, kR - key_sredo, // key_sredo, kRDO, %g - key_sreplace, // key_sreplace, kRPL, %h - key_sright, // key_sright, kRIT, %i - key_srsume, // key_srsume, kRES, %j - key_ssave, // key_ssave, kSAV, !1 - key_ssuspend, // key_ssuspend, kSPD, !2 - key_stab, // key_stab, khts, kT - key_sundo, // key_sundo, kUND, !3 - key_suspend, // key_suspend, kspd, &7 - key_undo, // key_undo, kund, &8 - key_up, // key_up, kcuu1, ku - keypad_local, // keypad_local, rmkx, ke - keypad_xmit, // keypad_xmit, smkx, ks - lab_f0, // lab_f0, lf0, l0 - lab_f1, // lab_f1, lf1, l1 - lab_f10, // lab_f10, lf10, la - lab_f2, // lab_f2, lf2, l2 - lab_f3, // lab_f3, lf3, l3 - lab_f4, // lab_f4, lf4, l4 - lab_f5, // lab_f5, lf5, l5 - lab_f6, // lab_f6, lf6, l6 - lab_f7, // lab_f7, lf7, l7 - lab_f8, // lab_f8, lf8, l8 - lab_f9, // lab_f9, lf9, l9 - label_format, // label_format, fln, Lf - label_off, // label_off, rmln, LF - label_on, // label_on, smln, LO - meta_off, // meta_off, rmm, mo - meta_on, // meta_on, smm, mm - micro_column_address, // micro_column_address, mhpa, ZY - micro_down, // micro_down, mcud1, ZZ - micro_left, // micro_left, mcub1, Za - micro_right, // micro_right, mcuf1, Zb - micro_row_address, // micro_row_address, mvpa, Zc - micro_up, // micro_up, mcuu1, Zd - newline, // newline, nel, nw - order_of_pins, // order_of_pins, porder, Ze - orig_colors, // orig_colors, oc, oc - orig_pair, // orig_pair, op, op - pad_char, // pad_char, pad, pc - parm_dch, // parm_dch, dch, DC - parm_delete_line, // parm_delete_line, dl, DL - parm_down_cursor, // parm_down_cursor, cud, DO - parm_down_micro, // parm_down_micro, mcud, Zf - parm_ich, // parm_ich, ich, IC - parm_index, // parm_index, indn, SF - parm_insert_line, // parm_insert_line, il, AL - parm_left_cursor, // parm_left_cursor, cub, LE - parm_left_micro, // parm_left_micro, mcub, Zg - parm_right_cursor, // parm_right_cursor, cuf, RI - parm_right_micro, // parm_right_micro, mcuf, Zh - parm_rindex, // parm_rindex, rin, SR - parm_up_cursor, // parm_up_cursor, cuu, UP - parm_up_micro, // parm_up_micro, mcuu, Zi - pkey_key, // pkey_key, pfkey, pk - pkey_local, // pkey_local, pfloc, pl - pkey_xmit, // pkey_xmit, pfx, px - plab_norm, // plab_norm, pln, pn - print_screen, // print_screen, mc0, ps - prtr_non, // prtr_non, mc5p, pO - prtr_off, // prtr_off, mc4, pf - prtr_on, // prtr_on, mc5, po - pulse, // pulse, pulse, PU - quick_dial, // quick_dial, qdial, QD - remove_clock, // remove_clock, rmclk, RC - repeat_char, // repeat_char, rep, rp - req_for_input, // req_for_input, rfi, RF - reset_1string, // reset_1string, rs1, r1 - reset_2string, // reset_2string, rs2, r2 - reset_3string, // reset_3string, rs3, r3 - reset_file, // reset_file, rf, rf - restore_cursor, // restore_cursor, rc, rc - row_address, // row_address, vpa, cv - save_cursor, // save_cursor, sc, sc - scroll_forward, // scroll_forward, ind, sf - scroll_reverse, // scroll_reverse, ri, sr - select_char_set, // select_char_set, scs, Zj - set_attributes, // set_attributes, sgr, sa - set_background, // set_background, setb, Sb - set_bottom_margin, // set_bottom_margin, smgb, Zk - set_bottom_margin_parm, // set_bottom_margin_parm, smgbp, Zl - set_clock, // set_clock, sclk, SC - set_color_pair, // set_color_pair, scp, sp - set_foreground, // set_foreground, setf, Sf - set_left_margin, // set_left_margin, smgl, ML - set_left_margin_parm, // set_left_margin_parm, smglp, Zm - set_right_margin, // set_right_margin, smgr, MR - set_right_margin_parm, // set_right_margin_parm, smgrp, Zn - set_tab, // set_tab, hts, st - set_top_margin, // set_top_margin, smgt, Zo - set_top_margin_parm, // set_top_margin_parm, smgtp, Zp - set_window, // set_window, wind, wi - start_bit_image, // start_bit_image, sbim, Zq - start_char_set_def, // start_char_set_def, scsd, Zr - stop_bit_image, // stop_bit_image, rbim, Zs - stop_char_set_def, // stop_char_set_def, rcsd, Zt - subscript_characters, // subscript_characters, subcs, Zu - superscript_characters, // superscript_characters, supcs, Zv - tab, // tab, ht, ta - these_cause_cr, // these_cause_cr, docr, Zw - to_status_line, // to_status_line, tsl, ts - tone, // tone, tone, TO - underline_char, // underline_char, uc, uc - up_half_line, // up_half_line, hu, hu - user0, // user0, u0, u0 - user1, // user1, u1, u1 - user2, // user2, u2, u2 - user3, // user3, u3, u3 - user4, // user4, u4, u4 - user5, // user5, u5, u5 - user6, // user6, u6, u6 - user7, // user7, u7, u7 - user8, // user8, u8, u8 - user9, // user9, u9, u9 - wait_tone, // wait_tone, wait, WA - xoff_character, // xoff_character, xoffc, XF - xon_character, // xon_character, xonc, XN - zero_motion, // zero_motion, zerom, Zx - alt_scancode_esc, // alt_scancode_esc, scesa, S8 - bit_image_carriage_return, // bit_image_carriage_return, bicr, Yv - bit_image_newline, // bit_image_newline, binel, Zz - bit_image_repeat, // bit_image_repeat, birep, Xy - char_set_names, // char_set_names, csnm, Zy - code_set_init, // code_set_init, csin, ci - color_names, // color_names, colornm, Yw - define_bit_image_region, // define_bit_image_region, defbi, Yx - device_type, // device_type, devt, dv - display_pc_char, // display_pc_char, dispc, S1 - end_bit_image_region, // end_bit_image_region, endbi, Yy - enter_pc_charset_mode, // enter_pc_charset_mode, smpch, S2 - enter_scancode_mode, // enter_scancode_mode, smsc, S4 - exit_pc_charset_mode, // exit_pc_charset_mode, rmpch, S3 - exit_scancode_mode, // exit_scancode_mode, rmsc, S5 - get_mouse, // get_mouse, getm, Gm - key_mouse, // key_mouse, kmous, Km - mouse_info, // mouse_info, minfo, Mi - pc_term_options, // pc_term_options, pctrm, S6 - pkey_plab, // pkey_plab, pfxl, xl - req_mouse_pos, // req_mouse_pos, reqmp, RQ - scancode_escape, // scancode_escape, scesc, S7 - set0_des_seq, // set0_des_seq, s0ds, s0 - set1_des_seq, // set1_des_seq, s1ds, s1 - set2_des_seq, // set2_des_seq, s2ds, s2 - set3_des_seq, // set3_des_seq, s3ds, s3 - set_a_background, // set_a_background, setab, AB - set_a_foreground, // set_a_foreground, setaf, AF - set_color_band, // set_color_band, setcolor, Yz - set_lr_margin, // set_lr_margin, smglr, ML - set_page_length, // set_page_length, slines, YZ - set_tb_margin, // set_tb_margin, smgtb, MT - enter_horizontal_hl_mode, // enter_horizontal_hl_mode, ehhlm, Xh - enter_left_hl_mode, // enter_left_hl_mode, elhlm, Xl - enter_low_hl_mode, // enter_low_hl_mode, elohlm, Xo - enter_right_hl_mode, // enter_right_hl_mode, erhlm, Xr - enter_top_hl_mode, // enter_top_hl_mode, ethlm, Xt - enter_vertical_hl_mode, // enter_vertical_hl_mode, evhlm, Xv - set_a_attributes, // set_a_attributes, sgr1, sA - set_pglen_inch, // set_pglen_inch, slength, sL) + auto_left_margin, // auto_left_margin, bw, bw + auto_right_margin, // auto_right_margin, am, am + back_color_erase, // back_color_erase, bce, ut + can_change, // can_change, ccc, cc + ceol_standout_glitch, // ceol_standout_glitch, xhp, xs + col_addr_glitch, // col_addr_glitch, xhpa, YA + cpi_changes_res, // cpi_changes_res, cpix, YF + cr_cancels_micro_mode, // cr_cancels_micro_mode, crxm, YB + dest_tabs_magic_smso, // dest_tabs_magic_smso, xt, xt + eat_newline_glitch, // eat_newline_glitch, xenl, xn + erase_overstrike, // erase_overstrike, eo, eo + generic_type, // generic_type, gn, gn + hard_copy, // hard_copy, hc, hc + hard_cursor, // hard_cursor, chts, HC + has_meta_key, // has_meta_key, km, km + has_print_wheel, // has_print_wheel, daisy, YC + has_status_line, // has_status_line, hs, hs + hue_lightness_saturation, // hue_lightness_saturation, hls, hl + insert_null_glitch, // insert_null_glitch, in, in + lpi_changes_res, // lpi_changes_res, lpix, YG + memory_above, // memory_above, da, da + memory_below, // memory_below, db, db + move_insert_mode, // move_insert_mode, mir, mi + move_standout_mode, // move_standout_mode, msgr, ms + needs_xon_xoff, // needs_xon_xoff, nxon, nx + no_esc_ctlc, // no_esc_ctlc, xsb, xb + no_pad_char, // no_pad_char, npc, NP + non_dest_scroll_region, // non_dest_scroll_region, ndscr, ND + non_rev_rmcup, // non_rev_rmcup, nrrmc, NR + over_strike, // over_strike, os, os + prtr_silent, // prtr_silent, mc5i, 5i + row_addr_glitch, // row_addr_glitch, xvpa, YD + semi_auto_right_margin, // semi_auto_right_margin, sam, YE + status_line_esc_ok, // status_line_esc_ok, eslok, es + tilde_glitch, // tilde_glitch, hz, hz + transparent_underline, // transparent_underline, ul, ul + xon_xoff, // xon_xoff, xon, xo + columns, // columns, cols, co + init_tabs, // init_tabs, it, it + label_height, // label_height, lh, lh + label_width, // label_width, lw, lw + lines, // lines, lines, li + lines_of_memory, // lines_of_memory, lm, lm + magic_cookie_glitch, // magic_cookie_glitch, xmc, sg + max_attributes, // max_attributes, ma, ma + max_colors, // max_colors, colors, Co + max_pairs, // max_pairs, pairs, pa + maximum_windows, // maximum_windows, wnum, MW + no_color_video, // no_color_video, ncv, NC + num_labels, // num_labels, nlab, Nl + padding_baud_rate, // padding_baud_rate, pb, pb + virtual_terminal, // virtual_terminal, vt, vt + width_status_line, // width_status_line, wsl, ws + bit_image_entwining, // bit_image_entwining, bitwin, Yo + bit_image_type, // bit_image_type, bitype, Yp + buffer_capacity, // buffer_capacity, bufsz, Ya + buttons, // buttons, btns, BT + dot_horz_spacing, // dot_horz_spacing, spinh, Yc + dot_vert_spacing, // dot_vert_spacing, spinv, Yb + max_micro_address, // max_micro_address, maddr, Yd + max_micro_jump, // max_micro_jump, mjump, Ye + micro_col_size, // micro_col_size, mcs, Yf + micro_line_size, // micro_line_size, mls, Yg + number_of_pins, // number_of_pins, npins, Yh + output_res_char, // output_res_char, orc, Yi + output_res_horz_inch, // output_res_horz_inch, orhi, Yk + output_res_line, // output_res_line, orl, Yj + output_res_vert_inch, // output_res_vert_inch, orvi, Yl + print_rate, // print_rate, cps, Ym + wide_char_size, // wide_char_size, widcs, Yn + acs_chars, // acs_chars, acsc, ac + back_tab, // back_tab, cbt, bt + bell, // bell, bel, bl + carriage_return, // carriage_return, cr, cr + change_char_pitch, // change_char_pitch, cpi, ZA + change_line_pitch, // change_line_pitch, lpi, ZB + change_res_horz, // change_res_horz, chr, ZC + change_res_vert, // change_res_vert, cvr, ZD + change_scroll_region, // change_scroll_region, csr, cs + char_padding, // char_padding, rmp, rP + clear_all_tabs, // clear_all_tabs, tbc, ct + clear_margins, // clear_margins, mgc, MC + clear_screen, // clear_screen, clear, cl + clr_bol, // clr_bol, el1, cb + clr_eol, // clr_eol, el, ce + clr_eos, // clr_eos, ed, cd + column_address, // column_address, hpa, ch + command_character, // command_character, cmdch, CC + create_window, // create_window, cwin, CW + cursor_address, // cursor_address, cup, cm + cursor_down, // cursor_down, cud1, do + cursor_home, // cursor_home, home, ho + cursor_invisible, // cursor_invisible, civis, vi + cursor_left, // cursor_left, cub1, le + cursor_mem_address, // cursor_mem_address, mrcup, CM + cursor_normal, // cursor_normal, cnorm, ve + cursor_right, // cursor_right, cuf1, nd + cursor_to_ll, // cursor_to_ll, ll, ll + cursor_up, // cursor_up, cuu1, up + cursor_visible, // cursor_visible, cvvis, vs + define_char, // define_char, defc, ZE + delete_character, // delete_character, dch1, dc + delete_line, // delete_line, dl1, dl + dial_phone, // dial_phone, dial, DI + dis_status_line, // dis_status_line, dsl, ds + display_clock, // display_clock, dclk, DK + down_half_line, // down_half_line, hd, hd + ena_acs, // ena_acs, enacs, eA + enter_alt_charset_mode, // enter_alt_charset_mode, smacs, as + enter_am_mode, // enter_am_mode, smam, SA + enter_blink_mode, // enter_blink_mode, blink, mb + enter_bold_mode, // enter_bold_mode, bold, md + enter_ca_mode, // enter_ca_mode, smcup, ti + enter_delete_mode, // enter_delete_mode, smdc, dm + enter_dim_mode, // enter_dim_mode, dim, mh + enter_doublewide_mode, // enter_doublewide_mode, swidm, ZF + enter_draft_quality, // enter_draft_quality, sdrfq, ZG + enter_insert_mode, // enter_insert_mode, smir, im + enter_italics_mode, // enter_italics_mode, sitm, ZH + enter_leftward_mode, // enter_leftward_mode, slm, ZI + enter_micro_mode, // enter_micro_mode, smicm, ZJ + enter_near_letter_quality, // enter_near_letter_quality, snlq, ZK + enter_normal_quality, // enter_normal_quality, snrmq, ZL + enter_protected_mode, // enter_protected_mode, prot, mp + enter_reverse_mode, // enter_reverse_mode, rev, mr + enter_secure_mode, // enter_secure_mode, invis, mk + enter_shadow_mode, // enter_shadow_mode, sshm, ZM + enter_standout_mode, // enter_standout_mode, smso, so + enter_subscript_mode, // enter_subscript_mode, ssubm, ZN + enter_superscript_mode, // enter_superscript_mode, ssupm, ZO + enter_underline_mode, // enter_underline_mode, smul, us + enter_upward_mode, // enter_upward_mode, sum, ZP + enter_xon_mode, // enter_xon_mode, smxon, SX + erase_chars, // erase_chars, ech, ec + exit_alt_charset_mode, // exit_alt_charset_mode, rmacs, ae + exit_am_mode, // exit_am_mode, rmam, RA + exit_attribute_mode, // exit_attribute_mode, sgr0, me + exit_ca_mode, // exit_ca_mode, rmcup, te + exit_delete_mode, // exit_delete_mode, rmdc, ed + exit_doublewide_mode, // exit_doublewide_mode, rwidm, ZQ + exit_insert_mode, // exit_insert_mode, rmir, ei + exit_italics_mode, // exit_italics_mode, ritm, ZR + exit_leftward_mode, // exit_leftward_mode, rlm, ZS + exit_micro_mode, // exit_micro_mode, rmicm, ZT + exit_shadow_mode, // exit_shadow_mode, rshm, ZU + exit_standout_mode, // exit_standout_mode, rmso, se + exit_subscript_mode, // exit_subscript_mode, rsubm, ZV + exit_superscript_mode, // exit_superscript_mode, rsupm, ZW + exit_underline_mode, // exit_underline_mode, rmul, ue + exit_upward_mode, // exit_upward_mode, rum, ZX + exit_xon_mode, // exit_xon_mode, rmxon, RX + fixed_pause, // fixed_pause, pause, PA + flash_hook, // flash_hook, hook, fh + flash_screen, // flash_screen, flash, vb + form_feed, // form_feed, ff, ff + from_status_line, // from_status_line, fsl, fs + goto_window, // goto_window, wingo, WG + hangup, // hangup, hup, HU + init_1string, // init_1string, is1, i1 + init_2string, // init_2string, is2, is + init_3string, // init_3string, is3, i3 + init_file, // init_file, if, if + init_prog, // init_prog, iprog, iP + initialize_color, // initialize_color, initc, Ic + initialize_pair, // initialize_pair, initp, Ip + insert_character, // insert_character, ich1, ic + insert_line, // insert_line, il1, al + insert_padding, // insert_padding, ip, ip + key_a1, // key_a1, ka1, K1 + key_a3, // key_a3, ka3, K3 + key_b2, // key_b2, kb2, K2 + key_backspace, // key_backspace, kbs, kb + key_beg, // key_beg, kbeg, @1 + key_btab, // key_btab, kcbt, kB + key_c1, // key_c1, kc1, K4 + key_c3, // key_c3, kc3, K5 + key_cancel, // key_cancel, kcan, @2 + key_catab, // key_catab, ktbc, ka + key_clear, // key_clear, kclr, kC + key_close, // key_close, kclo, @3 + key_command, // key_command, kcmd, @4 + key_copy, // key_copy, kcpy, @5 + key_create, // key_create, kcrt, @6 + key_ctab, // key_ctab, kctab, kt + key_dc, // key_dc, kdch1, kD + key_dl, // key_dl, kdl1, kL + key_down, // key_down, kcud1, kd + key_eic, // key_eic, krmir, kM + key_end, // key_end, kend, @7 + key_enter, // key_enter, kent, @8 + key_eol, // key_eol, kel, kE + key_eos, // key_eos, ked, kS + key_exit, // key_exit, kext, @9 + key_f0, // key_f0, kf0, k0 + key_f1, // key_f1, kf1, k1 + key_f10, // key_f10, kf10, k; + key_f11, // key_f11, kf11, F1 + key_f12, // key_f12, kf12, F2 + key_f13, // key_f13, kf13, F3 + key_f14, // key_f14, kf14, F4 + key_f15, // key_f15, kf15, F5 + key_f16, // key_f16, kf16, F6 + key_f17, // key_f17, kf17, F7 + key_f18, // key_f18, kf18, F8 + key_f19, // key_f19, kf19, F9 + key_f2, // key_f2, kf2, k2 + key_f20, // key_f20, kf20, FA + key_f21, // key_f21, kf21, FB + key_f22, // key_f22, kf22, FC + key_f23, // key_f23, kf23, FD + key_f24, // key_f24, kf24, FE + key_f25, // key_f25, kf25, FF + key_f26, // key_f26, kf26, FG + key_f27, // key_f27, kf27, FH + key_f28, // key_f28, kf28, FI + key_f29, // key_f29, kf29, FJ + key_f3, // key_f3, kf3, k3 + key_f30, // key_f30, kf30, FK + key_f31, // key_f31, kf31, FL + key_f32, // key_f32, kf32, FM + key_f33, // key_f33, kf33, FN + key_f34, // key_f34, kf34, FO + key_f35, // key_f35, kf35, FP + key_f36, // key_f36, kf36, FQ + key_f37, // key_f37, kf37, FR + key_f38, // key_f38, kf38, FS + key_f39, // key_f39, kf39, FT + key_f4, // key_f4, kf4, k4 + key_f40, // key_f40, kf40, FU + key_f41, // key_f41, kf41, FV + key_f42, // key_f42, kf42, FW + key_f43, // key_f43, kf43, FX + key_f44, // key_f44, kf44, FY + key_f45, // key_f45, kf45, FZ + key_f46, // key_f46, kf46, Fa + key_f47, // key_f47, kf47, Fb + key_f48, // key_f48, kf48, Fc + key_f49, // key_f49, kf49, Fd + key_f5, // key_f5, kf5, k5 + key_f50, // key_f50, kf50, Fe + key_f51, // key_f51, kf51, Ff + key_f52, // key_f52, kf52, Fg + key_f53, // key_f53, kf53, Fh + key_f54, // key_f54, kf54, Fi + key_f55, // key_f55, kf55, Fj + key_f56, // key_f56, kf56, Fk + key_f57, // key_f57, kf57, Fl + key_f58, // key_f58, kf58, Fm + key_f59, // key_f59, kf59, Fn + key_f6, // key_f6, kf6, k6 + key_f60, // key_f60, kf60, Fo + key_f61, // key_f61, kf61, Fp + key_f62, // key_f62, kf62, Fq + key_f63, // key_f63, kf63, Fr + key_f7, // key_f7, kf7, k7 + key_f8, // key_f8, kf8, k8 + key_f9, // key_f9, kf9, k9 + key_find, // key_find, kfnd, @0 + key_help, // key_help, khlp, %1 + key_home, // key_home, khome, kh + key_ic, // key_ic, kich1, kI + key_il, // key_il, kil1, kA + key_left, // key_left, kcub1, kl + key_ll, // key_ll, kll, kH + key_mark, // key_mark, kmrk, %2 + key_message, // key_message, kmsg, %3 + key_move, // key_move, kmov, %4 + key_next, // key_next, knxt, %5 + key_npage, // key_npage, knp, kN + key_open, // key_open, kopn, %6 + key_options, // key_options, kopt, %7 + key_ppage, // key_ppage, kpp, kP + key_previous, // key_previous, kprv, %8 + key_print, // key_print, kprt, %9 + key_redo, // key_redo, krdo, %0 + key_reference, // key_reference, kref, &1 + key_refresh, // key_refresh, krfr, &2 + key_replace, // key_replace, krpl, &3 + key_restart, // key_restart, krst, &4 + key_resume, // key_resume, kres, &5 + key_right, // key_right, kcuf1, kr + key_save, // key_save, ksav, &6 + key_sbeg, // key_sbeg, kBEG, &9 + key_scancel, // key_scancel, kCAN, &0 + key_scommand, // key_scommand, kCMD, *1 + key_scopy, // key_scopy, kCPY, *2 + key_screate, // key_screate, kCRT, *3 + key_sdc, // key_sdc, kDC, *4 + key_sdl, // key_sdl, kDL, *5 + key_select, // key_select, kslt, *6 + key_send, // key_send, kEND, *7 + key_seol, // key_seol, kEOL, *8 + key_sexit, // key_sexit, kEXT, *9 + key_sf, // key_sf, kind, kF + key_sfind, // key_sfind, kFND, *0 + key_shelp, // key_shelp, kHLP, #1 + key_shome, // key_shome, kHOM, #2 + key_sic, // key_sic, kIC, #3 + key_sleft, // key_sleft, kLFT, #4 + key_smessage, // key_smessage, kMSG, %a + key_smove, // key_smove, kMOV, %b + key_snext, // key_snext, kNXT, %c + key_soptions, // key_soptions, kOPT, %d + key_sprevious, // key_sprevious, kPRV, %e + key_sprint, // key_sprint, kPRT, %f + key_sr, // key_sr, kri, kR + key_sredo, // key_sredo, kRDO, %g + key_sreplace, // key_sreplace, kRPL, %h + key_sright, // key_sright, kRIT, %i + key_srsume, // key_srsume, kRES, %j + key_ssave, // key_ssave, kSAV, !1 + key_ssuspend, // key_ssuspend, kSPD, !2 + key_stab, // key_stab, khts, kT + key_sundo, // key_sundo, kUND, !3 + key_suspend, // key_suspend, kspd, &7 + key_undo, // key_undo, kund, &8 + key_up, // key_up, kcuu1, ku + keypad_local, // keypad_local, rmkx, ke + keypad_xmit, // keypad_xmit, smkx, ks + lab_f0, // lab_f0, lf0, l0 + lab_f1, // lab_f1, lf1, l1 + lab_f10, // lab_f10, lf10, la + lab_f2, // lab_f2, lf2, l2 + lab_f3, // lab_f3, lf3, l3 + lab_f4, // lab_f4, lf4, l4 + lab_f5, // lab_f5, lf5, l5 + lab_f6, // lab_f6, lf6, l6 + lab_f7, // lab_f7, lf7, l7 + lab_f8, // lab_f8, lf8, l8 + lab_f9, // lab_f9, lf9, l9 + label_format, // label_format, fln, Lf + label_off, // label_off, rmln, LF + label_on, // label_on, smln, LO + meta_off, // meta_off, rmm, mo + meta_on, // meta_on, smm, mm + micro_column_address, // micro_column_address, mhpa, ZY + micro_down, // micro_down, mcud1, ZZ + micro_left, // micro_left, mcub1, Za + micro_right, // micro_right, mcuf1, Zb + micro_row_address, // micro_row_address, mvpa, Zc + micro_up, // micro_up, mcuu1, Zd + newline, // newline, nel, nw + order_of_pins, // order_of_pins, porder, Ze + orig_colors, // orig_colors, oc, oc + orig_pair, // orig_pair, op, op + pad_char, // pad_char, pad, pc + parm_dch, // parm_dch, dch, DC + parm_delete_line, // parm_delete_line, dl, DL + parm_down_cursor, // parm_down_cursor, cud, DO + parm_down_micro, // parm_down_micro, mcud, Zf + parm_ich, // parm_ich, ich, IC + parm_index, // parm_index, indn, SF + parm_insert_line, // parm_insert_line, il, AL + parm_left_cursor, // parm_left_cursor, cub, LE + parm_left_micro, // parm_left_micro, mcub, Zg + parm_right_cursor, // parm_right_cursor, cuf, RI + parm_right_micro, // parm_right_micro, mcuf, Zh + parm_rindex, // parm_rindex, rin, SR + parm_up_cursor, // parm_up_cursor, cuu, UP + parm_up_micro, // parm_up_micro, mcuu, Zi + pkey_key, // pkey_key, pfkey, pk + pkey_local, // pkey_local, pfloc, pl + pkey_xmit, // pkey_xmit, pfx, px + plab_norm, // plab_norm, pln, pn + print_screen, // print_screen, mc0, ps + prtr_non, // prtr_non, mc5p, pO + prtr_off, // prtr_off, mc4, pf + prtr_on, // prtr_on, mc5, po + pulse, // pulse, pulse, PU + quick_dial, // quick_dial, qdial, QD + remove_clock, // remove_clock, rmclk, RC + repeat_char, // repeat_char, rep, rp + req_for_input, // req_for_input, rfi, RF + reset_1string, // reset_1string, rs1, r1 + reset_2string, // reset_2string, rs2, r2 + reset_3string, // reset_3string, rs3, r3 + reset_file, // reset_file, rf, rf + restore_cursor, // restore_cursor, rc, rc + row_address, // row_address, vpa, cv + save_cursor, // save_cursor, sc, sc + scroll_forward, // scroll_forward, ind, sf + scroll_reverse, // scroll_reverse, ri, sr + select_char_set, // select_char_set, scs, Zj + set_attributes, // set_attributes, sgr, sa + set_background, // set_background, setb, Sb + set_bottom_margin, // set_bottom_margin, smgb, Zk + set_bottom_margin_parm, // set_bottom_margin_parm, smgbp, Zl + set_clock, // set_clock, sclk, SC + set_color_pair, // set_color_pair, scp, sp + set_foreground, // set_foreground, setf, Sf + set_left_margin, // set_left_margin, smgl, ML + set_left_margin_parm, // set_left_margin_parm, smglp, Zm + set_right_margin, // set_right_margin, smgr, MR + set_right_margin_parm, // set_right_margin_parm, smgrp, Zn + set_tab, // set_tab, hts, st + set_top_margin, // set_top_margin, smgt, Zo + set_top_margin_parm, // set_top_margin_parm, smgtp, Zp + set_window, // set_window, wind, wi + start_bit_image, // start_bit_image, sbim, Zq + start_char_set_def, // start_char_set_def, scsd, Zr + stop_bit_image, // stop_bit_image, rbim, Zs + stop_char_set_def, // stop_char_set_def, rcsd, Zt + subscript_characters, // subscript_characters, subcs, Zu + superscript_characters, // superscript_characters, supcs, Zv + tab, // tab, ht, ta + these_cause_cr, // these_cause_cr, docr, Zw + to_status_line, // to_status_line, tsl, ts + tone, // tone, tone, TO + underline_char, // underline_char, uc, uc + up_half_line, // up_half_line, hu, hu + user0, // user0, u0, u0 + user1, // user1, u1, u1 + user2, // user2, u2, u2 + user3, // user3, u3, u3 + user4, // user4, u4, u4 + user5, // user5, u5, u5 + user6, // user6, u6, u6 + user7, // user7, u7, u7 + user8, // user8, u8, u8 + user9, // user9, u9, u9 + wait_tone, // wait_tone, wait, WA + xoff_character, // xoff_character, xoffc, XF + xon_character, // xon_character, xonc, XN + zero_motion, // zero_motion, zerom, Zx + alt_scancode_esc, // alt_scancode_esc, scesa, S8 + bit_image_carriage_return, // bit_image_carriage_return, bicr, Yv + bit_image_newline, // bit_image_newline, binel, Zz + bit_image_repeat, // bit_image_repeat, birep, Xy + char_set_names, // char_set_names, csnm, Zy + code_set_init, // code_set_init, csin, ci + color_names, // color_names, colornm, Yw + define_bit_image_region, // define_bit_image_region, defbi, Yx + device_type, // device_type, devt, dv + display_pc_char, // display_pc_char, dispc, S1 + end_bit_image_region, // end_bit_image_region, endbi, Yy + enter_pc_charset_mode, // enter_pc_charset_mode, smpch, S2 + enter_scancode_mode, // enter_scancode_mode, smsc, S4 + exit_pc_charset_mode, // exit_pc_charset_mode, rmpch, S3 + exit_scancode_mode, // exit_scancode_mode, rmsc, S5 + get_mouse, // get_mouse, getm, Gm + key_mouse, // key_mouse, kmous, Km + mouse_info, // mouse_info, minfo, Mi + pc_term_options, // pc_term_options, pctrm, S6 + pkey_plab, // pkey_plab, pfxl, xl + req_mouse_pos, // req_mouse_pos, reqmp, RQ + scancode_escape, // scancode_escape, scesc, S7 + set0_des_seq, // set0_des_seq, s0ds, s0 + set1_des_seq, // set1_des_seq, s1ds, s1 + set2_des_seq, // set2_des_seq, s2ds, s2 + set3_des_seq, // set3_des_seq, s3ds, s3 + set_a_background, // set_a_background, setab, AB + set_a_foreground, // set_a_foreground, setaf, AF + set_color_band, // set_color_band, setcolor, Yz + set_lr_margin, // set_lr_margin, smglr, ML + set_page_length, // set_page_length, slines, YZ + set_tb_margin, // set_tb_margin, smgtb, MT + enter_horizontal_hl_mode, // enter_horizontal_hl_mode, ehhlm, Xh + enter_left_hl_mode, // enter_left_hl_mode, elhlm, Xl + enter_low_hl_mode, // enter_low_hl_mode, elohlm, Xo + enter_right_hl_mode, // enter_right_hl_mode, erhlm, Xr + enter_top_hl_mode, // enter_top_hl_mode, ethlm, Xt + enter_vertical_hl_mode, // enter_vertical_hl_mode, evhlm, Xv + set_a_attributes, // set_a_attributes, sgr1, sA + set_pglen_inch, // set_pglen_inch, slength, sL) ; public String[] getNames() { @@ -515,8 +513,9 @@ public static Capability byName(String name) { public static Map getCapabilitiesByName() { Map capabilities = new LinkedHashMap<>(); try (InputStream is = InfoCmp.class.getResourceAsStream("capabilities.txt"); - BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { - br.lines().map(String::trim) + BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + br.lines() + .map(String::trim) .filter(s -> !s.startsWith("#")) .filter(s -> !s.isEmpty()) .forEach(s -> { @@ -539,9 +538,7 @@ public static void setDefaultInfoCmp(String terminal, Supplier caps) { CAPS.putIfAbsent(terminal, caps); } - public static String getInfoCmp( - String terminal - ) throws IOException, InterruptedException { + public static String getInfoCmp(String terminal) throws IOException, InterruptedException { String caps = getLoadedInfoCmp(terminal); if (caps == null) { Process p = new ProcessBuilder(OSUtils.INFOCMP_COMMAND, terminal).start(); @@ -563,8 +560,7 @@ public static void parseInfoCmp( String capabilities, Set bools, Map ints, - Map strings - ) { + Map strings) { Map capsByName = getCapabilitiesByName(); String[] lines = capabilities.split("\n"); for (int i = 1; i < lines.length; i++) { @@ -609,7 +605,7 @@ public static void parseInfoCmp( static String loadDefaultInfoCmp(String name) { try (InputStream is = InfoCmp.class.getResourceAsStream(name + ".caps"); - BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { return br.lines().collect(Collectors.joining("\n", "", "\n")); } catch (IOException e) { throw new IOError(e); @@ -617,11 +613,23 @@ static String loadDefaultInfoCmp(String name) { } static { - for (String s : Arrays.asList("dumb", "dumb-color", "ansi", "xterm", "xterm-256color", - "windows", "windows-256color", "windows-conemu", "windows-vtp", - "screen", "screen-256color", "rxvt-unicode", "rxvt-unicode-256color", "rxvt-basic", "rxvt")) { + for (String s : Arrays.asList( + "dumb", + "dumb-color", + "ansi", + "xterm", + "xterm-256color", + "windows", + "windows-256color", + "windows-conemu", + "windows-vtp", + "screen", + "screen-256color", + "rxvt-unicode", + "rxvt-unicode-256color", + "rxvt-basic", + "rxvt")) { setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s)); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java index fda314fb9b4aa..449d6aa69c85c 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,7 +22,6 @@ import java.nio.charset.MalformedInputException; import java.nio.charset.UnmappableCharacterException; - /** * * NOTE for JLine: the default InputStreamReader that comes from the JRE @@ -66,9 +65,10 @@ public class InputStreamReader extends Reader { public InputStreamReader(InputStream in) { super(in); this.in = in; - decoder = Charset.defaultCharset().newDecoder().onMalformedInput( - CodingErrorAction.REPLACE).onUnmappableCharacter( - CodingErrorAction.REPLACE); + decoder = Charset.defaultCharset() + .newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); bytes.limit(0); } @@ -87,20 +87,19 @@ public InputStreamReader(InputStream in) { * @throws UnsupportedEncodingException * if the encoding specified by {@code enc} cannot be found. */ - public InputStreamReader(InputStream in, final String enc) - throws UnsupportedEncodingException { + public InputStreamReader(InputStream in, final String enc) throws UnsupportedEncodingException { super(in); if (enc == null) { throw new NullPointerException(); } this.in = in; try { - decoder = Charset.forName(enc).newDecoder().onMalformedInput( - CodingErrorAction.REPLACE).onUnmappableCharacter( - CodingErrorAction.REPLACE); + decoder = Charset.forName(enc) + .newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); } catch (IllegalArgumentException e) { - throw (UnsupportedEncodingException) - new UnsupportedEncodingException(enc).initCause(e); + throw (UnsupportedEncodingException) new UnsupportedEncodingException(enc).initCause(e); } bytes.limit(0); } @@ -134,9 +133,9 @@ public InputStreamReader(InputStream in, CharsetDecoder dec) { public InputStreamReader(InputStream in, Charset charset) { super(in); this.in = in; - decoder = charset.newDecoder().onMalformedInput( - CodingErrorAction.REPLACE).onUnmappableCharacter( - CodingErrorAction.REPLACE); + decoder = charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); bytes.limit(0); } @@ -257,8 +256,7 @@ public int read(char[] buf, int offset, int length) throws IOException { // fill the buffer if needed if (needInput) { try { - if ((in.available() == 0) - && (out.position() > offset)) { + if ((in.available() == 0) && (out.position() > offset)) { // we could return the result without blocking read break; } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java index cc95593ed8071..015515f7d074e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -49,9 +49,8 @@ public static int distance(CharSequence lhs, CharSequence rhs) { return distance(lhs, rhs, 1, 1, 1, 1); } - public static int distance(CharSequence source, CharSequence target, - int deleteCost, int insertCost, - int replaceCost, int swapCost) { + public static int distance( + CharSequence source, CharSequence target, int deleteCost, int insertCost, int replaceCost, int swapCost) { /* * Required to facilitate the premise to the algorithm that two swaps of the * same character are never required for optimality. @@ -115,5 +114,4 @@ public static int distance(CharSequence source, CharSequence target, } return table[source.length() - 1][target.length() - 1]; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java index 91f18755e255f..254173d5bd971 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -73,8 +73,7 @@ static void render(final PrintStream out, final Object message) { } } out.print("]"); - } - else { + } else { out.print(message); } } @@ -84,11 +83,10 @@ static void render(final PrintStream out, final Object message) { // ByteArrayOutputStream baos = new ByteArrayOutputStream(); // PrintStream ps = new PrintStream(baos); // for (int i = 0; i < messages.length; i++) { -// // Special handling for the last message if its a throwable, render its stack on the next line +// // Special handling for the last message if it's a throwable, render its stack on the next line // if (i + 1 == messages.length && messages[i] instanceof Throwable) { // cause = (Throwable) messages[i]; -// } -// else { +// } else { // render(ps, messages[i]); // } // } @@ -122,5 +120,4 @@ static void render(final PrintStream out, final Object message) { // static boolean isEnabled(Level level) { // return logger.isLoggable(level); // } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java index f8cb53489f991..4130634ca4bfb 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -84,8 +84,7 @@ private NonBlockingReaderInputStream(NonBlockingReader reader, Charset charset) @Override public int available() { - return (int) (reader.available() * this.encoder.averageBytesPerChar()) - + bytes.remaining(); + return (int) (reader.available() * this.encoder.averageBytesPerChar()) + bytes.remaining(); } @Override @@ -124,7 +123,6 @@ public int read(long timeout, boolean isPeek) throws IOException { return READ_EXPIRED; } } - } private static class NonBlockingInputStreamReader extends NonBlockingReader { @@ -135,10 +133,12 @@ private static class NonBlockingInputStreamReader extends NonBlockingReader { private final CharBuffer chars; public NonBlockingInputStreamReader(NonBlockingInputStream inputStream, Charset encoding) { - this(inputStream, - (encoding != null ? encoding : Charset.defaultCharset()).newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE)); + this( + inputStream, + (encoding != null ? encoding : Charset.defaultCharset()) + .newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE)); } public NonBlockingInputStreamReader(NonBlockingInputStream input, CharsetDecoder decoder) { @@ -201,8 +201,8 @@ public int readBuffered(char[] b, int off, int len, long timeout) throws IOExcep bytes.position(0); bytes.limit(0); } - int nb = input.readBuffered(bytes.array(), bytes.limit(), - bytes.capacity() - bytes.limit(), t.timeout()); + int nb = input.readBuffered( + bytes.array(), bytes.limit(), bytes.capacity() - bytes.limit(), t.timeout()); if (nb < 0) { return nb; } @@ -227,5 +227,4 @@ public void close() throws IOException { input.close(); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java index a4283eb700625..10ab68cfd28e0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -74,7 +74,7 @@ public int read(byte b[], int off, int len) throws IOException { if (c == EOF) { return EOF; } - b[off] = (byte)c; + b[off] = (byte) c; return 1; } @@ -115,9 +115,7 @@ public int readBuffered(byte[] b, int off, int len, long timeout) throws IOExcep * thread is currently blocked waiting for I/O it may not actually * shut down until the I/O is received. */ - public void shutdown() { - } + public void shutdown() {} public abstract int read(long timeout, boolean isPeek) throws IOException; - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java index 680047fbe60e0..24cf13a0ee5ad 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -26,17 +26,15 @@ * the thread that handles blocking I/O. * */ -public class NonBlockingInputStreamImpl - extends NonBlockingInputStream -{ - private InputStream in; // The actual input stream - private int b = READ_EXPIRED; // Recently read byte - - private String name; - private boolean threadIsReading = false; - private IOException exception = null; - private long threadDelay = 60 * 1000; - private Thread thread; +public class NonBlockingInputStreamImpl extends NonBlockingInputStream { + private InputStream in; // The actual input stream + private int b = READ_EXPIRED; // Recently read byte + + private String name; + private boolean threadIsReading = false; + private IOException exception = null; + private long threadDelay = 60 * 1000; + private Thread thread; /** * Creates a NonBlockingReader out of a normal blocking @@ -97,8 +95,7 @@ public synchronized int read(long timeout, boolean isPeek) throws IOException { if (exception != null) { assert b == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -109,11 +106,9 @@ public synchronized int read(long timeout, boolean isPeek) throws IOException { */ if (b >= -1) { assert exception == null; - } - else if (!isPeek && timeout <= 0L && !threadIsReading) { + } else if (!isPeek && timeout <= 0L && !threadIsReading) { b = in.read(); - } - else { + } else { /* * If the thread isn't reading already, then ask it to do so. */ @@ -128,14 +123,13 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { * now we play the waiting game. */ Timeout t = new Timeout(timeout); - while (!t.elapsed()) { + while (!t.elapsed()) { try { if (Thread.interrupted()) { throw new InterruptedException(); } wait(t.timeout()); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { exception = (IOException) new InterruptedIOException().initCause(e); } @@ -143,8 +137,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { assert b == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -168,7 +161,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { return ret; } - private void run () { + private void run() { Log.debug("NonBlockingInputStream start"); boolean needToRead; @@ -236,5 +229,4 @@ private void run () { } } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java index 5a3613443508e..aad6e3d0f5af0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -57,11 +57,7 @@ private int wait(ByteBuffer buffer, long timeout) throws IOException { throw new InterruptedIOException(); } } - return buffer.hasRemaining() - ? 0 - : closed - ? EOF - : READ_EXPIRED; + return buffer.hasRemaining() ? 0 : closed ? EOF : READ_EXPIRED; } private static boolean rewind(ByteBuffer buffer, ByteBuffer other) { @@ -167,7 +163,7 @@ private class NbpOutputStream extends OutputStream { @Override public void write(int b) throws IOException { - NonBlockingPumpInputStream.this.write(new byte[] { (byte) b }, 0, 1); + NonBlockingPumpInputStream.this.write(new byte[] {(byte) b}, 0, 1); } @Override @@ -184,7 +180,5 @@ public void flush() throws IOException { public void close() throws IOException { NonBlockingPumpInputStream.this.close(); } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java index f36423f03b82f..63db6e5f5bf7f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -121,7 +121,7 @@ public int readBuffered(char[] b, int off, int len, long timeout) throws IOExcep try { if (timeout > 0) { if (!notEmpty.await(timeout, TimeUnit.MILLISECONDS)) { - throw new IOException( "Timeout reading" ); + throw new IOException("Timeout reading"); } } else { notEmpty.await(); @@ -207,14 +207,11 @@ public void write(char[] cbuf, int off, int len) throws IOException { } @Override - public void flush() throws IOException { - } + public void flush() throws IOException {} @Override public void close() throws IOException { NonBlockingPumpReader.this.close(); } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java index e2f664f29993b..460f548b5069f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -23,8 +23,7 @@ public abstract class NonBlockingReader extends Reader { * thread is currently blocked waiting for I/O it will not actually * shut down until the I/O is received. */ - public void shutdown() { - } + public void shutdown() {} @Override public int read() throws IOException { @@ -109,5 +108,4 @@ public int available() { * @throws IOException if anything wrong happens */ protected abstract int read(long timeout, boolean isPeek) throws IOException; - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java index d384cc9a0dc01..5aaabd1d3c0d0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -28,19 +28,17 @@ * @since 2.7 * @author Scott C. Gray <scottgray1@gmail.com> */ -public class NonBlockingReaderImpl - extends NonBlockingReader -{ +public class NonBlockingReaderImpl extends NonBlockingReader { public static final int READ_EXPIRED = -2; - private Reader in; // The actual input stream - private int ch = READ_EXPIRED; // Recently read character + private Reader in; // The actual input stream + private int ch = READ_EXPIRED; // Recently read character - private String name; - private boolean threadIsReading = false; - private IOException exception = null; - private long threadDelay = 60 * 1000; - private Thread thread; + private String name; + private boolean threadIsReading = false; + private IOException exception = null; + private long threadDelay = 60 * 1000; + private Thread thread; /** * Creates a NonBlockingReader out of a normal blocking @@ -135,8 +133,7 @@ protected synchronized int read(long timeout, boolean isPeek) throws IOException if (exception != null) { assert ch == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -147,11 +144,9 @@ protected synchronized int read(long timeout, boolean isPeek) throws IOException */ if (ch >= -1) { assert exception == null; - } - else if (!isPeek && timeout <= 0L && !threadIsReading) { + } else if (!isPeek && timeout <= 0L && !threadIsReading) { ch = in.read(); - } - else { + } else { /* * If the thread isn't reading already, then ask it to do so. */ @@ -166,14 +161,13 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { * now we play the waiting game. */ Timeout t = new Timeout(timeout); - while (!t.elapsed()) { + while (!t.elapsed()) { try { if (Thread.interrupted()) { throw new InterruptedException(); } wait(t.timeout()); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { exception = (IOException) new InterruptedIOException().initCause(e); } @@ -181,8 +175,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { assert ch == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -206,7 +199,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { return ret; } - private void run () { + private void run() { Log.debug("NonBlockingReader start"); boolean needToRead; @@ -245,12 +238,12 @@ private void run () { IOException failure = null; try { charRead = in.read(); -// if (charRead < 0) { -// continue; -// } + // if (charRead < 0) { + // continue; + // } } catch (IOException e) { failure = e; -// charRead = -1; + // charRead = -1; } /* diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java index 97487731852ef..344d081c12486 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -9,16 +9,23 @@ package jdk.internal.org.jline.utils; import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; public class OSUtils { - public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win"); + public static final boolean IS_LINUX = + System.getProperty("os.name").toLowerCase().contains("linux"); - public static final boolean IS_CYGWIN = IS_WINDOWS - && System.getenv("PWD") != null - && System.getenv("PWD").startsWith("/"); + public static final boolean IS_WINDOWS = + System.getProperty("os.name").toLowerCase().contains("win"); + + public static final boolean IS_OSX = + System.getProperty("os.name").toLowerCase().contains("mac"); + + public static final boolean IS_AIX = + System.getProperty("os.name").toLowerCase().contains("aix"); + + public static final boolean IS_CYGWIN = + IS_WINDOWS && System.getenv("PWD") != null && System.getenv("PWD").startsWith("/"); @Deprecated public static final boolean IS_MINGW = IS_WINDOWS @@ -28,7 +35,7 @@ public class OSUtils { public static final boolean IS_MSYSTEM = IS_WINDOWS && System.getenv("MSYSTEM") != null && (System.getenv("MSYSTEM").startsWith("MINGW") - || System.getenv("MSYSTEM").equals("MSYS")); + || System.getenv("MSYSTEM").equals("MSYS")); public static final boolean IS_WSL = System.getenv("WSL_DISTRO_NAME") != null; @@ -36,11 +43,7 @@ public class OSUtils { public static final boolean IS_WSL2 = IS_WSL && !IS_WSL1; - public static final boolean IS_CONEMU = IS_WINDOWS - && System.getenv("ConEmuPID") != null; - - public static final boolean IS_OSX = System.getProperty("os.name").toLowerCase().contains("mac"); - public static final boolean IS_AIX = System.getProperty("os.name").equals("AIX"); + public static final boolean IS_CONEMU = IS_WINDOWS && System.getenv("ConEmuPID") != null; public static String TTY_COMMAND; public static String STTY_COMMAND; @@ -48,64 +51,57 @@ public class OSUtils { public static String INFOCMP_COMMAND; public static String TEST_COMMAND; + private static boolean isExecutable(File f) { + return f.canExecute() && !f.isDirectory(); + } + static { - String tty; - String stty; - String sttyfopt; - String infocmp; - String test; - if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { - tty = null; - stty = null; - sttyfopt = null; - infocmp = null; - test = null; - String path = System.getenv("PATH"); - if (path != null) { - String[] paths = path.split(";"); - for (String p : paths) { - if (tty == null && new File(p, "tty.exe").exists()) { - tty = new File(p, "tty.exe").getAbsolutePath(); - } - if (stty == null && new File(p, "stty.exe").exists()) { - stty = new File(p, "stty.exe").getAbsolutePath(); - } - if (infocmp == null && new File(p, "infocmp.exe").exists()) { - infocmp = new File(p, "infocmp.exe").getAbsolutePath(); - } - if (test == null && new File(p, "test.exe").exists()) { - test = new File(p, "test.exe").getAbsolutePath(); - } + boolean cygwinOrMsys = OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM; + String suffix = cygwinOrMsys ? ".exe" : ""; + String tty = null; + String stty = null; + String sttyfopt = null; + String infocmp = null; + String test = null; + String path = System.getenv("PATH"); + if (path != null) { + String[] paths = path.split(File.pathSeparator); + for (String p : paths) { + File ttyFile = new File(p, "tty" + suffix); + if (tty == null && isExecutable(ttyFile)) { + tty = ttyFile.getAbsolutePath(); + } + File sttyFile = new File(p, "stty" + suffix); + if (stty == null && isExecutable(sttyFile)) { + stty = sttyFile.getAbsolutePath(); + } + File infocmpFile = new File(p, "infocmp" + suffix); + if (infocmp == null && isExecutable(infocmpFile)) { + infocmp = infocmpFile.getAbsolutePath(); + } + File testFile = new File(p, "test" + suffix); + if (test == null && isExecutable(testFile)) { + test = testFile.getAbsolutePath(); } } - if (tty == null) { - tty = "tty.exe"; - } - if (stty == null) { - stty = "stty.exe"; - } - if (infocmp == null) { - infocmp = "infocmp.exe"; - } - if (test == null) { - test = "test.exe"; - } - } else { - tty = "tty"; - stty = IS_OSX ? "/bin/stty" : "stty"; - sttyfopt = IS_OSX ? "-f" : "-F"; - infocmp = "infocmp"; - test = isTestCommandValid("/usr/bin/test") ? "/usr/bin/test" - : "/bin/test"; } + if (tty == null) { + tty = "tty" + suffix; + } + if (stty == null) { + stty = "stty" + suffix; + } + if (infocmp == null) { + infocmp = "infocmp" + suffix; + } + if (test == null) { + test = "test" + suffix; + } + sttyfopt = IS_OSX ? "-f" : "-F"; TTY_COMMAND = tty; STTY_COMMAND = stty; STTY_F_OPTION = sttyfopt; INFOCMP_COMMAND = infocmp; TEST_COMMAND = test; } - - private static boolean isTestCommandValid(String command) { - return Files.isExecutable(Paths.get(command)); - } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java index e80a18b6f3c23..12e9795c6f51f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -378,7 +378,6 @@ public void flush() throws IOException { public void close() throws IOException { reader.close(); } - } private static class InputStream extends java.io.InputStream { @@ -464,7 +463,5 @@ public int read(byte[] b, int off, int len) throws IOException { public void close() throws IOException { reader.close(); } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java index 8089de321cce6..d5456df03d36d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,8 +18,7 @@ * @author Jason Dillon * @since 2.7 */ -public final class ShutdownHooks -{ +public final class ShutdownHooks { private static final List tasks = new ArrayList<>(); private static Thread hook; @@ -29,8 +28,7 @@ public static synchronized T add(final T task) { // Install the hook thread if needed if (hook == null) { - hook = addHook(new Thread("JLine Shutdown Hook") - { + hook = addHook(new Thread("JLine Shutdown Hook") { @Override public void run() { runTasks(); @@ -53,8 +51,7 @@ private static synchronized void runTasks() { Log.debug("Running task: ", task); try { task.run(); - } - catch (Throwable e) { + } catch (Throwable e) { Log.warn("Task failed", e); } } @@ -91,8 +88,7 @@ private static void removeHook(final Thread thread) { try { Runtime.getRuntime().removeShutdownHook(thread); - } - catch (IllegalStateException e) { + } catch (IllegalStateException e) { // The VM is shutting down, not a big deal; ignore } } @@ -100,8 +96,7 @@ private static void removeHook(final Thread thread) { /** * Essentially a {@link Runnable} which allows running to throw an exception. */ - public interface Task - { + public interface Task { void run() throws Exception; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java index b94f1fa318e66..9b25a80473573 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,8 +21,7 @@ */ public final class Signals { - private Signals() { - } + private Signals() {} /** * @@ -41,8 +40,8 @@ public static Object register(String name, final Runnable handler, ClassLoader l try { Class signalHandlerClass = Class.forName("sun.misc.SignalHandler"); // Implement signal handler - Object signalHandler = Proxy.newProxyInstance(loader, - new Class[]{signalHandlerClass}, (proxy, method, args) -> { + Object signalHandler = + Proxy.newProxyInstance(loader, new Class[] {signalHandlerClass}, (proxy, method, args) -> { // only method we are proxying is handle() if (method.getDeclaringClass() == Object.class) { if ("toString".equals(method.getName())) { @@ -101,8 +100,7 @@ private static Object doRegister(String name, Object handler) throws Exception { return null; } Class signalHandlerClass = Class.forName("sun.misc.SignalHandler"); - return signalClass.getMethod("handle", signalClass, signalHandlerClass) - .invoke(null, signal, handler); + return signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signal, handler); } @SuppressWarnings("") @@ -120,5 +118,4 @@ private static String toString(Object handler) { } return handler != null ? handler.toString() : "null"; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java index e8d9e49e8b3a1..7348b1ea1c5f3 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,187 +8,266 @@ */ package jdk.internal.org.jline.utils; -import java.util.Objects; -import java.util.Collections; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.Terminal; import jdk.internal.org.jline.terminal.impl.AbstractTerminal; import jdk.internal.org.jline.utils.InfoCmp.Capability; -import jdk.internal.org.jline.terminal.Size; public class Status { - protected final AbstractTerminal terminal; + protected final Terminal terminal; protected final boolean supported; - protected List oldLines = Collections.emptyList(); - protected List linesToRestore = Collections.emptyList(); - protected int rows; - protected int columns; - protected boolean force; protected boolean suspended = false; protected AttributedString borderString; protected int border = 0; + protected Display display; + protected List lines = Collections.emptyList(); + protected int scrollRegion; public static Status getStatus(Terminal terminal) { return getStatus(terminal, true); } - public static Status getStatus(Terminal terminal, boolean create) { - return terminal instanceof AbstractTerminal - ? ((AbstractTerminal) terminal).getStatus(create) - : null; + public static Optional getExistingStatus(Terminal terminal) { + return Optional.ofNullable(getStatus(terminal, false)); } + public static Status getStatus(Terminal terminal, boolean create) { + return terminal instanceof AbstractTerminal ? ((AbstractTerminal) terminal).getStatus(create) : null; + } - public Status(AbstractTerminal terminal) { + @SuppressWarnings("this-escape") + public Status(Terminal terminal) { this.terminal = Objects.requireNonNull(terminal, "terminal can not be null"); this.supported = terminal.getStringCapability(Capability.change_scroll_region) != null - && terminal.getStringCapability(Capability.save_cursor) != null - && terminal.getStringCapability(Capability.restore_cursor) != null - && terminal.getStringCapability(Capability.cursor_address) != null; + && terminal.getStringCapability(Capability.save_cursor) != null + && terminal.getStringCapability(Capability.restore_cursor) != null + && terminal.getStringCapability(Capability.cursor_address) != null; if (supported) { - char borderChar = '\u2700'; - AttributedStringBuilder bb = new AttributedStringBuilder(); - for (int i = 0; i < 200; i++) { - bb.append(borderChar); - } - borderString = bb.toAttributedString(); + display = new MovingCursorDisplay(terminal); resize(); + display.reset(); + scrollRegion = display.rows - 1; } } + public void close() { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.change_scroll_region, 0, display.rows - 1); + terminal.puts(Capability.restore_cursor); + terminal.flush(); + } + public void setBorder(boolean border) { this.border = border ? 1 : 0; } public void resize() { - Size size = terminal.getSize(); - this.rows = size.getRows(); - this.columns = size.getColumns(); - this.force = true; + resize(terminal.getSize()); } - public void reset() { - this.force = true; + public void resize(Size size) { + display.resize(size.getRows(), size.getColumns()); } - public void hardReset() { - if (suspended) { - return; + public void reset() { + if (supported) { + display.reset(); + scrollRegion = display.rows; + terminal.puts(Capability.change_scroll_region, 0, scrollRegion); } - List lines = new ArrayList<>(oldLines); - int b = border; - update(null); - border = b; - update(lines); } public void redraw() { if (suspended) { return; } - update(oldLines); + update(lines); } - public void clear() { - privateClear(oldLines.size()); + public void hide() { + update(Collections.emptyList()); } - private void clearAll() { - int b = border; - border = 0; - privateClear(oldLines.size() + b); + public void update(List lines) { + update(lines, true); } - private void privateClear(int statusSize) { - List as = new ArrayList<>(); - for (int i = 0; i < statusSize; i++) { - as.add(new AttributedString("")); - } - if (!as.isEmpty()) { - update(as); - } - } + private final AttributedString ellipsis = + new AttributedStringBuilder().append("\u2026", AttributedStyle.INVERSE).toAttributedString(); - public void update(List lines) { + /** + * Returns true if the cursor may be misplaced and should + * be updated. + */ + public void update(List lines, boolean flush) { if (!supported) { return; } - if (lines == null) { - lines = Collections.emptyList(); - } + this.lines = new ArrayList<>(lines); if (suspended) { - linesToRestore = new ArrayList<>(lines); return; } - if (lines.isEmpty()) { - clearAll(); + + lines = new ArrayList<>(lines); + // add border + int rows = display.rows; + int columns = display.columns; + if (border == 1 && !lines.isEmpty() && rows > 1) { + lines.add(0, getBorderString(columns)); } - if (oldLines.equals(lines) && !force) { - return; + // trim or complete lines to the full width + for (int i = 0; i < lines.size(); i++) { + AttributedString str = lines.get(i); + if (str.columnLength() > columns) { + str = new AttributedStringBuilder(columns) + .append(lines.get(i).columnSubSequence(0, columns - ellipsis.columnLength())) + .append(ellipsis) + .toAttributedString(); + } else if (str.columnLength() < columns) { + str = new AttributedStringBuilder(columns) + .append(str) + .append(' ', columns - str.columnLength()) + .toAttributedString(); + } + lines.set(i, str); } - int statusSize = lines.size() + (lines.size() == 0 ? 0 : border); - int nb = statusSize - oldLines.size() - (oldLines.size() == 0 ? 0 : border); - if (nb > 0) { - for (int i = 0; i < nb; i++) { + + List oldLines = this.display.oldLines; + + int newScrollRegion = display.rows - 1 - lines.size(); + // Update the scroll region if needed. + // Note that settings the scroll region usually moves the cursor, so we need to get ready for that. + if (newScrollRegion < scrollRegion) { + // We need to scroll up to grow the status bar + terminal.puts(Capability.save_cursor); + for (int i = newScrollRegion; i < scrollRegion; i++) { terminal.puts(Capability.cursor_down); } - for (int i = 0; i < nb; i++) { + terminal.puts(Capability.change_scroll_region, 0, newScrollRegion); + terminal.puts(Capability.restore_cursor); + for (int i = newScrollRegion; i < scrollRegion; i++) { terminal.puts(Capability.cursor_up); } + scrollRegion = newScrollRegion; + } else if (newScrollRegion > scrollRegion) { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.change_scroll_region, 0, newScrollRegion); + terminal.puts(Capability.restore_cursor); + scrollRegion = newScrollRegion; } - terminal.puts(Capability.save_cursor); - terminal.puts(Capability.cursor_address, rows - statusSize, 0); - if (!terminal.puts(Capability.clr_eos)) { - for (int i = rows - statusSize; i < rows; i++) { - terminal.puts(Capability.cursor_address, i, 0); + + // if the display has more lines, we need to add empty ones to make sure they will be erased + List toDraw = new ArrayList<>(lines); + int nbToDraw = toDraw.size(); + int nbOldLines = oldLines.size(); + if (nbOldLines > nbToDraw) { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.cursor_address, display.rows - nbOldLines, 0); + for (int i = 0; i < nbOldLines - nbToDraw; i++) { terminal.puts(Capability.clr_eol); + if (i < nbOldLines - nbToDraw - 1) { + terminal.puts(Capability.cursor_down); + } + oldLines.remove(0); } + terminal.puts(Capability.restore_cursor); } - if (border == 1 && lines.size() > 0) { - terminal.puts(Capability.cursor_address, rows - statusSize, 0); - borderString.columnSubSequence(0, columns).print(terminal); - } - for (int i = 0; i < lines.size(); i++) { - terminal.puts(Capability.cursor_address, rows - lines.size() + i, 0); - if (lines.get(i).length() > columns) { - AttributedStringBuilder asb = new AttributedStringBuilder(); - asb.append(lines.get(i).substring(0, columns - 3)).append("...", new AttributedStyle(AttributedStyle.INVERSE)); - asb.toAttributedString().columnSubSequence(0, columns).print(terminal); - } else { - lines.get(i).columnSubSequence(0, columns).print(terminal); + // update display + display.update(lines, -1, flush); + } + + private AttributedString getBorderString(int columns) { + if (borderString == null || borderString.length() != columns) { + char borderChar = '\u2700'; + AttributedStringBuilder bb = new AttributedStringBuilder(); + for (int i = 0; i < columns; i++) { + bb.append(borderChar); } + borderString = bb.toAttributedString(); } - terminal.puts(Capability.change_scroll_region, 0, rows - 1 - statusSize); - terminal.puts(Capability.restore_cursor); - terminal.flush(); - oldLines = new ArrayList<>(lines); - force = false; + return borderString; } + /** + * The {@code suspend} method is used when a full-screen. + * If the status was not already suspended, the lines + * used by the status are cleared during this call. + */ public void suspend() { - if (suspended) { - return; + if (!suspended) { + suspended = true; } - linesToRestore = new ArrayList<>(oldLines); - int b = border; - update(null); - border = b; - suspended = true; } + /** + * The {@code restore()} call is the opposite of {@code suspend()} and + * will make the status bar be updated again. + * If the status was suspended, the lines + * used by the status will be drawn during this call. + */ public void restore() { - if (!suspended) { - return; + if (suspended) { + suspended = false; + update(this.lines); } - suspended = false; - update(linesToRestore); - linesToRestore = Collections.emptyList(); } public int size() { - return oldLines.size() + border; + return size(this.lines); + } + + private int size(List lines) { + int l = lines.size(); + return l > 0 ? l + border : 0; + } + + @Override + public String toString() { + return "Status[" + "supported=" + supported + ']'; } + static class MovingCursorDisplay extends Display { + protected int firstLine; + + public MovingCursorDisplay(Terminal terminal) { + super(terminal, false); + } + + @Override + public void update(List newLines, int targetCursorPos, boolean flush) { + cursorPos = -1; + firstLine = rows - newLines.size(); + super.update(newLines, targetCursorPos, flush); + if (cursorPos != -1) { + terminal.puts(Capability.restore_cursor); + } + } + + @Override + protected void moveVisualCursorTo(int targetPos, List newLines) { + initCursor(); + super.moveVisualCursorTo(targetPos, newLines); + } + + @Override + protected int moveVisualCursorTo(int i1) { + initCursor(); + return super.moveVisualCursorTo(i1); + } + + void initCursor() { + if (cursorPos == -1) { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.cursor_address, firstLine, 0); + cursorPos = 0; + } + } + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java index be1659957b445..29d87cbc3c85f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -55,12 +55,12 @@ private static Integer colorRgb(String name) { return null; } } else { - // load indexed color - Integer color = color(name); - if (color != null && color != -1) { - color = Colors.DEFAULT_COLORS_256[color]; - } - return color; + // load indexed color + Integer color = color(name); + if (color != null && color != -1) { + color = Colors.DEFAULT_COLORS_256[color]; + } + return color; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java index edea89cf2d9c3..1e3091e19a117 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -44,5 +44,4 @@ public boolean elapsed() { public long timeout() { return timeout > 0 ? Math.max(1, end - cur) : timeout; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java index db3a8d3d99084..7b0caf91c25c4 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -10,8 +10,7 @@ public final class WCWidth { - private WCWidth() { - } + private WCWidth() {} /* The following two functions define the column width of an ISO 10646 * character as follows: @@ -44,88 +43,86 @@ private WCWidth() { * This implementation assumes that wchar_t characters are encoded * in ISO 10646. */ - public static int wcwidth(int ucs) - { + public static int wcwidth(int ucs) { /* test for 8-bit control characters */ - if (ucs == 0) - return 0; - if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) - return -1; + if (ucs == 0) return 0; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return -1; /* binary search in table of non-spacing characters */ - if (bisearch(ucs, combining, combining.length - 1)) - return 0; + if (bisearch(ucs, combining, combining.length - 1)) return 0; /* if we arrive here, ucs is not a combining or C0/C1 control character */ - return 1 + - ((ucs >= 0x1100 && - (ucs <= 0x115f || /* Hangul Jamo init. consonants */ - ucs == 0x2329 || ucs == 0x232a || - (ucs >= 0x2e80 && ucs <= 0xa4cf && - ucs != 0x303f) || /* CJK ... Yi */ - (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ - (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ - (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ - (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ - (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ - (ucs >= 0xffe0 && ucs <= 0xffe6) || - (ucs >= 0x1f000 && ucs <= 0x1feee) || - (ucs >= 0x20000 && ucs <= 0x2fffd) || - (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0); + return 1 + + ((ucs >= 0x1100 + && (ucs <= 0x115f + || /* Hangul Jamo init. consonants */ ucs == 0x2329 + || ucs == 0x232a + || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) + || /* CJK ... Yi */ (ucs >= 0xac00 && ucs <= 0xd7a3) + || /* Hangul Syllables */ (ucs >= 0xf900 && ucs <= 0xfaff) + || /* CJK Compatibility Ideographs */ (ucs >= 0xfe10 && ucs <= 0xfe19) + || /* Vertical forms */ (ucs >= 0xfe30 && ucs <= 0xfe6f) + || /* CJK Compatibility Forms */ (ucs >= 0xff00 && ucs <= 0xff60) + || /* Fullwidth Forms */ (ucs >= 0xffe0 && ucs <= 0xffe6) + || (ucs >= 0x1f000 && ucs <= 0x1feee) + || (ucs >= 0x20000 && ucs <= 0x2fffd) + || (ucs >= 0x30000 && ucs <= 0x3fffd))) + ? 1 + : 0); } /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ static Interval[] combining = { - new Interval( 0x0300, 0x036F ), new Interval( 0x0483, 0x0486 ), new Interval( 0x0488, 0x0489 ), - new Interval( 0x0591, 0x05BD ), new Interval( 0x05BF, 0x05BF ), new Interval( 0x05C1, 0x05C2 ), - new Interval( 0x05C4, 0x05C5 ), new Interval( 0x05C7, 0x05C7 ), new Interval( 0x0600, 0x0603 ), - new Interval( 0x0610, 0x0615 ), new Interval( 0x064B, 0x065E ), new Interval( 0x0670, 0x0670 ), - new Interval( 0x06D6, 0x06E4 ), new Interval( 0x06E7, 0x06E8 ), new Interval( 0x06EA, 0x06ED ), - new Interval( 0x070F, 0x070F ), new Interval( 0x0711, 0x0711 ), new Interval( 0x0730, 0x074A ), - new Interval( 0x07A6, 0x07B0 ), new Interval( 0x07EB, 0x07F3 ), new Interval( 0x0901, 0x0902 ), - new Interval( 0x093C, 0x093C ), new Interval( 0x0941, 0x0948 ), new Interval( 0x094D, 0x094D ), - new Interval( 0x0951, 0x0954 ), new Interval( 0x0962, 0x0963 ), new Interval( 0x0981, 0x0981 ), - new Interval( 0x09BC, 0x09BC ), new Interval( 0x09C1, 0x09C4 ), new Interval( 0x09CD, 0x09CD ), - new Interval( 0x09E2, 0x09E3 ), new Interval( 0x0A01, 0x0A02 ), new Interval( 0x0A3C, 0x0A3C ), - new Interval( 0x0A41, 0x0A42 ), new Interval( 0x0A47, 0x0A48 ), new Interval( 0x0A4B, 0x0A4D ), - new Interval( 0x0A70, 0x0A71 ), new Interval( 0x0A81, 0x0A82 ), new Interval( 0x0ABC, 0x0ABC ), - new Interval( 0x0AC1, 0x0AC5 ), new Interval( 0x0AC7, 0x0AC8 ), new Interval( 0x0ACD, 0x0ACD ), - new Interval( 0x0AE2, 0x0AE3 ), new Interval( 0x0B01, 0x0B01 ), new Interval( 0x0B3C, 0x0B3C ), - new Interval( 0x0B3F, 0x0B3F ), new Interval( 0x0B41, 0x0B43 ), new Interval( 0x0B4D, 0x0B4D ), - new Interval( 0x0B56, 0x0B56 ), new Interval( 0x0B82, 0x0B82 ), new Interval( 0x0BC0, 0x0BC0 ), - new Interval( 0x0BCD, 0x0BCD ), new Interval( 0x0C3E, 0x0C40 ), new Interval( 0x0C46, 0x0C48 ), - new Interval( 0x0C4A, 0x0C4D ), new Interval( 0x0C55, 0x0C56 ), new Interval( 0x0CBC, 0x0CBC ), - new Interval( 0x0CBF, 0x0CBF ), new Interval( 0x0CC6, 0x0CC6 ), new Interval( 0x0CCC, 0x0CCD ), - new Interval( 0x0CE2, 0x0CE3 ), new Interval( 0x0D41, 0x0D43 ), new Interval( 0x0D4D, 0x0D4D ), - new Interval( 0x0DCA, 0x0DCA ), new Interval( 0x0DD2, 0x0DD4 ), new Interval( 0x0DD6, 0x0DD6 ), - new Interval( 0x0E31, 0x0E31 ), new Interval( 0x0E34, 0x0E3A ), new Interval( 0x0E47, 0x0E4E ), - new Interval( 0x0EB1, 0x0EB1 ), new Interval( 0x0EB4, 0x0EB9 ), new Interval( 0x0EBB, 0x0EBC ), - new Interval( 0x0EC8, 0x0ECD ), new Interval( 0x0F18, 0x0F19 ), new Interval( 0x0F35, 0x0F35 ), - new Interval( 0x0F37, 0x0F37 ), new Interval( 0x0F39, 0x0F39 ), new Interval( 0x0F71, 0x0F7E ), - new Interval( 0x0F80, 0x0F84 ), new Interval( 0x0F86, 0x0F87 ), new Interval( 0x0F90, 0x0F97 ), - new Interval( 0x0F99, 0x0FBC ), new Interval( 0x0FC6, 0x0FC6 ), new Interval( 0x102D, 0x1030 ), - new Interval( 0x1032, 0x1032 ), new Interval( 0x1036, 0x1037 ), new Interval( 0x1039, 0x1039 ), - new Interval( 0x1058, 0x1059 ), new Interval( 0x1160, 0x11FF ), new Interval( 0x135F, 0x135F ), - new Interval( 0x1712, 0x1714 ), new Interval( 0x1732, 0x1734 ), new Interval( 0x1752, 0x1753 ), - new Interval( 0x1772, 0x1773 ), new Interval( 0x17B4, 0x17B5 ), new Interval( 0x17B7, 0x17BD ), - new Interval( 0x17C6, 0x17C6 ), new Interval( 0x17C9, 0x17D3 ), new Interval( 0x17DD, 0x17DD ), - new Interval( 0x180B, 0x180D ), new Interval( 0x18A9, 0x18A9 ), new Interval( 0x1920, 0x1922 ), - new Interval( 0x1927, 0x1928 ), new Interval( 0x1932, 0x1932 ), new Interval( 0x1939, 0x193B ), - new Interval( 0x1A17, 0x1A18 ), new Interval( 0x1B00, 0x1B03 ), new Interval( 0x1B34, 0x1B34 ), - new Interval( 0x1B36, 0x1B3A ), new Interval( 0x1B3C, 0x1B3C ), new Interval( 0x1B42, 0x1B42 ), - new Interval( 0x1B6B, 0x1B73 ), new Interval( 0x1DC0, 0x1DCA ), new Interval( 0x1DFE, 0x1DFF ), - new Interval( 0x200B, 0x200F ), new Interval( 0x202A, 0x202E ), new Interval( 0x2060, 0x2063 ), - new Interval( 0x206A, 0x206F ), new Interval( 0x20D0, 0x20EF ), new Interval( 0x302A, 0x302F ), - new Interval( 0x3099, 0x309A ), new Interval( 0xA806, 0xA806 ), new Interval( 0xA80B, 0xA80B ), - new Interval( 0xA825, 0xA826 ), new Interval( 0xFB1E, 0xFB1E ), new Interval( 0xFE00, 0xFE0F ), - new Interval( 0xFE20, 0xFE23 ), new Interval( 0xFEFF, 0xFEFF ), new Interval( 0xFFF9, 0xFFFB ), - new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ), - new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ), - new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ), - new Interval( 0x1D242, 0x1D244 ), new Interval( 0x1F3FB, 0x1F3FF ), new Interval( 0xE0001, 0xE0001 ), - new Interval( 0xE0020, 0xE007F ), new Interval( 0xE0100, 0xE01EF ) + new Interval(0x0300, 0x036F), new Interval(0x0483, 0x0486), new Interval(0x0488, 0x0489), + new Interval(0x0591, 0x05BD), new Interval(0x05BF, 0x05BF), new Interval(0x05C1, 0x05C2), + new Interval(0x05C4, 0x05C5), new Interval(0x05C7, 0x05C7), new Interval(0x0600, 0x0603), + new Interval(0x0610, 0x0615), new Interval(0x064B, 0x065E), new Interval(0x0670, 0x0670), + new Interval(0x06D6, 0x06E4), new Interval(0x06E7, 0x06E8), new Interval(0x06EA, 0x06ED), + new Interval(0x070F, 0x070F), new Interval(0x0711, 0x0711), new Interval(0x0730, 0x074A), + new Interval(0x07A6, 0x07B0), new Interval(0x07EB, 0x07F3), new Interval(0x0901, 0x0902), + new Interval(0x093C, 0x093C), new Interval(0x0941, 0x0948), new Interval(0x094D, 0x094D), + new Interval(0x0951, 0x0954), new Interval(0x0962, 0x0963), new Interval(0x0981, 0x0981), + new Interval(0x09BC, 0x09BC), new Interval(0x09C1, 0x09C4), new Interval(0x09CD, 0x09CD), + new Interval(0x09E2, 0x09E3), new Interval(0x0A01, 0x0A02), new Interval(0x0A3C, 0x0A3C), + new Interval(0x0A41, 0x0A42), new Interval(0x0A47, 0x0A48), new Interval(0x0A4B, 0x0A4D), + new Interval(0x0A70, 0x0A71), new Interval(0x0A81, 0x0A82), new Interval(0x0ABC, 0x0ABC), + new Interval(0x0AC1, 0x0AC5), new Interval(0x0AC7, 0x0AC8), new Interval(0x0ACD, 0x0ACD), + new Interval(0x0AE2, 0x0AE3), new Interval(0x0B01, 0x0B01), new Interval(0x0B3C, 0x0B3C), + new Interval(0x0B3F, 0x0B3F), new Interval(0x0B41, 0x0B43), new Interval(0x0B4D, 0x0B4D), + new Interval(0x0B56, 0x0B56), new Interval(0x0B82, 0x0B82), new Interval(0x0BC0, 0x0BC0), + new Interval(0x0BCD, 0x0BCD), new Interval(0x0C3E, 0x0C40), new Interval(0x0C46, 0x0C48), + new Interval(0x0C4A, 0x0C4D), new Interval(0x0C55, 0x0C56), new Interval(0x0CBC, 0x0CBC), + new Interval(0x0CBF, 0x0CBF), new Interval(0x0CC6, 0x0CC6), new Interval(0x0CCC, 0x0CCD), + new Interval(0x0CE2, 0x0CE3), new Interval(0x0D41, 0x0D43), new Interval(0x0D4D, 0x0D4D), + new Interval(0x0DCA, 0x0DCA), new Interval(0x0DD2, 0x0DD4), new Interval(0x0DD6, 0x0DD6), + new Interval(0x0E31, 0x0E31), new Interval(0x0E34, 0x0E3A), new Interval(0x0E47, 0x0E4E), + new Interval(0x0EB1, 0x0EB1), new Interval(0x0EB4, 0x0EB9), new Interval(0x0EBB, 0x0EBC), + new Interval(0x0EC8, 0x0ECD), new Interval(0x0F18, 0x0F19), new Interval(0x0F35, 0x0F35), + new Interval(0x0F37, 0x0F37), new Interval(0x0F39, 0x0F39), new Interval(0x0F71, 0x0F7E), + new Interval(0x0F80, 0x0F84), new Interval(0x0F86, 0x0F87), new Interval(0x0F90, 0x0F97), + new Interval(0x0F99, 0x0FBC), new Interval(0x0FC6, 0x0FC6), new Interval(0x102D, 0x1030), + new Interval(0x1032, 0x1032), new Interval(0x1036, 0x1037), new Interval(0x1039, 0x1039), + new Interval(0x1058, 0x1059), new Interval(0x1160, 0x11FF), new Interval(0x135F, 0x135F), + new Interval(0x1712, 0x1714), new Interval(0x1732, 0x1734), new Interval(0x1752, 0x1753), + new Interval(0x1772, 0x1773), new Interval(0x17B4, 0x17B5), new Interval(0x17B7, 0x17BD), + new Interval(0x17C6, 0x17C6), new Interval(0x17C9, 0x17D3), new Interval(0x17DD, 0x17DD), + new Interval(0x180B, 0x180D), new Interval(0x18A9, 0x18A9), new Interval(0x1920, 0x1922), + new Interval(0x1927, 0x1928), new Interval(0x1932, 0x1932), new Interval(0x1939, 0x193B), + new Interval(0x1A17, 0x1A18), new Interval(0x1B00, 0x1B03), new Interval(0x1B34, 0x1B34), + new Interval(0x1B36, 0x1B3A), new Interval(0x1B3C, 0x1B3C), new Interval(0x1B42, 0x1B42), + new Interval(0x1B6B, 0x1B73), new Interval(0x1DC0, 0x1DCA), new Interval(0x1DFE, 0x1DFF), + new Interval(0x200B, 0x200F), new Interval(0x202A, 0x202E), new Interval(0x2060, 0x2063), + new Interval(0x206A, 0x206F), new Interval(0x20D0, 0x20EF), new Interval(0x302A, 0x302F), + new Interval(0x3099, 0x309A), new Interval(0xA806, 0xA806), new Interval(0xA80B, 0xA80B), + new Interval(0xA825, 0xA826), new Interval(0xFB1E, 0xFB1E), new Interval(0xFE00, 0xFE0F), + new Interval(0xFE20, 0xFE23), new Interval(0xFEFF, 0xFEFF), new Interval(0xFFF9, 0xFFFB), + new Interval(0x10A01, 0x10A03), new Interval(0x10A05, 0x10A06), new Interval(0x10A0C, 0x10A0F), + new Interval(0x10A38, 0x10A3A), new Interval(0x10A3F, 0x10A3F), new Interval(0x1D167, 0x1D169), + new Interval(0x1D173, 0x1D182), new Interval(0x1D185, 0x1D18B), new Interval(0x1D1AA, 0x1D1AD), + new Interval(0x1D242, 0x1D244), new Interval(0x1F3FB, 0x1F3FF), new Interval(0xE0001, 0xE0001), + new Interval(0xE0020, 0xE007F), new Interval(0xE0100, 0xE01EF) }; private static class Interval { @@ -143,20 +140,14 @@ private static boolean bisearch(int ucs, Interval[] table, int max) { int min = 0; int mid; - if (ucs < table[0].first || ucs > table[max].last) - return false; + if (ucs < table[0].first || ucs > table[max].last) return false; while (max >= min) { mid = (min + max) / 2; - if (ucs > table[mid].last) - min = mid + 1; - else if (ucs < table[mid].first) - max = mid - 1; - else - return true; + if (ucs > table[mid].last) min = mid + 1; + else if (ucs < table[mid].first) max = mid - 1; + else return true; } return false; } - - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java index 3ad63a8f38133..b1285f9636ea5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -35,9 +35,11 @@ public class WriterOutputStream extends OutputStream { private final CharBuffer decoderOut = CharBuffer.allocate(128); public WriterOutputStream(Writer out, Charset charset) { - this(out, charset.newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE)); + this( + out, + charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE)); } public WriterOutputStream(Writer out, CharsetDecoder decoder) { @@ -47,7 +49,7 @@ public WriterOutputStream(Writer out, CharsetDecoder decoder) { @Override public void write(int b) throws IOException { - write(new byte[] { (byte)b }, 0, 1); + write(new byte[] {(byte) b}, 0, 1); } @Override diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps index 719bcf8620296..f5caa4402bcc6 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps @@ -5,6 +5,9 @@ windows-conemu|conemu windows terminal, cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B, cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A, + civis=\E[?25l, cvvis=\E[?25h, + smcup=\E[?1049h, rmcup=\E[?1049l, + rc=\E8, sc=\E7, il=\E[%p1%dL, il1=\E[L, dl=\E[%p1%dM, dl1=\E[M, ech=\E[%p1%dX, diff --git a/src/jdk.internal.le/share/legal/jline.md b/src/jdk.internal.le/share/legal/jline.md index 6840c69cfc02b..5b813c0af2faf 100644 --- a/src/jdk.internal.le/share/legal/jline.md +++ b/src/jdk.internal.le/share/legal/jline.md @@ -1,9 +1,9 @@ -## JLine v3.22.0 +## JLine v3.26.1 ### JLine License
 
-Copyright (c) 2002-2018, the original author or authors.
+Copyright (c) 2002-2023, the original author or authors.
 All rights reserved.
 
 https://opensource.org/licenses/BSD-3-Clause
diff --git a/src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaNativePty.java b/src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaNativePty.java
deleted file mode 100644
index 2cf24e4ba8575..0000000000000
--- a/src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaNativePty.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2002-2020, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-package jdk.internal.org.jline.terminal.impl.jna;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Constructor;
-
-//import com.sun.jna.Platform;
-import jdk.internal.org.jline.terminal.Attributes;
-import jdk.internal.org.jline.terminal.Size;
-import jdk.internal.org.jline.terminal.impl.AbstractPty;
-import jdk.internal.org.jline.terminal.spi.TerminalProvider;
-import jdk.internal.org.jline.terminal.spi.Pty;
-//import jdk.internal.org.jline.terminal.impl.jna.freebsd.FreeBsdNativePty;
-//import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty;
-//import jdk.internal.org.jline.terminal.impl.jna.osx.OsXNativePty;
-//import jdk.internal.org.jline.terminal.impl.jna.solaris.SolarisNativePty;
-
-public abstract class JnaNativePty extends AbstractPty implements Pty {
-
-    private final int master;
-    private final int slave;
-    private final int slaveOut;
-    private final String name;
-    private final FileDescriptor masterFD;
-    private final FileDescriptor slaveFD;
-    private final FileDescriptor slaveOutFD;
-
-    public static JnaNativePty current(TerminalProvider.Stream console) throws IOException {
-//        if (Platform.isMac()) {
-//            if (Platform.is64Bit() && Platform.isARM()) {
-//                throw new UnsupportedOperationException();
-//            }
-//            return OsXNativePty.current(console);
-//        } else if (Platform.isLinux()) {
-//            return LinuxNativePty.current(console);
-//        } else if (Platform.isSolaris()) {
-//            return SolarisNativePty.current(console);
-//        } else if (Platform.isFreeBSD()) {
-//            return FreeBsdNativePty.current(console);
-//        } else {
-//            throw new UnsupportedOperationException();
-//        }
-        return JDKNativePty.current(console);
-    }
-
-    public static JnaNativePty open(Attributes attr, Size size) throws IOException {
-//        if (Platform.isMac()) {
-//            return OsXNativePty.open(attr, size);
-//        } else if (Platform.isLinux()) {
-//            return LinuxNativePty.open(attr, size);
-//        } else if (Platform.isSolaris()) {
-//            return SolarisNativePty.open(attr, size);
-//        } else if (Platform.isFreeBSD()) {
-//            return FreeBsdNativePty.open(attr, size);
-//        } else {
-//            throw new UnsupportedOperationException();
-//        }
-        return JDKNativePty.open(attr, size);
-    }
-
-    protected JnaNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
-        this(master, masterFD, slave, slaveFD, slave, slaveFD, name);
-    }
-
-    protected JnaNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) {
-        this.master = master;
-        this.slave = slave;
-        this.slaveOut = slaveOut;
-        this.name = name;
-        this.masterFD = masterFD;
-        this.slaveFD = slaveFD;
-        this.slaveOutFD = slaveOutFD;
-    }
-
-    @Override
-    public void close() throws IOException {
-        if (master > 0) {
-            getMasterInput().close();
-        }
-        if (slave > 0) {
-            getSlaveInput().close();
-        }
-    }
-
-    public int getMaster() {
-        return master;
-    }
-
-    public int getSlave() {
-        return slave;
-    }
-
-    public int getSlaveOut() {
-        return slaveOut;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public FileDescriptor getMasterFD() {
-        return masterFD;
-    }
-
-    public FileDescriptor getSlaveFD() {
-        return slaveFD;
-    }
-
-    public FileDescriptor getSlaveOutFD() {
-        return slaveOutFD;
-    }
-
-    public InputStream getMasterInput() {
-        return new FileInputStream(getMasterFD());
-    }
-
-    public OutputStream getMasterOutput() {
-        return new FileOutputStream(getMasterFD());
-    }
-
-    protected InputStream doGetSlaveInput() {
-        return new FileInputStream(getSlaveFD());
-    }
-
-    public OutputStream getSlaveOutput() {
-        return new FileOutputStream(getSlaveOutFD());
-    }
-
-    protected static FileDescriptor newDescriptor(int fd) {
-        try {
-            Constructor cns = FileDescriptor.class.getDeclaredConstructor(int.class);
-            cns.setAccessible(true);
-            return cns.newInstance(fd);
-        } catch (Throwable e) {
-            throw new RuntimeException("Unable to create FileDescriptor", e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "JnaNativePty[" + getName() + "]";
-    }
-
-    public static boolean isPosixSystemStream(TerminalProvider.Stream stream) {
-        switch (stream) {
-            case Input: return isatty(0);
-            case Output: return isatty(1);
-            case Error: return isatty(2);
-            default: return false;
-        }
-    }
-
-    public static String posixSystemStreamName(TerminalProvider.Stream stream) {
-        switch (stream) {
-            case Input: return ttyname(0);
-            case Output: return ttyname(1);
-            case Error: return ttyname(2);
-            default: return null;
-        }
-    }
-
-    private static boolean isatty(int fd) {
-//        if (Platform.isMac()) {
-//            return OsXNativePty.isatty(fd) == 1;
-//        } else if (Platform.isLinux()) {
-//            return LinuxNativePty.isatty(fd) == 1;
-//        } else if (Platform.isSolaris()) {
-//            return SolarisNativePty.isatty(fd) == 1;
-//        } else if (Platform.isFreeBSD()) {
-//            return FreeBsdNativePty.isatty(fd) == 1;
-//        } else {
-//            return false;
-//        }
-        return JDKNativePty.isatty(fd) == 1;
-    }
-
-    private static String ttyname(int fd) {
-//        if (Platform.isMac()) {
-//            return OsXNativePty.ttyname(fd);
-//        } else if (Platform.isLinux()) {
-//            return LinuxNativePty.ttyname(fd);
-//        } else if (Platform.isSolaris()) {
-//            return SolarisNativePty.ttyname(fd);
-//        } else if (Platform.isFreeBSD()) {
-//            return FreeBsdNativePty.ttyname(fd);
-//        } else {
-//            return null;
-//        }
-        return JDKNativePty.ttyname(fd);
-    }
-
-}
diff --git a/src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java b/src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
deleted file mode 100644
index 04052202030f7..0000000000000
--- a/src/jdk.internal.le/unix/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2002-2020, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-package jdk.internal.org.jline.terminal.impl.jna;
-
-import jdk.internal.org.jline.terminal.Attributes;
-import jdk.internal.org.jline.terminal.Size;
-import jdk.internal.org.jline.terminal.Terminal;
-import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
-import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
-//import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
-import jdk.internal.org.jline.terminal.spi.TerminalProvider;
-import jdk.internal.org.jline.terminal.spi.Pty;
-import jdk.internal.org.jline.utils.OSUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.function.Function;
-
-public class JnaTerminalProvider implements TerminalProvider
-{
-    @Override
-    public String name() {
-        return "jna";
-    }
-
-    public Pty current(TerminalProvider.Stream console) throws IOException {
-        return JnaNativePty.current(console);
-    }
-
-    public Pty open(Attributes attributes, Size size) throws IOException {
-        return JnaNativePty.open(attributes, size);
-    }
-
-    @Override
-    public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-                                boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-                                Stream consoleStream, Function inputStreamWrapper) throws IOException {
-//        if (OSUtils.IS_WINDOWS) {
-//            return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream );
-//        } else {
-            return posixSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
-//        }
-    }
-
-//    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-//                                   boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-//                                   Stream console, Function inputStreamWrapper) throws IOException {
-//        return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, console);
-//    }
-//
-    public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-                                     boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-                                     Stream consoleStream, Function inputStreamWrapper) throws IOException {
-//        Pty pty = jdk.internal.org.jline.terminal.impl.ExecPty.current(consoleStream);
-        Pty pty = current(consoleStream);
-        return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper);
-    }
-
-    @Override
-    public Terminal newTerminal(String name, String type, InputStream in, OutputStream out,
-                                Charset encoding, Terminal.SignalHandler signalHandler, boolean paused,
-                                Attributes attributes, Size size) throws IOException
-    {
-        Pty pty = open(attributes, size);
-        return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
-    }
-
-    @Override
-    public boolean isSystemStream(Stream stream) {
-        try {
-//            if (OSUtils.IS_WINDOWS) {
-//                return isWindowsSystemStream(stream);
-//            } else {
-                return isPosixSystemStream(stream);
-//            }
-        } catch (Throwable t) {
-            return false;
-        }
-    }
-
-//    public boolean isWindowsSystemStream(Stream stream) {
-//        return JnaWinSysTerminal.isWindowsSystemStream(stream);
-//    }
-
-    public boolean isPosixSystemStream(Stream stream) {
-        return JnaNativePty.isPosixSystemStream(stream);
-    }
-
-    @Override
-    public String systemStreamName(Stream stream) {
-        if (OSUtils.IS_WINDOWS) {
-            return null;
-        } else {
-            return JnaNativePty.posixSystemStreamName(stream);
-        }
-    }
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
deleted file mode 100644
index b820ce2187efe..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2002-2020, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-package jdk.internal.org.jline.terminal.impl.jna;
-
-import jdk.internal.org.jline.terminal.Attributes;
-import jdk.internal.org.jline.terminal.Size;
-import jdk.internal.org.jline.terminal.Terminal;
-import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
-import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
-import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
-import jdk.internal.org.jline.terminal.spi.TerminalProvider;
-import jdk.internal.org.jline.terminal.spi.Pty;
-import jdk.internal.org.jline.utils.OSUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.function.Function;
-
-public class JnaTerminalProvider implements TerminalProvider
-{
-    @Override
-    public String name() {
-        return "jna";
-    }
-
-//    public Pty current(TerminalProvider.Stream console) throws IOException {
-//        return JnaNativePty.current(console);
-//    }
-//
-//    public Pty open(Attributes attributes, Size size) throws IOException {
-//        return JnaNativePty.open(attributes, size);
-//    }
-
-    @Override
-    public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-                                boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-                                Stream consoleStream, Function inputStreamWrapper) throws IOException {
-        if (OSUtils.IS_WINDOWS) {
-            return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
-        } else {
-            return null;
-        }
-    }
-
-    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-                                   boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-                                   Stream console, Function inputStreamWrapper) throws IOException {
-        return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, console, inputStreamWrapper);
-    }
-
-//    public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-//                                     boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-//                                     Stream consoleStream) throws IOException {
-//        Pty pty = current(consoleStream);
-//        return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
-//    }
-
-    @Override
-    public Terminal newTerminal(String name, String type, InputStream in, OutputStream out,
-                                Charset encoding, Terminal.SignalHandler signalHandler, boolean paused,
-                                Attributes attributes, Size size) throws IOException
-    {
-//        Pty pty = open(attributes, size);
-//        return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
-        return null;
-    }
-
-    @Override
-    public boolean isSystemStream(Stream stream) {
-        try {
-            if (OSUtils.IS_WINDOWS) {
-                return isWindowsSystemStream(stream);
-            } else {
-//                return isPosixSystemStream(stream);
-                return false;
-            }
-        } catch (Throwable t) {
-            return false;
-        }
-    }
-
-    public boolean isWindowsSystemStream(Stream stream) {
-        return JnaWinSysTerminal.isWindowsSystemStream(stream);
-    }
-
-//    public boolean isPosixSystemStream(Stream stream) {
-//        return JnaNativePty.isPosixSystemStream(stream);
-//    }
-
-    @Override
-    public String systemStreamName(Stream stream) {
-//        if (OSUtils.IS_WINDOWS) {
-            return null;
-//        } else {
-//            return JnaNativePty.posixSystemStreamName(stream);
-//        }
-    }
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/IntByReference.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/IntByReference.java
deleted file mode 100644
index 7cfe401b58267..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/IntByReference.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2018, 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.
- */
-package jdk.internal.org.jline.terminal.impl.jna.win;
-
-class IntByReference {
-
-    public int value;
-
-    public int getValue() {
-        return value;
-    }
-
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
deleted file mode 100644
index 7fcbb5416a697..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2002-2017, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-package jdk.internal.org.jline.terminal.impl.jna.win;
-
-//import com.sun.jna.LastErrorException;
-//import com.sun.jna.Pointer;
-//import com.sun.jna.ptr.IntByReference;
-import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
-import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
-
-import java.io.IOException;
-
-class JnaWinConsoleWriter extends AbstractWindowsConsoleWriter {
-
-    private final Pointer console;
-    private final IntByReference writtenChars = new IntByReference();
-
-    JnaWinConsoleWriter(Pointer console) {
-        this.console = console;
-    }
-
-    @Override
-    protected void writeConsole(char[] text, int len) throws IOException {
-        try {
-            Kernel32.INSTANCE.WriteConsoleW(this.console, text, len, this.writtenChars, null);
-        } catch (LastErrorException e) {
-            throw new IOException("Failed to write to console", e);
-        }
-    }
-
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
deleted file mode 100644
index 9baafb89bd954..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (c) 2002-2020, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-package jdk.internal.org.jline.terminal.impl.jna.win;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.util.function.Function;
-import java.util.function.IntConsumer;
-
-//import com.sun.jna.LastErrorException;
-//import com.sun.jna.Pointer;
-//import com.sun.jna.ptr.IntByReference;
-import jdk.internal.org.jline.terminal.Cursor;
-import jdk.internal.org.jline.terminal.Size;
-import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
-import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
-import jdk.internal.org.jline.terminal.spi.TerminalProvider;
-import jdk.internal.org.jline.utils.InfoCmp;
-import jdk.internal.org.jline.utils.OSUtils;
-
-public class JnaWinSysTerminal extends AbstractWindowsTerminal {
-
-    private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
-    private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
-    private static final Pointer consoleErr = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_ERROR_HANDLE);
-
-    public static JnaWinSysTerminal createTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, boolean paused, TerminalProvider.Stream consoleStream, Function inputStreamWrapper) throws IOException {
-        Pointer console;
-        switch (consoleStream) {
-            case Output:
-                console = JnaWinSysTerminal.consoleOut;
-                break;
-            case Error:
-                console = JnaWinSysTerminal.consoleErr;
-                break;
-            default:
-                throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
-        }
-        Writer writer;
-        if (ansiPassThrough) {
-            if (type == null) {
-                type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
-            }
-            writer = new JnaWinConsoleWriter(console);
-        } else {
-            IntByReference mode = new IntByReference();
-            Kernel32.INSTANCE.GetConsoleMode(console, mode);
-            try {
-                Kernel32.INSTANCE.SetConsoleMode(console, mode.getValue() | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
-                if (type == null) {
-                    type = TYPE_WINDOWS_VTP;
-                }
-                writer = new JnaWinConsoleWriter(console);
-            } catch (LastErrorException e) {
-                if (OSUtils.IS_CONEMU) {
-                    if (type == null) {
-                        type = TYPE_WINDOWS_CONEMU;
-                    }
-                    writer = new JnaWinConsoleWriter(console);
-                } else {
-                    if (type == null) {
-                        type = TYPE_WINDOWS;
-                    }
-                    writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(console)), console);
-                }
-            }
-        }
-        JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
-        // Start input pump thread
-        if (!paused) {
-            terminal.resume();
-        }
-        return terminal;
-    }
-
-    public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
-        try {
-            IntByReference mode = new IntByReference();
-            Pointer console;
-            switch (stream) {
-                case Input: console = consoleIn; break;
-                case Output: console = consoleOut; break;
-                case Error: console = consoleErr; break;
-                default: return false;
-            }
-            Kernel32.INSTANCE.GetConsoleMode(console, mode);
-            return true;
-        } catch (LastErrorException e) {
-            return false;
-        }
-    }
-
-    JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
-            Function inputStreamWrapper) throws IOException {
-        super(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
-        strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
-    }
-
-    @Override
-    protected int getConsoleMode() {
-        IntByReference mode = new IntByReference();
-        Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
-        return mode.getValue();
-    }
-
-    @Override
-    protected void setConsoleMode(int mode) {
-        Kernel32.INSTANCE.SetConsoleMode(consoleIn, mode);
-    }
-
-    public Size getSize() {
-        Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
-        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
-        return new Size(info.windowWidth(), info.windowHeight());
-    }
-
-    public Size getBufferSize() {
-        Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
-        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
-        return new Size(info.dwSize.X, info.dwSize.Y);
-    }
-
-    protected boolean processConsoleInput() throws IOException {
-        Kernel32.INPUT_RECORD event = readConsoleInput(100);
-        if (event == null) {
-            return false;
-        }
-
-        switch (event.EventType) {
-            case Kernel32.INPUT_RECORD.KEY_EVENT:
-                processKeyEvent(event.Event.KeyEvent);
-                return true;
-            case Kernel32.INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT:
-                raise(Signal.WINCH);
-                return false;
-            case Kernel32.INPUT_RECORD.MOUSE_EVENT:
-                processMouseEvent(event.Event.MouseEvent);
-                return true;
-            case Kernel32.INPUT_RECORD.FOCUS_EVENT:
-                processFocusEvent(event.Event.FocusEvent.bSetFocus);
-                return true;
-            default:
-                // Skip event
-                return false;
-        }
-    }
-
-    private void processKeyEvent(Kernel32.KEY_EVENT_RECORD keyEvent) throws IOException {
-        processKeyEvent(keyEvent.bKeyDown, keyEvent.wVirtualKeyCode, keyEvent.uChar.UnicodeChar, keyEvent.dwControlKeyState);
-    }
-
-    private char[] focus = new char[] { '\033', '[', ' ' };
-
-    private void processFocusEvent(boolean hasFocus) throws IOException {
-        if (focusTracking) {
-            focus[2] = hasFocus ? 'I' : 'O';
-            slaveInputPipe.write(focus);
-        }
-    }
-
-    private char[] mouse = new char[] { '\033', '[', 'M', ' ', ' ', ' ' };
-
-    private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IOException {
-        int dwEventFlags = mouseEvent.dwEventFlags;
-        int dwButtonState = mouseEvent.dwButtonState;
-        if (tracking == MouseTracking.Off
-                || tracking == MouseTracking.Normal && dwEventFlags == Kernel32.MOUSE_MOVED
-                || tracking == MouseTracking.Button && dwEventFlags == Kernel32.MOUSE_MOVED && dwButtonState == 0) {
-            return;
-        }
-        int cb = 0;
-        dwEventFlags &= ~ Kernel32.DOUBLE_CLICK; // Treat double-clicks as normal
-        if (dwEventFlags == Kernel32.MOUSE_WHEELED) {
-            cb |= 64;
-            if ((dwButtonState >> 16) < 0) {
-                cb |= 1;
-            }
-        } else if (dwEventFlags == Kernel32.MOUSE_HWHEELED) {
-            return;
-        } else if ((dwButtonState & Kernel32.FROM_LEFT_1ST_BUTTON_PRESSED) != 0) {
-            cb |= 0x00;
-        } else if ((dwButtonState & Kernel32.RIGHTMOST_BUTTON_PRESSED) != 0) {
-            cb |= 0x01;
-        } else if ((dwButtonState & Kernel32.FROM_LEFT_2ND_BUTTON_PRESSED) != 0) {
-            cb |= 0x02;
-        } else {
-            cb |= 0x03;
-        }
-        int cx = mouseEvent.dwMousePosition.X;
-        int cy = mouseEvent.dwMousePosition.Y;
-        mouse[3] = (char) (' ' + cb);
-        mouse[4] = (char) (' ' + cx + 1);
-        mouse[5] = (char) (' ' + cy + 1);
-        slaveInputPipe.write(mouse);
-    }
-
-    private final Kernel32.INPUT_RECORD[] inputEvents = new Kernel32.INPUT_RECORD[1];
-    private final IntByReference eventsRead = new IntByReference();
-
-    private Kernel32.INPUT_RECORD readConsoleInput(int dwMilliseconds) throws IOException {
-        if (Kernel32.INSTANCE.WaitForSingleObject(consoleIn, dwMilliseconds) != 0) {
-            return null;
-        }
-        Kernel32.INSTANCE.ReadConsoleInput(consoleIn, inputEvents, 1, eventsRead);
-        if (eventsRead.getValue() == 1) {
-            return inputEvents[0];
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    public Cursor getCursorPosition(IntConsumer discarded) {
-        Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
-        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
-        return new Cursor(info.dwCursorPosition.X, info.dwCursorPosition.Y);
-    }
-
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
deleted file mode 100644
index 20c6eefeeced2..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Copyright (c) 2002-2018, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-package jdk.internal.org.jline.terminal.impl.jna.win;
-
-//OpenJDK changes:
-//-references to JNA types commented out
-//-replacement types provided where needed (IntByReference, LastErrorException, Pointer)
-//-methods not used by JLine commented out
-//-provided an implementation of the interface (Kernel32Impl), backed by a native implementation (Kernel32.cpp)
-
-//import com.sun.jna.LastErrorException;
-//import com.sun.jna.Native;
-//import com.sun.jna.Pointer;
-//import com.sun.jna.Structure;
-//import com.sun.jna.Union;
-//import com.sun.jna.ptr.IntByReference;
-//import com.sun.jna.win32.StdCallLibrary;
-//import com.sun.jna.win32.W32APIOptions;
-import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
-
-interface Kernel32 {//extends StdCallLibrary {
-
-    Kernel32 INSTANCE = new Kernel32Impl();
-//    Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
-
-//    Pointer INVALID_HANDLE_VALUE = Pointer.createConstant(-1L);
-
-    int STD_INPUT_HANDLE =  -10;
-    int STD_OUTPUT_HANDLE = -11;
-    int STD_ERROR_HANDLE =  -12;
-
-    int ENABLE_PROCESSED_INPUT =    0x0001;
-    int ENABLE_LINE_INPUT =         0x0002;
-    int ENABLE_ECHO_INPUT =         0x0004;
-    int ENABLE_WINDOW_INPUT =       0x0008;
-    int ENABLE_MOUSE_INPUT =        0x0010;
-    int ENABLE_INSERT_MODE =        0x0020;
-    int ENABLE_QUICK_EDIT_MODE =    0x0040;
-    int ENABLE_EXTENDED_FLAGS =     0x0080;
-
-    int RIGHT_ALT_PRESSED =     0x0001;
-    int LEFT_ALT_PRESSED =      0x0002;
-    int RIGHT_CTRL_PRESSED =    0x0004;
-    int LEFT_CTRL_PRESSED =     0x0008;
-    int SHIFT_PRESSED =         0x0010;
-
-    int FOREGROUND_BLUE =       0x0001;
-    int FOREGROUND_GREEN =      0x0002;
-    int FOREGROUND_RED =        0x0004;
-    int FOREGROUND_INTENSITY =  0x0008;
-    int BACKGROUND_BLUE =       0x0010;
-    int BACKGROUND_GREEN =      0x0020;
-    int BACKGROUND_RED =        0x0040;
-    int BACKGROUND_INTENSITY =  0x0080;
-
-    // Button state
-    int FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001;
-    int RIGHTMOST_BUTTON_PRESSED     = 0x0002;
-    int FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004;
-    int FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008;
-    int FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010;
-
-    // Event flags
-    int MOUSE_MOVED                  = 0x0001;
-    int DOUBLE_CLICK                 = 0x0002;
-    int MOUSE_WHEELED                = 0x0004;
-    int MOUSE_HWHEELED               = 0x0008;
-
-    // DWORD WINAPI WaitForSingleObject(
-    //  _In_ HANDLE hHandle,
-    //  _In_ DWORD  dwMilliseconds
-    // );
-    int WaitForSingleObject(Pointer in_hHandle, int in_dwMilliseconds);
-
-    // HANDLE WINAPI GetStdHandle(
-    // __in DWORD nStdHandle
-    // );
-    Pointer GetStdHandle(int nStdHandle);
-
-//    // BOOL WINAPI AllocConsole(void);
-//    void AllocConsole() throws LastErrorException;
-//
-//    // BOOL WINAPI FreeConsole(void);
-//    void FreeConsole() throws LastErrorException;
-//
-//    // HWND WINAPI GetConsoleWindow(void);
-//    Pointer GetConsoleWindow();
-//
-//    // UINT WINAPI GetConsoleCP(void)
-//    int GetConsoleCP();
-//
-    // UINT WINAPI GetConsoleOutputCP(void)
-    int GetConsoleOutputCP();
-
-    // BOOL WINAPI FillConsoleOutputCharacter(
-    // _In_ HANDLE hConsoleOutput,
-    // _In_ TCHAR cCharacter,
-    // _In_ DWORD nLength,
-    // _In_ COORD dwWriteCoord,
-    // _Out_ LPDWORD lpNumberOfCharsWritten);
-    void FillConsoleOutputCharacter(Pointer in_hConsoleOutput,
-                                    char in_cCharacter, int in_nLength, COORD in_dwWriteCoord,
-                                    IntByReference out_lpNumberOfCharsWritten)
-            throws LastErrorException;
-
-    // BOOL WINAPI FillConsoleOutputAttribute(
-    // _In_ HANDLE hConsoleOutput,
-    // _In_ WORD wAttribute,
-    // _In_ DWORD nLength,
-    // _In_ COORD dwWriteCoord,
-    // _Out_ LPDWORD lpNumberOfAttrsWritten);
-    void FillConsoleOutputAttribute(Pointer in_hConsoleOutput,
-                                    short in_wAttribute, int in_nLength, COORD in_dwWriteCoord,
-                                    IntByReference out_lpNumberOfAttrsWritten)
-            throws LastErrorException;
-//
-////    // BOOL WINAPI GetConsoleCursorInfo(
-////    // _In_ HANDLE hConsoleOutput,
-////    // _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
-////    void GetConsoleCursorInfo(Pointer in_hConsoleOutput,
-////                              CONSOLE_CURSOR_INFO.ByReference out_lpConsoleCursorInfo)
-////            throws LastErrorException;
-//
-    // BOOL WINAPI GetConsoleMode(
-    //   _In_   HANDLE hConsoleHandle,
-    //   _Out_  LPDWORD lpMode);
-    void GetConsoleMode(
-            Pointer in_hConsoleOutput,
-            IntByReference out_lpMode)
-            throws LastErrorException;
-
-    // BOOL WINAPI GetConsoleScreenBufferInfo(
-    // _In_   HANDLE hConsoleOutput,
-    // _Out_  PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
-    void GetConsoleScreenBufferInfo(
-            Pointer in_hConsoleOutput,
-            CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo)
-            throws LastErrorException;
-//
-//    // BOOL WINAPI GetNumberOfConsoleInputEvents(
-//    // _In_ HANDLE hConsoleInput,
-//    // _Out_ LPDWORD lpcNumberOfEvents);
-//    void GetNumberOfConsoleInputEvents(Pointer in_hConsoleOutput,
-//                                       IntByReference out_lpcNumberOfEvents) throws LastErrorException;
-//
-    // BOOL WINAPI ReadConsoleInput(
-    // _In_ HANDLE hConsoleInput,
-    // _Out_ PINPUT_RECORD lpBuffer,
-    // _In_ DWORD nLength,
-    // _Out_ LPDWORD lpNumberOfEventsRead);
-    void ReadConsoleInput(Pointer in_hConsoleOutput,
-                          INPUT_RECORD[] out_lpBuffer, int in_nLength,
-                          IntByReference out_lpNumberOfEventsRead) throws LastErrorException;
-
-//    // BOOL WINAPI SetConsoleCtrlHandler(
-//    // _In_opt_  PHANDLER_ROUTINE HandlerRoutine,
-//    // _In_      BOOL Add);
-//    void SetConsoleCtrlHandler(
-//            Pointer in_opt_HandlerRoutine,
-//            boolean in_Add)
-//            throws LastErrorException;
-//
-//    // BOOL WINAPI ReadConsoleOutput(
-//    // _In_     HANDLE hConsoleOutput,
-//    // _Out_    PCHAR_INFO lpBuffer,
-//    // _In_     COORD dwBufferSize,
-//    // _In_     COORD dwBufferCoord,
-//    // _Inout_  PSMALL_RECT lpReadRegion);
-////    void ReadConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
-////                           COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                           SMALL_RECT inout_lpReadRegion) throws LastErrorException;
-////    void ReadConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
-////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                            SMALL_RECT inout_lpReadRegion) throws LastErrorException;
-//
-//    // BOOL WINAPI ReadConsoleOutputCharacter(
-//    // _In_   HANDLE hConsoleOutput,
-//    // _Out_  LPTSTR lpCharacter,
-//    // _In_   DWORD nLength,
-//    // _In_   COORD dwReadCoord,
-//    // _Out_  LPDWORD lpNumberOfCharsRead);
-//    void ReadConsoleOutputCharacter(Pointer in_hConsoleOutput,
-//                                    char[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
-//                                    IntByReference out_lpNumberOfCharsRead)
-//            throws LastErrorException;
-//    void ReadConsoleOutputCharacterA(Pointer in_hConsoleOutput,
-//                                     byte[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
-//                                     IntByReference out_lpNumberOfCharsRead)
-//            throws LastErrorException;
-//
-//    // BOOL WINAPI SetConsoleCursorInfo(
-//    // _In_ HANDLE hConsoleOutput,
-//    // _In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
-//    void SetConsoleCursorInfo(Pointer in_hConsoleOutput,
-//                              CONSOLE_CURSOR_INFO in_lpConsoleCursorInfo)
-//            throws LastErrorException;
-//
-//    // BOOL WINAPI SetConsoleCP(
-//    // _In_ UINT wCodePageID);
-//    void SetConsoleCP(int in_wCodePageID) throws LastErrorException;
-//
-//    // BOOL WINAPI SetConsoleOutputCP(
-//    // _In_ UINT wCodePageID);
-//    void SetConsoleOutputCP(int in_wCodePageID) throws LastErrorException;
-//
-    // BOOL WINAPI SetConsoleCursorPosition(
-    // _In_ HANDLE hConsoleOutput,
-    // _In_ COORD dwCursorPosition);
-    void SetConsoleCursorPosition(Pointer in_hConsoleOutput,
-                                  COORD in_dwCursorPosition) throws LastErrorException;
-
-    // BOOL WINAPI SetConsoleMode(
-    //   _In_  HANDLE hConsoleHandle,
-    //   _In_  DWORD dwMode);
-    void SetConsoleMode(
-            Pointer in_hConsoleOutput,
-            int in_dwMode) throws LastErrorException;
-
-//    // BOOL WINAPI SetConsoleScreenBufferSize(
-//    // __in HANDLE hConsoleOutput,
-//    // __in COORD dwSize
-//    // );
-//    void SetConsoleScreenBufferSize(Pointer in_hConsoleOutput,
-//                                    COORD in_dwSize) throws LastErrorException;
-//
-    // BOOL WINAPI SetConsoleTextAttribute(
-    // _In_ HANDLE hConsoleOutput,
-    // _In_ WORD   wAttributes
-    // );
-    void SetConsoleTextAttribute(Pointer in_hConsoleOutput,
-                                 short in_wAttributes)
-            throws LastErrorException;
-
-    // BOOL WINAPI SetConsoleTitle(
-    // _In_ LPCTSTR lpConsoleTitle
-    // );
-    void SetConsoleTitle(String in_lpConsoleTitle)
-            throws LastErrorException;
-
-//    // BOOL WINAPI SetConsoleWindowInfo(
-//    // _In_ HANDLE hConsoleOutput,
-//    // _In_ BOOL bAbsolute,
-//    // _In_ const SMALL_RECT *lpConsoleWindow);
-//    void SetConsoleWindowInfo(Pointer in_hConsoleOutput,
-//                              boolean in_bAbsolute, SMALL_RECT in_lpConsoleWindow)
-//            throws LastErrorException;
-
-    // BOOL WINAPI WriteConsole(
-    //  _In_             HANDLE  hConsoleOutput,
-    //  _In_       const VOID    *lpBuffer,
-    //  _In_             DWORD   nNumberOfCharsToWrite,
-    //  _Out_            LPDWORD lpNumberOfCharsWritten,
-    //  _Reserved_       LPVOID  lpReserved
-    // );
-    void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumberOfCharsToWrite,
-                          IntByReference out_lpNumberOfCharsWritten, Pointer reserved_lpReserved) throws LastErrorException;
-
-//    // BOOL WINAPI WriteConsoleOutput(
-//    // _In_ HANDLE hConsoleOutput,
-//    // _In_ const CHAR_INFO *lpBuffer,
-//    // _In_ COORD dwBufferSize,
-//    // _In_ COORD dwBufferCoord,
-//    // _Inout_ PSMALL_RECT lpWriteRegion);
-////    void WriteConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
-////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                            SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
-////    void WriteConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
-////                             COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                             SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
-//
-//    // BOOL WINAPI WriteConsoleOutputCharacter(
-//    // _In_ HANDLE hConsoleOutput,
-//    // _In_ LPCTSTR lpCharacter,
-//    // _In_ DWORD nLength,
-//    // _In_ COORD dwWriteCoord,
-//    // _Out_ LPDWORD lpNumberOfCharsWritten);
-//    void WriteConsoleOutputCharacter(Pointer in_hConsoleOutput,
-//                                     char[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
-//                                     IntByReference out_lpNumberOfCharsWritten)
-//            throws LastErrorException;
-//    void WriteConsoleOutputCharacterA(Pointer in_hConsoleOutput,
-//                                      byte[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
-//                                      IntByReference out_lpNumberOfCharsWritten)
-//            throws LastErrorException;
-//
-    // BOOL WINAPI ScrollConsoleScreenBuffer(
-    //     _In_           HANDLE     hConsoleOutput,
-    //     _In_     const SMALL_RECT *lpScrollRectangle,
-    //     _In_opt_ const SMALL_RECT *lpClipRectangle,
-    //     _In_           COORD      dwDestinationOrigin,
-    //     _In_     const CHAR_INFO  *lpFill);
-    void ScrollConsoleScreenBuffer(Pointer in_hConsoleOutput,
-                                   SMALL_RECT in_lpScrollRectangle,
-                                   SMALL_RECT in_lpClipRectangle,
-                                   COORD in_dwDestinationOrigin,
-                                   CHAR_INFO in_lpFill)
-            throws LastErrorException;
-
-    // typedef struct _CHAR_INFO {
-    //   union {
-    //     WCHAR UnicodeChar;
-    //     CHAR  AsciiChar;
-    //   } Char;
-    //   WORD  Attributes;
-    // } CHAR_INFO, *PCHAR_INFO;
-    class CHAR_INFO {//extends Structure {
-        public CHAR_INFO() {
-        }
-
-        public CHAR_INFO(char c, short attr) {
-            uChar = new UnionChar(c);
-            Attributes = attr;
-        }
-
-//        public CHAR_INFO(byte c, short attr) {
-//            uChar = new UnionChar(c);
-//            Attributes = attr;
-//        }
-
-        public UnionChar uChar;
-        public short Attributes;
-
-//        public static CHAR_INFO[] createArray(int size) {
-//            return (CHAR_INFO[]) new CHAR_INFO().toArray(size);
-//        }
-//
-//        private static String[] fieldOrder = { "uChar", "Attributes" };
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _CONSOLE_CURSOR_INFO {
-    //   DWORD dwSize;
-    //   BOOL  bVisible;
-    // } CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
-    class CONSOLE_CURSOR_INFO {//extends Structure {
-        public int dwSize;
-        public boolean bVisible;
-
-//        public static class ByReference extends CONSOLE_CURSOR_INFO implements
-//                Structure.ByReference {
-//        }
-//
-//        private static String[] fieldOrder = { "dwSize", "bVisible" };
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
-    //   COORD      dwSize;
-    //   COORD      dwCursorPosition;
-    //   WORD       wAttributes;
-    //   SMALL_RECT srWindow;
-    //   COORD      dwMaximumWindowSize;
-    // } CONSOLE_SCREEN_BUFFER_INFO;
-    class CONSOLE_SCREEN_BUFFER_INFO {//extends Structure {
-        public COORD      dwSize;
-        public COORD      dwCursorPosition;
-        public short      wAttributes;
-        public SMALL_RECT srWindow;
-        public COORD      dwMaximumWindowSize;
-
-//        private static String[] fieldOrder = { "dwSize", "dwCursorPosition", "wAttributes", "srWindow", "dwMaximumWindowSize" };
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-
-        public int windowWidth() {
-            return this.srWindow.width() + 1;
-        }
-
-        public int windowHeight() {
-            return this.srWindow.height() + 1;
-        }
-    }
-
-    // typedef struct _COORD {
-    //    SHORT X;
-    //    SHORT Y;
-    //  } COORD, *PCOORD;
-    class COORD {//extends Structure implements Structure.ByValue {
-        public COORD() {
-        }
-
-        public COORD(short X, short Y) {
-            this.X = X;
-            this.Y = Y;
-        }
-
-        public short X;
-        public short Y;
-
-//        private static String[] fieldOrder = { "X", "Y" };
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _INPUT_RECORD {
-    //   WORD  EventType;
-    //   union {
-    //     KEY_EVENT_RECORD          KeyEvent;
-    //     MOUSE_EVENT_RECORD        MouseEvent;
-    //     WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
-    //     MENU_EVENT_RECORD         MenuEvent;
-    //     FOCUS_EVENT_RECORD        FocusEvent;
-    //   } Event;
-    // } INPUT_RECORD;
-    class INPUT_RECORD {//extends Structure {
-        public static final short KEY_EVENT = 0x0001;
-        public static final short MOUSE_EVENT = 0x0002;
-        public static final short WINDOW_BUFFER_SIZE_EVENT = 0x0004;
-        public static final short MENU_EVENT = 0x0008;
-        public static final short FOCUS_EVENT = 0x0010;
-
-        public short EventType;
-        public EventUnion Event;
-
-        public static class EventUnion {//extends Union {
-            public KEY_EVENT_RECORD KeyEvent;
-            public MOUSE_EVENT_RECORD MouseEvent;
-            public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
-            public MENU_EVENT_RECORD MenuEvent;
-            public FOCUS_EVENT_RECORD FocusEvent;
-        }
-
-//        @Override
-//        public void read() {
-//            readField("EventType");
-//            switch (EventType) {
-//                case KEY_EVENT:
-//                    Event.setType(KEY_EVENT_RECORD.class);
-//                    break;
-//                case MOUSE_EVENT:
-//                    Event.setType(MOUSE_EVENT_RECORD.class);
-//                    break;
-//                case WINDOW_BUFFER_SIZE_EVENT:
-//                    Event.setType(WINDOW_BUFFER_SIZE_RECORD.class);
-//                    break;
-//                case MENU_EVENT:
-//                    Event.setType(MENU_EVENT_RECORD.class);
-//                    break;
-//                case FOCUS_EVENT:
-//                    Event.setType(MENU_EVENT_RECORD.class);
-//                    break;
-//            }
-//            super.read();
-//        }
-
-//        private static String[] fieldOrder = {"EventType", "Event"};
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _KEY_EVENT_RECORD {
-    //   BOOL  bKeyDown;
-    //   WORD  wRepeatCount;
-    //   WORD  wVirtualKeyCode;
-    //   WORD  wVirtualScanCode;
-    //   union {
-    //     WCHAR UnicodeChar;
-    //     CHAR  AsciiChar;
-    //   } uChar;
-    //   DWORD dwControlKeyState;
-    // } KEY_EVENT_RECORD;
-    class KEY_EVENT_RECORD {//extends Structure {
-        public boolean bKeyDown;
-        public short wRepeatCount;
-        public short wVirtualKeyCode;
-        public short wVirtualScanCode;
-        public UnionChar uChar;
-        public int dwControlKeyState;
-
-//        private static String[] fieldOrder = {"bKeyDown", "wRepeatCount", "wVirtualKeyCode", "wVirtualScanCode", "uChar", "dwControlKeyState"};
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _MOUSE_EVENT_RECORD {
-    //   COORD dwMousePosition;
-    //   DWORD dwButtonState;
-    //   DWORD dwControlKeyState;
-    //   DWORD dwEventFlags;
-    // } MOUSE_EVENT_RECORD;
-    class MOUSE_EVENT_RECORD {//extends Structure {
-        public COORD dwMousePosition;
-        public int dwButtonState;
-        public int dwControlKeyState;
-        public int dwEventFlags;
-
-//        private static String[] fieldOrder = { "dwMousePosition", "dwButtonState", "dwControlKeyState", "dwEventFlags"};
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _WINDOW_BUFFER_SIZE_RECORD {
-    //   COORD dwSize;
-    // } WINDOW_BUFFER_SIZE_RECORD;
-    class WINDOW_BUFFER_SIZE_RECORD {//extends Structure {
-        public COORD dwSize;
-
-//        private static String[] fieldOrder = {"dwSize"};
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _MENU_EVENT_RECORD {
-    //   UINT dwCommandId;
-    // } MENU_EVENT_RECORD, *PMENU_EVENT_RECORD;
-    class MENU_EVENT_RECORD {//extends Structure {
-
-        public int dwCommandId;
-
-//        private static String[] fieldOrder = {"dwCommandId"};
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _FOCUS_EVENT_RECORD {
-    //  BOOL bSetFocus;
-    //} FOCUS_EVENT_RECORD;
-    class FOCUS_EVENT_RECORD {//extends Structure {
-        public boolean bSetFocus;
-
-//        private static String[] fieldOrder = {"bSetFocus"};
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-    }
-
-    // typedef struct _SMALL_RECT {
-    //    SHORT Left;
-    //    SHORT Top;
-    //    SHORT Right;
-    //    SHORT Bottom;
-    //  } SMALL_RECT;
-    class SMALL_RECT {//extends Structure {
-        public SMALL_RECT() {
-        }
-
-        public SMALL_RECT(SMALL_RECT org) {
-            this(org.Top, org.Left, org.Bottom, org.Right);
-        }
-
-        public SMALL_RECT(short Top, short Left, short Bottom, short Right) {
-            this.Top = Top;
-            this.Left = Left;
-            this.Bottom = Bottom;
-            this.Right = Right;
-        }
-
-        public short Left;
-        public short Top;
-        public short Right;
-        public short Bottom;
-
-//        private static String[] fieldOrder = { "Left", "Top", "Right", "Bottom" };
-//
-//        @Override
-//        protected java.util.List getFieldOrder() {
-//            return java.util.Arrays.asList(fieldOrder);
-//        }
-
-        public short width() {
-            return (short)(this.Right - this.Left);
-        }
-
-        public short height() {
-            return (short)(this.Bottom - this.Top);
-        }
-
-    }
-
-    class UnionChar {//extends Union {
-        public UnionChar() {
-        }
-
-        public UnionChar(char c) {
-//            setType(char.class);
-            UnicodeChar = c;
-        }
-
-//        public UnionChar(byte c) {
-//            setType(byte.class);
-//            AsciiChar = c;
-//        }
-
-        public void set(char c) {
-//            setType(char.class);
-            UnicodeChar = c;
-        }
-
-//        public void set(byte c) {
-//            setType(byte.class);
-//            AsciiChar = c;
-//        }
-
-        public char UnicodeChar;
-//        public byte AsciiChar;
-    }
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
deleted file mode 100644
index 67f69a6351163..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2018, 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.
- */
-package jdk.internal.org.jline.terminal.impl.jna.win;
-
-import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
-import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CHAR_INFO;
-import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_SCREEN_BUFFER_INFO;
-import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.COORD;
-import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD;
-import jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.SMALL_RECT;
-
-public class Kernel32Impl implements Kernel32 {
-
-    static {
-        System.loadLibrary("le");
-        initIDs();
-    }
-
-    private static native void initIDs();
-
-    @Override
-    public native int WaitForSingleObject(Pointer in_hHandle, int in_dwMilliseconds);
-
-    @Override
-    public native Pointer GetStdHandle(int nStdHandle);
-
-    @Override
-    public native int GetConsoleOutputCP();
-
-    @Override
-    public native void FillConsoleOutputCharacter(Pointer in_hConsoleOutput, char in_cCharacter, int in_nLength, COORD in_dwWriteCoord, IntByReference out_lpNumberOfCharsWritten) throws LastErrorException;
-
-    @Override
-    public native void FillConsoleOutputAttribute(Pointer in_hConsoleOutput, short in_wAttribute, int in_nLength, COORD in_dwWriteCoord, IntByReference out_lpNumberOfAttrsWritten) throws LastErrorException;
-
-    @Override
-    public native void GetConsoleMode(Pointer in_hConsoleOutput, IntByReference out_lpMode) throws LastErrorException;
-
-    @Override
-    public native void GetConsoleScreenBufferInfo(Pointer in_hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo) throws LastErrorException;
-
-    @Override
-    public native void ReadConsoleInput(Pointer in_hConsoleOutput, INPUT_RECORD[] out_lpBuffer, int in_nLength, IntByReference out_lpNumberOfEventsRead) throws LastErrorException;
-
-    @Override
-    public native void SetConsoleCursorPosition(Pointer in_hConsoleOutput, COORD in_dwCursorPosition) throws LastErrorException;
-
-    @Override
-    public native void SetConsoleMode(Pointer in_hConsoleOutput, int in_dwMode) throws LastErrorException;
-
-    @Override
-    public native void SetConsoleTextAttribute(Pointer in_hConsoleOutput, short in_wAttributes) throws LastErrorException;
-
-    @Override
-    public native void SetConsoleTitle(String in_lpConsoleTitle) throws LastErrorException;
-
-    @Override
-    public native void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumberOfCharsToWrite, IntByReference out_lpNumberOfCharsWritten, Pointer reserved_lpReserved) throws LastErrorException;
-
-    @Override
-    public native void ScrollConsoleScreenBuffer(Pointer in_hConsoleOutput, SMALL_RECT in_lpScrollRectangle, SMALL_RECT in_lpClipRectangle, COORD in_dwDestinationOrigin, CHAR_INFO in_lpFill) throws LastErrorException;
-
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Pointer.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Pointer.java
deleted file mode 100644
index aeb7f758e7dc1..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Pointer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2018, 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.
- */
-package jdk.internal.org.jline.terminal.impl.jna.win;
-
-class Pointer {
-    public final long value;
-
-    public Pointer(long value) {
-        this.value = value;
-    }
-
-}
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
deleted file mode 100644
index 5ae0df1b201b2..0000000000000
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * This software is distributable under the BSD license. See the terms of the
- * BSD license in the documentation provided with this software.
- *
- * https://opensource.org/licenses/BSD-3-Clause
- */
-package jdk.internal.org.jline.terminal.impl.jna.win;
-
-import java.io.IOException;
-import java.io.Writer;
-
-//import com.sun.jna.Pointer;
-//import com.sun.jna.ptr.IntByReference;
-import jdk.internal.org.jline.utils.AnsiWriter;
-import jdk.internal.org.jline.utils.Colors;
-
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_BLUE;
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_GREEN;
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_INTENSITY;
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_RED;
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_BLUE;
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_GREEN;
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_INTENSITY;
-import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_RED;
-
-
-/**
- * A Windows ANSI escape processor, uses JNA to access native platform
- * API's to change the console attributes.
- *
- * @since 1.0
- * @author Hiram Chirino
- * @author Joris Kuipers
- */
-public final class WindowsAnsiWriter extends AnsiWriter {
-
-    private static final short FOREGROUND_BLACK   = 0;
-    private static final short FOREGROUND_YELLOW  = (short) (FOREGROUND_RED|FOREGROUND_GREEN);
-    private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE|FOREGROUND_RED);
-    private static final short FOREGROUND_CYAN    = (short) (FOREGROUND_BLUE|FOREGROUND_GREEN);
-    private static final short FOREGROUND_WHITE   = (short) (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
-
-    private static final short BACKGROUND_BLACK   = 0;
-    private static final short BACKGROUND_YELLOW  = (short) (BACKGROUND_RED|BACKGROUND_GREEN);
-    private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE|BACKGROUND_RED);
-    private static final short BACKGROUND_CYAN    = (short) (BACKGROUND_BLUE|BACKGROUND_GREEN);
-    private static final short BACKGROUND_WHITE   = (short) (BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
-
-    private static final short ANSI_FOREGROUND_COLOR_MAP[] = {
-            FOREGROUND_BLACK,
-            FOREGROUND_RED,
-            FOREGROUND_GREEN,
-            FOREGROUND_YELLOW,
-            FOREGROUND_BLUE,
-            FOREGROUND_MAGENTA,
-            FOREGROUND_CYAN,
-            FOREGROUND_WHITE,
-    };
-
-    private static final short ANSI_BACKGROUND_COLOR_MAP[] = {
-            BACKGROUND_BLACK,
-            BACKGROUND_RED,
-            BACKGROUND_GREEN,
-            BACKGROUND_YELLOW,
-            BACKGROUND_BLUE,
-            BACKGROUND_MAGENTA,
-            BACKGROUND_CYAN,
-            BACKGROUND_WHITE,
-    };
-
-    private static final int MAX_ESCAPE_SEQUENCE_LENGTH = 100;
-
-    private final Pointer console;
-
-    private final Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
-    private final short originalColors;
-
-    private boolean negative;
-    private boolean bold;
-    private boolean underline;
-    private short savedX = -1;
-    private short savedY = -1;
-
-    public WindowsAnsiWriter(Writer out, Pointer console) throws IOException {
-        super(out);
-        this.console = console;
-        getConsoleInfo();
-        originalColors = info.wAttributes;
-    }
-
-    private void getConsoleInfo() throws IOException {
-        out.flush();
-        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(console, info);
-        if (negative) {
-            info.wAttributes = invertAttributeColors(info.wAttributes);
-        }
-    }
-
-    private void applyAttribute() throws IOException {
-        out.flush();
-        short attributes = info.wAttributes;
-        // bold is simulated by high foreground intensity
-        if (bold) {
-            attributes |= FOREGROUND_INTENSITY;
-        }
-        // underline is simulated by high foreground intensity
-        if (underline) {
-            attributes |= BACKGROUND_INTENSITY;
-        }
-        if (negative) {
-            attributes = invertAttributeColors(attributes);
-        }
-        Kernel32.INSTANCE.SetConsoleTextAttribute(console, attributes);
-    }
-
-    private short invertAttributeColors(short attributes) {
-        // Swap the the Foreground and Background bits.
-        int fg = 0x000F & attributes;
-        fg <<= 4;
-        int bg = 0X00F0 & attributes;
-        bg >>= 4;
-        attributes = (short) ((attributes & 0xFF00) | fg | bg);
-        return attributes;
-    }
-
-    private void applyCursorPosition() throws IOException {
-        info.dwCursorPosition.X = (short) Math.max(0, Math.min(info.dwSize.X - 1, info.dwCursorPosition.X));
-        info.dwCursorPosition.Y = (short) Math.max(0, Math.min(info.dwSize.Y - 1, info.dwCursorPosition.Y));
-        Kernel32.INSTANCE.SetConsoleCursorPosition(console, info.dwCursorPosition);
-    }
-
-    protected void processEraseScreen(int eraseOption) throws IOException {
-        getConsoleInfo();
-        IntByReference written = new IntByReference();
-        switch(eraseOption) {
-            case ERASE_SCREEN:
-                Kernel32.COORD topLeft = new Kernel32.COORD();
-                topLeft.X = 0;
-                topLeft.Y = info.srWindow.Top;
-                int screenLength = info.srWindow.height() * info.dwSize.X;
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', screenLength, topLeft, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, screenLength, topLeft, written);
-                break;
-            case ERASE_SCREEN_TO_BEGINING:
-                Kernel32.COORD topLeft2 = new Kernel32.COORD();
-                topLeft2.X = 0;
-                topLeft2.Y = info.srWindow.Top;
-                int lengthToCursor = (info.dwCursorPosition.Y - info.srWindow.Top) * info.dwSize.X + info.dwCursorPosition.X;
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToCursor, topLeft2, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToCursor, topLeft2, written);
-                break;
-            case ERASE_SCREEN_TO_END:
-                int lengthToEnd = (info.srWindow.Bottom - info.dwCursorPosition.Y) * info.dwSize.X +
-                        (info.dwSize.X - info.dwCursorPosition.X);
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToEnd, info.dwCursorPosition, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToEnd, info.dwCursorPosition, written);
-        }
-    }
-
-    protected void processEraseLine(int eraseOption) throws IOException {
-        getConsoleInfo();
-        IntByReference written = new IntByReference();
-        switch(eraseOption) {
-            case ERASE_LINE:
-                Kernel32.COORD leftColCurrRow = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwSize.X, leftColCurrRow, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwSize.X, leftColCurrRow, written);
-                break;
-            case ERASE_LINE_TO_BEGINING:
-                Kernel32.COORD leftColCurrRow2 = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwCursorPosition.X, leftColCurrRow2, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwCursorPosition.X, leftColCurrRow2, written);
-                break;
-            case ERASE_LINE_TO_END:
-                int lengthToLastCol = info.dwSize.X - info.dwCursorPosition.X;
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToLastCol, info.dwCursorPosition, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToLastCol, info.dwCursorPosition, written);
-        }
-    }
-
-    protected void processCursorUpLine(int count) throws IOException {
-        getConsoleInfo();
-        info.dwCursorPosition.X = 0;
-        info.dwCursorPosition.Y -= (short) count;
-        applyCursorPosition();
-    }
-
-    protected void processCursorDownLine(int count) throws IOException {
-        getConsoleInfo();
-        info.dwCursorPosition.X = 0;
-        info.dwCursorPosition.Y += (short) count;
-        applyCursorPosition();
-    }
-
-    protected void processCursorLeft(int count) throws IOException {
-        getConsoleInfo();
-        info.dwCursorPosition.X -= (short) count;
-        applyCursorPosition();
-    }
-
-    protected void processCursorRight(int count) throws IOException {
-        getConsoleInfo();
-        info.dwCursorPosition.X += (short) count;
-        applyCursorPosition();
-    }
-
-    protected void processCursorDown(int count) throws IOException {
-        getConsoleInfo();
-        int nb = Math.max(0, info.dwCursorPosition.Y + count - info.dwSize.Y + 1);
-        if (nb != count) {
-            info.dwCursorPosition.Y += (short) count;
-            applyCursorPosition();
-        }
-        if (nb > 0) {
-            Kernel32.SMALL_RECT scroll = new Kernel32.SMALL_RECT(info.srWindow);
-            scroll.Top = 0;
-            Kernel32.COORD org = new Kernel32.COORD();
-            org.X = 0;
-            org.Y = (short)(- nb);
-            Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
-            Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
-        }
-    }
-
-    protected void processCursorUp(int count) throws IOException {
-        getConsoleInfo();
-        info.dwCursorPosition.Y -= (short) count;
-        applyCursorPosition();
-    }
-
-    protected void processCursorTo(int row, int col) throws IOException {
-        getConsoleInfo();
-        info.dwCursorPosition.Y = (short) (info.srWindow.Top + row - 1);
-        info.dwCursorPosition.X = (short) (col - 1);
-        applyCursorPosition();
-    }
-
-    protected void processCursorToColumn(int x) throws IOException {
-        getConsoleInfo();
-        info.dwCursorPosition.X = (short) (x - 1);
-        applyCursorPosition();
-    }
-
-    @Override
-    protected void processSetForegroundColorExt(int paletteIndex) throws IOException {
-        int color = Colors.roundColor(paletteIndex, 16);
-        info.wAttributes = (short) ((info.wAttributes & ~0x0007) | ANSI_FOREGROUND_COLOR_MAP[color & 0x07]);
-        info.wAttributes = (short) ((info.wAttributes & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0));
-        applyAttribute();
-    }
-
-    protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {
-        int color = Colors.roundColor(paletteIndex, 16);
-        info.wAttributes = (short)((info.wAttributes & ~0x0070 ) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]);
-        info.wAttributes = (short) ((info.wAttributes & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0));
-        applyAttribute();
-    }
-
-    protected void processDefaultTextColor() throws IOException {
-        info.wAttributes = (short)((info.wAttributes & ~0x000F ) | (originalColors & 0x000F));
-        applyAttribute();
-    }
-
-    protected void processDefaultBackgroundColor() throws IOException {
-        info.wAttributes = (short)((info.wAttributes & ~0x00F0 ) | (originalColors & 0x00F0));
-        applyAttribute();
-    }
-
-    protected void processAttributeRest() throws IOException {
-        info.wAttributes = (short)((info.wAttributes & ~0x00FF ) | originalColors);
-        this.negative = false;
-        this.bold = false;
-        this.underline = false;
-        applyAttribute();
-    }
-
-    protected void processSetAttribute(int attribute) throws IOException {
-        switch(attribute) {
-            case ATTRIBUTE_INTENSITY_BOLD:
-                bold = true;
-                applyAttribute();
-                break;
-            case ATTRIBUTE_INTENSITY_NORMAL:
-                bold = false;
-                applyAttribute();
-                break;
-
-            case ATTRIBUTE_UNDERLINE:
-                underline = true;
-                applyAttribute();
-                break;
-            case ATTRIBUTE_UNDERLINE_OFF:
-                underline = false;
-                applyAttribute();
-                break;
-
-            case ATTRIBUTE_NEGATIVE_ON:
-                negative = true;
-                applyAttribute();
-                break;
-            case ATTRIBUTE_NEGATIVE_OFF:
-                negative = false;
-                applyAttribute();
-                break;
-        }
-    }
-
-    protected void processSaveCursorPosition() throws IOException {
-        getConsoleInfo();
-        savedX = info.dwCursorPosition.X;
-        savedY = info.dwCursorPosition.Y;
-    }
-
-    protected void processRestoreCursorPosition() throws IOException {
-        // restore only if there was a save operation first
-        if (savedX != -1 && savedY != -1) {
-            out.flush();
-            info.dwCursorPosition.X = savedX;
-            info.dwCursorPosition.Y = savedY;
-            applyCursorPosition();
-        }
-    }
-
-    @Override
-    protected void processInsertLine(int optionInt) throws IOException {
-        getConsoleInfo();
-        Kernel32.SMALL_RECT scroll = new Kernel32.SMALL_RECT(info.srWindow);
-        scroll.Top = info.dwCursorPosition.Y;
-        Kernel32.COORD org = new Kernel32.COORD();
-        org.X = 0;
-        org.Y = (short)(info.dwCursorPosition.Y + optionInt);
-        Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
-        Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
-    }
-
-    @Override
-    protected void processDeleteLine(int optionInt) throws IOException {
-        getConsoleInfo();
-        Kernel32.SMALL_RECT scroll = new Kernel32.SMALL_RECT(info.srWindow);
-        scroll.Top = info.dwCursorPosition.Y;
-        Kernel32.COORD org = new Kernel32.COORD();
-        org.X = 0;
-        org.Y = (short)(info.dwCursorPosition.Y - optionInt);
-        Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
-        Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
-    }
-
-    protected void processChangeWindowTitle(String label) {
-        Kernel32.INSTANCE.SetConsoleTitle(label);
-    }
-}
diff --git a/src/jdk.internal.le/windows/native/lible/Kernel32.cpp b/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
deleted file mode 100644
index 59f4df23fb334..0000000000000
--- a/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * Copyright (c) 2015, 2018, 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.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl.h"
-
-#include 
-#include 
-#include 
-
-static jclass pointerClass;
-static jmethodID pointerConstructor;
-static jfieldID pointerValue;
-
-static jclass intByReferenceClass;
-static jfieldID intByReferenceValue;
-
-static jclass lastErrorExceptionClass;
-static jmethodID lastErrorExceptionConstructor;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CHAR_INFO
-static jclass CHAR_INFO_Class;
-static jmethodID CHAR_INFO_Constructor;
-static jfieldID CHAR_INFO_uChar;
-static jfieldID CHAR_INFO_Attributes;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_CURSOR_INFO
-static jclass CONSOLE_CURSOR_INFO_Class;
-static jmethodID CONSOLE_CURSOR_INFO_Constructor;
-static jfieldID CONSOLE_CURSOR_INFO_dwSize;
-static jfieldID CONSOLE_CURSOR_INFO_bVisible;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_SCREEN_BUFFER_INFO
-static jclass CONSOLE_SCREEN_BUFFER_INFO_Class;
-static jmethodID CONSOLE_SCREEN_BUFFER_INFO_Constructor;
-static jfieldID CONSOLE_SCREEN_BUFFER_INFO_dwSize;
-static jfieldID CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition;
-static jfieldID CONSOLE_SCREEN_BUFFER_INFO_wAttributes;
-static jfieldID CONSOLE_SCREEN_BUFFER_INFO_srWindow;
-static jfieldID CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.COORD
-static jclass COORD_Class;
-static jmethodID COORD_Constructor;
-static jfieldID COORD_X;
-static jfieldID COORD_Y;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD
-static jclass INPUT_RECORD_Class;
-static jmethodID INPUT_RECORD_Constructor;
-static jfieldID INPUT_RECORD_EventType;
-static jfieldID INPUT_RECORD_Event;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD.EventUnion
-static jclass EventUnion_Class;
-static jmethodID EventUnion_Constructor;
-static jfieldID EventUnion_KeyEvent;
-static jfieldID EventUnion_MouseEvent;
-static jfieldID EventUnion_WindowBufferSizeEvent;
-static jfieldID EventUnion_MenuEvent;
-static jfieldID EventUnion_FocusEvent;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.KEY_EVENT_RECORD
-static jclass KEY_EVENT_RECORD_Class;
-static jmethodID KEY_EVENT_RECORD_Constructor;
-static jfieldID KEY_EVENT_RECORD_bKeyDown;
-static jfieldID KEY_EVENT_RECORD_wRepeatCount;
-static jfieldID KEY_EVENT_RECORD_wVirtualKeyCode;
-static jfieldID KEY_EVENT_RECORD_wVirtualScanCode;
-static jfieldID KEY_EVENT_RECORD_uChar;
-static jfieldID KEY_EVENT_RECORD_dwControlKeyState;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MOUSE_EVENT_RECORD
-static jclass MOUSE_EVENT_RECORD_Class;
-static jmethodID MOUSE_EVENT_RECORD_Constructor;
-static jfieldID MOUSE_EVENT_RECORD_dwMousePosition;
-static jfieldID MOUSE_EVENT_RECORD_dwButtonState;
-static jfieldID MOUSE_EVENT_RECORD_dwControlKeyState;
-static jfieldID MOUSE_EVENT_RECORD_dwEventFlags;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.WINDOW_BUFFER_SIZE_RECORD
-static jclass WINDOW_BUFFER_SIZE_RECORD_Class;
-static jmethodID WINDOW_BUFFER_SIZE_RECORD_Constructor;
-static jfieldID WINDOW_BUFFER_SIZE_RECORD_dwSize;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MENU_EVENT_RECORD
-static jclass MENU_EVENT_RECORD_Class;
-static jmethodID MENU_EVENT_RECORD_Constructor;
-static jfieldID MENU_EVENT_RECORD_dwCommandId;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOCUS_EVENT_RECORD
-static jclass FOCUS_EVENT_RECORD_Class;
-static jmethodID FOCUS_EVENT_RECORD_Constructor;
-static jfieldID FOCUS_EVENT_RECORD_bSetFocus;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.SMALL_RECT
-static jclass SMALL_RECT_Class;
-static jmethodID SMALL_RECT_Constructor;
-static jfieldID SMALL_RECT_Left;
-static jfieldID SMALL_RECT_Top;
-static jfieldID SMALL_RECT_Right;
-static jfieldID SMALL_RECT_Bottom;
-
-//jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.UnionChar
-static jclass UnionChar_Class;
-static jmethodID UnionChar_Constructor;
-static jfieldID UnionChar_UnicodeChar;
-
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_initIDs
-  (JNIEnv *env, jclass) {
-    jclass cls;
-    cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Pointer");
-    CHECK_NULL(cls);
-    pointerClass = (jclass) env->NewGlobalRef(cls);
-    pointerConstructor = env->GetMethodID(cls, "", "(J)V");
-    CHECK_NULL(pointerConstructor);
-    pointerValue  = env->GetFieldID(cls, "value", "J");
-    CHECK_NULL(pointerValue);
-
-    cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException");
-    CHECK_NULL(cls);
-    lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls);
-    lastErrorExceptionConstructor = env->GetMethodID(cls, "", "(J)V");
-    CHECK_NULL(lastErrorExceptionConstructor);
-
-    cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/IntByReference");
-    CHECK_NULL(cls);
-    intByReferenceClass = (jclass) env->NewGlobalRef(cls);
-    intByReferenceValue = env->GetFieldID(cls, "value", "I");
-    CHECK_NULL(intByReferenceValue);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CHAR_INFO
-    CHAR_INFO_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$CHAR_INFO"));
-    CHECK_NULL(CHAR_INFO_Class);
-    CHAR_INFO_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(CHAR_INFO_Constructor);
-    CHAR_INFO_uChar = env->GetFieldID(CHAR_INFO_Class, "uChar", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$UnionChar;");
-    CHECK_NULL(CHAR_INFO_uChar);
-    CHAR_INFO_Attributes = env->GetFieldID(CHAR_INFO_Class, "Attributes", "S");
-    CHECK_NULL(CHAR_INFO_Attributes);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_CURSOR_INFO
-    CONSOLE_CURSOR_INFO_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$CONSOLE_CURSOR_INFO"));
-    CHECK_NULL(CONSOLE_CURSOR_INFO_Class);
-    CONSOLE_CURSOR_INFO_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(CONSOLE_CURSOR_INFO_Constructor);
-    CONSOLE_CURSOR_INFO_dwSize = env->GetFieldID(CONSOLE_CURSOR_INFO_Class, "dwSize", "I");
-    CHECK_NULL(CONSOLE_CURSOR_INFO_dwSize);
-    CONSOLE_CURSOR_INFO_bVisible = env->GetFieldID(CONSOLE_CURSOR_INFO_Class, "bVisible", "Z");
-    CHECK_NULL(CONSOLE_CURSOR_INFO_bVisible);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.CONSOLE_SCREEN_BUFFER_INFO
-    CONSOLE_SCREEN_BUFFER_INFO_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$CONSOLE_SCREEN_BUFFER_INFO"));
-    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_Class);
-    CONSOLE_SCREEN_BUFFER_INFO_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_Constructor);
-    CONSOLE_SCREEN_BUFFER_INFO_dwSize = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "dwSize", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
-    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_dwSize);
-    CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "dwCursorPosition", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
-    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition);
-    CONSOLE_SCREEN_BUFFER_INFO_wAttributes = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "wAttributes", "S");
-    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_wAttributes);
-    CONSOLE_SCREEN_BUFFER_INFO_srWindow = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "srWindow", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$SMALL_RECT;");
-    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_srWindow);
-    CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize = env->GetFieldID(CONSOLE_SCREEN_BUFFER_INFO_Class, "dwMaximumWindowSize", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
-    CHECK_NULL(CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.COORD
-    COORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD"));
-    CHECK_NULL(COORD_Class);
-    COORD_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(COORD_Constructor);
-    COORD_X = env->GetFieldID(COORD_Class, "X", "S");
-    CHECK_NULL(COORD_X);
-    COORD_Y = env->GetFieldID(COORD_Class, "Y", "S");
-    CHECK_NULL(COORD_Y);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD
-    INPUT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$INPUT_RECORD"));
-    CHECK_NULL(INPUT_RECORD_Class);
-    INPUT_RECORD_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(INPUT_RECORD_Constructor);
-    INPUT_RECORD_EventType = env->GetFieldID(INPUT_RECORD_Class, "EventType", "S");
-    CHECK_NULL(INPUT_RECORD_EventType);
-    INPUT_RECORD_Event = env->GetFieldID(INPUT_RECORD_Class, "Event", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$INPUT_RECORD$EventUnion;");
-    CHECK_NULL(INPUT_RECORD_Event);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.INPUT_RECORD.EventUnion
-    EventUnion_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$INPUT_RECORD$EventUnion"));
-    CHECK_NULL(EventUnion_Class);
-    EventUnion_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(EventUnion_Constructor);
-    EventUnion_KeyEvent = env->GetFieldID(EventUnion_Class, "KeyEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$KEY_EVENT_RECORD;");
-    CHECK_NULL(EventUnion_KeyEvent);
-    EventUnion_MouseEvent = env->GetFieldID(EventUnion_Class, "MouseEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MOUSE_EVENT_RECORD;");
-    CHECK_NULL(EventUnion_MouseEvent);
-    EventUnion_WindowBufferSizeEvent = env->GetFieldID(EventUnion_Class, "WindowBufferSizeEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$WINDOW_BUFFER_SIZE_RECORD;");
-    CHECK_NULL(EventUnion_WindowBufferSizeEvent);
-    EventUnion_MenuEvent = env->GetFieldID(EventUnion_Class, "MenuEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MENU_EVENT_RECORD;");
-    CHECK_NULL(EventUnion_MenuEvent);
-    EventUnion_FocusEvent = env->GetFieldID(EventUnion_Class, "FocusEvent", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$FOCUS_EVENT_RECORD;");
-    CHECK_NULL(EventUnion_FocusEvent);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.KEY_EVENT_RECORD
-    KEY_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$KEY_EVENT_RECORD"));
-    CHECK_NULL(KEY_EVENT_RECORD_Class);
-    KEY_EVENT_RECORD_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(KEY_EVENT_RECORD_Constructor);
-    KEY_EVENT_RECORD_bKeyDown = env->GetFieldID(KEY_EVENT_RECORD_Class, "bKeyDown", "Z");
-    CHECK_NULL(KEY_EVENT_RECORD_bKeyDown);
-    KEY_EVENT_RECORD_wRepeatCount = env->GetFieldID(KEY_EVENT_RECORD_Class, "wRepeatCount", "S");
-    CHECK_NULL(KEY_EVENT_RECORD_wRepeatCount);
-    KEY_EVENT_RECORD_wVirtualKeyCode = env->GetFieldID(KEY_EVENT_RECORD_Class, "wVirtualKeyCode", "S");
-    CHECK_NULL(KEY_EVENT_RECORD_wVirtualKeyCode);
-    KEY_EVENT_RECORD_wVirtualScanCode = env->GetFieldID(KEY_EVENT_RECORD_Class, "wVirtualScanCode", "S");
-    CHECK_NULL(KEY_EVENT_RECORD_wVirtualScanCode);
-    KEY_EVENT_RECORD_uChar = env->GetFieldID(KEY_EVENT_RECORD_Class, "uChar", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$UnionChar;");
-    CHECK_NULL(KEY_EVENT_RECORD_uChar);
-    KEY_EVENT_RECORD_dwControlKeyState = env->GetFieldID(KEY_EVENT_RECORD_Class, "dwControlKeyState", "I");
-    CHECK_NULL(KEY_EVENT_RECORD_dwControlKeyState);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MOUSE_EVENT_RECORD
-    MOUSE_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MOUSE_EVENT_RECORD"));
-    CHECK_NULL(MOUSE_EVENT_RECORD_Class);
-    MOUSE_EVENT_RECORD_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(MOUSE_EVENT_RECORD_Constructor);
-    MOUSE_EVENT_RECORD_dwMousePosition = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwMousePosition", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
-    CHECK_NULL(MOUSE_EVENT_RECORD_dwMousePosition);
-    MOUSE_EVENT_RECORD_dwButtonState = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwButtonState", "I");
-    CHECK_NULL(MOUSE_EVENT_RECORD_dwButtonState);
-    MOUSE_EVENT_RECORD_dwControlKeyState = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwControlKeyState", "I");
-    CHECK_NULL(MOUSE_EVENT_RECORD_dwControlKeyState);
-    MOUSE_EVENT_RECORD_dwEventFlags = env->GetFieldID(MOUSE_EVENT_RECORD_Class, "dwEventFlags", "I");
-    CHECK_NULL(MOUSE_EVENT_RECORD_dwEventFlags);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.WINDOW_BUFFER_SIZE_RECORD
-    WINDOW_BUFFER_SIZE_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$WINDOW_BUFFER_SIZE_RECORD"));
-    CHECK_NULL(WINDOW_BUFFER_SIZE_RECORD_Class);
-    WINDOW_BUFFER_SIZE_RECORD_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(WINDOW_BUFFER_SIZE_RECORD_Constructor);
-    WINDOW_BUFFER_SIZE_RECORD_dwSize = env->GetFieldID(WINDOW_BUFFER_SIZE_RECORD_Class, "dwSize", "Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32$COORD;");
-    CHECK_NULL(WINDOW_BUFFER_SIZE_RECORD_dwSize);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.MENU_EVENT_RECORD
-    MENU_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$MENU_EVENT_RECORD"));
-    CHECK_NULL(MENU_EVENT_RECORD_Class);
-    MENU_EVENT_RECORD_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(MENU_EVENT_RECORD_Constructor);
-    MENU_EVENT_RECORD_dwCommandId = env->GetFieldID(MENU_EVENT_RECORD_Class, "dwCommandId", "I");
-    CHECK_NULL(MENU_EVENT_RECORD_dwCommandId);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOCUS_EVENT_RECORD
-    FOCUS_EVENT_RECORD_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$FOCUS_EVENT_RECORD"));
-    CHECK_NULL(FOCUS_EVENT_RECORD_Class);
-    FOCUS_EVENT_RECORD_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(FOCUS_EVENT_RECORD_Constructor);
-    FOCUS_EVENT_RECORD_bSetFocus = env->GetFieldID(FOCUS_EVENT_RECORD_Class, "bSetFocus", "Z");
-    CHECK_NULL(FOCUS_EVENT_RECORD_bSetFocus);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.SMALL_RECT
-    SMALL_RECT_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$SMALL_RECT"));
-    CHECK_NULL(SMALL_RECT_Class);
-    SMALL_RECT_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(SMALL_RECT_Constructor);
-    SMALL_RECT_Left = env->GetFieldID(SMALL_RECT_Class, "Left", "S");
-    CHECK_NULL(SMALL_RECT_Left);
-    SMALL_RECT_Top = env->GetFieldID(SMALL_RECT_Class, "Top", "S");
-    CHECK_NULL(SMALL_RECT_Top);
-    SMALL_RECT_Right = env->GetFieldID(SMALL_RECT_Class, "Right", "S");
-    CHECK_NULL(SMALL_RECT_Right);
-    SMALL_RECT_Bottom = env->GetFieldID(SMALL_RECT_Class, "Bottom", "S");
-    CHECK_NULL(SMALL_RECT_Bottom);
-
-    //jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.UnionChar
-    UnionChar_Class = (jclass) env->NewGlobalRef(env->FindClass("jdk/internal/org/jline/terminal/impl/jna/win/Kernel32$UnionChar"));
-    CHECK_NULL(UnionChar_Class);
-    UnionChar_Constructor = env->GetMethodID(cls, "", "()V");
-    CHECK_NULL(UnionChar_Constructor);
-    UnionChar_UnicodeChar = env->GetFieldID(UnionChar_Class, "UnicodeChar", "C");
-    CHECK_NULL(UnionChar_UnicodeChar);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    WaitForSingleObject
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;I)I
- */
-JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_WaitForSingleObject
-  (JNIEnv *env, jobject kernel, jobject in_hHandle, jint in_dwMilliseconds) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hHandle, pointerValue));
-    return WaitForSingleObject(h, in_dwMilliseconds);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    GetStdHandle
- * Signature: (I)Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;
- */
-JNIEXPORT jobject JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetStdHandle
-  (JNIEnv *env, jobject, jint nStdHandle) {
-    return env->NewObject(pointerClass,
-                          pointerConstructor,
-                          nStdHandle);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    GetConsoleOutputCP
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleOutputCP
-  (JNIEnv *, jobject) {
-    return GetConsoleOutputCP();
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    FillConsoleOutputCharacter
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;CILjdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;Ljdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_FillConsoleOutputCharacter
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jchar in_cCharacter, jint in_nLength, jobject in_dwWriteCoord, jobject out_lpNumberOfCharsWritten) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    DWORD written;
-    COORD coord;
-    coord.X = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_X);
-    coord.Y = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_Y);
-    if (!FillConsoleOutputCharacter(h, (CHAR) in_cCharacter, in_nLength, coord, &written)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-    env->SetIntField(out_lpNumberOfCharsWritten, intByReferenceValue, written);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    FillConsoleOutputAttribute
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;SILjdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;Ljdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_FillConsoleOutputAttribute
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jshort in_wAttribute, jint in_nLength, jobject in_dwWriteCoord, jobject out_lpNumberOfAttrsWritten) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    DWORD written;
-    COORD coord;
-    coord.X = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_X);
-    coord.Y = (SHORT) env->GetLongField(in_dwWriteCoord, COORD_Y);
-    if (!FillConsoleOutputAttribute(h, in_wAttribute, in_nLength, coord, &written)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-    env->SetIntField(out_lpNumberOfAttrsWritten, intByReferenceValue, written);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    GetConsoleMode
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleMode
-  (JNIEnv *env, jobject, jobject in_hConsoleOutput, jobject out_lpMode) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    DWORD mode;
-    if (!GetConsoleMode(h, &mode)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-    env->SetIntField(out_lpMode, intByReferenceValue, mode);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    GetConsoleScreenBufferInfo
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/CONSOLE_SCREEN_BUFFER_INFO;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleScreenBufferInfo
-  (JNIEnv *env, jobject, jobject in_hConsoleOutput, jobject/*CONSOLE_SCREEN_BUFFER_INFO*/ out_lpConsoleScreenBufferInfo) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    CONSOLE_SCREEN_BUFFER_INFO buffer;
-    if (!GetConsoleScreenBufferInfo(h, &buffer)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-
-    jobject dwSize = env->NewObject(COORD_Class,
-                                    COORD_Constructor);
-    env->SetIntField(dwSize, COORD_X, buffer.dwSize.X);
-    env->SetIntField(dwSize, COORD_Y, buffer.dwSize.Y);
-    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_dwSize, dwSize);
-
-    jobject dwCursorPosition = env->NewObject(COORD_Class,
-                                              COORD_Constructor);
-    env->SetIntField(dwCursorPosition, COORD_X, buffer.dwCursorPosition.X);
-    env->SetIntField(dwCursorPosition, COORD_Y, buffer.dwCursorPosition.Y);
-    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_dwCursorPosition, dwCursorPosition);
-
-    env->SetIntField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_wAttributes, buffer.wAttributes);
-
-    jobject srWindow = env->NewObject(SMALL_RECT_Class,
-                                      SMALL_RECT_Constructor);
-    env->SetIntField(srWindow, SMALL_RECT_Left, buffer.srWindow.Left);
-    env->SetIntField(srWindow, SMALL_RECT_Top, buffer.srWindow.Top);
-    env->SetIntField(srWindow, SMALL_RECT_Right, buffer.srWindow.Right);
-    env->SetIntField(srWindow, SMALL_RECT_Bottom, buffer.srWindow.Bottom);
-    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_srWindow, srWindow);
-
-    jobject dwMaximumWindowSize = env->NewObject(COORD_Class,
-                                                 COORD_Constructor);
-    env->SetIntField(dwMaximumWindowSize, COORD_X, buffer.dwMaximumWindowSize.X);
-    env->SetIntField(dwMaximumWindowSize, COORD_Y, buffer.dwMaximumWindowSize.Y);
-    env->SetObjectField(out_lpConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO_dwMaximumWindowSize, dwMaximumWindowSize);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    ReadConsoleInput
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;[Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/INPUT_RECORD;ILjdk/internal/org/jline/terminal/impl/jna/win/IntByReference;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_ReadConsoleInput
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jobjectArray/*INPUT_RECORD[]*/ out_lpBuffer, jint in_nLength, jobject out_lpNumberOfEventsRead) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    INPUT_RECORD *buffer = new INPUT_RECORD[in_nLength];
-    DWORD numberOfEventsRead;
-    if (!ReadConsoleInputW(h, buffer, in_nLength, &numberOfEventsRead)) {
-        delete[] buffer;
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-    for (unsigned int i = 0; i < numberOfEventsRead; i++) {
-        jobject record = env->NewObject(INPUT_RECORD_Class,
-                                        INPUT_RECORD_Constructor);
-        env->SetShortField(record, INPUT_RECORD_EventType, buffer[i].EventType);
-        switch (buffer[i].EventType) {
-            case KEY_EVENT: {
-                jobject keyEvent = env->NewObject(KEY_EVENT_RECORD_Class,
-                                                  KEY_EVENT_RECORD_Constructor);
-                env->SetBooleanField(keyEvent, KEY_EVENT_RECORD_bKeyDown, buffer[i].Event.KeyEvent.bKeyDown);
-                env->SetShortField(keyEvent, KEY_EVENT_RECORD_wRepeatCount, buffer[i].Event.KeyEvent.wRepeatCount);
-                env->SetShortField(keyEvent, KEY_EVENT_RECORD_wVirtualKeyCode, buffer[i].Event.KeyEvent.wVirtualKeyCode);
-                env->SetShortField(keyEvent, KEY_EVENT_RECORD_wVirtualScanCode, buffer[i].Event.KeyEvent.wVirtualScanCode);
-
-                jobject unionChar = env->NewObject(UnionChar_Class,
-                                                   UnionChar_Constructor);
-
-                env->SetIntField(unionChar, UnionChar_UnicodeChar, buffer[i].Event.KeyEvent.uChar.UnicodeChar);
-
-                env->SetObjectField(keyEvent, KEY_EVENT_RECORD_uChar, unionChar);
-
-                env->SetIntField(keyEvent, KEY_EVENT_RECORD_dwControlKeyState, buffer[i].Event.KeyEvent.dwControlKeyState);
-
-                jobject event = env->NewObject(EventUnion_Class,
-                                               EventUnion_Constructor);
-
-                env->SetObjectField(event, EventUnion_KeyEvent, keyEvent);
-                env->SetObjectField(record, INPUT_RECORD_Event, event);
-                break;
-            }
-            case MOUSE_EVENT: {
-                jobject mouseEvent = env->NewObject(MOUSE_EVENT_RECORD_Class,
-                                                    MOUSE_EVENT_RECORD_Constructor);
-
-                jobject dwMousePosition = env->NewObject(COORD_Class,
-                                                         COORD_Constructor);
-                env->SetIntField(dwMousePosition, COORD_X, buffer[i].Event.MouseEvent.dwMousePosition.X);
-                env->SetIntField(dwMousePosition, COORD_Y, buffer[i].Event.MouseEvent.dwMousePosition.Y);
-                env->SetObjectField(mouseEvent, MOUSE_EVENT_RECORD_dwMousePosition, dwMousePosition);
-                env->SetIntField(mouseEvent, MOUSE_EVENT_RECORD_dwButtonState, buffer[i].Event.MouseEvent.dwButtonState);
-                env->SetIntField(mouseEvent, MOUSE_EVENT_RECORD_dwControlKeyState, buffer[i].Event.MouseEvent.dwControlKeyState);
-                env->SetIntField(mouseEvent, MOUSE_EVENT_RECORD_dwEventFlags, buffer[i].Event.MouseEvent.dwEventFlags);
-
-                jobject event = env->NewObject(EventUnion_Class,
-                                               EventUnion_Constructor);
-
-                env->SetObjectField(event, EventUnion_MouseEvent, mouseEvent);
-                env->SetObjectField(record, INPUT_RECORD_Event, event);
-                break;
-            }
-            case WINDOW_BUFFER_SIZE_EVENT: {
-                jobject windowBufferSize = env->NewObject(WINDOW_BUFFER_SIZE_RECORD_Class,
-                                                          WINDOW_BUFFER_SIZE_RECORD_Constructor);
-
-                jobject dwSize = env->NewObject(COORD_Class,
-                                                COORD_Constructor);
-                env->SetIntField(dwSize, COORD_X, buffer[i].Event.WindowBufferSizeEvent.dwSize.X);
-                env->SetIntField(dwSize, COORD_Y, buffer[i].Event.WindowBufferSizeEvent.dwSize.Y);
-                env->SetObjectField(windowBufferSize, WINDOW_BUFFER_SIZE_RECORD_dwSize, dwSize);
-
-                jobject event = env->NewObject(EventUnion_Class,
-                                               EventUnion_Constructor);
-
-                env->SetObjectField(event, EventUnion_WindowBufferSizeEvent, windowBufferSize);
-                env->SetObjectField(record, INPUT_RECORD_Event, event);
-                break;
-            }
-            case MENU_EVENT: {
-                jobject menuEvent = env->NewObject(MENU_EVENT_RECORD_Class,
-                                                          MENU_EVENT_RECORD_Constructor);
-
-                env->SetBooleanField(menuEvent, MENU_EVENT_RECORD_dwCommandId, buffer[i].Event.MenuEvent.dwCommandId);
-
-                jobject event = env->NewObject(EventUnion_Class,
-                                               EventUnion_Constructor);
-
-                env->SetObjectField(event, EventUnion_MenuEvent, menuEvent);
-                env->SetObjectField(record, INPUT_RECORD_Event, event);
-                break;
-            }
-            case FOCUS_EVENT: {
-                jobject focusEvent = env->NewObject(FOCUS_EVENT_RECORD_Class,
-                                                    FOCUS_EVENT_RECORD_Constructor);
-
-                env->SetIntField(focusEvent, FOCUS_EVENT_RECORD_bSetFocus, buffer[i].Event.FocusEvent.bSetFocus);
-
-                jobject event = env->NewObject(EventUnion_Class,
-                                               EventUnion_Constructor);
-
-                env->SetObjectField(event, EventUnion_FocusEvent, focusEvent);
-                env->SetObjectField(record, INPUT_RECORD_Event, event);
-                break;
-            }
-        }
-        env->SetObjectArrayElement(out_lpBuffer, i, record);
-    }
-    env->SetIntField(out_lpNumberOfEventsRead, intByReferenceValue, numberOfEventsRead);
-    delete[] buffer;
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    SetConsoleCursorPosition
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleCursorPosition
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jobject in_dwCursorPosition) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    COORD coord;
-    coord.X = (SHORT) env->GetLongField(in_dwCursorPosition, COORD_X);
-    coord.Y = (SHORT) env->GetLongField(in_dwCursorPosition, COORD_Y);
-    if (!SetConsoleCursorPosition(h, coord)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return;
-    }
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    SetConsoleMode
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;I)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleMode
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jint in_dwMode) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    if (!SetConsoleMode(h, in_dwMode)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    SetConsoleTextAttribute
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;S)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleTextAttribute
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jshort in_wAttributes) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    if (!SetConsoleTextAttribute(h, in_wAttributes)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    SetConsoleTitle
- * Signature: (Ljava/lang/String;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_SetConsoleTitle
-  (JNIEnv *env, jobject, jstring in_lpConsoleTitle) {
-    const char *chars = env->GetStringUTFChars(in_lpConsoleTitle, NULL);
-    if (!SetConsoleTitle(chars)) {
-        env->ReleaseStringUTFChars(in_lpConsoleTitle, chars);
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-    env->ReleaseStringUTFChars(in_lpConsoleTitle, chars);
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    WriteConsoleW
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;[CILjdk/internal/org/jline/terminal/impl/jna/win/IntByReference;Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_WriteConsoleW
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jcharArray in_lpBuffer, jint in_nNumberOfCharsToWrite, jobject out_lpNumberOfCharsWritten, jobject) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-    jchar *chars = new jchar[in_nNumberOfCharsToWrite];
-    env->GetCharArrayRegion(in_lpBuffer, 0, in_nNumberOfCharsToWrite, chars);
-    DWORD written;
-    if (!WriteConsoleW(h, chars, in_nNumberOfCharsToWrite, &written, NULL)) {
-        delete[] chars;
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-
-    env->SetIntField(out_lpNumberOfCharsWritten, intByReferenceValue, written);
-    delete[] chars;
-}
-
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    ScrollConsoleScreenBuffer
- * Signature: (Ljdk/internal/org/jline/terminal/impl/jna/win/Pointer;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/SMALL_RECT;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/SMALL_RECT;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/COORD;Ljdk/internal/org/jline/terminal/impl/jna/win/Kernel32/CHAR_INFO;)V
- */
-JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_ScrollConsoleScreenBuffer
-  (JNIEnv *env, jobject kernel, jobject in_hConsoleOutput, jobject in_lpScrollRectangle, jobject in_lpClipRectangle, jobject in_dwDestinationOrigin, jobject in_lpFill) {
-    HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
-
-    SMALL_RECT scrollRectangle;
-    scrollRectangle.Left = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Left);
-    scrollRectangle.Top = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Top);
-    scrollRectangle.Right = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Right);
-    scrollRectangle.Bottom = (SHORT) env->GetLongField(in_lpScrollRectangle, SMALL_RECT_Bottom);
-
-    SMALL_RECT clipRectangle;
-    clipRectangle.Left = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Left);
-    clipRectangle.Top = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Top);
-    clipRectangle.Right = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Right);
-    clipRectangle.Bottom = (SHORT) env->GetLongField(in_lpClipRectangle, SMALL_RECT_Bottom);
-
-    COORD destinationOrigin;
-    destinationOrigin.X = (SHORT) env->GetLongField(in_dwDestinationOrigin, COORD_X);
-    destinationOrigin.Y = (SHORT) env->GetLongField(in_dwDestinationOrigin, COORD_Y);
-
-    CHAR_INFO charInfo;
-    charInfo.Char.UnicodeChar = env->GetCharField(env->GetObjectField(in_lpFill, CHAR_INFO_uChar), UnionChar_UnicodeChar);
-    charInfo.Attributes = env->GetShortField(in_lpFill, CHAR_INFO_Attributes);
-
-    if (!ScrollConsoleScreenBuffer(h, &scrollRectangle, &clipRectangle, destinationOrigin, &charInfo)) {
-        DWORD error = GetLastError();
-        jobject exc = env->NewObject(lastErrorExceptionClass,
-                                     lastErrorExceptionConstructor,
-                                     (jlong) error);
-        env->Throw((jthrowable) exc);
-        return ;
-    }
-}
diff --git a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java
index d53c9b20309db..1ca4c091d27ee 100644
--- a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java
+++ b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java
@@ -25,8 +25,10 @@
  * @test
  * @bug 8218287
  * @summary Verify the wrapper input stream is used when using Terminal.reader()
- * @modules jdk.internal.le/jdk.internal.org.jline.terminal
+ * @modules jdk.internal.le/jdk.internal.org.jline
+ *          jdk.internal.le/jdk.internal.org.jline.terminal
  *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.spi
  *          jdk.internal.le/jdk.internal.org.jline.utils
  */
 
@@ -39,6 +41,7 @@
 import jdk.internal.org.jline.terminal.Size;
 import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
 import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
 
 
 public class AbstractWindowsTerminalTest {
@@ -56,14 +59,17 @@ public int read() throws IOException {
                 return is.read();
             }
         };
-        var t = new AbstractWindowsTerminal(out, "test", "vt100", null, false, SignalHandler.SIG_DFL, isWrapper) {
+        var t = new AbstractWindowsTerminal(null, SystemStream.Output, out,
+                                                    "test", "vt100", null, false,
+                                                    SignalHandler.SIG_DFL, "", 0,
+                                                    "", 0, isWrapper) {
             @Override
-            protected int getConsoleMode() {
+            protected int getConsoleMode(String console) {
                 return -1;
             }
 
             @Override
-            protected void setConsoleMode(int mode) {
+            protected void setConsoleMode(String console, int mode) {
                 throw new UnsupportedOperationException("unexpected.");
             }
 
diff --git a/test/jdk/jdk/internal/jline/KeyConversionTest.java b/test/jdk/jdk/internal/jline/KeyConversionTest.java
index aed9a726715cf..ffd116dbbc263 100644
--- a/test/jdk/jdk/internal/jline/KeyConversionTest.java
+++ b/test/jdk/jdk/internal/jline/KeyConversionTest.java
@@ -27,6 +27,7 @@
  * @summary Verify the conversion from key events to escape sequences works properly.
  * @modules jdk.internal.le/jdk.internal.org.jline.terminal
  *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.spi
  */
 
 import java.io.IOException;
@@ -36,6 +37,7 @@
 import jdk.internal.org.jline.terminal.Size;
 import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
 import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
 
 public class KeyConversionTest {
     public static void main(String... args) throws Exception {
@@ -58,14 +60,17 @@ void run() throws Exception {
 
     void checkKeyConversion(KeyEvent event, String expected) throws IOException {
         StringBuilder result = new StringBuilder();
-        new AbstractWindowsTerminal(new StringWriter(), "", "windows", Charset.forName("UTF-8"),
-                                    true, SignalHandler.SIG_DFL, in -> in) {
+        new AbstractWindowsTerminal(null, SystemStream.Output,
+                                            new StringWriter(), "", "windows",
+                                            Charset.forName("UTF-8"), true,
+                                            SignalHandler.SIG_DFL, "", 0,
+                                            "", 0, in -> in) {
             @Override
-            protected int getConsoleMode() {
+            protected int getConsoleMode(String console) {
                 return 0;
             }
             @Override
-            protected void setConsoleMode(int mode) {
+            protected void setConsoleMode(String console, int mode) {
                 throw new UnsupportedOperationException("Not supported yet.");
             }
             @Override
diff --git a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java
index 36f966449612e..efd1cd010cdc0 100644
--- a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java
+++ b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java
@@ -26,7 +26,7 @@
  * @bug 8224184
  * @summary Control Char  check for pty
  * @modules jdk.internal.le/jdk.internal.org.jline.terminal
- *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.impl.exec
  *          jdk.internal.le/jdk.internal.org.jline.terminal.spi
  * @requires (os.family == "linux") | (os.family == "aix")
  */
@@ -35,12 +35,13 @@
 import jdk.internal.org.jline.terminal.Attributes;
 import jdk.internal.org.jline.terminal.Attributes.ControlChar;
 import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
-import jdk.internal.org.jline.terminal.impl.ExecPty;
+import jdk.internal.org.jline.terminal.impl.exec.ExecPty;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
 import jdk.internal.org.jline.terminal.spi.TerminalProvider;
 
 public class ExecPtyGetFlagsToSetTest extends ExecPty {
-    public ExecPtyGetFlagsToSetTest(String name, TerminalProvider.Stream stream) {
-        super(name, stream);
+    public ExecPtyGetFlagsToSetTest(TerminalProvider provider, SystemStream stream, String name) {
+        super(provider, stream, name);
     }
 
     @Override
@@ -50,7 +51,7 @@ protected List getFlagsToSet(Attributes attr, Attributes current) {
 
     public static void main(String[] args) {
         ExecPtyGetFlagsToSetTest testPty =
-            new ExecPtyGetFlagsToSetTest("stty", TerminalProvider.Stream.Output);
+            new ExecPtyGetFlagsToSetTest(null, SystemStream.Output, "stty");
 
         Attributes attr = new Attributes();
         Attributes current = new Attributes();

From c4ff58b9bcfd08eae0623a648a837e08f25b3f9b Mon Sep 17 00:00:00 2001
From: Serguei Spitsyn 
Date: Thu, 9 May 2024 14:30:15 +0000
Subject: [PATCH 139/203] 8330146:
 assert(!_thread->is_in_any_VTMS_transition()) failed

Reviewed-by: cjplummer, kevinw
---
 src/hotspot/share/prims/jvmtiExport.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp
index 5a87e16c855b2..c2b6d27986b94 100644
--- a/src/hotspot/share/prims/jvmtiExport.cpp
+++ b/src/hotspot/share/prims/jvmtiExport.cpp
@@ -929,7 +929,9 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
     _cached_class_file_ptr = cache_ptr;
     _has_been_modified = false;
 
-    assert(!_thread->is_in_any_VTMS_transition(), "CFLH events are not allowed in any VTMS transition");
+    if (_thread->is_in_any_VTMS_transition()) {
+      return; // no events should be posted if thread is in any VTMS transition
+    }
     _state = JvmtiExport::get_jvmti_thread_state(_thread);
     if (_state != nullptr) {
       _class_being_redefined = _state->get_class_being_redefined();
@@ -1366,10 +1368,9 @@ void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {
   if (state == nullptr) {
     return;
   }
-  if (thread->is_in_tmp_VTMS_transition()) {
-    return; // skip ClassLoad events in tmp VTMS transition
+  if (thread->is_in_any_VTMS_transition()) {
+    return; // no events should be posted if thread is in any VTMS transition
   }
-  assert(!thread->is_in_any_VTMS_transition(), "class load events are not allowed in any VTMS transition");
 
   EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_LOAD, ("[%s] Trg Class Load triggered",
                       JvmtiTrace::safe_get_thread_name(thread)));
@@ -1404,10 +1405,9 @@ void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {
   if (state == nullptr) {
     return;
   }
-  if (thread->is_in_tmp_VTMS_transition()) {
-    return; // skip ClassPrepare events in tmp VTMS transition
+  if (thread->is_in_any_VTMS_transition()) {
+    return; // no events should be posted if thread is in any VTMS transition
   }
-  assert(!thread->is_in_any_VTMS_transition(), "class prepare events are not allowed in any VTMS transition");
 
   EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("[%s] Trg Class Prepare triggered",
                       JvmtiTrace::safe_get_thread_name(thread)));

From aa4cddd4b8a6a12ba5d0360a721aebaabf362fff Mon Sep 17 00:00:00 2001
From: Kevin Walls 
Date: Thu, 9 May 2024 15:42:41 +0000
Subject: [PATCH 140/203] 8331950: Remove
 MemoryPoolMBean/isCollectionUsageThresholdExceeded from ZGC ProblemLists

Reviewed-by: sspitsyn
---
 test/hotspot/jtreg/ProblemList-generational-zgc.txt | 1 -
 test/hotspot/jtreg/ProblemList-zgc.txt              | 1 -
 2 files changed, 2 deletions(-)

diff --git a/test/hotspot/jtreg/ProblemList-generational-zgc.txt b/test/hotspot/jtreg/ProblemList-generational-zgc.txt
index a92751cc62106..4d5e985c0a677 100644
--- a/test/hotspot/jtreg/ProblemList-generational-zgc.txt
+++ b/test/hotspot/jtreg/ProblemList-generational-zgc.txt
@@ -116,5 +116,4 @@ serviceability/sa/sadebugd/SADebugDTest.java                  8307393   generic-
 
 vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java        8289582   windows-x64
 
-vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java 8298302 generic-all
 vmTestbase/nsk/sysdict/vm/stress/chain/chain007/chain007.java 8298991 linux-x64
diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt
index 4684d8359bc55..d7d600aad490c 100644
--- a/test/hotspot/jtreg/ProblemList-zgc.txt
+++ b/test/hotspot/jtreg/ProblemList-zgc.txt
@@ -47,5 +47,4 @@ serviceability/sa/TestHeapDumpForInvokeDynamic.java           8315646   generic-
 
 vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java        8289582   windows-x64
 
-vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java 8298302 generic-all
 vmTestbase/nsk/sysdict/vm/stress/chain/chain007/chain007.java 8298991 linux-x64

From c7d98df2ac509ebc8f4e801a0874a9497c54c602 Mon Sep 17 00:00:00 2001
From: Naoto Sato 
Date: Thu, 9 May 2024 15:54:25 +0000
Subject: [PATCH 141/203] 8329691: Support `nonlikelyScript` parent locale
 inheritance

Reviewed-by: joehw
---
 .../tools/cldrconverter/CLDRConverter.java    |  45 +++++-
 .../ResourceBundleGenerator.java              | 143 ++++++++++--------
 .../SupplementalDataParseHandler.java         |  23 ++-
 .../util/cldr/CLDRLocaleProviderAdapter.java  |  20 ++-
 .../locale/provider/NonLikelyScriptTest.java  | 101 +++++++++++++
 5 files changed, 256 insertions(+), 76 deletions(-)
 create mode 100644 test/jdk/sun/util/locale/provider/NonLikelyScriptTest.java

diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
index 8d39ef4c1d55b..15251358a01a1 100644
--- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
+++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
@@ -87,6 +87,7 @@ public class CLDRConverter {
     static final String ZONE_NAME_PREFIX = "timezone.displayname.";
     static final String METAZONE_ID_PREFIX = "metazone.id.";
     static final String PARENT_LOCALE_PREFIX = "parentLocale.";
+    static final String LIKELY_SCRIPT_PREFIX = "likelyScript.";
     static final String META_EMPTY_ZONE_NAME = "EMPTY_ZONE";
     static final String[] EMPTY_ZONE = {"", "", "", "", "", ""};
     static final String META_ETCUTC_ZONE_NAME = "ETC_UTC";
@@ -114,9 +115,13 @@ public class CLDRConverter {
 
     // "parentLocales" map
     private static final Map> parentLocalesMap = new HashMap<>();
+    static boolean nonlikelyScript;
     private static final ResourceBundle.Control defCon =
         ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
 
+    // "likelyScript" map
+    private static final Map> likelyScriptMap = new HashMap<>();
+
     private static Set AVAILABLE_TZIDS;
     static int copyrightYear;
     static String jdkHeaderTemplate;
@@ -175,7 +180,7 @@ String getKeyword() {
     private static boolean verbose;
 
     private CLDRConverter() {
-       // no instantiation
+        // no instantiation
     }
 
     @SuppressWarnings("AssignmentToForLoopParameter")
@@ -475,8 +480,8 @@ private static void parseSupplemental() throws Exception {
         parseLDMLFile(new File(SPPL_SOURCE_FILE), handlerSuppl);
         Map parentData = handlerSuppl.getData("root");
         parentData.keySet().stream()
-                .filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
-                .forEach(key -> {
+            .filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
+            .forEach(key -> {
                 parentLocalesMap.put(key, new TreeSet(
                     Arrays.asList(((String)parentData.get(key)).split(" "))));
             });
@@ -492,6 +497,16 @@ private static void parseSupplemental() throws Exception {
         // Parse likelySubtags
         handlerLikelySubtags = new LikelySubtagsParseHandler();
         parseLDMLFile(new File(LIKELYSUBTAGS_SOURCE_FILE), handlerLikelySubtags);
+        handlerLikelySubtags.getData().forEach((from, to) -> {
+            if (!from.contains("-")) { // look for language-only tag
+                var script = to.split("-")[1];
+                var key = LIKELY_SCRIPT_PREFIX + script;
+                var prev = likelyScriptMap.putIfAbsent(key, new TreeSet(Set.of(from)));
+                if (prev != null) {
+                    prev.add(from);
+                }
+            }
+        });
 
         // Parse supplementalMetadata
         // Currently interested in deprecated time zone ids and language aliases.
@@ -561,6 +576,7 @@ private static void convertBundles(List bundles) throws Exception {
         // for now.
         if (isBaseModule) {
             metaInfo.putAll(parentLocalesMap);
+            metaInfo.putAll(likelyScriptMap);
         }
 
         for (Bundle bundle : bundles) {
@@ -1135,7 +1151,7 @@ private static List applyParentLocales(String baseName, List can
         // check irregular parents
         for (int i = 0; i < candidates.size(); i++) {
             Locale l = candidates.get(i);
-            Locale p = childToParentLocaleMap.get(l);
+            Locale p = getParentLocale(l);
             if (!l.equals(Locale.ROOT) &&
                 Objects.nonNull(p) &&
                 !candidates.get(i+1).equals(p)) {
@@ -1152,6 +1168,27 @@ private static List applyParentLocales(String baseName, List can
         return candidates;
     }
 
+    private static Locale getParentLocale(Locale child) {
+        Locale parent = childToParentLocaleMap.get(child);
+
+        // check non-likely script for root
+        if (nonlikelyScript && parent == null && child.getCountry().isEmpty()) {
+            var lang = " " + child.getLanguage() + " ";
+            var script = child.getScript();
+
+            if (!script.isEmpty()) {
+                parent = likelyScriptMap.entrySet().stream()
+                    .filter(e -> e.getValue().contains(lang))
+                    .findAny()
+                    .map(Map.Entry::getKey)
+                    .map(likely -> likely.equals(script) ? null : Locale.ROOT)
+                    .orElse(null);
+            }
+        }
+
+        return parent;
+    }
+
     private static void generateZoneName() throws Exception {
         Files.createDirectories(Paths.get(DESTINATION_DIR, "java", "time", "format"));
         Files.write(Paths.get(DESTINATION_DIR, "java", "time", "format", "ZoneName.java"),
diff --git a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
index 49c74544be66e..3953f38f653e6 100644
--- a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
+++ b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.SortedSet;
+import java.util.stream.Collectors;
 
 class ResourceBundleGenerator implements BundleGenerator {
     // preferred timezones - keeping compatibility with JDK1.1 3 letter abbreviations
@@ -306,81 +307,77 @@ public void generateMetaInfo(Map> metaInfo) throws IOE
                 import sun.util.locale.provider.LocaleProviderAdapter;
 
                 public class %s implements LocaleDataMetaInfo {
-                    private static final Map resourceNameToLocales = HashMap.newHashMap(%d);
-                %s
-                    static {
-                """, CLDRConverter.isBaseModule ? "cldr" : "resources.cldr.provider",
-                className, metaInfo.keySet().stream().filter(k -> k.equals("AvailableLocales")).count(),
-                CLDRConverter.isBaseModule ?
-                    """
+                """,
+                    CLDRConverter.isBaseModule ? "cldr" : "resources.cldr.provider",
+                    className);
+
+            if (CLDRConverter.isBaseModule) {
+                out.printf("""
                         private static final Map parentLocalesMap = HashMap.newHashMap(%d);
                         private static final Map languageAliasMap = HashMap.newHashMap(%d);
+                        static final boolean nonlikelyScript = %s; // package access from CLDRLocaleProviderAdapter
+
+                        static {
                     """.formatted(
                         metaInfo.keySet().stream().filter(k -> k.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)).count(),
-                        CLDRConverter.handlerSupplMeta.getLanguageAliasData().size()) :
-                    "");
-
-            for (String key : metaInfo.keySet()) {
-                if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) {
-                    String parentTag = key.substring(CLDRConverter.PARENT_LOCALE_PREFIX.length());
-                    if ("root".equals(parentTag)) {
-                        out.printf("        parentLocalesMap.put(Locale.ROOT,\n");
-                    } else {
-                        out.printf("        parentLocalesMap.put(Locale.forLanguageTag(\"%s\"),\n",
-                                   parentTag);
-                    }
-                    String[] children = toLocaleList(metaInfo.get(key), true).split(" ");
-                    Arrays.sort(children);
-                    out.printf("            new String[] {\n" +
-                               "                ");
-                    int count = 0;
-                    for (int i = 0; i < children.length; i++) {
-                        String child = children[i];
-                        out.printf("\"%s\", ", child);
-                        count += child.length() + 4;
-                        if (i != children.length - 1 && count > 64) {
-                            out.printf("\n                ");
-                            count = 0;
+                        CLDRConverter.handlerSupplMeta.getLanguageAliasData().size(),
+                        Boolean.valueOf(CLDRConverter.nonlikelyScript)));
+
+                for (String key : metaInfo.keySet()) {
+                    if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) {
+                        String parentTag = key.substring(CLDRConverter.PARENT_LOCALE_PREFIX.length());
+                        if ("root".equals(parentTag)) {
+                            out.printf("        parentLocalesMap.put(Locale.ROOT,\n");
+                        } else {
+                            out.printf("        parentLocalesMap.put(Locale.forLanguageTag(\"%s\"),\n",
+                                    parentTag);
                         }
-                    }
-                    out.printf("\n            });\n");
-                } else {
-                    if ("AvailableLocales".equals(key)) {
-                        out.printf("        resourceNameToLocales.put(\"%s\",\n", key);
-                        out.printf("            \"%s\");\n", toLocaleList(applyLanguageAliases(metaInfo.get(key)), false));
+                        generateStringArray(metaInfo.get(key), out);
                     }
                 }
-            }
-            // for languageAliasMap
-            if (CLDRConverter.isBaseModule) {
+                out.println();
+
+                // for languageAliasMap
                 CLDRConverter.handlerSupplMeta.getLanguageAliasData().forEach((key, value) -> {
                     out.printf("        languageAliasMap.put(\"%s\", \"%s\");\n", key, value);
                 });
-            }
+                out.printf("    }\n\n");
 
-            out.printf("    }\n\n");
+                // end of static initializer block.
 
-            // end of static initializer block.
-
-            // Canonical TZ names for delayed initialization
-            if (CLDRConverter.isBaseModule) {
+                // Delayed initialization section
                 out.printf("""
-                               private static class TZCanonicalIDMapHolder {
-                                   static final Map tzCanonicalIDMap = HashMap.newHashMap(%d);
+                               private static class CLDRMapHolder {
+                                   private static final Map tzCanonicalIDMap = HashMap.newHashMap(%d);
+                                   private static final Map likelyScriptMap = HashMap.newHashMap(%d);
+
                                    static {
-                           """, CLDRConverter.handlerTimeZone.getData().size());
+                           """, CLDRConverter.handlerTimeZone.getData().size(),
+                                metaInfo.keySet().stream().filter(k -> k.startsWith(CLDRConverter.LIKELY_SCRIPT_PREFIX)).count());
                 CLDRConverter.handlerTimeZone.getData().entrySet().stream()
                     .forEach(e -> {
                         String[] ids = ((String)e.getValue()).split("\\s");
                         out.printf("            tzCanonicalIDMap.put(\"%s\", \"%s\");\n", e.getKey(),
-                                ids[0]);
+                            ids[0]);
                         for (int i = 1; i < ids.length; i++) {
                             out.printf("            tzCanonicalIDMap.put(\"%s\", \"%s\");\n", ids[i],
                                 ids[0]);
                         }
                     });
-                out.printf("        }\n    }\n\n");
+                out.println();
+
+                // for likelyScript map
+                for (String key : metaInfo.keySet()) {
+                    if (key.startsWith(CLDRConverter.LIKELY_SCRIPT_PREFIX)) {
+                        // ensure spaces at the begin/end for delimiting purposes
+                        out.printf("            likelyScriptMap.put(\"%s\", \"%s\");\n",
+                                key.substring(CLDRConverter.LIKELY_SCRIPT_PREFIX.length()),
+                                " " + metaInfo.get(key).stream().collect(Collectors.joining(" ")) + " ");
+                    }
+                }
+                out.printf("        }\n    }\n");
             }
+            out.println();
 
             out.printf("""
                     @Override
@@ -390,12 +387,13 @@ public LocaleProviderAdapter.Type getType() {
 
                     @Override
                     public String availableLanguageTags(String category) {
-                        return resourceNameToLocales.getOrDefault(category, "");
+                        return " %s";
                     }
-                    %s
-                }
                 """,
-                CLDRConverter.isBaseModule ? """
+                toLocaleList(applyLanguageAliases(metaInfo.get("AvailableLocales")), false));
+
+            if(CLDRConverter.isBaseModule) {
+                out.printf("""
 
                     @Override
                     public Map getLanguageAliasMap() {
@@ -404,16 +402,41 @@ public Map getLanguageAliasMap() {
 
                     @Override
                     public Map tzCanonicalIDs() {
-                        return TZCanonicalIDMapHolder.tzCanonicalIDMap;
+                        return CLDRMapHolder.tzCanonicalIDMap;
                     }
 
                     public Map parentLocales() {
                         return parentLocalesMap;
                     }
-                """ : "");
+
+                    // package access from CLDRLocaleProviderAdapter
+                    Map likelyScriptMap() {
+                        return CLDRMapHolder.likelyScriptMap;
+                    }
+                """);
+            }
+            out.printf("}\n");
         }
     }
 
+    private static void generateStringArray(SortedSet set, PrintWriter out) throws IOException {
+        String[] children = toLocaleList(set, true).split(" ");
+        Arrays.sort(children);
+        out.printf("            new String[] {\n" +
+                "                ");
+        int count = 0;
+        for (int i = 0; i < children.length; i++) {
+            String child = children[i];
+            out.printf("\"%s\", ", child);
+            count += child.length() + 4;
+            if (i != children.length - 1 && count > 64) {
+                out.printf("\n                ");
+                count = 0;
+            }
+        }
+        out.printf("\n            });\n");
+    }
+
     private static final Locale.Builder LOCALE_BUILDER = new Locale.Builder();
     private static boolean isBaseLocale(String localeID) {
         localeID = localeID.replaceAll("-", "_");
@@ -433,7 +456,9 @@ private static String toLocaleList(SortedSet set, boolean all) {
                 if (!all && CLDRConverter.isBaseModule ^ isBaseLocale(id)) {
                     continue;
                 }
-                sb.append(' ');
+                if (sb.length() > 0) {
+                    sb.append(' ');
+                }
                 sb.append(id);
             }
         }
diff --git a/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java
index f4d20160ffb3b..9ba4d64519949 100644
--- a/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java
+++ b/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java
@@ -57,29 +57,22 @@ class SupplementalDataParseHandler extends AbstractLDMLHandler {
     // the weekData is listed using country code.
     //
     // weekData are generated per each country
-    private final Map firstDayMap;
-    private final Map minDaysMap;
+    private static final Map firstDayMap = new HashMap<>();
+    private static final Map minDaysMap = new HashMap<>();
 
     // Parent locales. These information will only be
     // generated towards the base meta info, with the format of
     //
     // parentLocale.=(" ")+
-    private final Map parentLocalesMap;
+    private static final Map parentLocalesMap = new HashMap<>();
 
     // Input Skeleton map for "preferred" and "allowed"
     // Map<"preferred"/"allowed", Map<"skeleton", SortedSet<"regions">>>
-    private final Map>> inputSkeletonMap;
+    private static final Map>> inputSkeletonMap = new HashMap<>();
 
     // "component" specific to this parent locale chain
     private String currentParentLocaleComponent;
 
-    SupplementalDataParseHandler() {
-        firstDayMap = new HashMap<>();
-        minDaysMap = new HashMap<>();
-        parentLocalesMap = new HashMap<>();
-        inputSkeletonMap = new HashMap<>();
-    }
-
     /**
      * It returns Map that contains the firstDay and minDays information for
      * the country. The Map is created in JRE format after obtaining the data
@@ -158,9 +151,15 @@ public void startElement(String uri, String localName, String qName, Attributes
                 // Ignore component for now, otherwise "zh-Hant" falling back to "zh" would happen
                 // https://github.com/unicode-org/cldr/pull/2664
                 if (currentParentLocaleComponent == null) {
+                    var parent = attributes.getValue("parent").replaceAll("_", "-");
+
                     parentLocalesMap.put(
-                        attributes.getValue("parent").replaceAll("_", "-"),
+                        parent,
                         attributes.getValue("locales").replaceAll("_", "-"));
+
+                    if ("root".equals(parent)) {
+                        CLDRConverter.nonlikelyScript = "nonlikelyScript".equals(attributes.getValue("localeRules"));
+                    }
                 }
             }
             break;
diff --git a/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java b/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java
index 9f65e32fa27cd..0ce080c20547f 100644
--- a/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java
+++ b/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -259,6 +259,24 @@ private static Locale getParentLocale(Locale locale) {
                     break;
                 }
             }
+
+            if (parent == null) {
+                // check nonlikelyScript locales
+                if (CLDRBaseLocaleDataMetaInfo.nonlikelyScript && locale.getCountry().isEmpty()) {
+                    var lang = " " + locale.getLanguage() + " ";
+                    var script= locale.getScript();
+                    if (!script.isEmpty()) {
+                        parent = baseMetaInfo.likelyScriptMap().entrySet().stream()
+                            .filter(e -> e.getValue().contains(lang))
+                            .findAny()
+                            .map(Map.Entry::getKey)
+                            .map(likely -> likely.equals(script) ? null : Locale.ROOT)
+                            .orElse(null);
+                    }
+                }
+            }
+
+            // no parent found
             if (parent == null) {
                 parent = locale; // non existent marker
             }
diff --git a/test/jdk/sun/util/locale/provider/NonLikelyScriptTest.java b/test/jdk/sun/util/locale/provider/NonLikelyScriptTest.java
new file mode 100644
index 0000000000000..dbbfaf6f0054b
--- /dev/null
+++ b/test/jdk/sun/util/locale/provider/NonLikelyScriptTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8329691
+ * @modules java.base/sun.util.locale.provider
+ *          java.base/sun.util.cldr
+ * @summary Tests CLDR's `nonlikelyScript` attribute is correctly implemented
+ *      with the CLDRLocaleProviderAdapter
+ * @run junit NonLikelyScriptTest
+ */
+
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Stream;
+
+import sun.util.cldr.CLDRLocaleProviderAdapter;
+import sun.util.locale.provider.LocaleProviderAdapter;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class NonLikelyScriptTest {
+    private static final CLDRLocaleProviderAdapter CLDR_LOCALE_PROVIDER_ADAPTER
+        = (CLDRLocaleProviderAdapter) LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.CLDR);
+    private static final Locale AZ_ARAB = Locale.forLanguageTag("az-Arab");
+    private static final Locale AZ_CYRL = Locale.forLanguageTag("az-Cyrl");
+    private static final Locale AZ_LATN = Locale.forLanguageTag("az-Latn");
+    private static final Locale AZ_XXXX = Locale.forLanguageTag("az-Xxxx");
+    private static final Locale RU_LATN = Locale.forLanguageTag("ru-Latn");
+    private static final Locale RU_CYRL = Locale.forLanguageTag("ru-Cyrl");
+    private static final Locale RU_XXXX = Locale.forLanguageTag("ru-Xxxx");
+    private static final Locale EN_LATN = Locale.forLanguageTag("en-Latn");
+    private static final Locale EN_DSRT = Locale.forLanguageTag("en-Dsrt");
+    private static final Locale EN_XXXX = Locale.forLanguageTag("en-Xxxx");
+    private static final Locale ZH_HANT_MO = Locale.forLanguageTag("zh-Hant-MO");
+    private static final Locale ZH_HANS_SG = Locale.forLanguageTag("zh-Hans-SG");
+    private static final Locale ZH_HANS = Locale.forLanguageTag("zh-Hans");
+    private static final Locale ZH_HANT = Locale.forLanguageTag("zh-Hant");
+    private static final Locale ZH_XXXX = Locale.forLanguageTag("zh-Xxxx");
+
+    private static Stream parentLocales() {
+
+        return Stream.of(
+            // likely script
+            Arguments.of(AZ_LATN, List.of(AZ_LATN, Locale.of("az"), Locale.ROOT)),
+            Arguments.of(RU_CYRL, List.of(RU_CYRL, Locale.of("ru"), Locale.ROOT)),
+            Arguments.of(EN_LATN, List.of(EN_LATN, Locale.ENGLISH, Locale.ROOT)),
+            Arguments.of(ZH_HANS, List.of(ZH_HANS, Locale.CHINA, Locale.CHINESE, Locale.ROOT)),
+            Arguments.of(Locale.CHINA, List.of(Locale.forLanguageTag("zh-Hans-CN"), ZH_HANS, Locale.CHINA, Locale.CHINESE, Locale.ROOT)),
+            Arguments.of(ZH_HANS_SG, List.of(ZH_HANS_SG, ZH_HANS, Locale.forLanguageTag("zh-SG"), Locale.CHINESE, Locale.ROOT)),
+
+            // non-likely script, explicit (as of CLDR 45)
+            Arguments.of(AZ_ARAB, List.of(AZ_ARAB, Locale.ROOT)),
+            Arguments.of(AZ_CYRL, List.of(AZ_CYRL, Locale.ROOT)),
+            Arguments.of(EN_DSRT, List.of(EN_DSRT, Locale.ROOT)),
+            Arguments.of(ZH_HANT, List.of(ZH_HANT, Locale.ROOT)),
+            Arguments.of(Locale.TAIWAN, List.of(Locale.forLanguageTag("zh-Hant-TW"), ZH_HANT, Locale.ROOT)),
+            Arguments.of(ZH_HANT_MO, List.of(ZH_HANT_MO, Locale.forLanguageTag("zh-Hant-HK"), ZH_HANT, Locale.ROOT)),
+
+            // non-likely script, implicit
+            Arguments.of(AZ_XXXX, List.of(AZ_XXXX, Locale.ROOT)),
+            Arguments.of(RU_LATN, List.of(RU_LATN, Locale.ROOT)),
+            Arguments.of(RU_XXXX, List.of(RU_XXXX, Locale.ROOT)),
+            Arguments.of(EN_XXXX, List.of(EN_XXXX, Locale.ROOT)),
+            Arguments.of(ZH_XXXX, List.of(ZH_XXXX, Locale.ROOT))
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource("parentLocales")
+    public void checkParentLocales(Locale locale, List expected) {
+        var actual = CLDR_LOCALE_PROVIDER_ADAPTER.getCandidateLocales("", locale);
+        assertEquals(expected, actual);
+    }
+}

From ffbdfffbc702253f32fa45dc1855b663c72074a6 Mon Sep 17 00:00:00 2001
From: Alexey Ivanov 
Date: Thu, 9 May 2024 18:01:27 +0000
Subject: [PATCH 142/203] 8331999: BasicDirectoryModel/LoaderThreadCount.java
 frequently fails on Windows in CI

Introduce tolerance factor: count > loaderCount.size() / 2
Fail the test only if the number of snapshots with more than
2 file loader threads is greater than half of the number
of valid snapshots.

Reviewed-by: prr, honkar
---
 .../swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java
index 689aca5bbdb1e..770c8f92b2656 100644
--- a/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java
+++ b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java
@@ -164,7 +164,7 @@ private static void runTest(final long timeStart) throws Throwable {
             System.out.println("  = 1: " + ones);
             System.out.println("  = 2: " + twos);
             System.out.println("  > 2: " + count);
-            if (count > 0) {
+            if (count > loaderCount.size() / 2) {
                 throw new RuntimeException("Detected " + count + " snapshots "
                                            + "with several loading threads");
             }

From 0bf728212fb4bce067076780aaa5b9341d7cdb6b Mon Sep 17 00:00:00 2001
From: Mikhailo Seledtsov 
Date: Thu, 9 May 2024 22:53:10 +0000
Subject: [PATCH 143/203] 8331231: containers/docker/TestContainerInfo.java
 fails

Reviewed-by: dholmes
---
 test/hotspot/jtreg/containers/docker/TestContainerInfo.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java
index dadc262cd5a4e..6bcb706fa7a6a 100644
--- a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java
+++ b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java
@@ -26,6 +26,7 @@
 /*
  * @test
  * @summary Test container info for cgroup v2
+ * @key cgroups
  * @requires docker.support
  * @library /test/lib
  * @modules java.base/jdk.internal.misc

From d47a4e9f63a9414b90e09514bc26f6f7142ad49f Mon Sep 17 00:00:00 2001
From: Zhao Song 
Date: Thu, 9 May 2024 23:05:05 +0000
Subject: [PATCH 144/203] 8332008: Enable issuestitle check

Reviewed-by: erikj
---
 .jcheck/conf | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.jcheck/conf b/.jcheck/conf
index 17552ee7361ab..617f3d95ed8e6 100644
--- a/.jcheck/conf
+++ b/.jcheck/conf
@@ -5,6 +5,7 @@ version=23
 
 [checks]
 error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists
+warning=issuestitle
 
 [repository]
 tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d)

From a643d6c7ac8a7bc0d3a288c1ef3f07876cf70590 Mon Sep 17 00:00:00 2001
From: Vladimir Kozlov 
Date: Thu, 9 May 2024 23:37:45 +0000
Subject: [PATCH 145/203] 8331862: Remove split relocation info implementation

Reviewed-by: dlong
---
 src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp |  2 +-
 src/hotspot/cpu/arm/relocInfo_arm.cpp         |  8 +-
 src/hotspot/cpu/ppc/relocInfo_ppc.cpp         |  7 +-
 src/hotspot/cpu/riscv/relocInfo_riscv.cpp     |  4 +-
 src/hotspot/cpu/s390/assembler_s390.hpp       |  6 +-
 src/hotspot/cpu/s390/relocInfo_s390.cpp       | 14 ++-
 src/hotspot/cpu/x86/relocInfo_x86.cpp         |  9 +-
 src/hotspot/cpu/zero/relocInfo_zero.cpp       |  4 +-
 src/hotspot/share/code/relocInfo.cpp          | 40 ++------
 src/hotspot/share/code/relocInfo.hpp          | 93 +++++++------------
 10 files changed, 62 insertions(+), 125 deletions(-)

diff --git a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp
index 5424f0d9c7572..332f24996930f 100644
--- a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp
@@ -32,7 +32,7 @@
 #include "runtime/safepoint.hpp"
 
 
-void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
+void Relocation::pd_set_data_value(address x, bool verify_only) {
   if (verify_only)
     return;
 
diff --git a/src/hotspot/cpu/arm/relocInfo_arm.cpp b/src/hotspot/cpu/arm/relocInfo_arm.cpp
index fc5b2981ce69c..fb112cdcfc0fa 100644
--- a/src/hotspot/cpu/arm/relocInfo_arm.cpp
+++ b/src/hotspot/cpu/arm/relocInfo_arm.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,13 +30,13 @@
 #include "oops/oop.hpp"
 #include "runtime/safepoint.hpp"
 
-void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
+void Relocation::pd_set_data_value(address x, bool verify_only) {
 
   NativeMovConstReg* ni = nativeMovConstReg_at(addr());
   if (verify_only) {
-    guarantee(ni->data() == (intptr_t)(x + o), "instructions must match");
+    guarantee(ni->data() == (intptr_t)x, "instructions must match");
   } else {
-    ni->set_data((intptr_t)(x + o));
+    ni->set_data((intptr_t)x);
   }
 }
 
diff --git a/src/hotspot/cpu/ppc/relocInfo_ppc.cpp b/src/hotspot/cpu/ppc/relocInfo_ppc.cpp
index 39e50465231ae..5d0d2785bf427 100644
--- a/src/hotspot/cpu/ppc/relocInfo_ppc.cpp
+++ b/src/hotspot/cpu/ppc/relocInfo_ppc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -32,10 +32,7 @@
 #include "oops/oop.hpp"
 #include "runtime/safepoint.hpp"
 
-void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
-  // Currently we don't support splitting of relocations.
-  assert(o == 0, "tried to split relocations");
-
+void Relocation::pd_set_data_value(address x, bool verify_only) {
   if (!verify_only) {
     if (format() != 1) {
       nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x), code());
diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp
index 0e50d0b0796ca..b3cdb93a979d8 100644
--- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp
+++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -31,7 +31,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/safepoint.hpp"
 
-void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
+void Relocation::pd_set_data_value(address x, bool verify_only) {
   if (verify_only) {
     return;
   }
diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp
index 91cc7e611bfd1..cf80d164fafe6 100644
--- a/src/hotspot/cpu/s390/assembler_s390.hpp
+++ b/src/hotspot/cpu/s390/assembler_s390.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2016, 2023 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -352,10 +352,6 @@ class AddressLiteral {
 
   relocInfo::relocType rtype()       const { return _rspec.type(); }
   const RelocationHolder&    rspec() const { return _rspec; }
-
-  RelocationHolder rspec(int offset) const {
-    return offset == 0 ? _rspec : _rspec.plus(offset);
-  }
 };
 
 // Convenience classes
diff --git a/src/hotspot/cpu/s390/relocInfo_s390.cpp b/src/hotspot/cpu/s390/relocInfo_s390.cpp
index 747ae9c535d06..9e352be20a3a2 100644
--- a/src/hotspot/cpu/s390/relocInfo_s390.cpp
+++ b/src/hotspot/cpu/s390/relocInfo_s390.cpp
@@ -30,27 +30,25 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/safepoint.hpp"
 
-void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
-  // we don't support splitting of relocations, so o must be zero:
-  assert(o == 0, "tried to split relocations");
+void Relocation::pd_set_data_value(address x, bool verify_only) {
   if (!verify_only) {
     switch (format()) {
       case relocInfo::uncompressed_format:
-        nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x) + o, code());
+        nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x), code());
         break;
       case relocInfo::compressed_format:
         if (type() == relocInfo::metadata_type)
-          nativeMovConstReg_at(addr())->set_narrow_klass(((intptr_t)x) + o);
+          nativeMovConstReg_at(addr())->set_narrow_klass(((intptr_t)x));
         else if (type() == relocInfo::oop_type)
-          nativeMovConstReg_at(addr())->set_narrow_oop(((intptr_t)x) + o);
+          nativeMovConstReg_at(addr())->set_narrow_oop(((intptr_t)x));
         else
           guarantee(false, "bad relocInfo type for relocInfo::narrow_oop_format");
         break;
       case relocInfo::pcrel_addr_format:  // patch target location
-        nativeMovConstReg_at(addr())->set_pcrel_addr(((intptr_t)x) + o, code());
+        nativeMovConstReg_at(addr())->set_pcrel_addr(((intptr_t)x), code());
         break;
       case relocInfo::pcrel_data_format:  // patch data at target location
-        nativeMovConstReg_at(addr())->set_pcrel_data(((intptr_t)x) + o, code());
+        nativeMovConstReg_at(addr())->set_pcrel_data(((intptr_t)x), code());
         break;
       default:
         assert(false, "not a valid relocInfo format");
diff --git a/src/hotspot/cpu/x86/relocInfo_x86.cpp b/src/hotspot/cpu/x86/relocInfo_x86.cpp
index db806419b51d4..d7fddf838ac8e 100644
--- a/src/hotspot/cpu/x86/relocInfo_x86.cpp
+++ b/src/hotspot/cpu/x86/relocInfo_x86.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,9 +36,8 @@
 #include "utilities/checkedCast.hpp"
 
 
-void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
+void Relocation::pd_set_data_value(address x, bool verify_only) {
 #ifdef AMD64
-  x += o;
   typedef Assembler::WhichOperand WhichOperand;
   WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm, call32, narrow oop
   assert(which == Assembler::disp32_operand ||
@@ -80,9 +79,9 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
   }
 #else
   if (verify_only) {
-    guarantee(*pd_address_in_code() == (x + o), "instructions must match");
+    guarantee(*pd_address_in_code() == x, "instructions must match");
   } else {
-    *pd_address_in_code() = x + o;
+    *pd_address_in_code() = x;
   }
 #endif // AMD64
 }
diff --git a/src/hotspot/cpu/zero/relocInfo_zero.cpp b/src/hotspot/cpu/zero/relocInfo_zero.cpp
index 1e9fdc1081d48..b926f20cfe7d8 100644
--- a/src/hotspot/cpu/zero/relocInfo_zero.cpp
+++ b/src/hotspot/cpu/zero/relocInfo_zero.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2009, 2010, 2011 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -30,7 +30,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/safepoint.hpp"
 
-void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
+void Relocation::pd_set_data_value(address x, bool verify_only) {
   ShouldNotCallThis();
 }
 
diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp
index 69ff4bc78d639..d0f732edac486 100644
--- a/src/hotspot/share/code/relocInfo.cpp
+++ b/src/hotspot/share/code/relocInfo.cpp
@@ -277,30 +277,6 @@ DEFINE_COPY_INTO_AUX(Relocation)
 #undef DEFINE_COPY_INTO_AUX
 #undef DEFINE_COPY_INTO
 
-//////// Methods for RelocationHolder
-
-RelocationHolder RelocationHolder::plus(int offset) const {
-  if (offset != 0) {
-    switch (type()) {
-    case relocInfo::none:
-      break;
-    case relocInfo::oop_type:
-      {
-        oop_Relocation* r = (oop_Relocation*)reloc();
-        return oop_Relocation::spec(r->oop_index(), r->offset() + offset);
-      }
-    case relocInfo::metadata_type:
-      {
-        metadata_Relocation* r = (metadata_Relocation*)reloc();
-        return metadata_Relocation::spec(r->metadata_index(), r->offset() + offset);
-      }
-    default:
-      ShouldNotReachHere();
-    }
-  }
-  return (*this);
-}
-
 //////// Methods for flyweight Relocation types
 
 // some relocations can compute their own values
@@ -402,24 +378,24 @@ void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer
 
 void oop_Relocation::pack_data_to(CodeSection* dest) {
   short* p = (short*) dest->locs_end();
-  p = pack_2_ints_to(p, _oop_index, _offset);
+  p = pack_1_int_to(p, _oop_index);
   dest->set_locs_end((relocInfo*) p);
 }
 
 
 void oop_Relocation::unpack_data() {
-  unpack_2_ints(_oop_index, _offset);
+  _oop_index = unpack_1_int();
 }
 
 void metadata_Relocation::pack_data_to(CodeSection* dest) {
   short* p = (short*) dest->locs_end();
-  p = pack_2_ints_to(p, _metadata_index, _offset);
+  p = pack_1_int_to(p, _metadata_index);
   dest->set_locs_end((relocInfo*) p);
 }
 
 
 void metadata_Relocation::unpack_data() {
-  unpack_2_ints(_metadata_index, _offset);
+  _metadata_index = unpack_1_int();
 }
 
 
@@ -855,8 +831,8 @@ void RelocIterator::print_current() {
         raw_oop   = *oop_addr;
         oop_value = r->oop_value();
       }
-      tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]",
-                 p2i(oop_addr), p2i(raw_oop), r->offset());
+      tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT "]",
+                 p2i(oop_addr), p2i(raw_oop));
       // Do not print the oop by default--we want this routine to
       // work even during GC or other inconvenient times.
       if (WizardMode && oop_value != nullptr) {
@@ -878,8 +854,8 @@ void RelocIterator::print_current() {
         raw_metadata   = *metadata_addr;
         metadata_value = r->metadata_value();
       }
-      tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]",
-                 p2i(metadata_addr), p2i(raw_metadata), r->offset());
+      tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT "]",
+                 p2i(metadata_addr), p2i(raw_metadata));
       if (metadata_value != nullptr) {
         tty->print("metadata_value=" INTPTR_FORMAT ": ", p2i(metadata_value));
         metadata_value->print_value_on(tty);
diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp
index 9f1db9f4684e3..6d0907d97dedc 100644
--- a/src/hotspot/share/code/relocInfo.hpp
+++ b/src/hotspot/share/code/relocInfo.hpp
@@ -129,12 +129,7 @@ class nmethod;
 //   Value:  an oop, or else the address (handle) of an oop
 //   Instruction types: memory (load), set (load address)
 //   Data:  []       an oop stored in 4 bytes of instruction
-//          [n]      n is the index of an oop in the CodeBlob's oop pool
-//          [[N]n l] and l is a byte offset to be applied to the oop
-//          [Nn Ll]  both index and offset may be 32 bits if necessary
-//   Here is a special hack, used only by the old compiler:
-//          [[N]n 00] the value is the __address__ of the nth oop in the pool
-//   (Note that the offset allows optimal references to class variables.)
+//          [[N]n]   the index of an oop in the CodeBlob's oop pool
 //
 // relocInfo::internal_word_type -- an address within the same CodeBlob
 // relocInfo::section_word_type -- same, but can refer to another section
@@ -515,9 +510,6 @@ class RelocationHolder {
   Relocation* reloc() const { return (Relocation*)_relocbuf; }
   inline relocInfo::relocType type() const;
 
-  // Add a constant offset to a relocation.  Helper for class Address.
-  RelocationHolder plus(int offset) const;
-
   // Return a holder containing a relocation of type Reloc, constructed using args.
   template
   static RelocationHolder construct(const Args&... args) {
@@ -788,8 +780,8 @@ class Relocation {
   void       const_set_data_value    (address x);
   void       const_verify_data_value (address x);
   // platform-dependent utilities for decoding and patching instructions
-  void       pd_set_data_value       (address x, intptr_t off, bool verify_only = false); // a set or mem-ref
-  void       pd_verify_data_value    (address x, intptr_t off) { pd_set_data_value(x, off, true); }
+  void       pd_set_data_value       (address x, bool verify_only = false); // a set or mem-ref
+  void       pd_verify_data_value    (address x) { pd_set_data_value(x, true); }
   address    pd_call_destination     (address orig_addr = nullptr);
   void       pd_set_call_destination (address x);
 
@@ -895,41 +887,28 @@ relocInfo::relocType RelocationHolder::type() const {
 // A DataRelocation always points at a memory or load-constant instruction..
 // It is absolute on most machines, and the constant is split on RISCs.
 // The specific subtypes are oop, external_word, and internal_word.
-// By convention, the "value" does not include a separately reckoned "offset".
 class DataRelocation : public Relocation {
  public:
   DataRelocation(relocInfo::relocType type) : Relocation(type) {}
 
-  bool          is_data() override             { return true; }
+  bool    is_data() override { return true; }
 
-  // both target and offset must be computed somehow from relocation data
-  virtual int    offset()                      { return 0; }
-  address         value() override             = 0;
-  void        set_value(address x) override    { set_value(x, offset()); }
-  void        set_value(address x, intptr_t o) {
-    if (addr_in_const())
+  // target must be computed somehow from relocation data
+  address value() override = 0;
+  void    set_value(address x) override {
+    if (addr_in_const()) {
       const_set_data_value(x);
-    else
-      pd_set_data_value(x, o);
+    } else {
+      pd_set_data_value(x);
+    }
   }
-  void        verify_value(address x) {
-    if (addr_in_const())
+  void    verify_value(address x) {
+    if (addr_in_const()) {
       const_verify_data_value(x);
-    else
-      pd_verify_data_value(x, offset());
+    } else {
+      pd_verify_data_value(x);
+    }
   }
-
-  // The "o" (displacement) argument is relevant only to split relocations
-  // on RISC machines.  In some CPUs (SPARC), the set-hi and set-lo ins'ns
-  // can encode more than 32 bits between them.  This allows compilers to
-  // share set-hi instructions between addresses that differ by a small
-  // offset (e.g., different static variables in the same class).
-  // On such machines, the "x" argument to set_value on all set-lo
-  // instructions must be the same as the "x" argument for the
-  // corresponding set-hi instructions.  The "o" arguments for the
-  // set-hi instructions are ignored, and must not affect the high-half
-  // immediate constant.  The "o" arguments for the set-lo instructions are
-  // added into the low-half immediate constant, and must not overflow it.
 };
 
 class post_call_nop_Relocation : public Relocation {
@@ -976,40 +955,36 @@ class CallRelocation : public Relocation {
 
 class oop_Relocation : public DataRelocation {
  public:
-  // encode in one of these formats:  [] [n] [n l] [Nn l] [Nn Ll]
-  // an oop in the CodeBlob's oop pool
-  static RelocationHolder spec(int oop_index, int offset = 0) {
+  // an oop in the CodeBlob's oop pool; encoded as [n] or [Nn]
+  static RelocationHolder spec(int oop_index) {
     assert(oop_index > 0, "must be a pool-resident oop");
-    return RelocationHolder::construct(oop_index, offset);
+    return RelocationHolder::construct(oop_index);
   }
-  // an oop in the instruction stream
+  // an oop in the instruction stream; encoded as []
   static RelocationHolder spec_for_immediate() {
     // If no immediate oops are generated, we can skip some walks over nmethods.
     // Assert that they don't get generated accidentally!
     assert(relocInfo::mustIterateImmediateOopsInCode(),
            "Must return true so we will search for oops as roots etc. in the code.");
     const int oop_index = 0;
-    const int offset    = 0;    // if you want an offset, use the oop pool
-    return RelocationHolder::construct(oop_index, offset);
+    return RelocationHolder::construct(oop_index);
   }
 
   void copy_into(RelocationHolder& holder) const override;
 
  private:
   jint _oop_index;                  // if > 0, index into CodeBlob::oop_at
-  jint _offset;                     // byte offset to apply to the oop itself
 
-  oop_Relocation(int oop_index, int offset)
-    : DataRelocation(relocInfo::oop_type), _oop_index(oop_index), _offset(offset) { }
+  oop_Relocation(int oop_index)
+    : DataRelocation(relocInfo::oop_type), _oop_index(oop_index) { }
 
   friend class RelocationHolder;
   oop_Relocation() : DataRelocation(relocInfo::oop_type) {}
 
  public:
   int oop_index() { return _oop_index; }
-  int offset() override { return _offset; }
 
-  // data is packed in "2_ints" format:  [i o] or [Ii Oo]
+  // oop_index is packed in "1_int" format:  [n] or [Nn]
   void pack_data_to(CodeSection* dest) override;
   void unpack_data() override;
 
@@ -1031,27 +1006,24 @@ class oop_Relocation : public DataRelocation {
 class metadata_Relocation : public DataRelocation {
 
  public:
-  // encode in one of these formats:  [] [n] [n l] [Nn l] [Nn Ll]
-  // an metadata in the CodeBlob's metadata pool
-  static RelocationHolder spec(int metadata_index, int offset = 0) {
+  // an metadata in the CodeBlob's metadata pool; encoded as [n] or [Nn]
+  static RelocationHolder spec(int metadata_index) {
     assert(metadata_index > 0, "must be a pool-resident metadata");
-    return RelocationHolder::construct(metadata_index, offset);
+    return RelocationHolder::construct(metadata_index);
   }
-  // an metadata in the instruction stream
+  // an metadata in the instruction stream; encoded as []
   static RelocationHolder spec_for_immediate() {
     const int metadata_index = 0;
-    const int offset    = 0;    // if you want an offset, use the metadata pool
-    return RelocationHolder::construct(metadata_index, offset);
+    return RelocationHolder::construct(metadata_index);
   }
 
   void copy_into(RelocationHolder& holder) const override;
 
  private:
   jint _metadata_index;            // if > 0, index into nmethod::metadata_at
-  jint _offset;                     // byte offset to apply to the metadata itself
 
-  metadata_Relocation(int metadata_index, int offset)
-    : DataRelocation(relocInfo::metadata_type), _metadata_index(metadata_index), _offset(offset) { }
+  metadata_Relocation(int metadata_index)
+    : DataRelocation(relocInfo::metadata_type), _metadata_index(metadata_index) { }
 
   friend class RelocationHolder;
   metadata_Relocation() : DataRelocation(relocInfo::metadata_type) { }
@@ -1063,9 +1035,8 @@ class metadata_Relocation : public DataRelocation {
 
  public:
   int metadata_index() { return _metadata_index; }
-  int offset() override { return _offset; }
 
-  // data is packed in "2_ints" format:  [i o] or [Ii Oo]
+  // metadata_index is packed in "1_int" format:  [n] or [Nn]
   void pack_data_to(CodeSection* dest) override;
   void unpack_data() override;
 

From a706ca4fdb4db4ba36c6ad04a37c37a348f8af0b Mon Sep 17 00:00:00 2001
From: Matias Saavedra Silva 
Date: Fri, 10 May 2024 01:34:02 +0000
Subject: [PATCH 146/203] 8329418: Replace pointers to tables with offsets in
 relocation bitmap

Reviewed-by: cjplummer, iklam
---
 src/hotspot/share/cds/archiveBuilder.cpp      | 20 +++---
 src/hotspot/share/cds/archiveBuilder.hpp      | 16 ++---
 src/hotspot/share/cds/archiveUtils.cpp        | 28 ++-------
 src/hotspot/share/cds/archiveUtils.hpp        |  7 ++-
 src/hotspot/share/cds/cppVtables.cpp          | 21 ++++---
 src/hotspot/share/cds/cppVtables.hpp          |  5 +-
 src/hotspot/share/cds/dynamicArchive.cpp      |  2 +-
 src/hotspot/share/cds/metaspaceShared.cpp     |  4 +-
 src/hotspot/share/cds/serializeClosure.hpp    | 16 ++++-
 src/hotspot/share/classfile/vmSymbols.cpp     |  4 +-
 .../sun/jvm/hotspot/memory/FileMapInfo.java   | 63 ++++++++++++++-----
 11 files changed, 113 insertions(+), 73 deletions(-)

diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp
index 51399f03434f6..a98fd04ba6862 100644
--- a/src/hotspot/share/cds/archiveBuilder.cpp
+++ b/src/hotspot/share/cds/archiveBuilder.cpp
@@ -146,7 +146,7 @@ void ArchiveBuilder::SourceObjList::relocate(int i, ArchiveBuilder* builder) {
 }
 
 ArchiveBuilder::ArchiveBuilder() :
-  _current_dump_space(nullptr),
+  _current_dump_region(nullptr),
   _buffer_bottom(nullptr),
   _last_verified_top(nullptr),
   _num_dump_regions_used(0),
@@ -341,10 +341,10 @@ address ArchiveBuilder::reserve_buffer() {
 
   _buffer_bottom = buffer_bottom;
   _last_verified_top = buffer_bottom;
-  _current_dump_space = &_rw_region;
+  _current_dump_region = &_rw_region;
   _num_dump_regions_used = 1;
   _other_region_used_bytes = 0;
-  _current_dump_space->init(&_shared_rs, &_shared_vs);
+  _current_dump_region->init(&_shared_rs, &_shared_vs);
 
   ArchivePtrMarker::initialize(&_ptrmap, &_shared_vs);
 
@@ -560,21 +560,21 @@ ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref
   }
 }
 
-void ArchiveBuilder::start_dump_space(DumpRegion* next) {
+void ArchiveBuilder::start_dump_region(DumpRegion* next) {
   address bottom = _last_verified_top;
-  address top = (address)(current_dump_space()->top());
+  address top = (address)(current_dump_region()->top());
   _other_region_used_bytes += size_t(top - bottom);
 
-  current_dump_space()->pack(next);
-  _current_dump_space = next;
+  current_dump_region()->pack(next);
+  _current_dump_region = next;
   _num_dump_regions_used ++;
 
-  _last_verified_top = (address)(current_dump_space()->top());
+  _last_verified_top = (address)(current_dump_region()->top());
 }
 
 void ArchiveBuilder::verify_estimate_size(size_t estimate, const char* which) {
   address bottom = _last_verified_top;
-  address top = (address)(current_dump_space()->top());
+  address top = (address)(current_dump_region()->top());
   size_t used = size_t(top - bottom) + _other_region_used_bytes;
   int diff = int(estimate) - int(used);
 
@@ -630,7 +630,7 @@ void ArchiveBuilder::dump_ro_metadata() {
   ResourceMark rm;
   log_info(cds)("Allocating RO objects ... ");
 
-  start_dump_space(&_ro_region);
+  start_dump_region(&_ro_region);
   make_shallow_copies(&_ro_region, &_ro_src_objs);
 
 #if INCLUDE_CDS_JAVA_HEAP
diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp
index dab369265b0b4..cbde5a7e02cbc 100644
--- a/src/hotspot/share/cds/archiveBuilder.hpp
+++ b/src/hotspot/share/cds/archiveBuilder.hpp
@@ -91,7 +91,7 @@ const int SharedSpaceObjectAlignment = KlassAlignmentInBytes;
 //
 class ArchiveBuilder : public StackObj {
 protected:
-  DumpRegion* _current_dump_space;
+  DumpRegion* _current_dump_region;
   address _buffer_bottom;                      // for writing the contents of rw/ro regions
   address _last_verified_top;
   int _num_dump_regions_used;
@@ -114,7 +114,7 @@ class ArchiveBuilder : public StackObj {
 
   intx _buffer_to_requested_delta;
 
-  DumpRegion* current_dump_space() const {  return _current_dump_space;  }
+  DumpRegion* current_dump_region() const {  return _current_dump_region;  }
 
 public:
   enum FollowMode {
@@ -278,17 +278,17 @@ class ArchiveBuilder : public StackObj {
 
   size_t estimate_archive_size();
 
-  void start_dump_space(DumpRegion* next);
+  void start_dump_region(DumpRegion* next);
   void verify_estimate_size(size_t estimate, const char* which);
 
 public:
   address reserve_buffer();
 
-  address buffer_bottom()                    const { return _buffer_bottom;                       }
-  address buffer_top()                       const { return (address)current_dump_space()->top(); }
-  address requested_static_archive_bottom()  const { return  _requested_static_archive_bottom;    }
-  address mapped_static_archive_bottom()     const { return  _mapped_static_archive_bottom;       }
-  intx buffer_to_requested_delta()           const { return _buffer_to_requested_delta;           }
+  address buffer_bottom()                    const { return _buffer_bottom;                        }
+  address buffer_top()                       const { return (address)current_dump_region()->top(); }
+  address requested_static_archive_bottom()  const { return  _requested_static_archive_bottom;     }
+  address mapped_static_archive_bottom()     const { return  _mapped_static_archive_bottom;        }
+  intx buffer_to_requested_delta()           const { return _buffer_to_requested_delta;            }
 
   bool is_in_buffer_space(address p) const {
     return (buffer_bottom() <= p && p < buffer_top());
diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp
index 5ba36960c55b1..8fd20e2026700 100644
--- a/src/hotspot/share/cds/archiveUtils.cpp
+++ b/src/hotspot/share/cds/archiveUtils.cpp
@@ -310,18 +310,11 @@ void WriteClosure::do_ptr(void** p) {
   if (ptr != nullptr && !ArchiveBuilder::current()->is_in_buffer_space(ptr)) {
     ptr = ArchiveBuilder::current()->get_buffered_addr(ptr);
   }
-  _dump_region->append_intptr_t((intptr_t)ptr, true);
-}
-
-void WriteClosure::do_region(u_char* start, size_t size) {
-  assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");
-  assert(size % sizeof(intptr_t) == 0, "bad size");
-  do_tag((int)size);
-  while (size > 0) {
-    do_ptr((void**)start);
-    start += sizeof(intptr_t);
-    size -= sizeof(intptr_t);
+  // null pointers do not need to be converted to offsets
+  if (ptr != nullptr) {
+    ptr = (address)ArchiveBuilder::current()->buffer_to_offset(ptr);
   }
+  _dump_region->append_intptr_t((intptr_t)ptr, false);
 }
 
 void ReadClosure::do_ptr(void** p) {
@@ -329,7 +322,7 @@ void ReadClosure::do_ptr(void** p) {
   intptr_t obj = nextPtr();
   assert((intptr_t)obj >= 0 || (intptr_t)obj < -100,
          "hit tag while initializing ptrs.");
-  *p = (void*)obj;
+  *p = (void*)obj != nullptr ? (void*)(SharedBaseAddress + obj) : (void*)obj;
 }
 
 void ReadClosure::do_u4(u4* p) {
@@ -355,17 +348,6 @@ void ReadClosure::do_tag(int tag) {
   FileMapInfo::assert_mark(tag == old_tag);
 }
 
-void ReadClosure::do_region(u_char* start, size_t size) {
-  assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");
-  assert(size % sizeof(intptr_t) == 0, "bad size");
-  do_tag((int)size);
-  while (size > 0) {
-    *(intptr_t*)start = nextPtr();
-    start += sizeof(intptr_t);
-    size -= sizeof(intptr_t);
-  }
-}
-
 void ArchiveUtils::log_to_classlist(BootstrapInfo* bootstrap_specifier, TRAPS) {
   if (ClassListWriter::is_enabled()) {
     if (SystemDictionaryShared::is_supported_invokedynamic(bootstrap_specifier)) {
diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp
index efe5a468b93b4..32cef97886f06 100644
--- a/src/hotspot/share/cds/archiveUtils.hpp
+++ b/src/hotspot/share/cds/archiveUtils.hpp
@@ -215,7 +215,10 @@ class WriteClosure : public SerializeClosure {
     _dump_region->append_intptr_t((intptr_t)tag);
   }
 
-  void do_region(u_char* start, size_t size);
+  char* region_top() {
+    return _dump_region->top();
+  }
+
   bool reading() const { return false; }
 };
 
@@ -238,8 +241,8 @@ class ReadClosure : public SerializeClosure {
   void do_int(int* p);
   void do_bool(bool *p);
   void do_tag(int tag);
-  void do_region(u_char* start, size_t size);
   bool reading() const { return true; }
+  char* region_top() { return nullptr; }
 };
 
 class ArchiveUtils {
diff --git a/src/hotspot/share/cds/cppVtables.cpp b/src/hotspot/share/cds/cppVtables.cpp
index c339ce9c0deaa..f17d94a82fdb5 100644
--- a/src/hotspot/share/cds/cppVtables.cpp
+++ b/src/hotspot/share/cds/cppVtables.cpp
@@ -213,23 +213,30 @@ void CppVtableCloner::init_orig_cpp_vtptr(int kind) {
 // the following holds true:
 //     _index[ConstantPool_Kind]->cloned_vtable()  == ((intptr_t**)cp)[0]
 //     _index[InstanceKlass_Kind]->cloned_vtable() == ((intptr_t**)ik)[0]
-CppVtableInfo** CppVtables::_index = nullptr;
+static CppVtableInfo* _index[_num_cloned_vtable_kinds];
 
-char* CppVtables::dumptime_init(ArchiveBuilder* builder) {
+// Vtables are all fixed offsets from ArchiveBuilder::current()->mapped_base()
+// E.g. ConstantPool is at offset 0x58. We can archive these offsets in the
+// RO region and use them to alculate their location at runtime without storing
+// the pointers in the RW region
+char* CppVtables::_vtables_serialized_base = nullptr;
+
+void CppVtables::dumptime_init(ArchiveBuilder* builder) {
   assert(CDSConfig::is_dumping_static_archive(), "cpp tables are only dumped into static archive");
-  size_t vtptrs_bytes = _num_cloned_vtable_kinds * sizeof(CppVtableInfo*);
-  _index = (CppVtableInfo**)builder->rw_region()->allocate(vtptrs_bytes);
 
   CPP_VTABLE_TYPES_DO(ALLOCATE_AND_INITIALIZE_VTABLE);
 
   size_t cpp_tables_size = builder->rw_region()->top() - builder->rw_region()->base();
   builder->alloc_stats()->record_cpp_vtables((int)cpp_tables_size);
-
-  return (char*)_index;
 }
 
 void CppVtables::serialize(SerializeClosure* soc) {
-  soc->do_ptr(&_index);
+  if (!soc->reading()) {
+    _vtables_serialized_base = (char*)ArchiveBuilder::current()->buffer_top();
+  }
+  for (int i = 0; i < _num_cloned_vtable_kinds; i++) {
+    soc->do_ptr(&_index[i]);
+  }
   if (soc->reading()) {
     CPP_VTABLE_TYPES_DO(INITIALIZE_VTABLE);
   }
diff --git a/src/hotspot/share/cds/cppVtables.hpp b/src/hotspot/share/cds/cppVtables.hpp
index 5318a9de2ba95..973502909ddf4 100644
--- a/src/hotspot/share/cds/cppVtables.hpp
+++ b/src/hotspot/share/cds/cppVtables.hpp
@@ -36,13 +36,14 @@ class CppVtableInfo;
 
 // Support for C++ vtables in CDS archive.
 class CppVtables : AllStatic {
-  static CppVtableInfo** _index;
+  static char* _vtables_serialized_base;
 public:
-  static char* dumptime_init(ArchiveBuilder* builder);
+  static void dumptime_init(ArchiveBuilder* builder);
   static void zero_archived_vtables();
   static intptr_t* get_archived_vtable(MetaspaceObj::Type msotype, address obj);
   static void serialize(SerializeClosure* sc);
   static bool is_valid_shared_method(const Method* m) NOT_CDS_RETURN_(false);
+  static char* vtables_serialized_base() { return _vtables_serialized_base; }
 };
 
 #endif // SHARE_CDS_CPPVTABLES_HPP
diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp
index cd5dd88b09939..f255b337d148f 100644
--- a/src/hotspot/share/cds/dynamicArchive.cpp
+++ b/src/hotspot/share/cds/dynamicArchive.cpp
@@ -137,7 +137,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder {
       // Note that these tables still point to the *original* objects, so
       // they would need to call DynamicArchive::original_to_target() to
       // get the correct addresses.
-      assert(current_dump_space() == ro_region(), "Must be RO space");
+      assert(current_dump_region() == ro_region(), "Must be RO space");
       SymbolTable::write_to_archive(symbols());
 
       ArchiveBuilder::OtherROAllocMark mark;
diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp
index c7d14f83d036a..93c5c1a1e3b00 100644
--- a/src/hotspot/share/cds/metaspaceShared.cpp
+++ b/src/hotspot/share/cds/metaspaceShared.cpp
@@ -511,7 +511,7 @@ void VM_PopulateDumpSharedSpace::doit() {
   builder.gather_source_objs();
   builder.reserve_buffer();
 
-  char* cloned_vtables = CppVtables::dumptime_init(&builder);
+  CppVtables::dumptime_init(&builder);
 
   builder.sort_metadata_objs();
   builder.dump_rw_metadata();
@@ -542,7 +542,7 @@ void VM_PopulateDumpSharedSpace::doit() {
   FileMapInfo* mapinfo = new FileMapInfo(static_archive, true);
   mapinfo->populate_header(MetaspaceShared::core_region_alignment());
   mapinfo->set_serialized_data(serialized_data);
-  mapinfo->set_cloned_vtables(cloned_vtables);
+  mapinfo->set_cloned_vtables(CppVtables::vtables_serialized_base());
   mapinfo->open_for_write();
   builder.write_archive(mapinfo, &_heap_info);
 
diff --git a/src/hotspot/share/cds/serializeClosure.hpp b/src/hotspot/share/cds/serializeClosure.hpp
index 275009286cb81..3d401407f37a1 100644
--- a/src/hotspot/share/cds/serializeClosure.hpp
+++ b/src/hotspot/share/cds/serializeClosure.hpp
@@ -48,8 +48,20 @@ class SerializeClosure : public StackObj {
   // Read/write the bool pointed to by p.
   virtual void do_bool(bool* p) = 0;
 
-  // Read/write the region specified.
-  virtual void do_region(u_char* start, size_t size) = 0;
+  // Iterate on the pointers from p[0] through p[num_pointers-1]
+  void do_ptrs(void** p, size_t size) {
+    assert((intptr_t)p % sizeof(intptr_t) == 0, "bad alignment");
+    assert(size % sizeof(intptr_t) == 0, "bad size");
+    do_tag((int)size);
+    while (size > 0) {
+      do_ptr(p);
+      p++;
+      size -= sizeof(intptr_t);
+    }
+  }
+
+  // Address of the first element being written (write only)
+  virtual char* region_top() = 0;
 
   // Check/write the tag.  If reading, then compare the tag against
   // the passed in value and fail is they don't match.  This allows
diff --git a/src/hotspot/share/classfile/vmSymbols.cpp b/src/hotspot/share/classfile/vmSymbols.cpp
index 05cd4767e9a6d..172d074255b38 100644
--- a/src/hotspot/share/classfile/vmSymbols.cpp
+++ b/src/hotspot/share/classfile/vmSymbols.cpp
@@ -205,9 +205,9 @@ void vmSymbols::metaspace_pointers_do(MetaspaceClosure *closure) {
 }
 
 void vmSymbols::serialize(SerializeClosure* soc) {
-  soc->do_region((u_char*)&Symbol::_vm_symbols[FIRST_SID],
+  soc->do_ptrs((void**)&Symbol::_vm_symbols[FIRST_SID],
                  (SID_LIMIT - FIRST_SID) * sizeof(Symbol::_vm_symbols[0]));
-  soc->do_region((u_char*)_type_signatures, sizeof(_type_signatures));
+  soc->do_ptrs((void**)_type_signatures, sizeof(_type_signatures));
 }
 
 #ifndef PRODUCT
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java
index 3dfb2bc5d1013..37b586116a50b 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java
@@ -40,6 +40,7 @@ public class FileMapInfo {
   private static Address rwRegionBaseAddress;
   private static Address rwRegionEndAddress;
   private static Address vtablesIndex;
+  private static Address mapped_base_address;
 
   // HashMap created by mapping the vTable addresses in the rw region with
   // the corresponding metadata type.
@@ -98,7 +99,7 @@ private static void initialize(TypeDataBase db) {
     // char* mapped_base_address = header->_mapped_base_address
     // size_t cloned_vtable_offset = header->_cloned_vtable_offset
     // CppVtableInfo** vtablesIndex = mapped_base_address + cloned_vtable_offset;
-    Address mapped_base_address = get_AddressField(FileMapHeader_type, header, "_mapped_base_address");
+    mapped_base_address = get_AddressField(FileMapHeader_type, header, "_mapped_base_address");
     long cloned_vtable_offset = get_CIntegerField(FileMapHeader_type, header, "_cloned_vtables_offset");
     vtablesIndex = mapped_base_address.addOffsetTo(cloned_vtable_offset);
 
@@ -168,23 +169,57 @@ public void createVtableTypeMapping() {
       vTableTypeMap = new HashMap();
       long addressSize = VM.getVM().getAddressSize();
 
-      // vtablesIndex points to this:
-      //     class CppVtableInfo {
-      //         intptr_t _vtable_size;
-      //         intptr_t _cloned_vtable[1];
-      //         ...
-      //     };
-      //     CppVtableInfo** CppVtables::_index;
-      // This is the index of all the cloned vtables. E.g., for
+      // vtablesIndex points to to an array like this:
+      // long info[] = {
+      //   offset of the CppVtableInfo for ConstantPool,
+      //   offset of the CppVtableInfo for InstanceKlass,
+      //   offset of the CppVtableInfo for InstanceClassLoaderKlass,
+      //   ...
+      // };
+      //
+      // class CppVtableInfo {
+      //   intptr_t _vtable_size;
+      //   intptr_t _cloned_vtable[1];
+      //   ...
+      // };
+      //
+      // The loop below computes the following
+      //     CppVtableInfo* t_ConstantPool  = mapped_base_address + info[0];
+      //     CppVtableInfo* t_InstanceKlass = mapped_base_address + info[1];
+      //     ...
+      //
+      // If we have the following objects
       //     ConstantPool* cp = ....; // an archived constant pool
       //     InstanceKlass* ik = ....;// an archived class
-      // the following holds true:
-      //     &_index[ConstantPool_Kind]->_cloned_vtable[0]  == ((intptr_t**)cp)[0]
-      //     &_index[InstanceKlass_Kind]->_cloned_vtable[0] == ((intptr_t**)ik)[0]
+      //
+      // then the following holds true:
+      //     ((intptr_t**)cp)[0] == &t_ConstantPool->_cloned_vtable[0]  // The vtable for archived ConstantPools
+      //     ((intptr_t**)ik)[0] == &t_InstanceKlass->_cloned_vtable[0] // The vtable for archived InstanceKlasses
+      //
+      // To get an idea what these address look like, do this:
+      //
+      // $ java -Xlog:cds+vtables=debug -XX:+UnlockDiagnosticVMOptions -XX:ArchiveRelocationMode=0 --version
+      // [0.002s][debug][cds,vtables] Copying  14 vtable entries for ConstantPool to 0x800000018
+      // [0.002s][debug][cds,vtables] Copying  41 vtable entries for InstanceKlass to 0x800000090
+      // [0.002s][debug][cds,vtables] Copying  41 vtable entries for InstanceClassLoaderKlass to 0x8000001e0
+      // [0.002s][debug][cds,vtables] Copying  41 vtable entries for InstanceMirrorKlass to 0x800000330
+      // [0.002s][debug][cds,vtables] Copying  41 vtable entries for InstanceRefKlass to 0x800000480
+      // [0.002s][debug][cds,vtables] Copying  41 vtable entries for InstanceStackChunkKlass to 0x8000005d0
+      // [0.002s][debug][cds,vtables] Copying  14 vtable entries for Method to 0x800000720
+      // [0.002s][debug][cds,vtables] Copying  42 vtable entries for ObjArrayKlass to 0x800000798
+      // [0.002s][debug][cds,vtables] Copying  42 vtable entries for TypeArrayKlass to 0x8000008f0
+      // java 23-internal 2024-09-17
+      // ...
 
       for (int i=0; i < metadataTypeArray.length; i++) {
-        Address vtableInfoAddress = vtablesIndex.getAddressAt(i * addressSize); // = _index[i]
-        Address vtableAddress = vtableInfoAddress.addOffsetTo(addressSize); // = &_index[i]->_cloned_vtable[0]
+        long vtable_offset = vtablesIndex.getJLongAt(i * addressSize); // long offset = _index[i]
+
+        // CppVtableInfo* t = the address of the CppVtableInfo for the i-th table
+        Address vtableInfoAddress = mapped_base_address.addOffsetTo(vtable_offset);
+
+        // vtableAddress = &t->_cloned_vtable[0]
+        Address vtableAddress = vtableInfoAddress.addOffsetTo(addressSize);
+
         vTableTypeMap.put(vtableAddress, metadataTypeArray[i]);
       }
     }

From d2d37c913e5b55f7aec2c7a6b5a2328348ded223 Mon Sep 17 00:00:00 2001
From: Thomas Stuefe 
Date: Fri, 10 May 2024 04:30:17 +0000
Subject: [PATCH 147/203] 8331942: On Linux aarch64, CDS archives should be
 using 64K alignment by default

Reviewed-by: aph, iklam
---
 make/autoconf/jdk-options.m4 | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
index 8c91a2ccd33eb..23f331e79b7f9 100644
--- a/make/autoconf/jdk-options.m4
+++ b/make/autoconf/jdk-options.m4
@@ -190,6 +190,17 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
   fi
   AC_SUBST(INCLUDE_SA)
 
+  # Setup default CDS alignment. On platforms where one build may run on machines with different
+  # page sizes, the JVM choses a compatible alignment to fit all possible page sizes. This slightly
+  # increases archive size.
+  # The only platform having this problem at the moment is Linux on aarch64, which may encounter
+  # three different page sizes: 4K, 64K, and if run on Mac m1 hardware, 16K.
+  COMPATIBLE_CDS_ALIGNMENT_DEFAULT=false
+  if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then
+    COMPATIBLE_CDS_ALIGNMENT_DEFAULT=true
+  fi
+  AC_SUBST(COMPATIBLE_CDS_ALIGNMENT_DEFAULT)
+
   # Compress jars
   COMPRESS_JARS=false
 
@@ -673,7 +684,7 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE],
 #
 AC_DEFUN([JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT],
 [
-  UTIL_ARG_ENABLE(NAME: compatible-cds-alignment, DEFAULT: false,
+  UTIL_ARG_ENABLE(NAME: compatible-cds-alignment, DEFAULT: $COMPATIBLE_CDS_ALIGNMENT_DEFAULT,
       RESULT: ENABLE_COMPATIBLE_CDS_ALIGNMENT,
       DESC: [enable use alternative compatible cds core region alignment],
       DEFAULT_DESC: [disabled],

From b9a142a2243676b3f4fe288e7a28f4957a4d1edd Mon Sep 17 00:00:00 2001
From: Abhishek Kumar 
Date: Fri, 10 May 2024 04:45:01 +0000
Subject: [PATCH 148/203] 8226990: GTK & Nimbus LAF: Tabbed pane's background
 color is not expected one when change the opaque checkbox.

Reviewed-by: tr, honkar, psadhukhan
---
 .../java/swing/plaf/gtk/GTKLookAndFeel.java   |   9 +-
 .../sun/java/swing/plaf/gtk/GTKPainter.java   |   5 +-
 .../classes/javax/swing/plaf/nimbus/skin.laf  |  10 +-
 .../swing/plaf/synth/SynthTabbedPaneUI.java   |  50 +++-
 .../TestJTabbedPaneOpaqueColor.java           | 248 ++++++++++++++++++
 5 files changed, 315 insertions(+), 7 deletions(-)
 create mode 100644 test/jdk/javax/swing/JTabbedPane/TestJTabbedPaneOpaqueColor.java

diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java
index 72b8c759e30b5..65f29ea8384fe 100644
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -348,6 +348,8 @@ protected void initComponentDefaults(UIDefaults table) {
         Double defaultCaretAspectRatio = Double.valueOf(0.025);
         Color caretColor = table.getColor("caretColor");
         Color controlText = table.getColor("controlText");
+        Color tabbedPaneBg = new ColorUIResource(238, 238, 238);
+        Color unselectedTabColor = new ColorUIResource(255, 255, 255);
 
         Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[] {
                        "ctrl C", DefaultEditorKit.copyAction,
@@ -1020,6 +1022,11 @@ public Object createValue(UIDefaults table) {
             "TabbedPane.selectedLabelShift", 3,
             "TabbedPane.font", new FontLazyValue(Region.TABBED_PANE),
             "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 0, 1),
+            "TabbedPane.selected", tabbedPaneBg,
+            "TabbedPane.contentOpaque", Boolean.TRUE,
+            "TabbedPane.tabsOpaque", Boolean.TRUE,
+            "TabbedPane.contentAreaColor", tabbedPaneBg,
+            "TabbedPane.unselectedBackground", unselectedTabColor,
 
             "Table.scrollPaneBorder", zeroBorder,
             "Table.background", tableBg,
diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java
index 1635ff66f89c1..e643d3d28ff3d 100644
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -972,6 +972,9 @@ public void paintTabbedPaneTabBackground(SynthContext context,
         JTabbedPane pane = (JTabbedPane)context.getComponent();
         int placement = pane.getTabPlacement();
 
+        // Fill the tab rect area
+        g.fillRect(x, y, w, h);
+
         synchronized (UNIXToolkit.GTK_LOCK) {
             if (! ENGINE.paintCachedImage(g, x, y, w, h,
                     id, gtkState, placement, tabIndex)) {
diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf
index 38e8530983aad..1d486f9fe0644 100644
--- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf
+++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf
@@ -1,7 +1,7 @@