From 6d37e633e6afa11ecd40bed10c0efbde6f9f6181 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Sat, 5 Apr 2025 20:25:30 +0000 Subject: [PATCH 001/843] 8353753: Remove unnecessary forward declaration in oop.hpp Reviewed-by: kbarrett --- src/hotspot/share/oops/oop.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index f52baab0de6..8048c8770c2 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,11 +44,6 @@ // // no virtual functions allowed -// Forward declarations. -class OopClosure; -class PSPromotionManager; -class ParCompactionManager; - class oopDesc { friend class VMStructs; friend class JVMCIVMStructs; From 660b17a6b9afe26dee2d9647755c75d817888eda Mon Sep 17 00:00:00 2001 From: Evgeny Astigeevich Date: Sun, 6 Apr 2025 17:38:28 +0000 Subject: [PATCH 002/843] 8350852: Implement JMH benchmark for sparse CodeCache Reviewed-by: kvn --- .../bench/vm/compiler/SparseCodeCache.java | 368 ++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 test/micro/org/openjdk/bench/vm/compiler/SparseCodeCache.java diff --git a/test/micro/org/openjdk/bench/vm/compiler/SparseCodeCache.java b/test/micro/org/openjdk/bench/vm/compiler/SparseCodeCache.java new file mode 100644 index 00000000000..473ce100e0a --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/SparseCodeCache.java @@ -0,0 +1,368 @@ +/* + * 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. + * + */ + +package org.openjdk.bench.vm.compiler; + +import java.lang.reflect.Method; +import java.util.Random; + +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import org.openjdk.bench.util.InMemoryJavaCompiler; + +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.code.NMethod; + +/* + * This benchmark is used to check performance when the code cache is sparse. + * + * We use C2 compiler to compile the same Java method multiple times + * to produce as many code as needed. + * These compiled methods represent the active methods in the code cache. + * We split active methods into groups. + * We put a group into a fixed size code region. + * We make a code region size aligned. + * CodeCache becomes sparse when code regions are not fully filled. + * + * The benchmark parameters are active method count, group count, and code region size. + */ + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +@Fork(value = 3, jvmArgs = { + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+WhiteBoxAPI", + "-Xbootclasspath/a:lib-test/wb.jar", + "-XX:CompileCommand=dontinline,A::sum", + "-XX:-UseCodeCacheFlushing", + "-XX:-TieredCompilation", + "-XX:+SegmentedCodeCache", + "-XX:ReservedCodeCacheSize=512m", + "-XX:InitialCodeCacheSize=512m", + "-XX:+UseSerialGC", + "-XX:+PrintCodeCache" +}) +public class SparseCodeCache { + + private static final int C2_LEVEL = 4; + private static final int DUMMY_BLOB_SIZE = 1024 * 1024; + private static final int DUMMY_BLOB_COUNT = 128; + + static byte[] num1; + static byte[] num2; + + @State(Scope.Thread) + public static class ThreadState { + byte[] result; + + @Setup + public void setup() { + result = new byte[num1.length + 1]; + } + } + + private static Object WB; + + @Param({"256", "512", "1024"}) + public int activeMethodCount; + + @Param({"1", "32", "64", "128"}) + public int groupCount; + + @Param({"2097152"}) + public int codeRegionSize; + + private TestMethod[] methods = {}; + + private static byte[] genNum(Random random, int digitCount) { + byte[] num = new byte[digitCount]; + int d; + do { + d = random.nextInt(10); + } while (d == 0); + + num[0] = (byte)d; + for (int i = 1; i < digitCount; ++i) { + num[i] = (byte)random.nextInt(10); + } + return num; + } + + private static void initWhiteBox() { + WB = WhiteBox.getWhiteBox(); + } + + private static void initNums() { + final long seed = 8374592837465123L; + Random random = new Random(seed); + + final int digitCount = 40; + num1 = genNum(random, digitCount); + num2 = genNum(random, digitCount); + } + + private static WhiteBox getWhiteBox() { + return (WhiteBox)WB; + } + + private static final class TestMethod { + private static final String CLASS_NAME = "A"; + private static final String METHOD_TO_COMPILE = "sum"; + private static final String JAVA_CODE = """ + public class A { + + public static void sum(byte[] n1, byte[] n2, byte[] out) { + final int digitCount = n1.length; + int carry = 0; + for (int i = digitCount - 1; i >= 0; --i) { + int sum = n1[i] + n2[i] + carry; + out[i] = (byte)(sum % 10); + carry = sum / 10; + } + if (carry != 0) { + for (int i = digitCount; i > 0; --i) { + out[i] = out[i - 1]; + } + out[0] = (byte)carry; + } + } + }"""; + + private static final byte[] BYTE_CODE; + + static { + BYTE_CODE = InMemoryJavaCompiler.compile(CLASS_NAME, JAVA_CODE); + } + + private final Method method; + + private static ClassLoader createClassLoaderFor() { + return new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (!name.equals(CLASS_NAME)) { + return super.loadClass(name); + } + + return defineClass(name, BYTE_CODE, 0, BYTE_CODE.length); + } + }; + } + + public TestMethod() throws Exception { + var cl = createClassLoaderFor().loadClass(CLASS_NAME); + method = cl.getMethod(METHOD_TO_COMPILE, byte[].class, byte[].class, byte[].class); + getWhiteBox().testSetDontInlineMethod(method, true); + } + + public void profile(byte[] num1, byte[] num2, byte[] result) throws Exception { + method.invoke(null, num1, num2, result); + getWhiteBox().markMethodProfiled(method); + } + + public void invoke(byte[] num1, byte[] num2, byte[] result) throws Exception { + method.invoke(null, num1, num2, result); + } + + public void compileWithC2() throws Exception { + getWhiteBox().enqueueMethodForCompilation(method, C2_LEVEL); + while (getWhiteBox().isMethodQueuedForCompilation(method)) { + Thread.onSpinWait(); + } + if (getWhiteBox().getMethodCompilationLevel(method) != C2_LEVEL) { + throw new IllegalStateException("Method " + method + " is not compiled by C2."); + } + } + + public NMethod getNMethod() { + return NMethod.get(method, false); + } + } + + private void generateOneGroupCode() throws Exception { + byte[] result = new byte[num1.length + 1]; + + methods = new TestMethod[activeMethodCount]; + for (int i = 0; i < activeMethodCount; ++i) { + methods[i] = new TestMethod(); + methods[i].profile(num1, num2, result); + methods[i].compileWithC2(); + } + allocateDummyBlobs(DUMMY_BLOB_COUNT, DUMMY_BLOB_SIZE, methods[activeMethodCount - 1].getNMethod().code_blob_type.id); + compileCallMethods(); + } + + private void allocateDummyBlobs(int count, int size, int codeBlobType) { + getWhiteBox().lockCompilation(); + for (int i = 0; i < count; i++) { + var dummyBlob = getWhiteBox().allocateCodeBlob(size, codeBlobType); + if (dummyBlob == 0) { + throw new IllegalStateException("Failed to allocate dummy blob."); + } + } + getWhiteBox().unlockCompilation(); + } + + private void generateCode() throws Exception { + initNums(); + + if (groupCount == 1) { + generateOneGroupCode(); + return; + } + + final int defaultMethodsPerGroup = activeMethodCount / groupCount; + if (defaultMethodsPerGroup == 0) { + throw new IllegalArgumentException("activeMethodCount = " + activeMethodCount + + ", groupCount = " + groupCount + + ". 'activeMethodCount' must be greater than or equal to 'groupCount'."); + } + + if ((codeRegionSize & (codeRegionSize - 1)) != 0) { + throw new IllegalArgumentException("codeRegionSize = " + codeRegionSize + + ". 'codeRegionSize' must be a power of 2."); + } + + byte[] result = new byte[num1.length + 1]; + methods = new TestMethod[activeMethodCount]; + methods[0] = new TestMethod(); + methods[0].profile(num1, num2, result); + methods[0].compileWithC2(); + final var nmethod = methods[0].getNMethod(); + if (nmethod.size * defaultMethodsPerGroup > codeRegionSize) { + throw new IllegalArgumentException("codeRegionSize = " + codeRegionSize + + ", methodsPerRegion = " + defaultMethodsPerGroup + + ", nmethod size = " + nmethod.size + + ". One code region does not have enough space to hold " + defaultMethodsPerGroup + " nmethods."); + } + + final var codeHeapSize = nmethod.code_blob_type.getSize(); + final var neededSpace = groupCount * codeRegionSize; + if (neededSpace > codeHeapSize) { + throw new IllegalArgumentException(nmethod.code_blob_type.sizeOptionName + " = " + codeHeapSize + + ". Not enough space to hold " + groupCount + " groups " + + "of code region size " + codeRegionSize + "."); + } + + int j = 1; + for (; j < defaultMethodsPerGroup; ++j) { + methods[j] = new TestMethod(); + methods[j].profile(num1, num2, result); + methods[j].compileWithC2(); + } + + int methodsPerGroup = defaultMethodsPerGroup; + int remainingMethods = activeMethodCount % groupCount; + for (int i = 1; i < groupCount; ++i) { + getWhiteBox().lockCompilation(); + var firstNmethodInPrevGroup = methods[j - methodsPerGroup].getNMethod(); + var regionStart = firstNmethodInPrevGroup.address & ~(codeRegionSize - 1); + var regionEnd = regionStart + codeRegionSize; + var lastNmethodInPrevGroup = methods[j - 1].getNMethod(); + + // We have disabled code cache flushing. This should guarantee our just compiled + // not yet used code will not be flushed. + // Besides our test methods, we don't use a lot of Java methods in this benchmark. + // This should guarantee that most of code in the code cache is our test methods. + // If C2 occasionally compiles other methods, it should not affect test methods code placement much. + // We don't expect a lot of deoptimizations in this benchmark. So we don't expect + // CodeCache to be fragmented. + // We assume addresses of our compiled methods and dummy code blobs are in increasing order. + // Methods compiled during the same iteration are in the same code region. + if ((lastNmethodInPrevGroup.address + lastNmethodInPrevGroup.size) < regionEnd) { + var dummyBlob = getWhiteBox().allocateCodeBlob(regionEnd - lastNmethodInPrevGroup.address - lastNmethodInPrevGroup.size, + lastNmethodInPrevGroup.code_blob_type.id); + if (dummyBlob == 0) { + throw new IllegalStateException("Failed to allocate dummy blob."); + } + } + getWhiteBox().unlockCompilation(); + + methodsPerGroup = defaultMethodsPerGroup; + if (remainingMethods > 0) { + ++methodsPerGroup; + --remainingMethods; + } + + for (int k = 0; k < methodsPerGroup; ++k, ++j) { + methods[j] = new TestMethod(); + methods[j].profile(num1, num2, result); + methods[j].compileWithC2(); + } + } + + allocateDummyBlobs(DUMMY_BLOB_COUNT, DUMMY_BLOB_SIZE, methods[j - 1].getNMethod().code_blob_type.id); + compileCallMethods(); + } + + private void compileCallMethods() throws Exception { + var threadState = new ThreadState(); + threadState.setup(); + callMethods(threadState); + Method method = SparseCodeCache.class.getDeclaredMethod("callMethods", ThreadState.class); + getWhiteBox().markMethodProfiled(method); + getWhiteBox().enqueueMethodForCompilation(method, C2_LEVEL); + while (getWhiteBox().isMethodQueuedForCompilation(method)) { + Thread.onSpinWait(); + } + if (getWhiteBox().getMethodCompilationLevel(method) != C2_LEVEL) { + throw new IllegalStateException("Method SparseCodeCache::callMethods is not compiled by C2."); + } + getWhiteBox().testSetDontInlineMethod(method, true); + } + + @Setup(Level.Trial) + public void setupCodeCache() throws Exception { + initWhiteBox(); + generateCode(); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private void callMethods(ThreadState s) throws Exception { + for (var m : methods) { + m.invoke(num1, num2, s.result); + } + } + + @Benchmark + @Warmup(iterations = 2) + public void runMethodsWithReflection(ThreadState s) throws Exception { + callMethods(s); + } +} From 97ed536125645304aed03a4afbc3ded627de0bb0 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Mon, 7 Apr 2025 05:21:44 +0000 Subject: [PATCH 003/843] 8346989: C2: deoptimization and re-execution cycle with Math.*Exact in case of frequent overflow Reviewed-by: thartmann, vlivanov --- src/hotspot/share/opto/graphKit.cpp | 157 ++++--- src/hotspot/share/opto/graphKit.hpp | 10 + src/hotspot/share/opto/library_call.cpp | 18 +- src/hotspot/share/opto/library_call.hpp | 2 +- .../intrinsics/mathexact/OverflowTest.java | 274 ++++++++++++ .../openjdk/bench/vm/compiler/MathExact.java | 403 ++++++++++++++++++ 6 files changed, 787 insertions(+), 77 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/intrinsics/mathexact/OverflowTest.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/MathExact.java diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index e10a87171fc..df9177a4938 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -527,71 +527,29 @@ void GraphKit::uncommon_trap_if_should_post_on_exceptions(Deoptimization::DeoptR //------------------------------builtin_throw---------------------------------- void GraphKit::builtin_throw(Deoptimization::DeoptReason reason) { - bool must_throw = true; - - // If this particular condition has not yet happened at this - // bytecode, then use the uncommon trap mechanism, and allow for - // a future recompilation if several traps occur here. - // If the throw is hot, try to use a more complicated inline mechanism - // which keeps execution inside the compiled code. - bool treat_throw_as_hot = false; - ciMethodData* md = method()->method_data(); - - if (ProfileTraps) { - if (too_many_traps(reason)) { - treat_throw_as_hot = true; - } - // (If there is no MDO at all, assume it is early in - // execution, and that any deopts are part of the - // startup transient, and don't need to be remembered.) - - // Also, if there is a local exception handler, treat all throws - // as hot if there has been at least one in this method. - if (C->trap_count(reason) != 0 - && method()->method_data()->trap_count(reason) != 0 - && has_exception_handler()) { - treat_throw_as_hot = true; - } - } + builtin_throw(reason, builtin_throw_exception(reason), /*allow_too_many_traps*/ true); +} +void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, + ciInstance* ex_obj, + bool allow_too_many_traps) { // If this throw happens frequently, an uncommon trap might cause // a performance pothole. If there is a local exception handler, // and if this particular bytecode appears to be deoptimizing often, // let us handle the throw inline, with a preconstructed instance. // Note: If the deopt count has blown up, the uncommon trap // runtime is going to flush this nmethod, not matter what. - if (treat_throw_as_hot && method()->can_omit_stack_trace()) { - // If the throw is local, we use a pre-existing instance and - // punt on the backtrace. This would lead to a missing backtrace - // (a repeat of 4292742) if the backtrace object is ever asked - // for its backtrace. - // Fixing this remaining case of 4292742 requires some flavor of - // escape analysis. Leave that for the future. - ciInstance* ex_obj = nullptr; - switch (reason) { - case Deoptimization::Reason_null_check: - ex_obj = env()->NullPointerException_instance(); - break; - case Deoptimization::Reason_div0_check: - ex_obj = env()->ArithmeticException_instance(); - break; - case Deoptimization::Reason_range_check: - ex_obj = env()->ArrayIndexOutOfBoundsException_instance(); - break; - case Deoptimization::Reason_class_check: - ex_obj = env()->ClassCastException_instance(); - break; - case Deoptimization::Reason_array_check: - ex_obj = env()->ArrayStoreException_instance(); - break; - default: - break; - } - // If we have a preconstructed exception object, use it. - if (ex_obj != nullptr) { + if (is_builtin_throw_hot(reason)) { + if (method()->can_omit_stack_trace() && ex_obj != nullptr) { + // If the throw is local, we use a pre-existing instance and + // punt on the backtrace. This would lead to a missing backtrace + // (a repeat of 4292742) if the backtrace object is ever asked + // for its backtrace. + // Fixing this remaining case of 4292742 requires some flavor of + // escape analysis. Leave that for the future. if (env()->jvmti_can_post_on_exceptions()) { // check if we must post exception events, take uncommon trap if so - uncommon_trap_if_should_post_on_exceptions(reason, must_throw); + uncommon_trap_if_should_post_on_exceptions(reason, true /*must_throw*/); // here if should_post_on_exceptions is false // continue on with the normal codegen } @@ -622,6 +580,18 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason) { add_exception_state(make_exception_state(ex_node)); return; + } else if (builtin_throw_too_many_traps(reason, ex_obj)) { + // We cannot afford to take too many traps here. Suffer in the interpreter instead. + assert(allow_too_many_traps, "not allowed"); + if (C->log() != nullptr) { + C->log()->elem("hot_throw preallocated='0' reason='%s' mcount='%d'", + Deoptimization::trap_reason_name(reason), + C->trap_count(reason)); + } + uncommon_trap(reason, Deoptimization::Action_none, + (ciKlass*) nullptr, (char*) nullptr, + true /*must_throw*/); + return; } } @@ -633,27 +603,72 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason) { // Usual case: Bail to interpreter. // Reserve the right to recompile if we haven't seen anything yet. - ciMethod* m = Deoptimization::reason_is_speculate(reason) ? C->method() : nullptr; - Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile; - if (treat_throw_as_hot - && (method()->method_data()->trap_recompiled_at(bci(), m) - || C->too_many_traps(reason))) { - // We cannot afford to take more traps here. Suffer in the interpreter. - if (C->log() != nullptr) - C->log()->elem("hot_throw preallocated='0' reason='%s' mcount='%d'", - Deoptimization::trap_reason_name(reason), - C->trap_count(reason)); - action = Deoptimization::Action_none; - } - // "must_throw" prunes the JVM state to include only the stack, if there // are no local exception handlers. This should cut down on register // allocation time and code size, by drastically reducing the number // of in-edges on the call to the uncommon trap. - - uncommon_trap(reason, action, (ciKlass*)nullptr, (char*)nullptr, must_throw); + uncommon_trap(reason, Deoptimization::Action_maybe_recompile, + (ciKlass*) nullptr, (char*) nullptr, + true /*must_throw*/); } +bool GraphKit::is_builtin_throw_hot(Deoptimization::DeoptReason reason) { + // If this particular condition has not yet happened at this + // bytecode, then use the uncommon trap mechanism, and allow for + // a future recompilation if several traps occur here. + // If the throw is hot, try to use a more complicated inline mechanism + // which keeps execution inside the compiled code. + if (ProfileTraps) { + if (too_many_traps(reason)) { + return true; + } + // (If there is no MDO at all, assume it is early in + // execution, and that any deopts are part of the + // startup transient, and don't need to be remembered.) + + // Also, if there is a local exception handler, treat all throws + // as hot if there has been at least one in this method. + if (C->trap_count(reason) != 0 && + method()->method_data()->trap_count(reason) != 0 && + has_exception_handler()) { + return true; + } + } + return false; +} + +bool GraphKit::builtin_throw_too_many_traps(Deoptimization::DeoptReason reason, + ciInstance* ex_obj) { + if (is_builtin_throw_hot(reason)) { + if (method()->can_omit_stack_trace() && ex_obj != nullptr) { + return false; // no traps; throws preallocated exception instead + } + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? C->method() : nullptr; + if (method()->method_data()->trap_recompiled_at(bci(), m) || + C->too_many_traps(reason)) { + return true; + } + } + return false; +} + +ciInstance* GraphKit::builtin_throw_exception(Deoptimization::DeoptReason reason) const { + // Preallocated exception objects to use when we don't need the backtrace. + switch (reason) { + case Deoptimization::Reason_null_check: + return env()->NullPointerException_instance(); + case Deoptimization::Reason_div0_check: + return env()->ArithmeticException_instance(); + case Deoptimization::Reason_range_check: + return env()->ArrayIndexOutOfBoundsException_instance(); + case Deoptimization::Reason_class_check: + return env()->ClassCastException_instance(); + case Deoptimization::Reason_array_check: + return env()->ArrayStoreException_instance(); + default: + return nullptr; + } +} //----------------------------PreserveJVMState--------------------------------- PreserveJVMState::PreserveJVMState(GraphKit* kit, bool clone_map) { diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp index d9a725fc10c..d1b58526a6d 100644 --- a/src/hotspot/share/opto/graphKit.hpp +++ b/src/hotspot/share/opto/graphKit.hpp @@ -276,6 +276,16 @@ class GraphKit : public Phase { // Helper to throw a built-in exception. // The JVMS must allow the bytecode to be re-executed via an uncommon trap. void builtin_throw(Deoptimization::DeoptReason reason); + void builtin_throw(Deoptimization::DeoptReason reason, + ciInstance* exception_object, + bool allow_too_many_traps); + bool builtin_throw_too_many_traps(Deoptimization::DeoptReason reason, + ciInstance* exception_object); + private: + bool is_builtin_throw_hot(Deoptimization::DeoptReason reason); + ciInstance* builtin_throw_exception(Deoptimization::DeoptReason reason) const; + + public: // Helper to check the JavaThread::_should_post_on_exceptions flag // and branch to an uncommon_trap if it is true (with the specified reason and must_throw) diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 3bb432ac607..708225ba3aa 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -2003,7 +2003,14 @@ bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) { return true; } -void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) { +bool LibraryCallKit::inline_math_mathExact(Node* math, Node* test) { + if (builtin_throw_too_many_traps(Deoptimization::Reason_intrinsic, + env()->ArithmeticException_instance())) { + // It has been already too many times, but we cannot use builtin_throw (e.g. we care about backtraces), + // so let's bail out intrinsic rather than risking deopting again. + return false; + } + Node* bol = _gvn.transform( new BoolNode(test, BoolTest::overflow) ); IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); Node* fast_path = _gvn.transform( new IfFalseNode(check)); @@ -2017,12 +2024,14 @@ void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) { set_control(slow_path); set_i_o(i_o()); - uncommon_trap(Deoptimization::Reason_intrinsic, - Deoptimization::Action_none); + builtin_throw(Deoptimization::Reason_intrinsic, + env()->ArithmeticException_instance(), + /*allow_too_many_traps*/ false); } set_control(fast_path); set_result(math); + return true; } template @@ -2032,8 +2041,7 @@ bool LibraryCallKit::inline_math_overflow(Node* arg1, Node* arg2) { MathOp* mathOp = new MathOp(arg1, arg2); Node* operation = _gvn.transform( mathOp ); Node* ofcheck = _gvn.transform( new OverflowOp(arg1, arg2) ); - inline_math_mathExact(operation, ofcheck); - return true; + return inline_math_mathExact(operation, ofcheck); } bool LibraryCallKit::inline_math_addExactI(bool is_increment) { diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index 1f83e28932b..ad1ce71c374 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -209,7 +209,7 @@ class LibraryCallKit : public GraphKit { bool inline_math_pow(); template bool inline_math_overflow(Node* arg1, Node* arg2); - void inline_math_mathExact(Node* math, Node* test); + bool inline_math_mathExact(Node* math, Node* test); bool inline_math_addExactI(bool is_increment); bool inline_math_addExactL(bool is_increment); bool inline_math_multiplyExactI(); diff --git a/test/hotspot/jtreg/compiler/intrinsics/mathexact/OverflowTest.java b/test/hotspot/jtreg/compiler/intrinsics/mathexact/OverflowTest.java new file mode 100644 index 00000000000..eba6686ee47 --- /dev/null +++ b/test/hotspot/jtreg/compiler/intrinsics/mathexact/OverflowTest.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Math.*Exact intrinsics, especially in case of overflow + * The base case + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:+WhiteBoxAPI + * -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.mathexact.OverflowTest::comp_* + * -XX:CompileCommand=dontinline,compiler.intrinsics.mathexact.OverflowTest::* + * compiler.intrinsics.mathexact.OverflowTest + */ + +/* + * @test + * @summary Math.*Exact intrinsics, especially in case of overflow + * With ProfileTraps enabled to allow builtin_throw to work + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:+WhiteBoxAPI + * -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.mathexact.OverflowTest::comp_* + * -XX:CompileCommand=dontinline,compiler.intrinsics.mathexact.OverflowTest::* + * -XX:+ProfileTraps -XX:+StackTraceInThrowable -XX:+OmitStackTraceInFastThrow + * compiler.intrinsics.mathexact.OverflowTest + */ + +/* + * @test + * @summary Math.*Exact intrinsics, especially in case of overflow + * ProfileTraps off => throw will never be hot for builtin_throw + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:+WhiteBoxAPI + * -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.mathexact.OverflowTest::comp_* + * -XX:CompileCommand=dontinline,compiler.intrinsics.mathexact.OverflowTest::* + * -XX:-ProfileTraps + * compiler.intrinsics.mathexact.OverflowTest + */ + +/* + * @test + * @summary Math.*Exact intrinsics, especially in case of overflow + * OmitStackTraceInFastThrow off => can_omit_stack_trace is false => no builtin_throw + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:+WhiteBoxAPI + * -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.mathexact.OverflowTest::comp_* + * -XX:CompileCommand=dontinline,compiler.intrinsics.mathexact.OverflowTest::* + * -XX:+ProfileTraps -XX:+StackTraceInThrowable -XX:-OmitStackTraceInFastThrow + * compiler.intrinsics.mathexact.OverflowTest + */ + +/* + * @test + * @summary Math.*Exact intrinsics, especially in case of overflow + * StackTraceInThrowable off => can_omit_stack_trace is true => yes builtin_throw + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:+WhiteBoxAPI + * -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.mathexact.OverflowTest::comp_* + * -XX:CompileCommand=dontinline,compiler.intrinsics.mathexact.OverflowTest::* + * -XX:+ProfileTraps -XX:-StackTraceInThrowable -XX:+OmitStackTraceInFastThrow + * compiler.intrinsics.mathexact.OverflowTest + */ + +/* + * @test + * @summary Math.*Exact intrinsics, especially in case of overflow + * StackTraceInThrowable off && OmitStackTraceInFastThrow off => can_omit_stack_trace is true => yes builtin_throw + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:+WhiteBoxAPI + * -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.mathexact.OverflowTest::comp_* + * -XX:CompileCommand=dontinline,compiler.intrinsics.mathexact.OverflowTest::* + * -XX:+ProfileTraps -XX:-StackTraceInThrowable -XX:-OmitStackTraceInFastThrow + * compiler.intrinsics.mathexact.OverflowTest + */ + +/* + * @test + * @summary Math.*Exact intrinsics, especially in case of overflow + * Without intrinsics + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:+WhiteBoxAPI + * -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.intrinsics.mathexact.OverflowTest::comp_* + * -XX:CompileCommand=dontinline,compiler.intrinsics.mathexact.OverflowTest::* + * -XX:DisableIntrinsic=_addExactI,_incrementExactI,_addExactL,_incrementExactL,_subtractExactI,_decrementExactI,_subtractExactL,_decrementExactL,_negateExactI,_negateExactL,_multiplyExactI,_multiplyExactL + * compiler.intrinsics.mathexact.OverflowTest + */ + +package compiler.intrinsics.mathexact; + +import java.lang.reflect.Method; + +import compiler.lib.generators.RestrictableGenerator; +import jdk.test.lib.Asserts; +import jdk.test.whitebox.WhiteBox; + +import static compiler.lib.generators.Generators.G; + +public class OverflowTest { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final RestrictableGenerator int_gen = G.ints(); + private static final int LIMIT = 10_000; + + public static void main(String... args) throws NoSuchMethodException { + OverflowTest t = new OverflowTest(); + t.run(); + } + + void run() throws NoSuchMethodException { + check_compilation(); + check_multiplyI(); + } + + void check_compilation() throws NoSuchMethodException { + // Force Math loading + Math.min(2, 3); + comp_multiplyI(0, 0); + comp_multiplyI_no_catch(0, 0); + int_multiplyI(0, 0); + + Method comp_multiplyI_meth = OverflowTest.class.getDeclaredMethod("comp_multiplyI", int.class, int.class); + Asserts.assertTrue(WHITE_BOX.isMethodCompiled(comp_multiplyI_meth), "comp_multiplyI(int, int) is not compiled"); + + Method comp_multiplyI_no_catch_meth = OverflowTest.class.getDeclaredMethod("comp_multiplyI_no_catch", int.class, int.class); + Asserts.assertTrue(WHITE_BOX.isMethodCompiled(comp_multiplyI_no_catch_meth), "comp_multiplyI_no_catch(int, int) is not compiled"); + + Method int_multiplyI_meth = OverflowTest.class.getDeclaredMethod("int_multiplyI", int.class, int.class); + Asserts.assertFalse(WHITE_BOX.isMethodCompiled(int_multiplyI_meth), "int_multiplyI(int, int) is compiled"); + } + + void assert_consistent(Integer comp_res, Integer int_res) { + if (int_res == null) { + Asserts.assertNull(comp_res); + } else { + Asserts.assertNotNull(comp_res); + Asserts.assertEquals(comp_res, int_res); + } + } + + Integer comp_multiplyI(int a, int b) { + try { + return Math.multiplyExact(a, b); + } catch (ArithmeticException e) { + return null; + } + } + + int comp_multiplyI_no_catch(int a, int b) { + return Math.multiplyExact(a, b); + } + + Integer int_multiplyI(int a, int b) { + try { + return Math.multiplyExact(a, b); + } catch (ArithmeticException e) { + return null; + } + } + + void check_multiplyI() { + // 46_340 < 2 ^ 15.5 < 46_341 => + // 46_340^2 < 2 ^ 31 < 46_341^2 + int limit_square_do_not_overflow = 46_340; + + // In bound cases + for (int i = 0; i < LIMIT; i++) { + int a = limit_square_do_not_overflow - i; + Integer comp_res = comp_multiplyI(a, a); + Integer int_res = int_multiplyI(a, a); + Asserts.assertNotNull(int_res); + assert_consistent(comp_res, int_res); + } + for (int i = 0; i < LIMIT; i++) { + int a = limit_square_do_not_overflow - i; + Integer comp_res; + try { + comp_res = comp_multiplyI_no_catch(a, a); + } catch (ArithmeticException _) { + comp_res = null; + } + Integer int_res = int_multiplyI(a, a); + Asserts.assertNotNull(int_res); + assert_consistent(comp_res, int_res); + } + + // Out of bound cases + for (int i = 0; i < LIMIT; i++) { + int a = limit_square_do_not_overflow + 1 + i; + Integer comp_res = comp_multiplyI(a, a); + Integer int_res = int_multiplyI(a, a); + Asserts.assertNull(int_res); + assert_consistent(comp_res, int_res); + } + for (int i = 0; i < LIMIT; i++) { + int a = limit_square_do_not_overflow + 1 + i; + Integer comp_res; + try { + comp_res = comp_multiplyI_no_catch(a, a); + } catch (ArithmeticException _) { + comp_res = null; + } + Integer int_res = int_multiplyI(a, a); + Asserts.assertNull(int_res); + assert_consistent(comp_res, int_res); + } + + // Random slice + int lhs = int_gen.next(); + int rhs_start = int_gen.next() & 0xff_ff_00_00; + for (int i = 0; i < 0x1_00_00; i++) { + int rhs = rhs_start | i; + Integer comp_res = comp_multiplyI(lhs, rhs); + Integer int_res = int_multiplyI(lhs, rhs); + assert_consistent(comp_res, int_res); + } + for (int i = 0; i < 0x1_00_00; i++) { + int rhs = rhs_start | i; + Integer comp_res; + try { + comp_res = comp_multiplyI_no_catch(lhs, rhs); + } catch (ArithmeticException _) { + comp_res = null; + } + Integer int_res = int_multiplyI(lhs, rhs); + assert_consistent(comp_res, int_res); + } + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/MathExact.java b/test/micro/org/openjdk/bench/vm/compiler/MathExact.java new file mode 100644 index 00000000000..5558af08722 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/MathExact.java @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.*; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.MILLISECONDS) +public abstract class MathExact { + @Param({"1000000"}) + public int SIZE; + + + // === multiplyExact(int, int) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int testMultiplyI(int i) { + try { + return Math.multiplyExact(i, i); + } catch (ArithmeticException e) { + return 0; + } + } + + @Benchmark + public void loopMultiplyIOverflow() { + for (int i = 0; i < SIZE; i++) { + testMultiplyI(i); + } + } + + @Benchmark + public void loopMultiplyIInBounds() { + for (int i = 0; i < SIZE; i++) { + // 46_340 < 2 ^ 15.5 (< 46_341, but that's not important) + // so + // 46_340 ^ 2 < 2 ^ 31 + testMultiplyI(i % 46_341); + } + } + + + // === multiplyExact(long, long) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long testMultiplyL(long i) { + try { + return Math.multiplyExact(i, i); + } catch (ArithmeticException e) { + return 0L; + } + } + + @Benchmark + public void loopMultiplyLOverflow() { + for (long i = 0L; i < (long)SIZE; i++) { + // (2 ^ 63 - 1)^0.5 ~= 3_037_000_499.9761 + // Starting at 3_037_000_000 so that almost all computations overflow + testMultiplyL(3_037_000_000L + i); + } + } + + @Benchmark + public void loopMultiplyLInBounds() { + for (long i = 0L; i < (long)SIZE; i++) { + testMultiplyL(i); + } + } + + + // === negateExact(int) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int testNegateI(int i) { + try { + return Math.negateExact(i); + } catch (ArithmeticException e) { + return 0; + } + } + + @Benchmark + public void loopNegateIOverflow() { + for (int i = 0; i < SIZE; i++) { + testNegateI(i); + } + for (int i = 0; i < SIZE; i++) { + testNegateI(Integer.MIN_VALUE); + } + } + + @Benchmark + public void loopNegateIInBounds() { + for (int i = 0; i < SIZE; i++) { + testNegateI(i); + } + for (int i = 0; i < SIZE; i++) { + testNegateI(Integer.MAX_VALUE); + } + } + + + // === negateExact(long) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long testNegateL(long i) { + try { + return Math.negateExact(i); + } catch (ArithmeticException e) { + return 0L; + } + } + + @Benchmark + public void loopNegateLOverflow() { + for (long i = 0L; i < (long)SIZE; i++) { + testNegateL(i); + } + for (long i = 0L; i < (long)SIZE; i++) { + testNegateL(Long.MIN_VALUE); + } + } + + @Benchmark + public void loopNegateLInBounds() { + for (long i = 0L; i < (long)SIZE; i++) { + testNegateL(i); + } + for (long i = 0L; i < (long)SIZE; i++) { + testNegateL(Long.MAX_VALUE); + } + } + + + // === incrementExact(int) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int testIncrementI(int i) { + try { + return Math.incrementExact(i); + } catch (ArithmeticException e) { + return 0; + } + } + + @Benchmark + public void loopIncrementIOverflow() { + for (int i = 0; i < SIZE; i++) { + testIncrementI(i); + } + for (int i = 0; i < SIZE; i++) { + testIncrementI(Integer.MAX_VALUE); + } + } + + @Benchmark + public void loopIncrementIInBounds() { + for (int i = 0; i < SIZE; i++) { + testIncrementI(i); + } + for (int i = 0; i < SIZE; i++) { + testIncrementI(Integer.MIN_VALUE + i); + } + } + + + // === incrementExact(long) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long testIncrementL(long i) { + try { + return Math.incrementExact(i); + } catch (ArithmeticException e) { + return 0L; + } + } + + @Benchmark + public void loopIncrementLOverflow() { + for (long i = 0L; i < (long)SIZE; i++) { + testIncrementL(i); + } + for (long i = 0L; i < (long)SIZE; i++) { + testIncrementL(Long.MAX_VALUE); + } + } + + @Benchmark + public void loopIncrementLInBounds() { + for (long i = 0L; i < (long)SIZE; i++) { + testIncrementL(i); + } + for (long i = 0L; i < (long)SIZE; i++) { + testIncrementL(Long.MIN_VALUE + i); + } + } + + + // === decrementExact(int) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int testDecrementI(int i) { + try { + return Math.decrementExact(i); + } catch (ArithmeticException e) { + return 0; + } + } + + @Benchmark + public void loopDecrementIOverflow() { + for (int i = 0; i < SIZE; i++) { + testDecrementI(i); + } + for (int i = 0; i < SIZE; i++) { + testDecrementI(Integer.MIN_VALUE); + } + } + + @Benchmark + public void loopDecrementIInBounds() { + for (int i = 0; i < SIZE; i++) { + testDecrementI(i); + } + for (int i = 0; i < SIZE; i++) { + testDecrementI(Integer.MAX_VALUE - i); + } + } + + + // === decrementExact(long) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long testDecrementL(long i) { + try { + return Math.decrementExact(i); + } catch (ArithmeticException e) { + return 0L; + } + } + + @Benchmark + public void loopDecrementLOverflow() { + for (long i = 0L; i < (long)SIZE; i++) { + testDecrementL(i); + } + for (long i = 0L; i < (long)SIZE; i++) { + testDecrementL(Long.MIN_VALUE); + } + } + + @Benchmark + public void loopDecrementLInBounds() { + for (long i = 0L; i < (long)SIZE; i++) { + testDecrementL(i); + } + for (long i = 0L; i < (long)SIZE; i++) { + testDecrementL(Long.MAX_VALUE - i); + } + } + + + // === addExact(int) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int testAddI(int l, int r) { + try { + return Math.addExact(l, r); + } catch (ArithmeticException e) { + return 0; + } + } + + @Benchmark + public void loopAddIOverflow() { + for (int i = 0; i < SIZE; i++) { + testAddI(Integer.MAX_VALUE - 1_000, i); + } + } + + @Benchmark + public void loopAddIInBounds() { + for (int i = 0; i < SIZE; i++) { + testAddI(i * 5, i); + } + } + + + // === addExact(long) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long testAddL(long l, long r) { + try { + return Math.addExact(l, r); + } catch (ArithmeticException e) { + return 0L; + } + } + + @Benchmark + public void loopAddLOverflow() { + for (long i = 0L; i < (long)SIZE; i++) { + testAddL(Long.MAX_VALUE - 1_000L, i); + } + } + + @Benchmark + public void loopAddLInBounds() { + for (long i = 0L; i < (long)SIZE; i++) { + testAddL(i * 5L, i); + } + } + + + // === subtractExact(int) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int testSubtractI(int l, int r) { + try { + return Math.subtractExact(l, r); + } catch (ArithmeticException e) { + return 0; + } + } + + @Benchmark + public void loopSubtractIOverflow() { + for (int i = 0; i < SIZE; i++) { + testSubtractI(Integer.MIN_VALUE + 1_000, i); + } + } + + @Benchmark + public void loopSubtractIInBounds() { + for (int i = 0; i < SIZE; i++) { + testSubtractI(i * 5, i); + } + } + + + // === subtractExact(long) === + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long testSubtractL(long l, long r) { + try { + return Math.subtractExact(l, r); + } catch (ArithmeticException e) { + return 0L; + } + } + + @Benchmark + public void loopSubtractLOverflow() { + for (long i = 0L; i < (long)SIZE; i++) { + testSubtractL(Long.MIN_VALUE + 1_000L, i); + } + } + + @Benchmark + public void loopSubtractLInBounds() { + for (long i = 0L; i < (long)SIZE; i++) { + testSubtractL(i * 5L, i); + } + } + + + + @Fork(value = 1, jvmArgs = {"-XX:TieredStopAtLevel=1"}) + public static class C1_1 extends MathExact {} + + @Fork(value = 1, jvmArgs = {"-XX:TieredStopAtLevel=2"}) + public static class C1_2 extends MathExact {} + + @Fork(value = 1, jvmArgs = {"-XX:TieredStopAtLevel=3"}) + public static class C1_3 extends MathExact {} + + @Fork(value = 1) + public static class C2 extends MathExact {} + + @Fork(value = 1, + jvmArgs = { + "-XX:+UnlockDiagnosticVMOptions", + "-XX:DisableIntrinsic=_addExactI,_incrementExactI,_addExactL,_incrementExactL,_subtractExactI,_decrementExactI,_subtractExactL,_decrementExactL,_negateExactI,_negateExactL,_multiplyExactI,_multiplyExactL", + }) + public static class C2_no_intrinsics extends MathExact {} + + @Fork(value = 1, jvmArgs = {"-XX:-OmitStackTraceInFastThrow"}) + public static class C2_no_builtin_throw extends MathExact {} +} From 6d9ece73a96dd32fccf4a740205407a76dcd907a Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Mon, 7 Apr 2025 07:09:51 +0000 Subject: [PATCH 004/843] 8351949: RISC-V: Cleanup and enable store-load peephole for membars Reviewed-by: fyang, fjiang, mli --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 4 +- .../cpu/riscv/macroAssembler_riscv.cpp | 24 ++- .../cpu/riscv/macroAssembler_riscv.hpp | 32 ++-- src/hotspot/cpu/riscv/riscv.ad | 164 +++++++++++------- 4 files changed, 134 insertions(+), 90 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 3c19673f1e7..e036cb6b1ec 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -815,7 +815,7 @@ protected: emit(insn); } - public: + protected: enum barrier { i = 0b1000, o = 0b0100, r = 0b0010, w = 0b0001, @@ -846,6 +846,8 @@ protected: emit(insn); } + public: + #define INSN(NAME, op, funct3, funct7) \ void NAME() { \ unsigned insn = 0; \ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 1916fbdeb18..71481565fc7 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -183,7 +183,6 @@ void MacroAssembler::set_membar_kind(address addr, uint32_t order_kind) { Assembler::sd_instr(membar, insn); } - static void pass_arg0(MacroAssembler* masm, Register arg) { if (c_rarg0 != arg) { masm->mv(c_rarg0, arg); @@ -3556,6 +3555,14 @@ void MacroAssembler::lookup_virtual_method(Register recv_klass, } void MacroAssembler::membar(uint32_t order_constraint) { + if (UseZtso && ((order_constraint & StoreLoad) != StoreLoad)) { + // TSO allows for stores to be reordered after loads. When the compiler + // generates a fence to disallow that, we are required to generate the + // fence for correctness. + BLOCK_COMMENT("elided tso membar"); + return; + } + address prev = pc() - MacroAssembler::instruction_size; address last = code()->last_insn(); @@ -3564,15 +3571,14 @@ void MacroAssembler::membar(uint32_t order_constraint) { // can do this simply by ORing them together. set_membar_kind(prev, get_membar_kind(prev) | order_constraint); BLOCK_COMMENT("merged membar"); - } else { - code()->set_last_insn(pc()); - - uint32_t predecessor = 0; - uint32_t successor = 0; - - membar_mask_to_pred_succ(order_constraint, predecessor, successor); - fence(predecessor, successor); + return; } + + code()->set_last_insn(pc()); + uint32_t predecessor = 0; + uint32_t successor = 0; + membar_mask_to_pred_succ(order_constraint, predecessor, successor); + fence(predecessor, successor); } void MacroAssembler::cmodx_fence() { diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 5d36a5f6fcd..153b6d77f99 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -417,15 +417,17 @@ class MacroAssembler: public Assembler { // We used four bit to indicate the read and write bits in the predecessors and successors, // and extended i for r, o for w if UseConservativeFence enabled. enum Membar_mask_bits { - StoreStore = 0b0101, // (pred = ow + succ = ow) - LoadStore = 0b1001, // (pred = ir + succ = ow) - StoreLoad = 0b0110, // (pred = ow + succ = ir) - LoadLoad = 0b1010, // (pred = ir + succ = ir) - AnyAny = LoadStore | StoreLoad // (pred = iorw + succ = iorw) + StoreStore = 0b0101, // (pred = w + succ = w) + LoadStore = 0b1001, // (pred = r + succ = w) + StoreLoad = 0b0110, // (pred = w + succ = r) + LoadLoad = 0b1010, // (pred = r + succ = r) + AnyAny = LoadStore | StoreLoad // (pred = rw + succ = rw) }; void membar(uint32_t order_constraint); + private: + static void membar_mask_to_pred_succ(uint32_t order_constraint, uint32_t& predecessor, uint32_t& successor) { predecessor = (order_constraint >> 2) & 0x3; @@ -437,7 +439,7 @@ class MacroAssembler: public Assembler { // 11(rw)-> 1111(iorw) if (UseConservativeFence) { predecessor |= predecessor << 2; - successor |= successor << 2; + successor |= successor << 2; } } @@ -445,25 +447,13 @@ class MacroAssembler: public Assembler { return ((predecessor & 0x3) << 2) | (successor & 0x3); } - void fence(uint32_t predecessor, uint32_t successor) { - if (UseZtso) { - if ((pred_succ_to_membar_mask(predecessor, successor) & StoreLoad) == StoreLoad) { - // TSO allows for stores to be reordered after loads. When the compiler - // generates a fence to disallow that, we are required to generate the - // fence for correctness. - Assembler::fence(predecessor, successor); - } else { - // TSO guarantees other fences already. - } - } else { - // always generate fence for RVWMO - Assembler::fence(predecessor, successor); - } - } + public: void cmodx_fence(); void pause() { + // Zihintpause + // PAUSE is encoded as a FENCE instruction with pred=W, succ=0, fm=0, rd=x0, and rs1=x0. Assembler::fence(w, 0); } diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 59171d84c9b..4ebfdf9f16c 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -4397,6 +4397,12 @@ pipe_class pipe_slow() LDST : MEM; %} +// The real do-nothing guy +pipe_class real_empty() +%{ + instruction_count(0); +%} + // Empty pipeline class pipe_class pipe_class_empty() %{ @@ -7902,78 +7908,102 @@ instruct xorL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{ // ============================================================================ // MemBar Instruction -instruct load_fence() %{ +// RVTSO + +instruct unnecessary_membar_rvtso() %{ + predicate(UseZtso); match(LoadFence); - ins_cost(ALU_COST); - - format %{ "#@load_fence" %} - - ins_encode %{ - __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); - %} - ins_pipe(pipe_serial); -%} - -instruct membar_acquire() %{ + match(StoreFence); + match(StoreStoreFence); match(MemBarAcquire); - ins_cost(ALU_COST); - - format %{ "#@membar_acquire\n\t" - "fence ir iorw" %} - - ins_encode %{ - __ block_comment("membar_acquire"); - __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); - %} - - ins_pipe(pipe_serial); -%} - -instruct membar_acquire_lock() %{ + match(MemBarRelease); + match(MemBarStoreStore); match(MemBarAcquireLock); + match(MemBarReleaseLock); + ins_cost(0); - format %{ "#@membar_acquire_lock (elided)" %} + size(0); + + format %{ "#@unnecessary_membar_rvtso elided/tso (empty encoding)" %} + ins_encode %{ + __ block_comment("unnecessary_membar_rvtso"); + %} + ins_pipe(real_empty); +%} + +instruct membar_volatile_rvtso() %{ + predicate(UseZtso); + match(MemBarVolatile); + ins_cost(VOLATILE_REF_COST); + + format %{ "#@membar_volatile_rvtso\n\t" + "fence w, r"%} ins_encode %{ - __ block_comment("membar_acquire_lock (elided)"); + __ block_comment("membar_volatile_rvtso"); + __ membar(MacroAssembler::StoreLoad); %} + ins_pipe(pipe_slow); +%} + +instruct unnecessary_membar_volatile_rvtso() %{ + predicate(UseZtso && Matcher::post_store_load_barrier(n)); + match(MemBarVolatile); + ins_cost(0); + + size(0); + + format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %} + ins_encode %{ + __ block_comment("unnecessary_membar_volatile_rvtso"); + %} + ins_pipe(real_empty); +%} + +// RVWMO + +instruct membar_aqcuire_rvwmo() %{ + predicate(!UseZtso); + match(LoadFence); + match(MemBarAcquire); + ins_cost(VOLATILE_REF_COST); + + format %{ "#@membar_aqcuire_rvwmo\n\t" + "fence r, rw" %} + + ins_encode %{ + __ block_comment("membar_aqcuire_rvwmo"); + __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); + %} ins_pipe(pipe_serial); %} -instruct store_fence() %{ +instruct membar_release_rvwmo() %{ + predicate(!UseZtso); match(StoreFence); - ins_cost(ALU_COST); - - format %{ "#@store_fence" %} - - ins_encode %{ - __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); - %} - ins_pipe(pipe_serial); -%} - -instruct membar_release() %{ match(MemBarRelease); - ins_cost(ALU_COST); + ins_cost(VOLATILE_REF_COST); - format %{ "#@membar_release\n\t" - "fence iorw ow" %} + format %{ "#@membar_release_rvwmo\n\t" + "fence rw, w" %} ins_encode %{ - __ block_comment("membar_release"); + __ block_comment("membar_release_rvwmo"); __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); %} ins_pipe(pipe_serial); %} -instruct membar_storestore() %{ +instruct membar_storestore_rvwmo() %{ + predicate(!UseZtso); match(MemBarStoreStore); match(StoreStoreFence); - ins_cost(ALU_COST); + ins_cost(VOLATILE_REF_COST); - format %{ "MEMBAR-store-store\t#@membar_storestore" %} + format %{ "#@membar_storestore_rvwmo\n\t" + "fence w, w" %} ins_encode %{ __ membar(MacroAssembler::StoreStore); @@ -7981,34 +8011,50 @@ instruct membar_storestore() %{ ins_pipe(pipe_serial); %} -instruct membar_release_lock() %{ - match(MemBarReleaseLock); - ins_cost(0); +instruct membar_volatile_rvwmo() %{ + predicate(!UseZtso); + match(MemBarVolatile); + ins_cost(VOLATILE_REF_COST); - format %{ "#@membar_release_lock (elided)" %} + format %{ "#@membar_volatile_rvwmo\n\t" + "fence w, r"%} ins_encode %{ - __ block_comment("membar_release_lock (elided)"); + __ block_comment("membar_volatile_rvwmo"); + __ membar(MacroAssembler::StoreLoad); %} ins_pipe(pipe_serial); %} -instruct membar_volatile() %{ - match(MemBarVolatile); - ins_cost(ALU_COST); +instruct membar_lock_rvwmo() %{ + predicate(!UseZtso); + match(MemBarAcquireLock); + match(MemBarReleaseLock); + ins_cost(0); - format %{ "#@membar_volatile\n\t" - "fence iorw iorw"%} + format %{ "#@membar_lock_rvwmo (elided)" %} ins_encode %{ - __ block_comment("membar_volatile"); - __ membar(MacroAssembler::StoreLoad); + __ block_comment("membar_lock_rvwmo (elided)"); %} ins_pipe(pipe_serial); %} +instruct unnecessary_membar_volatile_rvwmo() %{ + predicate(!UseZtso && Matcher::post_store_load_barrier(n)); + match(MemBarVolatile); + ins_cost(0); + + size(0); + format %{ "#@unnecessary_membar_volatile_rvwmo (unnecessary so empty encoding)" %} + ins_encode %{ + __ block_comment("unnecessary_membar_volatile_rvwmo"); + %} + ins_pipe(real_empty); +%} + instruct spin_wait() %{ predicate(UseZihintpause); match(OnSpinWait); From 6abf4e6d4d9f948b8ae51aec731b94ba7acd022e Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Mon, 7 Apr 2025 07:14:32 +0000 Subject: [PATCH 005/843] 8353568: SEGV_BNDERR signal code adjust definition Reviewed-by: stuefe --- src/hotspot/os/posix/signals_posix.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 5f5a2ccfa4a..555ac832aae 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -49,8 +49,12 @@ #include -#if !defined(SEGV_BNDERR) -#define SEGV_BNDERR 3 +#define SEGV_BNDERR_value 3 + +#if defined(SEGV_BNDERR) +STATIC_ASSERT(SEGV_BNDERR == SEGV_BNDERR_value); +#else +#define SEGV_BNDERR SEGV_BNDERR_value #endif static const char* get_signal_name(int sig, char* out, size_t outlen); From d1e91fcd620ce7e5527363dfa44543872f419c73 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Mon, 7 Apr 2025 07:21:15 +0000 Subject: [PATCH 006/843] 8353344: RISC-V: Detect and enable several extensions for debug builds Reviewed-by: mli, fjiang, rehn --- .../os_cpu/linux_riscv/riscv_hwprobe.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index 5b427693a8d..8572d54716b 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -187,18 +187,43 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBS)) { VM_Version::ext_Zbs.enable_feature(); } +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBKB)) { + VM_Version::ext_Zbkb.enable_feature(); + } +#endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFH)) { VM_Version::ext_Zfh.enable_feature(); } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFHMIN)) { VM_Version::ext_Zfhmin.enable_feature(); } +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVBB)) { + VM_Version::ext_Zvbb.enable_feature(); + } +#endif +#ifndef PRODUCT if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVBC)) { VM_Version::ext_Zvbc.enable_feature(); } +#endif +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNED) && + is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNHB) && + is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKB) && + is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKT)) { + VM_Version::ext_Zvkn.enable_feature(); + } +#endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVFH)) { VM_Version::ext_Zvfh.enable_feature(); } +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFA)) { + VM_Version::ext_Zfa.enable_feature(); + } +#endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) { VM_Version::ext_Zicond.enable_feature(); } From d63b561fffd42d76f14771c47951dd1d08efe3a7 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 7 Apr 2025 07:39:17 +0000 Subject: [PATCH 007/843] 8353188: C1: Clean up x86 backend after 32-bit x86 removal Reviewed-by: kvn, vlivanov --- src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp | 54 --- src/hotspot/cpu/x86/c1_Defs_x86.hpp | 12 +- src/hotspot/cpu/x86/c1_FrameMap_x86.cpp | 43 +- src/hotspot/cpu/x86/c1_FrameMap_x86.hpp | 18 - src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 450 +----------------- src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp | 4 +- src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp | 190 +------- src/hotspot/cpu/x86/c1_LIR_x86.cpp | 7 - src/hotspot/cpu/x86/c1_LinearScan_x86.hpp | 12 - src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 26 +- src/hotspot/cpu/x86/c1_Runtime1_x86.cpp | 308 +----------- 11 files changed, 45 insertions(+), 1079 deletions(-) diff --git a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp index 80365878061..73262b21365 100644 --- a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp +++ b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp @@ -37,66 +37,12 @@ #define __ ce->masm()-> -#ifndef _LP64 -float ConversionStub::float_zero = 0.0; -double ConversionStub::double_zero = 0.0; - -void ConversionStub::emit_code(LIR_Assembler* ce) { - __ bind(_entry); - assert(bytecode() == Bytecodes::_f2i || bytecode() == Bytecodes::_d2i, "other conversions do not require stub"); - - - if (input()->is_single_xmm()) { - __ comiss(input()->as_xmm_float_reg(), - ExternalAddress((address)&float_zero)); - } else if (input()->is_double_xmm()) { - __ comisd(input()->as_xmm_double_reg(), - ExternalAddress((address)&double_zero)); - } else { - __ push(rax); - __ ftst(); - __ fnstsw_ax(); - __ sahf(); - __ pop(rax); - } - - Label NaN, do_return; - __ jccb(Assembler::parity, NaN); - __ jccb(Assembler::below, do_return); - - // input is > 0 -> return maxInt - // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff - __ decrement(result()->as_register()); - __ jmpb(do_return); - - // input is NaN -> return 0 - __ bind(NaN); - __ xorptr(result()->as_register(), result()->as_register()); - - __ bind(do_return); - __ jmp(_continuation); -} -#endif // !_LP64 - void C1SafepointPollStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); InternalAddress safepoint_pc(ce->masm()->pc() - ce->masm()->offset() + safepoint_offset()); -#ifdef _LP64 __ lea(rscratch1, safepoint_pc); __ movptr(Address(r15_thread, JavaThread::saved_exception_pc_offset()), rscratch1); -#else - const Register tmp1 = rcx; - const Register tmp2 = rdx; - __ push(tmp1); - __ push(tmp2); - __ lea(tmp1, safepoint_pc); - __ get_thread(tmp2); - __ movptr(Address(tmp2, JavaThread::saved_exception_pc_offset()), tmp1); - - __ pop(tmp2); - __ pop(tmp1); -#endif /* _LP64 */ assert(SharedRuntime::polling_page_return_handler_blob() != nullptr, "polling page return stub not created yet"); diff --git a/src/hotspot/cpu/x86/c1_Defs_x86.hpp b/src/hotspot/cpu/x86/c1_Defs_x86.hpp index 1637789e798..bfb885a1b73 100644 --- a/src/hotspot/cpu/x86/c1_Defs_x86.hpp +++ b/src/hotspot/cpu/x86/c1_Defs_x86.hpp @@ -33,15 +33,11 @@ enum { // registers enum { - pd_nof_cpu_regs_frame_map = NOT_LP64(8) LP64_ONLY(16), // number of registers used during code emission + pd_nof_cpu_regs_frame_map = 16, // number of registers used during code emission pd_nof_fpu_regs_frame_map = FloatRegister::number_of_registers, // number of registers used during code emission pd_nof_xmm_regs_frame_map = XMMRegister::number_of_registers, // number of registers used during code emission -#ifdef _LP64 #define UNALLOCATED 4 // rsp, rbp, r15, r10 -#else - #define UNALLOCATED 2 // rsp, rbp -#endif // LP64 pd_nof_caller_save_cpu_regs_frame_map = pd_nof_cpu_regs_frame_map - UNALLOCATED, // number of registers killed by calls pd_nof_caller_save_fpu_regs_frame_map = pd_nof_fpu_regs_frame_map, // number of registers killed by calls @@ -54,9 +50,9 @@ enum { pd_nof_fpu_regs_linearscan = pd_nof_fpu_regs_frame_map, // number of registers visible to linear scan pd_nof_xmm_regs_linearscan = pd_nof_xmm_regs_frame_map, // number of registers visible to linear scan pd_first_cpu_reg = 0, - pd_last_cpu_reg = NOT_LP64(5) LP64_ONLY(11), - pd_first_byte_reg = NOT_LP64(2) LP64_ONLY(0), - pd_last_byte_reg = NOT_LP64(5) LP64_ONLY(11), + pd_last_cpu_reg = 11, + pd_first_byte_reg = 0, + pd_last_byte_reg = 11, pd_first_fpu_reg = pd_nof_cpu_regs_frame_map, pd_last_fpu_reg = pd_first_fpu_reg + 7, pd_first_xmm_reg = pd_nof_cpu_regs_frame_map + pd_nof_fpu_regs_frame_map, diff --git a/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp b/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp index e3c78792602..bdbab432180 100644 --- a/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp +++ b/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp @@ -32,7 +32,6 @@ const int FrameMap::pd_c_runtime_reserved_arg_size = 0; LIR_Opr FrameMap::map_to_opr(BasicType type, VMRegPair* reg, bool) { LIR_Opr opr = LIR_OprFact::illegalOpr; VMReg r_1 = reg->first(); - VMReg r_2 = reg->second(); if (r_1->is_stack()) { // Convert stack slot to an SP offset // The calling convention does not count the SharedRuntime::out_preserve_stack_slots() value @@ -41,14 +40,8 @@ LIR_Opr FrameMap::map_to_opr(BasicType type, VMRegPair* reg, bool) { opr = LIR_OprFact::address(new LIR_Address(rsp_opr, st_off, type)); } else if (r_1->is_Register()) { Register reg = r_1->as_Register(); - if (r_2->is_Register() && (type == T_LONG || type == T_DOUBLE)) { - Register reg2 = r_2->as_Register(); -#ifdef _LP64 - assert(reg2 == reg, "must be same register"); + if (type == T_LONG || type == T_DOUBLE) { opr = as_long_opr(reg); -#else - opr = as_long_opr(reg2, reg); -#endif // _LP64 } else if (is_reference_type(type)) { opr = as_oop_opr(reg); } else if (type == T_METADATA) { @@ -111,8 +104,6 @@ LIR_Opr FrameMap::long1_opr; LIR_Opr FrameMap::xmm0_float_opr; LIR_Opr FrameMap::xmm0_double_opr; -#ifdef _LP64 - LIR_Opr FrameMap::r8_opr; LIR_Opr FrameMap::r9_opr; LIR_Opr FrameMap::r10_opr; @@ -137,7 +128,6 @@ LIR_Opr FrameMap::r11_metadata_opr; LIR_Opr FrameMap::r12_metadata_opr; LIR_Opr FrameMap::r13_metadata_opr; LIR_Opr FrameMap::r14_metadata_opr; -#endif // _LP64 LIR_Opr FrameMap::_caller_save_cpu_regs[] = {}; LIR_Opr FrameMap::_caller_save_fpu_regs[] = {}; @@ -157,23 +147,17 @@ XMMRegister FrameMap::nr2xmmreg(int rnr) { void FrameMap::initialize() { assert(!_init_done, "once"); - assert(nof_cpu_regs == LP64_ONLY(16) NOT_LP64(8), "wrong number of CPU registers"); + assert(nof_cpu_regs == 16, "wrong number of CPU registers"); map_register(0, rsi); rsi_opr = LIR_OprFact::single_cpu(0); map_register(1, rdi); rdi_opr = LIR_OprFact::single_cpu(1); map_register(2, rbx); rbx_opr = LIR_OprFact::single_cpu(2); map_register(3, rax); rax_opr = LIR_OprFact::single_cpu(3); map_register(4, rdx); rdx_opr = LIR_OprFact::single_cpu(4); map_register(5, rcx); rcx_opr = LIR_OprFact::single_cpu(5); - -#ifndef _LP64 - // The unallocatable registers are at the end - map_register(6, rsp); - map_register(7, rbp); -#else - map_register( 6, r8); r8_opr = LIR_OprFact::single_cpu(6); - map_register( 7, r9); r9_opr = LIR_OprFact::single_cpu(7); - map_register( 8, r11); r11_opr = LIR_OprFact::single_cpu(8); - map_register( 9, r13); r13_opr = LIR_OprFact::single_cpu(9); + map_register(6, r8); r8_opr = LIR_OprFact::single_cpu(6); + map_register(7, r9); r9_opr = LIR_OprFact::single_cpu(7); + map_register(8, r11); r11_opr = LIR_OprFact::single_cpu(8); + map_register(9, r13); r13_opr = LIR_OprFact::single_cpu(9); map_register(10, r14); r14_opr = LIR_OprFact::single_cpu(10); // r12 is allocated conditionally. With compressed oops it holds // the heapbase value and is not visible to the allocator. @@ -183,15 +167,9 @@ void FrameMap::initialize() { map_register(13, r15); r15_opr = LIR_OprFact::single_cpu(13); map_register(14, rsp); map_register(15, rbp); -#endif // _LP64 -#ifdef _LP64 long0_opr = LIR_OprFact::double_cpu(3 /*eax*/, 3 /*eax*/); long1_opr = LIR_OprFact::double_cpu(2 /*ebx*/, 2 /*ebx*/); -#else - long0_opr = LIR_OprFact::double_cpu(3 /*eax*/, 4 /*edx*/); - long1_opr = LIR_OprFact::double_cpu(2 /*ebx*/, 5 /*ecx*/); -#endif // _LP64 xmm0_float_opr = LIR_OprFact::single_xmm(0); xmm0_double_opr = LIR_OprFact::double_xmm(0); @@ -201,16 +179,12 @@ void FrameMap::initialize() { _caller_save_cpu_regs[3] = rax_opr; _caller_save_cpu_regs[4] = rdx_opr; _caller_save_cpu_regs[5] = rcx_opr; - -#ifdef _LP64 _caller_save_cpu_regs[6] = r8_opr; _caller_save_cpu_regs[7] = r9_opr; _caller_save_cpu_regs[8] = r11_opr; _caller_save_cpu_regs[9] = r13_opr; _caller_save_cpu_regs[10] = r14_opr; _caller_save_cpu_regs[11] = r12_opr; -#endif // _LP64 - _xmm_regs[0] = xmm0; _xmm_regs[1] = xmm1; @@ -220,8 +194,6 @@ void FrameMap::initialize() { _xmm_regs[5] = xmm5; _xmm_regs[6] = xmm6; _xmm_regs[7] = xmm7; - -#ifdef _LP64 _xmm_regs[8] = xmm8; _xmm_regs[9] = xmm9; _xmm_regs[10] = xmm10; @@ -246,7 +218,6 @@ void FrameMap::initialize() { _xmm_regs[29] = xmm29; _xmm_regs[30] = xmm30; _xmm_regs[31] = xmm31; -#endif // _LP64 for (int i = 0; i < 8; i++) { _caller_save_fpu_regs[i] = LIR_OprFact::single_fpu(i); @@ -276,7 +247,6 @@ void FrameMap::initialize() { rsp_opr = as_pointer_opr(rsp); rbp_opr = as_pointer_opr(rbp); -#ifdef _LP64 r8_oop_opr = as_oop_opr(r8); r9_oop_opr = as_oop_opr(r9); r11_oop_opr = as_oop_opr(r11); @@ -290,7 +260,6 @@ void FrameMap::initialize() { r12_metadata_opr = as_metadata_opr(r12); r13_metadata_opr = as_metadata_opr(r13); r14_metadata_opr = as_metadata_opr(r14); -#endif // _LP64 VMRegPair regs; BasicType sig_bt = T_OBJECT; diff --git a/src/hotspot/cpu/x86/c1_FrameMap_x86.hpp b/src/hotspot/cpu/x86/c1_FrameMap_x86.hpp index ce892efbed2..08b872cb095 100644 --- a/src/hotspot/cpu/x86/c1_FrameMap_x86.hpp +++ b/src/hotspot/cpu/x86/c1_FrameMap_x86.hpp @@ -41,13 +41,8 @@ nof_xmm_regs = pd_nof_xmm_regs_frame_map, nof_caller_save_xmm_regs = pd_nof_caller_save_xmm_regs_frame_map, first_available_sp_in_frame = 0, -#ifndef _LP64 - frame_pad_in_bytes = 8, - nof_reg_args = 2 -#else frame_pad_in_bytes = 16, nof_reg_args = 6 -#endif // _LP64 }; private: @@ -81,8 +76,6 @@ static LIR_Opr rdx_metadata_opr; static LIR_Opr rcx_metadata_opr; -#ifdef _LP64 - static LIR_Opr r8_opr; static LIR_Opr r9_opr; static LIR_Opr r10_opr; @@ -108,28 +101,17 @@ static LIR_Opr r13_metadata_opr; static LIR_Opr r14_metadata_opr; -#endif // _LP64 - static LIR_Opr long0_opr; static LIR_Opr long1_opr; static LIR_Opr xmm0_float_opr; static LIR_Opr xmm0_double_opr; -#ifdef _LP64 static LIR_Opr as_long_opr(Register r) { return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); } static LIR_Opr as_pointer_opr(Register r) { return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); } -#else - static LIR_Opr as_long_opr(Register r, Register r2) { - return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r2)); - } - static LIR_Opr as_pointer_opr(Register r) { - return LIR_OprFact::single_cpu(cpu_reg2rnr(r)); - } -#endif // _LP64 // VMReg name for spilled physical FPU stack slot n static VMReg fpu_regname (int n); diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index ed16f81cba1..fa1bfaa71db 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -169,7 +169,6 @@ void LIR_Assembler::push(LIR_Opr opr) { if (opr->is_single_cpu()) { __ push_reg(opr->as_register()); } else if (opr->is_double_cpu()) { - NOT_LP64(__ push_reg(opr->as_register_hi())); __ push_reg(opr->as_register_lo()); } else if (opr->is_stack()) { __ push_addr(frame_map()->address_for_slot(opr->single_stack_ix())); @@ -325,11 +324,9 @@ void LIR_Assembler::clinit_barrier(ciMethod* method) { Label L_skip_barrier; Register klass = rscratch1; - Register thread = LP64_ONLY( r15_thread ) NOT_LP64( noreg ); - assert(thread != noreg, "x86_32 not implemented"); __ mov_metadata(klass, method->holder()->constant_encoding()); - __ clinit_barrier(klass, thread, &L_skip_barrier /*L_fast_path*/); + __ clinit_barrier(klass, r15_thread, &L_skip_barrier /*L_fast_path*/); __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); @@ -401,11 +398,9 @@ int LIR_Assembler::emit_unwind_handler() { int offset = code_offset(); // Fetch the exception from TLS and clear out exception related thread state - Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread); - NOT_LP64(__ get_thread(thread)); - __ movptr(rax, Address(thread, JavaThread::exception_oop_offset())); - __ movptr(Address(thread, JavaThread::exception_oop_offset()), NULL_WORD); - __ movptr(Address(thread, JavaThread::exception_pc_offset()), NULL_WORD); + __ movptr(rax, Address(r15_thread, JavaThread::exception_oop_offset())); + __ movptr(Address(r15_thread, JavaThread::exception_oop_offset()), NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::exception_pc_offset()), NULL_WORD); __ bind(_unwind_handler_entry); __ verify_not_null_oop(rax); @@ -427,14 +422,8 @@ int LIR_Assembler::emit_unwind_handler() { } if (compilation()->env()->dtrace_method_probes()) { -#ifdef _LP64 __ mov(rdi, r15_thread); __ mov_metadata(rsi, method()->constant_encoding()); -#else - __ get_thread(rax); - __ movptr(Address(rsp, 0), rax); - __ mov_metadata(Address(rsp, sizeof(void*)), method()->constant_encoding(), noreg); -#endif __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit))); } @@ -491,15 +480,9 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { // Note: we do not need to round double result; float result has the right precision // the poll sets the condition code, but no data registers -#ifdef _LP64 - const Register thread = r15_thread; -#else - const Register thread = rbx; - __ get_thread(thread); -#endif code_stub->set_safepoint_offset(__ offset()); __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub->entry(), thread, true /* at_return */, true /* in_nmethod */); + __ safepoint_poll(*code_stub->entry(), r15_thread, true /* at_return */, true /* in_nmethod */); __ ret(0); } @@ -507,21 +490,14 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { guarantee(info != nullptr, "Shouldn't be null"); int offset = __ offset(); -#ifdef _LP64 const Register poll_addr = rscratch1; __ movptr(poll_addr, Address(r15_thread, JavaThread::polling_page_offset())); -#else - assert(tmp->is_cpu_register(), "needed"); - const Register poll_addr = tmp->as_register(); - __ get_thread(poll_addr); - __ movptr(poll_addr, Address(poll_addr, in_bytes(JavaThread::polling_page_offset()))); -#endif add_debug_info_for_branch(info); __ relocate(relocInfo::poll_type); address pre_pc = __ pc(); __ testl(rax, Address(poll_addr, 0)); address post_pc = __ pc(); - guarantee(pointer_delta(post_pc, pre_pc, 1) == 2 LP64_ONLY(+1), "must be exact length"); + guarantee(pointer_delta(post_pc, pre_pc, 1) == 3, "must be exact length"); return offset; } @@ -555,12 +531,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod case T_LONG: { assert(patch_code == lir_patch_none, "no patching handled here"); -#ifdef _LP64 __ movptr(dest->as_register_lo(), (intptr_t)c->as_jlong()); -#else - __ movptr(dest->as_register_lo(), c->as_jint_lo()); - __ movptr(dest->as_register_hi(), c->as_jint_hi()); -#endif // _LP64 break; } @@ -636,17 +607,10 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { case T_LONG: // fall through case T_DOUBLE: -#ifdef _LP64 __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), lo_word_offset_in_bytes), (intptr_t)c->as_jlong_bits(), rscratch1); -#else - __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), - lo_word_offset_in_bytes), c->as_jint_lo_bits()); - __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), - hi_word_offset_in_bytes), c->as_jint_hi_bits()); -#endif // _LP64 break; default: @@ -677,20 +641,15 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi if (UseCompressedOops && !wide) { __ movl(as_Address(addr), NULL_WORD); } else { -#ifdef _LP64 __ xorptr(rscratch1, rscratch1); null_check_here = code_offset(); __ movptr(as_Address(addr), rscratch1); -#else - __ movptr(as_Address(addr), NULL_WORD); -#endif } } else { if (is_literal_address(addr)) { ShouldNotReachHere(); __ movoop(as_Address(addr, noreg), c->as_jobject(), rscratch1); } else { -#ifdef _LP64 __ movoop(rscratch1, c->as_jobject()); if (UseCompressedOops && !wide) { __ encode_heap_oop(rscratch1); @@ -700,16 +659,12 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi null_check_here = code_offset(); __ movptr(as_Address_lo(addr), rscratch1); } -#else - __ movoop(as_Address(addr), c->as_jobject(), noreg); -#endif } } break; case T_LONG: // fall through case T_DOUBLE: -#ifdef _LP64 if (is_literal_address(addr)) { ShouldNotReachHere(); __ movptr(as_Address(addr, r15_thread), (intptr_t)c->as_jlong_bits()); @@ -718,11 +673,6 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi null_check_here = code_offset(); __ movptr(as_Address_lo(addr), r10); } -#else - // Always reachable in 32bit so this doesn't produce useless move literal - __ movptr(as_Address_hi(addr), c->as_jint_hi_bits()); - __ movptr(as_Address_lo(addr), c->as_jint_lo_bits()); -#endif // _LP64 break; case T_BOOLEAN: // fall through @@ -751,13 +701,11 @@ void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { // move between cpu-registers if (dest->is_single_cpu()) { -#ifdef _LP64 if (src->type() == T_LONG) { // Can do LONG -> OBJECT move_regs(src->as_register_lo(), dest->as_register()); return; } -#endif assert(src->is_single_cpu(), "must match"); if (src->type() == T_OBJECT) { __ verify_oop(src->as_register()); @@ -765,39 +713,20 @@ void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { move_regs(src->as_register(), dest->as_register()); } else if (dest->is_double_cpu()) { -#ifdef _LP64 if (is_reference_type(src->type())) { // Surprising to me but we can see move of a long to t_object __ verify_oop(src->as_register()); move_regs(src->as_register(), dest->as_register_lo()); return; } -#endif assert(src->is_double_cpu(), "must match"); Register f_lo = src->as_register_lo(); Register f_hi = src->as_register_hi(); Register t_lo = dest->as_register_lo(); Register t_hi = dest->as_register_hi(); -#ifdef _LP64 assert(f_hi == f_lo, "must be same"); assert(t_hi == t_lo, "must be same"); move_regs(f_lo, t_lo); -#else - assert(f_lo != f_hi && t_lo != t_hi, "invalid register allocation"); - - - if (f_lo == t_hi && f_hi == t_lo) { - swap_reg(f_lo, f_hi); - } else if (f_hi == t_lo) { - assert(f_lo != t_hi, "overwriting register"); - move_regs(f_hi, t_hi); - move_regs(f_lo, t_lo); - } else { - assert(f_hi != t_lo, "overwriting register"); - move_regs(f_lo, t_lo); - move_regs(f_hi, t_hi); - } -#endif // LP64 // move between xmm-registers } else if (dest->is_single_xmm()) { @@ -831,7 +760,6 @@ void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { Address dstLO = frame_map()->address_for_slot(dest->double_stack_ix(), lo_word_offset_in_bytes); Address dstHI = frame_map()->address_for_slot(dest->double_stack_ix(), hi_word_offset_in_bytes); __ movptr (dstLO, src->as_register_lo()); - NOT_LP64(__ movptr (dstHI, src->as_register_hi())); } else if (src->is_single_xmm()) { Address dst_addr = frame_map()->address_for_slot(dest->single_stack_ix()); @@ -854,7 +782,6 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch if (is_reference_type(type)) { __ verify_oop(src->as_register()); -#ifdef _LP64 if (UseCompressedOops && !wide) { __ movptr(compressed_src, src->as_register()); __ encode_heap_oop(compressed_src); @@ -862,7 +789,6 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch info->oop_map()->set_narrowoop(compressed_src->as_VMReg()); } } -#endif } if (patch_code != lir_patch_none) { @@ -893,14 +819,6 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch __ movptr(as_Address(to_addr), src->as_register()); } break; - case T_METADATA: - // We get here to store a method pointer to the stack to pass to - // a dtrace runtime call. This can't work on 64 bit with - // compressed klass ptrs: T_METADATA can be a compressed klass - // ptr or a 64 bit method pointer. - LP64_ONLY(ShouldNotReachHere()); - __ movptr(as_Address(to_addr), src->as_register()); - break; case T_ADDRESS: __ movptr(as_Address(to_addr), src->as_register()); break; @@ -911,35 +829,7 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch case T_LONG: { Register from_lo = src->as_register_lo(); Register from_hi = src->as_register_hi(); -#ifdef _LP64 __ movptr(as_Address_lo(to_addr), from_lo); -#else - Register base = to_addr->base()->as_register(); - Register index = noreg; - if (to_addr->index()->is_register()) { - index = to_addr->index()->as_register(); - } - if (base == from_lo || index == from_lo) { - assert(base != from_hi, "can't be"); - assert(index == noreg || (index != base && index != from_hi), "can't handle this"); - __ movl(as_Address_hi(to_addr), from_hi); - if (patch != nullptr) { - patching_epilog(patch, lir_patch_high, base, info); - patch = new PatchingStub(_masm, PatchingStub::access_field_id); - patch_code = lir_patch_low; - } - __ movl(as_Address_lo(to_addr), from_lo); - } else { - assert(index == noreg || (index != base && index != from_lo), "can't handle this"); - __ movl(as_Address_lo(to_addr), from_lo); - if (patch != nullptr) { - patching_epilog(patch, lir_patch_low, base, info); - patch = new PatchingStub(_masm, PatchingStub::access_field_id); - patch_code = lir_patch_high; - } - __ movl(as_Address_hi(to_addr), from_hi); - } -#endif // _LP64 break; } @@ -988,7 +878,6 @@ void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) { Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(), lo_word_offset_in_bytes); Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes); __ movptr(dest->as_register_lo(), src_addr_LO); - NOT_LP64(__ movptr(dest->as_register_hi(), src_addr_HI)); } else if (dest->is_single_xmm()) { Address src_addr = frame_map()->address_for_slot(src->single_stack_ix()); @@ -1010,27 +899,14 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { __ pushptr(frame_map()->address_for_slot(src ->single_stack_ix())); __ popptr (frame_map()->address_for_slot(dest->single_stack_ix())); } else { -#ifndef _LP64 - __ pushl(frame_map()->address_for_slot(src ->single_stack_ix())); - __ popl (frame_map()->address_for_slot(dest->single_stack_ix())); -#else //no pushl on 64bits __ movl(rscratch1, frame_map()->address_for_slot(src ->single_stack_ix())); __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), rscratch1); -#endif } } else if (src->is_double_stack()) { -#ifdef _LP64 __ pushptr(frame_map()->address_for_slot(src ->double_stack_ix())); __ popptr (frame_map()->address_for_slot(dest->double_stack_ix())); -#else - __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 0)); - // push and pop the part at src + wordSize, adding wordSize for the previous push - __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 2 * wordSize)); - __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 2 * wordSize)); - __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 0)); -#endif // _LP64 } else { ShouldNotReachHere(); @@ -1113,44 +989,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch case T_LONG: { Register to_lo = dest->as_register_lo(); Register to_hi = dest->as_register_hi(); -#ifdef _LP64 __ movptr(to_lo, as_Address_lo(addr)); -#else - Register base = addr->base()->as_register(); - Register index = noreg; - if (addr->index()->is_register()) { - index = addr->index()->as_register(); - } - if ((base == to_lo && index == to_hi) || - (base == to_hi && index == to_lo)) { - // addresses with 2 registers are only formed as a result of - // array access so this code will never have to deal with - // patches or null checks. - assert(info == nullptr && patch == nullptr, "must be"); - __ lea(to_hi, as_Address(addr)); - __ movl(to_lo, Address(to_hi, 0)); - __ movl(to_hi, Address(to_hi, BytesPerWord)); - } else if (base == to_lo || index == to_lo) { - assert(base != to_hi, "can't be"); - assert(index == noreg || (index != base && index != to_hi), "can't handle this"); - __ movl(to_hi, as_Address_hi(addr)); - if (patch != nullptr) { - patching_epilog(patch, lir_patch_high, base, info); - patch = new PatchingStub(_masm, PatchingStub::access_field_id); - patch_code = lir_patch_low; - } - __ movl(to_lo, as_Address_lo(addr)); - } else { - assert(index == noreg || (index != base && index != to_lo), "can't handle this"); - __ movl(to_lo, as_Address_lo(addr)); - if (patch != nullptr) { - patching_epilog(patch, lir_patch_low, base, info); - patch = new PatchingStub(_masm, PatchingStub::access_field_id); - patch_code = lir_patch_high; - } - __ movl(to_hi, as_Address_hi(addr)); - } -#endif // _LP64 break; } @@ -1200,11 +1039,9 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch } if (is_reference_type(type)) { -#ifdef _LP64 if (UseCompressedOops && !wide) { __ decode_heap_oop(dest->as_register()); } -#endif __ verify_oop(dest->as_register()); } @@ -1299,21 +1136,11 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { switch (op->bytecode()) { case Bytecodes::_i2l: -#ifdef _LP64 __ movl2ptr(dest->as_register_lo(), src->as_register()); -#else - move_regs(src->as_register(), dest->as_register_lo()); - move_regs(src->as_register(), dest->as_register_hi()); - __ sarl(dest->as_register_hi(), 31); -#endif // LP64 break; case Bytecodes::_l2i: -#ifdef _LP64 __ movl(dest->as_register(), src->as_register_lo()); -#else - move_regs(src->as_register_lo(), dest->as_register()); -#endif break; case Bytecodes::_i2b: @@ -1396,7 +1223,7 @@ void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) { void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { Register len = op->len()->as_register(); - LP64_ONLY( __ movslq(len, len); ) + __ movslq(len, len); if (UseSlowPath || (!UseFastNewObjectArray && is_reference_type(op->type())) || @@ -1464,7 +1291,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L Register dst = op->result_opr()->as_register(); ciKlass* k = op->klass(); Register Rtmp1 = noreg; - Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg); + Register tmp_load_klass = rscratch1; // check if it needs to be profiled ciMethodData* md = nullptr; @@ -1526,29 +1353,19 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L if (!k->is_loaded()) { klass2reg_with_patching(k_RInfo, op->info_for_patch()); } else { -#ifdef _LP64 __ mov_metadata(k_RInfo, k->constant_encoding()); -#endif // _LP64 } __ verify_oop(obj); if (op->fast_check()) { // get object class // not a safepoint as obj null check happens earlier -#ifdef _LP64 if (UseCompressedClassPointers) { __ load_klass(Rtmp1, obj, tmp_load_klass); __ cmpptr(k_RInfo, Rtmp1); } else { __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); } -#else - if (k->is_loaded()) { - __ cmpklass(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); - } else { - __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); - } -#endif __ jcc(Assembler::notEqual, *failure_target); // successful cast, fall through to profile or jump } else { @@ -1557,11 +1374,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L __ load_klass(klass_RInfo, obj, tmp_load_klass); if (k->is_loaded()) { // See if we get an immediate positive hit -#ifdef _LP64 __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset())); -#else - __ cmpklass(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); -#endif // _LP64 if ((juint)in_bytes(Klass::secondary_super_cache_offset()) != k->super_check_offset()) { __ jcc(Assembler::notEqual, *failure_target); // successful cast, fall through to profile or jump @@ -1569,19 +1382,11 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L // See if we get an immediate positive hit __ jcc(Assembler::equal, *success_target); // check for self -#ifdef _LP64 __ cmpptr(klass_RInfo, k_RInfo); -#else - __ cmpklass(klass_RInfo, k->constant_encoding()); -#endif // _LP64 __ jcc(Assembler::equal, *success_target); __ push(klass_RInfo); -#ifdef _LP64 __ push(k_RInfo); -#else - __ pushklass(k->constant_encoding(), noreg); -#endif // _LP64 __ call(RuntimeAddress(Runtime1::entry_for(C1StubId::slow_subtype_check_id))); __ pop(klass_RInfo); __ pop(klass_RInfo); @@ -1610,7 +1415,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { - Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg); + Register tmp_load_klass = rscratch1; LIR_Code code = op->code(); if (code == lir_store_check) { Register value = op->object()->as_register(); @@ -1714,17 +1519,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { - if (LP64_ONLY(false &&) op->code() == lir_cas_long) { - assert(op->cmp_value()->as_register_lo() == rax, "wrong register"); - assert(op->cmp_value()->as_register_hi() == rdx, "wrong register"); - assert(op->new_value()->as_register_lo() == rbx, "wrong register"); - assert(op->new_value()->as_register_hi() == rcx, "wrong register"); - Register addr = op->addr()->as_register(); - __ lock(); - NOT_LP64(__ cmpxchg8(Address(addr, 0))); - - } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj ) { - NOT_LP64(assert(op->addr()->is_single_cpu(), "must be single");) + if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { Register addr = (op->addr()->is_single_cpu() ? op->addr()->as_register() : op->addr()->as_register_lo()); Register newval = op->new_value()->as_register(); Register cmpval = op->cmp_value()->as_register(); @@ -1734,8 +1529,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { assert(cmpval != addr, "cmp and addr must be in different registers"); assert(newval != addr, "new value and addr must be in different registers"); - if ( op->code() == lir_cas_obj) { -#ifdef _LP64 + if (op->code() == lir_cas_obj) { if (UseCompressedOops) { __ encode_heap_oop(cmpval); __ mov(rscratch1, newval); @@ -1743,9 +1537,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { __ lock(); // cmpval (rax) is implicitly used by this instruction __ cmpxchgl(rscratch1, Address(addr, 0)); - } else -#endif - { + } else { __ lock(); __ cmpxchgptr(newval, Address(addr, 0)); } @@ -1754,7 +1546,6 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { __ lock(); __ cmpxchgl(newval, Address(addr, 0)); } -#ifdef _LP64 } else if (op->code() == lir_cas_long) { Register addr = (op->addr()->is_single_cpu() ? op->addr()->as_register() : op->addr()->as_register_lo()); Register newval = op->new_value()->as_register_lo(); @@ -1766,7 +1557,6 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { assert(newval != addr, "new value and addr must be in different registers"); __ lock(); __ cmpxchgq(newval, Address(addr, 0)); -#endif // _LP64 } else { Unimplemented(); } @@ -1809,12 +1599,10 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L assert(opr2->cpu_regnrLo() != result->cpu_regnrLo() && opr2->cpu_regnrLo() != result->cpu_regnrHi(), "opr2 already overwritten by previous move"); assert(opr2->cpu_regnrHi() != result->cpu_regnrLo() && opr2->cpu_regnrHi() != result->cpu_regnrHi(), "opr2 already overwritten by previous move"); __ cmovptr(ncond, result->as_register_lo(), opr2->as_register_lo()); - NOT_LP64(__ cmovptr(ncond, result->as_register_hi(), opr2->as_register_hi());) } else if (opr2->is_single_stack()) { __ cmovl(ncond, result->as_register(), frame_map()->address_for_slot(opr2->single_stack_ix())); } else if (opr2->is_double_stack()) { __ cmovptr(ncond, result->as_register_lo(), frame_map()->address_for_slot(opr2->double_stack_ix(), lo_word_offset_in_bytes)); - NOT_LP64(__ cmovptr(ncond, result->as_register_hi(), frame_map()->address_for_slot(opr2->double_stack_ix(), hi_word_offset_in_bytes));) } else { ShouldNotReachHere(); } @@ -1890,28 +1678,16 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr // cpu register - cpu register Register rreg_lo = right->as_register_lo(); Register rreg_hi = right->as_register_hi(); - NOT_LP64(assert_different_registers(lreg_lo, lreg_hi, rreg_lo, rreg_hi)); - LP64_ONLY(assert_different_registers(lreg_lo, rreg_lo)); + assert_different_registers(lreg_lo, rreg_lo); switch (code) { case lir_add: __ addptr(lreg_lo, rreg_lo); - NOT_LP64(__ adcl(lreg_hi, rreg_hi)); break; case lir_sub: __ subptr(lreg_lo, rreg_lo); - NOT_LP64(__ sbbl(lreg_hi, rreg_hi)); break; case lir_mul: -#ifdef _LP64 __ imulq(lreg_lo, rreg_lo); -#else - assert(lreg_lo == rax && lreg_hi == rdx, "must be"); - __ imull(lreg_hi, rreg_lo); - __ imull(rreg_hi, lreg_lo); - __ addl (rreg_hi, lreg_hi); - __ mull (rreg_lo); - __ addl (lreg_hi, rreg_hi); -#endif // _LP64 break; default: ShouldNotReachHere(); @@ -1919,7 +1695,6 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr } else if (right->is_constant()) { // cpu register - constant -#ifdef _LP64 jlong c = right->as_constant_ptr()->as_jlong_bits(); __ movptr(r10, (intptr_t) c); switch (code) { @@ -1932,22 +1707,6 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr default: ShouldNotReachHere(); } -#else - jint c_lo = right->as_constant_ptr()->as_jint_lo(); - jint c_hi = right->as_constant_ptr()->as_jint_hi(); - switch (code) { - case lir_add: - __ addptr(lreg_lo, c_lo); - __ adcl(lreg_hi, c_hi); - break; - case lir_sub: - __ subptr(lreg_lo, c_lo); - __ sbbl(lreg_hi, c_hi); - break; - default: - ShouldNotReachHere(); - } -#endif // _LP64 } else { ShouldNotReachHere(); @@ -2123,7 +1882,6 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr Register l_lo = left->as_register_lo(); Register l_hi = left->as_register_hi(); if (right->is_constant()) { -#ifdef _LP64 __ mov64(rscratch1, right->as_constant_ptr()->as_jlong()); switch (code) { case lir_logic_and: @@ -2137,50 +1895,22 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr break; default: ShouldNotReachHere(); } -#else - int r_lo = right->as_constant_ptr()->as_jint_lo(); - int r_hi = right->as_constant_ptr()->as_jint_hi(); - switch (code) { - case lir_logic_and: - __ andl(l_lo, r_lo); - __ andl(l_hi, r_hi); - break; - case lir_logic_or: - __ orl(l_lo, r_lo); - __ orl(l_hi, r_hi); - break; - case lir_logic_xor: - __ xorl(l_lo, r_lo); - __ xorl(l_hi, r_hi); - break; - default: ShouldNotReachHere(); - } -#endif // _LP64 } else { -#ifdef _LP64 Register r_lo; if (is_reference_type(right->type())) { r_lo = right->as_register(); } else { r_lo = right->as_register_lo(); } -#else - Register r_lo = right->as_register_lo(); - Register r_hi = right->as_register_hi(); - assert(l_lo != r_hi, "overwriting registers"); -#endif switch (code) { case lir_logic_and: __ andptr(l_lo, r_lo); - NOT_LP64(__ andptr(l_hi, r_hi);) break; case lir_logic_or: __ orptr(l_lo, r_lo); - NOT_LP64(__ orptr(l_hi, r_hi);) break; case lir_logic_xor: __ xorptr(l_lo, r_lo); - NOT_LP64(__ xorptr(l_hi, r_hi);) break; default: ShouldNotReachHere(); } @@ -2189,19 +1919,7 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr Register dst_lo = dst->as_register_lo(); Register dst_hi = dst->as_register_hi(); -#ifdef _LP64 move_regs(l_lo, dst_lo); -#else - if (dst_lo == l_hi) { - assert(dst_hi != l_lo, "overwriting registers"); - move_regs(l_hi, dst_hi); - move_regs(l_lo, dst_lo); - } else { - assert(dst_lo != l_hi, "overwriting registers"); - move_regs(l_lo, dst_lo); - move_regs(l_hi, dst_hi); - } -#endif // _LP64 } } @@ -2329,27 +2047,11 @@ void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, Register xlo = opr1->as_register_lo(); Register xhi = opr1->as_register_hi(); if (opr2->is_double_cpu()) { -#ifdef _LP64 __ cmpptr(xlo, opr2->as_register_lo()); -#else - // cpu register - cpu register - Register ylo = opr2->as_register_lo(); - Register yhi = opr2->as_register_hi(); - __ subl(xlo, ylo); - __ sbbl(xhi, yhi); - if (condition == lir_cond_equal || condition == lir_cond_notEqual) { - __ orl(xhi, xlo); - } -#endif // _LP64 } else if (opr2->is_constant()) { // cpu register - constant 0 assert(opr2->as_jlong() == (jlong)0, "only handles zero"); -#ifdef _LP64 __ cmpptr(xlo, (int32_t)opr2->as_jlong()); -#else - assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "only handles equals case"); - __ orl(xhi, xlo); -#endif // _LP64 } else { ShouldNotReachHere(); } @@ -2398,12 +2100,10 @@ void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, } else if (opr1->is_address() && opr2->is_constant()) { LIR_Const* c = opr2->as_constant_ptr(); -#ifdef _LP64 if (is_reference_type(c->type())) { assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "need to reverse"); __ movoop(rscratch1, c->as_jobject()); } -#endif // LP64 if (op->info() != nullptr) { add_debug_info_for_null_check_here(op->info()); } @@ -2412,13 +2112,9 @@ void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, if (c->type() == T_INT) { __ cmpl(as_Address(addr), c->as_jint()); } else if (is_reference_type(c->type())) { -#ifdef _LP64 // %%% Make this explode if addr isn't reachable until we figure out a // better strategy by giving noreg as the temp for as_Address __ cmpoop(rscratch1, as_Address(addr, noreg)); -#else - __ cmpoop(as_Address(addr), c->as_jobject()); -#endif // _LP64 } else { ShouldNotReachHere(); } @@ -2442,7 +2138,6 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op } } else { assert(code == lir_cmp_l2i, "check"); -#ifdef _LP64 Label done; Register dest = dst->as_register(); __ cmpptr(left->as_register_lo(), right->as_register_lo()); @@ -2451,13 +2146,6 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op __ setb(Assembler::notZero, dest); __ movzbl(dest, dest); __ bind(done); -#else - __ lcmp2int(left->as_register_hi(), - left->as_register_lo(), - right->as_register_hi(), - right->as_register_lo()); - move_regs(left->as_register_hi(), dst->as_register()); -#endif // _LP64 } } @@ -2583,22 +2271,12 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr Register lo = left->as_register_lo(); Register hi = left->as_register_hi(); assert(lo != SHIFT_count && hi != SHIFT_count, "left cannot be ECX"); -#ifdef _LP64 switch (code) { case lir_shl: __ shlptr(lo); break; case lir_shr: __ sarptr(lo); break; case lir_ushr: __ shrptr(lo); break; default: ShouldNotReachHere(); } -#else - - switch (code) { - case lir_shl: __ lshl(hi, lo); break; - case lir_shr: __ lshr(hi, lo, true); break; - case lir_ushr: __ lshr(hi, lo, false); break; - default: ShouldNotReachHere(); - } -#endif // LP64 } else { ShouldNotReachHere(); } @@ -2619,9 +2297,6 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr de default: ShouldNotReachHere(); } } else if (dest->is_double_cpu()) { -#ifndef _LP64 - Unimplemented(); -#else // first move left into dest so that left is not destroyed by the shift Register value = dest->as_register_lo(); count = count & 0x1F; // Java spec @@ -2633,7 +2308,6 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr de case lir_ushr: __ shrptr(value, count); break; default: ShouldNotReachHere(); } -#endif // _LP64 } else { ShouldNotReachHere(); } @@ -2683,7 +2357,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { Register dst_pos = op->dst_pos()->as_register(); Register length = op->length()->as_register(); Register tmp = op->tmp()->as_register(); - Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg); + Register tmp_load_klass = rscratch1; Register tmp2 = UseCompactObjectHeaders ? rscratch2 : noreg; CodeStub* stub = op->stub(); @@ -2708,13 +2382,11 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // these are just temporary placements until we need to reload store_parameter(src_pos, 3); store_parameter(src, 4); - NOT_LP64(assert(src == rcx && src_pos == rdx, "mismatch in calling convention");) address copyfunc_addr = StubRoutines::generic_arraycopy(); assert(copyfunc_addr != nullptr, "generic arraycopy stub required"); // pass arguments: may push as this is not a safepoint; SP must be fix at each safepoint -#ifdef _LP64 // The arguments are in java calling convention so we can trivially shift them to C // convention assert_different_registers(c_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4); @@ -2745,21 +2417,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { #endif __ call(RuntimeAddress(copyfunc_addr)); #endif // _WIN64 -#else - __ push(length); - __ push(dst_pos); - __ push(dst); - __ push(src_pos); - __ push(src); - -#ifndef PRODUCT - if (PrintC1Statistics) { - __ incrementl(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt), rscratch1); - } -#endif - __ call_VM_leaf(copyfunc_addr, 5); // removes pushed parameter from the stack - -#endif // _LP64 __ testl(rax, rax); __ jcc(Assembler::equal, *stub->continuation()); @@ -2865,10 +2522,8 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ jcc(Assembler::less, *stub->entry()); } -#ifdef _LP64 __ movl2ptr(src_pos, src_pos); //higher 32bits must be null __ movl2ptr(dst_pos, dst_pos); //higher 32bits must be null -#endif if (flags & LIR_OpArrayCopy::type_check) { // We don't know the array types are compatible @@ -2932,21 +2587,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { store_parameter(src_pos, 3); store_parameter(src, 4); -#ifndef _LP64 - Address dst_klass_addr = Address(dst, oopDesc::klass_offset_in_bytes()); - __ movptr(tmp, dst_klass_addr); - __ movptr(tmp, Address(tmp, ObjArrayKlass::element_klass_offset())); - __ push(tmp); - __ movl(tmp, Address(tmp, Klass::super_check_offset_offset())); - __ push(tmp); - __ push(length); - __ lea(tmp, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); - __ push(tmp); - __ lea(tmp, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); - __ push(tmp); - - __ call_VM_leaf(copyfunc_addr, 5); -#else __ movl2ptr(length, length); //higher 32bits must be null __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); @@ -2973,8 +2613,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ call(RuntimeAddress(copyfunc_addr)); #endif -#endif - #ifndef PRODUCT if (PrintC1Statistics) { Label failed; @@ -3030,11 +2668,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // but not necessarily exactly of type default_type. Label known_ok, halt; __ mov_metadata(tmp, default_type->constant_encoding()); -#ifdef _LP64 if (UseCompressedClassPointers) { __ encode_klass_not_null(tmp, rscratch1); } -#endif if (basic_type != T_OBJECT) { __ cmp_klass(tmp, dst, tmp2); @@ -3059,21 +2695,12 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { } #endif -#ifdef _LP64 assert_different_registers(c_rarg0, dst, dst_pos, length); __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); assert_different_registers(c_rarg1, length); __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); __ mov(c_rarg2, length); -#else - __ lea(tmp, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); - store_parameter(tmp, 0); - __ lea(tmp, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); - store_parameter(tmp, 1); - store_parameter(length, 2); -#endif // _LP64 - bool disjoint = (flags & LIR_OpArrayCopy::overlapping) == 0; bool aligned = (flags & LIR_OpArrayCopy::unaligned) == 0; const char *name; @@ -3146,7 +2773,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ciMethod* method = op->profiled_method(); int bci = op->profiled_bci(); ciMethod* callee = op->profiled_callee(); - Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg); + Register tmp_load_klass = rscratch1; // Update counter for all call types ciMethodData* md = method->method_data_or_null(); @@ -3217,7 +2844,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { Register obj = op->obj()->as_register(); Register tmp = op->tmp()->as_pointer_register(); - Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg); + Register tmp_load_klass = rscratch1; Address mdo_addr = as_Address(op->mdp()->as_address_ptr()); ciKlass* exact_klass = op->exact_klass(); intptr_t current_klass = op->current_klass(); @@ -3237,17 +2864,9 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { #ifdef ASSERT if (obj == tmp) { -#ifdef _LP64 assert_different_registers(obj, rscratch1, mdo_addr.base(), mdo_addr.index()); -#else - assert_different_registers(obj, mdo_addr.base(), mdo_addr.index()); -#endif } else { -#ifdef _LP64 assert_different_registers(obj, tmp, rscratch1, mdo_addr.base(), mdo_addr.index()); -#else - assert_different_registers(obj, tmp, mdo_addr.base(), mdo_addr.index()); -#endif } #endif if (do_null) { @@ -3301,9 +2920,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { } else { __ load_klass(tmp, obj, tmp_load_klass); } -#ifdef _LP64 __ mov(rscratch1, tmp); // save original value before XOR -#endif __ xorptr(tmp, mdo_addr); __ testptr(tmp, TypeEntries::type_klass_mask); // klass seen before, nothing to do. The unknown bit may have been @@ -3316,7 +2933,6 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { if (TypeEntries::is_type_none(current_klass)) { __ testptr(mdo_addr, TypeEntries::type_mask); __ jccb(Assembler::zero, none); -#ifdef _LP64 // There is a chance that the checks above (re-reading profiling // data from memory) fail if another thread has just set the // profiling to this obj's klass @@ -3324,7 +2940,6 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { __ xorptr(tmp, mdo_addr); __ testptr(tmp, TypeEntries::type_klass_mask); __ jccb(Assembler::zero, next); -#endif } } else { assert(ciTypeEntries::valid_ciklass(current_klass) != nullptr && @@ -3418,22 +3033,9 @@ void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest, LIR_Opr tmp) { } else if (left->is_double_cpu()) { Register lo = left->as_register_lo(); -#ifdef _LP64 Register dst = dest->as_register_lo(); __ movptr(dst, lo); __ negptr(dst); -#else - Register hi = left->as_register_hi(); - __ lneg(hi, lo); - if (dest->as_register_lo() == hi) { - assert(dest->as_register_hi() != lo, "destroying register"); - move_regs(hi, dest->as_register_hi()); - move_regs(lo, dest->as_register_lo()); - } else { - move_regs(lo, dest->as_register_lo()); - move_regs(hi, dest->as_register_hi()); - } -#endif // _LP64 } else if (dest->is_single_xmm()) { assert(!tmp->is_valid(), "do not need temporary"); @@ -3496,13 +3098,7 @@ void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, if (src->is_double_xmm()) { if (dest->is_double_cpu()) { -#ifdef _LP64 __ movdq(dest->as_register_lo(), src->as_xmm_double_reg()); -#else - __ movdl(dest->as_register_lo(), src->as_xmm_double_reg()); - __ psrlq(src->as_xmm_double_reg(), 32); - __ movdl(dest->as_register_hi(), src->as_xmm_double_reg()); -#endif // _LP64 } else if (dest->is_double_stack()) { __ movdbl(frame_map()->address_for_slot(dest->double_stack_ix()), src->as_xmm_double_reg()); } else if (dest->is_address()) { @@ -3519,6 +3115,7 @@ void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, } else { ShouldNotReachHere(); } + } else { ShouldNotReachHere(); } @@ -3601,12 +3198,7 @@ void LIR_Assembler::on_spin_wait() { void LIR_Assembler::get_thread(LIR_Opr result_reg) { assert(result_reg->is_register(), "check"); -#ifdef _LP64 - // __ get_thread(result_reg->as_register_lo()); __ mov(result_reg->as_register(), r15_thread); -#else - __ get_thread(result_reg->as_register()); -#endif // _LP64 } @@ -3627,7 +3219,6 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr } else if (data->is_oop()) { assert (code == lir_xchg, "xadd for oops"); Register obj = data->as_register(); -#ifdef _LP64 if (UseCompressedOops) { __ encode_heap_oop(obj); __ xchgl(obj, as_Address(src->as_address_ptr())); @@ -3635,11 +3226,7 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr } else { __ xchgptr(obj, as_Address(src->as_address_ptr())); } -#else - __ xchgl(obj, as_Address(src->as_address_ptr())); -#endif } else if (data->type() == T_LONG) { -#ifdef _LP64 assert(data->as_register_lo() == data->as_register_hi(), "should be a single register"); if (code == lir_xadd) { __ lock(); @@ -3647,9 +3234,6 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr } else { __ xchgq(data->as_register_lo(), as_Address(src->as_address_ptr())); } -#else - ShouldNotReachHere(); -#endif } else { ShouldNotReachHere(); } diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp index c8f97cece6d..8524dc90276 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp @@ -46,9 +46,9 @@ Register recv, Label* update_done); enum { - _call_stub_size = NOT_LP64(15) LP64_ONLY(28), + _call_stub_size = 28, _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175), - _deopt_handler_size = NOT_LP64(10) LP64_ONLY(17) + _deopt_handler_size = 17 }; public: diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp index fe6d6a58b00..60ce3419dfb 100644 --- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp @@ -142,7 +142,6 @@ bool LIRGenerator::can_inline_as_constant(LIR_Const* c) const { LIR_Opr LIRGenerator::safepoint_poll_register() { - NOT_LP64( return new_register(T_ADDRESS); ) return LIR_OprFact::illegalOpr; } @@ -152,7 +151,6 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, assert(base->is_register(), "must be"); if (index->is_constant()) { LIR_Const *constant = index->as_constant_ptr(); -#ifdef _LP64 jlong c; if (constant->type() == T_INT) { c = (jlong(index->as_jint()) << shift) + disp; @@ -167,11 +165,6 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, __ move(index, tmp); return new LIR_Address(base, tmp, type); } -#else - return new LIR_Address(base, - ((intx)(constant->as_jint()) << shift) + disp, - type); -#endif } else { return new LIR_Address(base, index, (LIR_Address::Scale)shift, disp, type); } @@ -185,7 +178,6 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o LIR_Address* addr; if (index_opr->is_constant()) { int elem_size = type2aelembytes(type); -#ifdef _LP64 jint index = index_opr->as_jint(); jlong disp = offset_in_bytes + (jlong)(index) * elem_size; if (disp > max_jint) { @@ -197,28 +189,12 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o } else { addr = new LIR_Address(array_opr, (intx)disp, type); } -#else - // A displacement overflow can also occur for x86 but that is not a problem due to the 32-bit address range! - // Let's assume an array 'a' and an access with displacement 'disp'. When disp overflows, then "a + disp" will - // always be negative (i.e. underflows the 32-bit address range): - // Let N = 2^32: a + signed_overflow(disp) = a + disp - N. - // "a + disp" is always smaller than N. If an index was chosen which would point to an address beyond N, then - // range checks would catch that and throw an exception. Thus, a + disp < 0 holds which means that it always - // underflows the 32-bit address range: - // unsigned_underflow(a + signed_overflow(disp)) = unsigned_underflow(a + disp - N) - // = (a + disp - N) + N = a + disp - // This shows that we still end up at the correct address with a displacement overflow due to the 32-bit address - // range limitation. This overflow only needs to be handled if addresses can be larger as on 64-bit platforms. - addr = new LIR_Address(array_opr, offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); -#endif // _LP64 } else { -#ifdef _LP64 if (index_opr->type() == T_INT) { LIR_Opr tmp = new_register(T_LONG); __ convert(Bytecodes::_i2l, index_opr, tmp); index_opr = tmp; } -#endif // _LP64 addr = new LIR_Address(array_opr, index_opr, LIR_Address::scale(type), @@ -358,34 +334,12 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) { left.dont_load_item(); } -#ifndef _LP64 - // do not load right operand if it is a constant. only 0 and 1 are - // loaded because there are special instructions for loading them - // without memory access (not needed for SSE2 instructions) - bool must_load_right = false; - if (right.is_constant()) { - LIR_Const* c = right.result()->as_constant_ptr(); - assert(c != nullptr, "invalid constant"); - assert(c->type() == T_FLOAT || c->type() == T_DOUBLE, "invalid type"); - - if (c->type() == T_FLOAT) { - must_load_right = UseSSE < 1 && (c->is_one_float() || c->is_zero_float()); - } else { - must_load_right = UseSSE < 2 && (c->is_one_double() || c->is_zero_double()); - } - } -#endif // !LP64 - if (must_load_both) { // frem and drem destroy also right operand, so move it to a new register right.set_destroys_register(); right.load_item(); } else if (right.is_register()) { right.load_item(); -#ifndef _LP64 - } else if (must_load_right) { - right.load_item(); -#endif // !LP64 } else { right.dont_load_item(); } @@ -395,7 +349,6 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) { tmp = new_register(T_DOUBLE); } -#ifdef _LP64 if (x->op() == Bytecodes::_frem || x->op() == Bytecodes::_drem) { // frem and drem are implemented as a direct call into the runtime. LIRItem left(x->x(), this); @@ -430,27 +383,6 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) { arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), tmp); set_result(x, reg); } -#else - if ((UseSSE >= 1 && x->op() == Bytecodes::_frem) || (UseSSE >= 2 && x->op() == Bytecodes::_drem)) { - // special handling for frem and drem: no SSE instruction, so must use FPU with temporary fpu stack slots - LIR_Opr fpu0, fpu1; - if (x->op() == Bytecodes::_frem) { - fpu0 = LIR_OprFact::single_fpu(0); - fpu1 = LIR_OprFact::single_fpu(1); - } else { - fpu0 = LIR_OprFact::double_fpu(0); - fpu1 = LIR_OprFact::double_fpu(1); - } - __ move(right.result(), fpu1); // order of left and right operand is important! - __ move(left.result(), fpu0); - __ rem (fpu0, fpu1, fpu0); - __ move(fpu0, reg); - - } else { - arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), tmp); - } - set_result(x, reg); -#endif // _LP64 } @@ -740,7 +672,7 @@ LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) value.load_item(); // Because we want a 2-arg form of xchg and xadd __ move(value.result(), result); - assert(type == T_INT || is_oop LP64_ONLY( || type == T_LONG ), "unexpected type"); + assert(type == T_INT || is_oop || type == T_LONG, "unexpected type"); __ xchg(addr, result, result, LIR_OprFact::illegalOpr); return result; } @@ -750,7 +682,7 @@ LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) { value.load_item(); // Because we want a 2-arg form of xchg and xadd __ move(value.result(), result); - assert(type == T_INT LP64_ONLY( || type == T_LONG ), "unexpected type"); + assert(type == T_INT || type == T_LONG, "unexpected type"); __ xadd(addr, result, result, LIR_OprFact::illegalOpr); return result; } @@ -788,10 +720,7 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog || x->id() == vmIntrinsics::_dpow || x->id() == vmIntrinsics::_dcos || x->id() == vmIntrinsics::_dsin || x->id() == vmIntrinsics::_dtan || - x->id() == vmIntrinsics::_dlog10 -#ifdef _LP64 - || x->id() == vmIntrinsics::_dtanh -#endif + x->id() == vmIntrinsics::_dlog10 || x->id() == vmIntrinsics::_dtanh ) { do_LibmIntrinsic(x); return; @@ -799,12 +728,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { LIRItem value(x->argument_at(0), this); - bool use_fpu = false; -#ifndef _LP64 - if (UseSSE < 2) { - value.set_destroys_register(); - } -#endif // !LP64 value.load_item(); LIR_Opr calc_input = value.result(); @@ -832,10 +755,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { default: ShouldNotReachHere(); } - - if (use_fpu) { - __ move(calc_result, x->operand()); - } } void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) { @@ -956,20 +875,6 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { flags = 0; } -#ifndef _LP64 - src.load_item_force (FrameMap::rcx_oop_opr); - src_pos.load_item_force (FrameMap::rdx_opr); - dst.load_item_force (FrameMap::rax_oop_opr); - dst_pos.load_item_force (FrameMap::rbx_opr); - length.load_item_force (FrameMap::rdi_opr); - LIR_Opr tmp = (FrameMap::rsi_opr); - - if (expected_type != nullptr && flags == 0) { - FrameMap* f = Compilation::current()->frame_map(); - f->update_reserved_argument_area_size(3 * BytesPerWord); - } -#else - // The java calling convention will give us enough registers // so that on the stub side the args will be perfect already. // On the other slow/special case side we call C and the arg @@ -985,7 +890,6 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { length.load_item_force (FrameMap::as_opr(j_rarg4)); LIR_Opr tmp = FrameMap::as_opr(j_rarg5); -#endif // LP64 set_no_result(x); @@ -1027,18 +931,11 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } LIR_Opr base_op = buf.result(); -#ifndef _LP64 - if (!is_updateBytes) { // long b raw address - base_op = new_register(T_INT); - __ convert(Bytecodes::_l2i, buf.result(), base_op); - } -#else if (index->is_valid()) { LIR_Opr tmp = new_register(T_LONG); __ convert(Bytecodes::_i2l, index, tmp); index = tmp; } -#endif LIR_Address* a = new LIR_Address(base_op, index, @@ -1172,14 +1069,6 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { } LIR_Opr result_b = b.result(); -#ifndef _LP64 - result_a = new_register(T_INT); - __ convert(Bytecodes::_l2i, a.result(), result_a); - result_b = new_register(T_INT); - __ convert(Bytecodes::_l2i, b.result(), result_b); -#endif - - LIR_Address* addr_a = new LIR_Address(result_a, result_aOffset, constant_aOffset, @@ -1214,7 +1103,6 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { } void LIRGenerator::do_Convert(Convert* x) { -#ifdef _LP64 LIRItem value(x->value(), this); value.load_item(); LIR_Opr input = value.result(); @@ -1222,66 +1110,6 @@ void LIRGenerator::do_Convert(Convert* x) { __ convert(x->op(), input, result); assert(result->is_virtual(), "result must be virtual register"); set_result(x, result); -#else - // flags that vary for the different operations and different SSE-settings - bool fixed_input = false, fixed_result = false, round_result = false, needs_stub = false; - - switch (x->op()) { - case Bytecodes::_i2l: // fall through - case Bytecodes::_l2i: // fall through - case Bytecodes::_i2b: // fall through - case Bytecodes::_i2c: // fall through - case Bytecodes::_i2s: fixed_input = false; fixed_result = false; round_result = false; needs_stub = false; break; - - case Bytecodes::_f2d: fixed_input = UseSSE == 1; fixed_result = false; round_result = false; needs_stub = false; break; - case Bytecodes::_d2f: fixed_input = false; fixed_result = UseSSE == 1; round_result = UseSSE < 1; needs_stub = false; break; - case Bytecodes::_i2f: fixed_input = false; fixed_result = false; round_result = UseSSE < 1; needs_stub = false; break; - case Bytecodes::_i2d: fixed_input = false; fixed_result = false; round_result = false; needs_stub = false; break; - case Bytecodes::_f2i: fixed_input = false; fixed_result = false; round_result = false; needs_stub = true; break; - case Bytecodes::_d2i: fixed_input = false; fixed_result = false; round_result = false; needs_stub = true; break; - case Bytecodes::_l2f: fixed_input = false; fixed_result = UseSSE >= 1; round_result = UseSSE < 1; needs_stub = false; break; - case Bytecodes::_l2d: fixed_input = false; fixed_result = UseSSE >= 2; round_result = UseSSE < 2; needs_stub = false; break; - case Bytecodes::_f2l: fixed_input = true; fixed_result = true; round_result = false; needs_stub = false; break; - case Bytecodes::_d2l: fixed_input = true; fixed_result = true; round_result = false; needs_stub = false; break; - default: ShouldNotReachHere(); - } - - LIRItem value(x->value(), this); - value.load_item(); - LIR_Opr input = value.result(); - LIR_Opr result = rlock(x); - - // arguments of lir_convert - LIR_Opr conv_input = input; - LIR_Opr conv_result = result; - ConversionStub* stub = nullptr; - - if (fixed_input) { - conv_input = fixed_register_for(input->type()); - __ move(input, conv_input); - } - - assert(fixed_result == false || round_result == false, "cannot set both"); - if (fixed_result) { - conv_result = fixed_register_for(result->type()); - } else if (round_result) { - result = new_register(result->type()); - set_vreg_flag(result, must_start_in_memory); - } - - if (needs_stub) { - stub = new ConversionStub(x->op(), conv_input, conv_result); - } - - __ convert(x->op(), conv_input, conv_result, stub); - - if (result != conv_result) { - __ move(conv_result, result); - } - - assert(result->is_virtual(), "result must be virtual register"); - set_result(x, result); -#endif // _LP64 } @@ -1547,13 +1375,7 @@ void LIRGenerator::do_If(If* x) { LIR_Opr LIRGenerator::getThreadPointer() { -#ifdef _LP64 return FrameMap::as_pointer_opr(r15_thread); -#else - LIR_Opr result = new_register(T_INT); - __ get_thread(result); - return result; -#endif // } void LIRGenerator::trace_block_entry(BlockBegin* block) { @@ -1598,12 +1420,6 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result, LIR_Opr temp_double = new_register(T_DOUBLE); __ volatile_move(LIR_OprFact::address(address), temp_double, T_LONG, info); __ volatile_move(temp_double, result, T_LONG); -#ifndef _LP64 - if (UseSSE < 2) { - // no spill slot needed in SSE2 mode because xmm->cpu register move is possible - set_vreg_flag(result, must_start_in_memory); - } -#endif // !LP64 } else { __ load(address, result, info); } diff --git a/src/hotspot/cpu/x86/c1_LIR_x86.cpp b/src/hotspot/cpu/x86/c1_LIR_x86.cpp index adcc53c44ce..ce831c5f956 100644 --- a/src/hotspot/cpu/x86/c1_LIR_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIR_x86.cpp @@ -58,16 +58,9 @@ LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) { #ifndef PRODUCT void LIR_Address::verify() const { -#ifdef _LP64 assert(base()->is_cpu_register(), "wrong base operand"); assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand"); assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA, "wrong type for addresses"); -#else - assert(base()->is_single_cpu(), "wrong base operand"); - assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand"); - assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA, - "wrong type for addresses"); -#endif } #endif // PRODUCT diff --git a/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp b/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp index 8669c9ab8a1..62a1bd6510e 100644 --- a/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp +++ b/src/hotspot/cpu/x86/c1_LinearScan_x86.hpp @@ -26,12 +26,6 @@ #define CPU_X86_C1_LINEARSCAN_X86_HPP inline bool LinearScan::is_processed_reg_num(int reg_num) { -#ifndef _LP64 - // rsp and rbp (numbers 6 ancd 7) are ignored - assert(FrameMap::rsp_opr->cpu_regnr() == 6, "wrong assumption below"); - assert(FrameMap::rbp_opr->cpu_regnr() == 7, "wrong assumption below"); - assert(reg_num >= 0, "invalid reg_num"); -#else // rsp and rbp, r10, r15 (numbers [12,15]) are ignored // r12 (number 11) is conditional on compressed oops. assert(FrameMap::r12_opr->cpu_regnr() == 11, "wrong assumption below"); @@ -40,16 +34,10 @@ inline bool LinearScan::is_processed_reg_num(int reg_num) { assert(FrameMap::rsp_opr->cpu_regnrLo() == 14, "wrong assumption below"); assert(FrameMap::rbp_opr->cpu_regnrLo() == 15, "wrong assumption below"); assert(reg_num >= 0, "invalid reg_num"); -#endif // _LP64 return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map; } inline int LinearScan::num_physical_regs(BasicType type) { - // Intel requires two cpu registers for long, - // but requires only one fpu register for double - if (LP64_ONLY(false &&) type == T_LONG) { - return 2; - } return 1; } diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index 238a1bd048a..7ffa6d9bdd4 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -62,15 +62,8 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr } if (LockingMode == LM_LIGHTWEIGHT) { -#ifdef _LP64 const Register thread = r15_thread; lightweight_lock(disp_hdr, obj, hdr, thread, tmp, slow_case); -#else - // Implicit null check. - movptr(hdr, Address(obj, oopDesc::mark_offset_in_bytes())); - // Lacking registers and thread on x86_32. Always take slow path. - jmp(slow_case); -#endif } else if (LockingMode == LM_LEGACY) { Label done; // Load object header @@ -135,12 +128,7 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_ verify_oop(obj); if (LockingMode == LM_LIGHTWEIGHT) { -#ifdef _LP64 lightweight_unlock(obj, disp_hdr, r15_thread, hdr, slow_case); -#else - // Lacking registers and thread on x86_32. Always take slow path. - jmp(slow_case); -#endif } else if (LockingMode == LM_LEGACY) { // test if object header is pointing to the displaced header, and if so, restore // the displaced header in the object - if the object header is not pointing to @@ -169,7 +157,6 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) { assert_different_registers(obj, klass, len, t1, t2); -#ifdef _LP64 if (UseCompactObjectHeaders) { movptr(t1, Address(klass, Klass::prototype_header_offset())); movptr(Address(obj, oopDesc::mark_offset_in_bytes()), t1); @@ -178,16 +165,13 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register movptr(t1, klass); encode_klass_not_null(t1, rscratch1); movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1); - } else -#endif - { + } else { movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast(markWord::prototype().value())); movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass); } if (len->is_valid()) { movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len); -#ifdef _LP64 int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt; if (!is_aligned(base_offset, BytesPerWord)) { assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned"); @@ -195,14 +179,10 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register xorl(t1, t1); movl(Address(obj, base_offset), t1); } -#endif - } -#ifdef _LP64 - else if (UseCompressedClassPointers && !UseCompactObjectHeaders) { + } else if (UseCompressedClassPointers && !UseCompactObjectHeaders) { xorptr(t1, t1); store_klass_gap(obj, t1); } -#endif } @@ -265,8 +245,6 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register bind(loop); movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - (1*BytesPerWord)), t1_zero); - NOT_LP64(movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - (2*BytesPerWord)), - t1_zero);) decrement(index); jcc(Assembler::notZero, loop); } diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index cb4cb3af8c3..bb5111fa652 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -51,27 +51,18 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, int args_size) { // setup registers - const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); // is callee-saved register (Visual C++ calling conventions) + const Register thread = r15_thread; // is callee-saved register (Visual C++ calling conventions) assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different"); assert(oop_result1 != thread && metadata_result != thread, "registers must be different"); assert(args_size >= 0, "illegal args_size"); bool align_stack = false; -#ifdef _LP64 + // At a method handle call, the stack may not be properly aligned // when returning with an exception. align_stack = (stub_id() == (int)C1StubId::handle_exception_from_callee_id); -#endif -#ifdef _LP64 mov(c_rarg0, thread); set_num_rt_args(0); // Nothing on stack -#else - set_num_rt_args(1 + args_size); - - // push java thread (becomes first argument of C function) - get_thread(thread); - push(thread); -#endif // _LP64 int call_offset = -1; if (!align_stack) { @@ -104,9 +95,6 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre #endif reset_last_Java_frame(thread, true); - // discard thread and arguments - NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord)); - // check for pending exceptions { Label L; cmpptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); @@ -144,17 +132,12 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1) { -#ifdef _LP64 mov(c_rarg1, arg1); -#else - push(arg1); -#endif // _LP64 return call_RT(oop_result1, metadata_result, entry, 1); } int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2) { -#ifdef _LP64 if (c_rarg1 == arg2) { if (c_rarg2 == arg1) { xchgq(arg1, arg2); @@ -166,16 +149,11 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre mov(c_rarg1, arg1); mov(c_rarg2, arg2); } -#else - push(arg2); - push(arg1); -#endif // _LP64 return call_RT(oop_result1, metadata_result, entry, 2); } int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3) { -#ifdef _LP64 // if there is any conflict use the stack if (arg1 == c_rarg2 || arg1 == c_rarg3 || arg2 == c_rarg1 || arg2 == c_rarg3 || @@ -191,11 +169,6 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre mov(c_rarg2, arg2); mov(c_rarg3, arg3); } -#else - push(arg3); - push(arg2); - push(arg1); -#endif // _LP64 return call_RT(oop_result1, metadata_result, entry, 3); } @@ -262,20 +235,13 @@ const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2; // but the code in save_live_registers will take the argument count into // account. // -#ifdef _LP64 - #define SLOT2(x) x, - #define SLOT_PER_WORD 2 -#else - #define SLOT2(x) - #define SLOT_PER_WORD 1 -#endif // _LP64 +#define SLOT2(x) x, +#define SLOT_PER_WORD 2 enum reg_save_layout { // 64bit needs to keep stack 16 byte aligned. So we add some alignment dummies to make that // happen and will assert if the stack size we create is misaligned -#ifdef _LP64 align_dummy_0, align_dummy_1, -#endif // _LP64 #ifdef _WIN64 // Windows always allocates space for it's argument registers (see // frame::arg_reg_save_area_bytes). @@ -291,7 +257,6 @@ enum reg_save_layout { fpu_state_end_off = fpu_state_off + (FPUStateSizeInWords / SLOT_PER_WORD), // 352 marker = fpu_state_end_off, SLOT2(markerH) // 352, 356 extra_space_offset, // 360 -#ifdef _LP64 r15_off = extra_space_offset, r15H_off, // 360, 364 r14_off, r14H_off, // 368, 372 r13_off, r13H_off, // 376, 380 @@ -301,9 +266,6 @@ enum reg_save_layout { r9_off, r9H_off, // 408, 412 r8_off, r8H_off, // 416, 420 rdi_off, rdiH_off, // 424, 428 -#else - rdi_off = extra_space_offset, -#endif // _LP64 rsi_off, SLOT2(rsiH_off) // 432, 436 rbp_off, SLOT2(rbpH_off) // 440, 444 rsp_off, SLOT2(rspH_off) // 448, 452 @@ -329,8 +291,8 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args, bool save_fpu_registers = true) { // In 64bit all the args are in regs so there are no additional stack slots - LP64_ONLY(num_rt_args = 0); - LP64_ONLY(assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");) + num_rt_args = 0; + assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned"); int frame_size_in_slots = reg_save_frame_size + num_rt_args; // args + thread sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word); @@ -343,7 +305,6 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args, map->set_callee_saved(VMRegImpl::stack2reg(rbx_off + num_rt_args), rbx->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(rsi_off + num_rt_args), rsi->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(rdi_off + num_rt_args), rdi->as_VMReg()); -#ifdef _LP64 map->set_callee_saved(VMRegImpl::stack2reg(r8_off + num_rt_args), r8->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(r9_off + num_rt_args), r9->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(r10_off + num_rt_args), r10->as_VMReg()); @@ -369,37 +330,10 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args, map->set_callee_saved(VMRegImpl::stack2reg(r13H_off + num_rt_args), r13->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg(r14H_off + num_rt_args), r14->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg(r15H_off + num_rt_args), r15->as_VMReg()->next()); -#endif // _LP64 int xmm_bypass_limit = FrameMap::get_num_caller_save_xmms(); if (save_fpu_registers) { -#ifndef _LP64 - if (UseSSE < 2) { - int fpu_off = float_regs_as_doubles_off; - for (int n = 0; n < FrameMap::nof_fpu_regs; n++) { - VMReg fpu_name_0 = FrameMap::fpu_regname(n); - map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + num_rt_args), fpu_name_0); - // %%% This is really a waste but we'll keep things as they were for now - if (true) { - map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + 1 + num_rt_args), fpu_name_0->next()); - } - fpu_off += 2; - } - assert(fpu_off == fpu_state_off, "incorrect number of fpu stack slots"); - - if (UseSSE == 1) { - int xmm_off = xmm_regs_as_doubles_off; - for (int n = 0; n < FrameMap::nof_fpu_regs; n++) { - VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg(); - map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0); - xmm_off += 2; - } - assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers"); - } - } -#endif // !LP64 - if (UseSSE >= 2) { int xmm_off = xmm_regs_as_doubles_off; for (int n = 0; n < FrameMap::nof_xmm_regs; n++) { @@ -426,14 +360,7 @@ void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers) __ block_comment("save_live_registers"); // Push CPU state in multiple of 16 bytes -#ifdef _LP64 __ save_legacy_gprs(); -#else - __ pusha(); -#endif - - // assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset"); - // assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset"); __ subptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size); @@ -442,46 +369,6 @@ void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers) #endif if (save_fpu_registers) { -#ifndef _LP64 - if (UseSSE < 2) { - // save FPU stack - __ fnsave(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size)); - __ fwait(); - -#ifdef ASSERT - Label ok; - __ cmpw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::x86::fpu_cntrl_wrd_std()); - __ jccb(Assembler::equal, ok); - __ stop("corrupted control word detected"); - __ bind(ok); -#endif - - // Reset the control word to guard against exceptions being unmasked - // since fstp_d can cause FPU stack underflow exceptions. Write it - // into the on stack copy and then reload that to make sure that the - // current and future values are correct. - __ movw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::x86::fpu_cntrl_wrd_std()); - __ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size)); - - // Save the FPU registers in de-opt-able form - int offset = 0; - for (int n = 0; n < FrameMap::nof_fpu_regs; n++) { - __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset)); - offset += 8; - } - - if (UseSSE == 1) { - // save XMM registers as float because double not supported without SSE2(num MMX == num fpu) - int offset = 0; - for (int n = 0; n < FrameMap::nof_fpu_regs; n++) { - XMMRegister xmm_name = as_XMMRegister(n); - __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name); - offset += 8; - } - } - } -#endif // !_LP64 - if (UseSSE >= 2) { // save XMM registers // XMM registers can contain float or double values, but this is not known here, @@ -497,16 +384,12 @@ void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers) } } } - - // FPU stack must be empty now - NOT_LP64( __ verify_FPU(0, "save_live_registers"); ) } #undef __ #define __ sasm-> static void restore_fpu(C1_MacroAssembler* sasm, bool restore_fpu_registers) { -#ifdef _LP64 if (restore_fpu_registers) { // restore XMM registers int xmm_bypass_limit = FrameMap::get_num_caller_save_xmms(); @@ -517,38 +400,6 @@ static void restore_fpu(C1_MacroAssembler* sasm, bool restore_fpu_registers) { offset += 8; } } -#else - if (restore_fpu_registers) { - if (UseSSE >= 2) { - // restore XMM registers - int xmm_bypass_limit = FrameMap::nof_xmm_regs; - int offset = 0; - for (int n = 0; n < xmm_bypass_limit; n++) { - XMMRegister xmm_name = as_XMMRegister(n); - __ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset)); - offset += 8; - } - } else if (UseSSE == 1) { - // restore XMM registers(num MMX == num fpu) - int offset = 0; - for (int n = 0; n < FrameMap::nof_fpu_regs; n++) { - XMMRegister xmm_name = as_XMMRegister(n); - __ movflt(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset)); - offset += 8; - } - } - - if (UseSSE < 2) { - __ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size)); - } else { - // check that FPU stack is really empty - __ verify_FPU(0, "restore_live_registers"); - } - } else { - // check that FPU stack is really empty - __ verify_FPU(0, "restore_live_registers"); - } -#endif // _LP64 #ifdef ASSERT { @@ -570,12 +421,7 @@ void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) { __ block_comment("restore_live_registers"); restore_fpu(this, restore_fpu_registers); -#ifdef _LP64 __ restore_legacy_gprs(); -#else - __ popa(); -#endif - } @@ -584,7 +430,6 @@ void C1_MacroAssembler::restore_live_registers_except_rax(bool restore_fpu_regis restore_fpu(this, restore_fpu_registers); -#ifdef _LP64 __ movptr(r15, Address(rsp, 0)); __ movptr(r14, Address(rsp, wordSize)); __ movptr(r13, Address(rsp, 2 * wordSize)); @@ -602,17 +447,6 @@ void C1_MacroAssembler::restore_live_registers_except_rax(bool restore_fpu_regis __ movptr(rcx, Address(rsp, 14 * wordSize)); __ addptr(rsp, 16 * wordSize); -#else - - __ pop(rdi); - __ pop(rsi); - __ pop(rbp); - __ pop(rbx); // skip this value - __ pop(rbx); - __ pop(rdx); - __ pop(rcx); - __ addptr(rsp, BytesPerWord); -#endif // _LP64 } #undef __ @@ -639,12 +473,7 @@ void Runtime1::initialize_pd() { // return: offset in 64-bit words. uint Runtime1::runtime_blob_current_thread_offset(frame f) { -#ifdef _LP64 return r15_off / 2; // rsp offsets are in halfwords -#else - Unimplemented(); - return 0; -#endif } // Target: the entry point of the method that creates and posts the exception oop. @@ -664,15 +493,8 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe // Load arguments for exception that are passed as arguments into the stub. if (has_argument) { -#ifdef _LP64 __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord)); __ movptr(c_rarg2, Address(rbp, 3*BytesPerWord)); -#else - __ movptr(temp_reg, Address(rbp, 3*BytesPerWord)); - __ push(temp_reg); - __ movptr(temp_reg, Address(rbp, 2*BytesPerWord)); - __ push(temp_reg); -#endif // _LP64 } int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1); @@ -692,7 +514,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) const Register exception_oop = rax; const Register exception_pc = rdx; // other registers used in this stub - const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); + const Register thread = r15_thread; // Save registers, if required. OopMapSet* oop_maps = new OopMapSet(); @@ -725,7 +547,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) case C1StubId::handle_exception_from_callee_id: { // At this point all registers except exception oop (RAX) and // exception pc (RDX) are dead. - const int frame_size = 2 /*BP, return address*/ NOT_LP64(+ 1 /*thread*/) WIN64_ONLY(+ frame::arg_reg_save_area_bytes / BytesPerWord); + const int frame_size = 2 /*BP, return address*/ WIN64_ONLY(+ frame::arg_reg_save_area_bytes / BytesPerWord); oop_map = new OopMap(frame_size * VMRegImpl::slots_per_word, 0); sasm->set_frame_size(frame_size); WIN64_ONLY(__ subq(rsp, frame::arg_reg_save_area_bytes)); @@ -734,21 +556,11 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) default: ShouldNotReachHere(); } -#if !defined(_LP64) && defined(COMPILER2) - if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_jvmci()) { - // C2 can leave the fpu stack dirty - __ empty_FPU_stack(); - } -#endif // !_LP64 && COMPILER2 - // verify that only rax, and rdx is valid at this time __ invalidate_registers(false, true, true, false, true, true); // verify that rax, contains a valid exception __ verify_not_null_oop(exception_oop); - // load address of JavaThread object for thread-local data - NOT_LP64(__ get_thread(thread);) - #ifdef ASSERT // check that fields in JavaThread for exception oop and issuing pc are // empty before writing to them @@ -815,11 +627,11 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // incoming parameters const Register exception_oop = rax; // callee-saved copy of exception_oop during runtime call - const Register exception_oop_callee_saved = NOT_LP64(rsi) LP64_ONLY(r14); + const Register exception_oop_callee_saved = r14; // other registers used in this stub const Register exception_pc = rdx; const Register handler_addr = rbx; - const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); + const Register thread = r15_thread; if (AbortVMOnException) { __ enter(); @@ -834,7 +646,6 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { #ifdef ASSERT // check that fields in JavaThread for exception oop and issuing pc are empty - NOT_LP64(__ get_thread(thread);) Label oop_empty; __ cmpptr(Address(thread, JavaThread::exception_oop_offset()), 0); __ jcc(Assembler::equal, oop_empty); @@ -848,14 +659,10 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { __ bind(pc_empty); #endif - // clear the FPU stack in case any FPU results are left behind - NOT_LP64( __ empty_FPU_stack(); ) - // save exception_oop in callee-saved register to preserve it during runtime calls __ verify_not_null_oop(exception_oop); __ movptr(exception_oop_callee_saved, exception_oop); - NOT_LP64(__ get_thread(thread);) // Get return address (is on top of stack after leave). __ movptr(exception_pc, Address(rsp, 0)); @@ -905,18 +712,10 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { OopMap* oop_map = save_live_registers(sasm, num_rt_args); -#ifdef _LP64 const Register thread = r15_thread; // No need to worry about dummy __ mov(c_rarg0, thread); -#else - __ push(rax); // push dummy - const Register thread = rdi; // is callee-saved register (Visual C++ calling conventions) - // push java thread (becomes first argument of C function) - __ get_thread(thread); - __ push(thread); -#endif // _LP64 __ set_last_Java_frame(thread, noreg, rbp, nullptr, rscratch1); // do the call __ call(RuntimeAddress(target)); @@ -936,10 +735,6 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { __ pop(rax); #endif __ reset_last_Java_frame(thread, true); -#ifndef _LP64 - __ pop(rcx); // discard thread arg - __ pop(rcx); // discard dummy -#endif // _LP64 // check for pending exceptions { Label L; @@ -1166,15 +961,8 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { // This is called via call_runtime so the arguments // will be place in C abi locations -#ifdef _LP64 __ verify_oop(c_rarg0); __ mov(rax, c_rarg0); -#else - // The object is passed on the stack and we haven't pushed a - // frame yet so it's one work away from top of stack. - __ movptr(rax, Address(rsp, 1 * BytesPerWord)); - __ verify_oop(rax); -#endif // _LP64 // load the klass and check the has finalizer flag Label register_finalizer; @@ -1467,9 +1255,8 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { // the live registers get saved. save_live_registers(sasm, 1); - __ NOT_LP64(push(rax)) LP64_ONLY(mov(c_rarg0, rax)); + __ mov(c_rarg0, rax); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, static_cast(SharedRuntime::dtrace_object_alloc)))); - NOT_LP64(__ pop(rax)); restore_live_registers(sasm); } @@ -1477,7 +1264,6 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { case C1StubId::fpu2long_stub_id: { -#ifdef _LP64 Label done; __ cvttsd2siq(rax, Address(rsp, wordSize)); __ cmp64(rax, ExternalAddress((address) StubRoutines::x86::double_sign_flip())); @@ -1489,78 +1275,6 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { __ pop(rax); __ bind(done); __ ret(0); -#else - // rax, and rdx are destroyed, but should be free since the result is returned there - // preserve rsi,ecx - __ push(rsi); - __ push(rcx); - - // check for NaN - Label return0, do_return, return_min_jlong, do_convert; - - Address value_high_word(rsp, wordSize + 4); - Address value_low_word(rsp, wordSize); - Address result_high_word(rsp, 3*wordSize + 4); - Address result_low_word(rsp, 3*wordSize); - - __ subptr(rsp, 32); // more than enough on 32bit - __ fst_d(value_low_word); - __ movl(rax, value_high_word); - __ andl(rax, 0x7ff00000); - __ cmpl(rax, 0x7ff00000); - __ jcc(Assembler::notEqual, do_convert); - __ movl(rax, value_high_word); - __ andl(rax, 0xfffff); - __ orl(rax, value_low_word); - __ jcc(Assembler::notZero, return0); - - __ bind(do_convert); - __ fnstcw(Address(rsp, 0)); - __ movzwl(rax, Address(rsp, 0)); - __ orl(rax, 0xc00); - __ movw(Address(rsp, 2), rax); - __ fldcw(Address(rsp, 2)); - __ fwait(); - __ fistp_d(result_low_word); - __ fldcw(Address(rsp, 0)); - __ fwait(); - // This gets the entire long in rax on 64bit - __ movptr(rax, result_low_word); - // testing of high bits - __ movl(rdx, result_high_word); - __ mov(rcx, rax); - // What the heck is the point of the next instruction??? - __ xorl(rcx, 0x0); - __ movl(rsi, 0x80000000); - __ xorl(rsi, rdx); - __ orl(rcx, rsi); - __ jcc(Assembler::notEqual, do_return); - __ fldz(); - __ fcomp_d(value_low_word); - __ fnstsw_ax(); - __ sahf(); - __ jcc(Assembler::above, return_min_jlong); - // return max_jlong - __ movl(rdx, 0x7fffffff); - __ movl(rax, 0xffffffff); - __ jmp(do_return); - - __ bind(return_min_jlong); - __ movl(rdx, 0x80000000); - __ xorl(rax, rax); - __ jmp(do_return); - - __ bind(return0); - __ fpop(); - __ xorptr(rdx,rdx); - __ xorptr(rax,rax); - - __ bind(do_return); - __ addptr(rsp, 32); - __ pop(rcx); - __ pop(rsi); - __ ret(0); -#endif // _LP64 } break; From 39549f89905019fa90dd20ff8b6822c1351cbaa6 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 7 Apr 2025 09:13:43 +0000 Subject: [PATCH 008/843] 8352116: Deadlock with GCLocker and JVMTI after JDK-8192647 Reviewed-by: kbarrett, tschatzl, eosterlund --- src/hotspot/share/gc/shared/gcLocker.cpp | 9 ++++---- .../share/gc/shared/gcVMOperations.cpp | 21 +++++++++++++------ src/hotspot/share/runtime/mutexLocker.cpp | 4 +++- src/hotspot/share/runtime/mutexLocker.hpp | 1 + 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/gc/shared/gcLocker.cpp b/src/hotspot/share/gc/shared/gcLocker.cpp index aa13209a37a..caf752f70c8 100644 --- a/src/hotspot/share/gc/shared/gcLocker.cpp +++ b/src/hotspot/share/gc/shared/gcLocker.cpp @@ -65,8 +65,8 @@ volatile bool GCLocker::_is_gc_request_pending; DEBUG_ONLY(uint64_t GCLocker::_verify_in_cr_count;) void GCLocker::initialize() { - assert(Heap_lock != nullptr, "inv"); - _lock = Heap_lock; + assert(JNICritical_lock != nullptr, "inv"); + _lock = JNICritical_lock; _is_gc_request_pending = false; DEBUG_ONLY(_verify_in_cr_count = 0;) @@ -82,7 +82,8 @@ bool GCLocker::is_active() { } void GCLocker::block() { - assert(_lock->is_locked(), "precondition"); + // _lock is held from the beginning of block() to the end of of unblock(). + _lock->lock(); assert(Atomic::load(&_is_gc_request_pending) == false, "precondition"); GCLockerTimingDebugLogger logger("Thread blocked to start GC."); @@ -116,10 +117,10 @@ void GCLocker::block() { } void GCLocker::unblock() { - assert(_lock->is_locked(), "precondition"); assert(Atomic::load(&_is_gc_request_pending) == true, "precondition"); Atomic::store(&_is_gc_request_pending, false); + _lock->unlock(); } void GCLocker::enter_slow(JavaThread* current_thread) { diff --git a/src/hotspot/share/gc/shared/gcVMOperations.cpp b/src/hotspot/share/gc/shared/gcVMOperations.cpp index b28007962d3..8e5768ce6a9 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.cpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.cpp @@ -93,6 +93,11 @@ bool VM_GC_Operation::skip_operation() const { return skip; } +static bool should_use_gclocker() { + // Only Serial and Parallel use GCLocker to synchronize with threads in JNI critical-sections, in order to handle pinned objects. + return UseSerialGC || UseParallelGC; +} + bool VM_GC_Operation::doit_prologue() { assert(((_gc_cause != GCCause::_no_gc) && (_gc_cause != GCCause::_no_cause_specified)), "Illegal GCCause"); @@ -106,17 +111,21 @@ bool VM_GC_Operation::doit_prologue() { proper_unit_for_byte_size(NewSize))); } + + if (should_use_gclocker()) { + GCLocker::block(); + } VM_GC_Sync_Operation::doit_prologue(); // Check invocations if (skip_operation()) { // skip collection Heap_lock->unlock(); + if (should_use_gclocker()) { + GCLocker::unblock(); + } _prologue_succeeded = false; } else { - if (UseSerialGC || UseParallelGC) { - GCLocker::block(); - } _prologue_succeeded = true; } return _prologue_succeeded; @@ -124,9 +133,6 @@ bool VM_GC_Operation::doit_prologue() { void VM_GC_Operation::doit_epilogue() { - if (UseSerialGC || UseParallelGC) { - GCLocker::unblock(); - } // GC thread root traversal likely used OopMapCache a lot, which // might have created lots of old entries. Trigger the cleanup now. OopMapCache::try_trigger_cleanup(); @@ -134,6 +140,9 @@ void VM_GC_Operation::doit_epilogue() { Heap_lock->notify_all(); } VM_GC_Sync_Operation::doit_epilogue(); + if (should_use_gclocker()) { + GCLocker::unblock(); + } } bool VM_GC_HeapInspection::doit_prologue() { diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 2733cbcb14c..3db53d038b6 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -46,6 +46,7 @@ Mutex* CompiledIC_lock = nullptr; Mutex* VMStatistic_lock = nullptr; Mutex* JmethodIdCreation_lock = nullptr; Mutex* JfieldIdCreation_lock = nullptr; +Monitor* JNICritical_lock = nullptr; Mutex* JvmtiThreadState_lock = nullptr; Monitor* EscapeBarrier_lock = nullptr; Monitor* JvmtiVTMSTransition_lock = nullptr; @@ -318,7 +319,8 @@ void mutex_init() { MUTEX_DEFL(Threads_lock , PaddedMonitor, CompileThread_lock, true); MUTEX_DEFL(Compile_lock , PaddedMutex , MethodCompileQueue_lock); - MUTEX_DEFL(Heap_lock , PaddedMonitor, AdapterHandlerLibrary_lock); + MUTEX_DEFL(JNICritical_lock , PaddedMonitor, AdapterHandlerLibrary_lock); // used for JNI critical regions + MUTEX_DEFL(Heap_lock , PaddedMonitor, JNICritical_lock); MUTEX_DEFL(PerfDataMemAlloc_lock , PaddedMutex , Heap_lock); MUTEX_DEFL(PerfDataManager_lock , PaddedMutex , Heap_lock); diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 1913c64d6a6..bd2073dfe88 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -44,6 +44,7 @@ extern Mutex* CompiledIC_lock; // a lock used to guard compile extern Mutex* VMStatistic_lock; // a lock used to guard statistics count increment extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers +extern Monitor* JNICritical_lock; // a lock used while synchronizing with threads entering/leaving JNI critical regions extern Mutex* JvmtiThreadState_lock; // a lock on modification of JVMTI thread data extern Monitor* EscapeBarrier_lock; // a lock to sync reallocating and relocking objects because of JVMTI access extern Monitor* JvmtiVTMSTransition_lock; // a lock for Virtual Thread Mount State transition (VTMS transition) management From 32d6d031514be9cfee5b0fd778cb738b7ff9d770 Mon Sep 17 00:00:00 2001 From: Mikhail Yankelevich Date: Mon, 7 Apr 2025 09:57:12 +0000 Subject: [PATCH 009/843] 8349348: Refactor ClassLoaderDeadlock.sh and Deadlock.sh to run fully in java Reviewed-by: jpai, mullan --- .../ClassLoaderDeadlock.java | 11 +- .../ClassLoaderDeadlock.sh | 106 ------------------ .../ClassLoaderDeadlock/Deadlock.java | 11 +- .../Security/ClassLoaderDeadlock/Deadlock.sh | 66 ----------- 4 files changed, 17 insertions(+), 177 deletions(-) delete mode 100644 test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh delete mode 100644 test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh diff --git a/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java b/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java index f5af071654c..d2794e70a2d 100644 --- a/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java +++ b/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,14 @@ * questions. */ -// See bug 5094825 / ClassLoadDeadlock.sh +/* +* @test +* @bug 5094825 +* @summary verify no deadlock if crypto provider in other classloader is used to verify signed jars +* @library ./Deadlock.jar +* @compile provider/HashProvider.java +* @run main/othervm/timeout=30 ClassLoaderDeadlock +*/ import java.net.*; diff --git a/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh b/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh deleted file mode 100644 index e2e57392853..00000000000 --- a/test/jdk/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright (c) 2004, 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 5094825 -# @summary verify no deadlock if crypto provider in other classloader is used to verify signed jars -# -# @run shell/timeout=30 ClassLoaderDeadlock.sh - -# set a few environment variables so that the shell-script can run stand-alone -# in the source directory -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi - -if [ "${TESTCLASSES}" = "" ] ; then - TESTCLASSES="." -fi - -if [ "${TESTJAVA}" = "" ] ; then - echo "TESTJAVA not set. Test cannot execute." - echo "FAILED!!!" - exit 1 -fi - -if [ "${COMPILEJAVA}" = "" ]; then - COMPILEJAVA="${TESTJAVA}" -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Linux ) - PATHSEP=":" - FILESEP="/" - ;; - Darwin ) - PATHSEP=":" - FILESEP="/" - ;; - AIX ) - PATHSEP=":" - FILESEP="/" - ;; - CYGWIN* ) - PATHSEP=";" - FILESEP="/" - ;; - Windows* ) - PATHSEP=";" - FILESEP="\\" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -cd ${TESTCLASSES}${FILESEP} -if [ ! -d provider ] ; then - mkdir provider -fi - -# compile the test program -${COMPILEJAVA}${FILESEP}bin${FILESEP}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ - -d ${TESTCLASSES}${FILESEP} \ - ${TESTSRC}${FILESEP}ClassLoaderDeadlock.java - -${COMPILEJAVA}${FILESEP}bin${FILESEP}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ - -d ${TESTCLASSES}${FILESEP}provider${FILESEP} \ - ${TESTSRC}${FILESEP}provider${FILESEP}HashProvider.java - -# run the test -${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} ${TESTJAVAOPTS} \ - -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" \ - -Djava.awt.headless=true \ - ClassLoaderDeadlock - -STATUS=$? - -# clean up -rm -f 'ClassLoaderDeadlock.class' 'ClassLoaderDeadlock$1.class' \ -'ClassLoaderDeadlock$DelayClassLoader.class' \ -provider${FILESEP}HashProvider.class - -exit $STATUS diff --git a/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java b/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java index 5693f4933aa..0d46b5c8660 100644 --- a/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java +++ b/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,8 +21,13 @@ * questions. */ - -// see Deadlock.sh +/* + * @test + * @bug 4944382 + * @summary make sure we do not deadlock loading signed JAR with getInstance() + * @library ./Deadlock.jar + * @run main/othervm/timeout=30 Deadlock + */ import java.security.*; diff --git a/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh b/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh deleted file mode 100644 index 7013c4cc33a..00000000000 --- a/test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh - -# -# 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 -# 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 4944382 -# @summary make sure we do not deadlock loading signed JAR with getInstance() -# @author Andreas Sterbenz -# @build Deadlock -# @run shell/timeout=30 Deadlock.sh - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Linux ) - PATHSEP=":" - FILESEP="/" - ;; - Darwin ) - PATHSEP=":" - FILESEP="/" - ;; - AIX ) - PATHSEP=":" - FILESEP="/" - ;; - CYGWIN* ) - PATHSEP=";" - FILESEP="/" - ;; - Windows* ) - PATHSEP=";" - FILESEP="\\" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -JAVA="${TESTJAVA}${FILESEP}bin${FILESEP}java" - -${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" Deadlock - From c494a00a66d21d2e403fd9ce253eb132c34e455d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Mon, 7 Apr 2025 11:31:06 +0000 Subject: [PATCH 010/843] 8353559: Restructure CollectedHeap error printing Reviewed-by: stefank, eosterlund, ayang --- src/hotspot/share/gc/epsilon/epsilonHeap.cpp | 10 ++++++ src/hotspot/share/gc/epsilon/epsilonHeap.hpp | 3 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 8 ++++- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 2 +- .../gc/parallel/parallelScavengeHeap.cpp | 8 ++++- src/hotspot/share/gc/serial/serialHeap.cpp | 10 ++++++ src/hotspot/share/gc/serial/serialHeap.hpp | 3 +- src/hotspot/share/gc/shared/collectedHeap.cpp | 11 ------- src/hotspot/share/gc/shared/collectedHeap.hpp | 12 ++----- .../share/gc/shenandoah/shenandoahHeap.cpp | 12 +++---- .../share/gc/shenandoah/shenandoahHeap.hpp | 4 +-- src/hotspot/share/gc/z/zCollectedHeap.cpp | 28 +--------------- src/hotspot/share/gc/z/zCollectedHeap.hpp | 3 +- src/hotspot/share/gc/z/zHeap.cpp | 33 ++++++++++++++++++- src/hotspot/share/gc/z/zHeap.hpp | 6 ++-- src/hotspot/share/utilities/vmError.cpp | 2 ++ 16 files changed, 89 insertions(+), 66 deletions(-) diff --git a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp index 8bc98835844..d5ee7835fea 100644 --- a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp @@ -310,6 +310,16 @@ void EpsilonHeap::print_on(outputStream *st) const { MetaspaceUtils::print_on(st); } +void EpsilonHeap::print_on_error(outputStream *st) const { + print_on(st); + st->cr(); + + BarrierSet* bs = BarrierSet::barrier_set(); + if (bs != nullptr) { + bs->print_on(st); + } +} + bool EpsilonHeap::print_location(outputStream* st, void* addr) const { return BlockLocationPrinter::print_location(st, addr); } diff --git a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp index b2b522c1435..81bcd61916f 100644 --- a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp +++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2022, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -132,6 +132,7 @@ public: HeapWord* allocate_loaded_archive_space(size_t size) override; void print_on(outputStream* st) const override; + void print_on_error(outputStream* st) const override; void print_tracing_info() const override; bool print_location(outputStream* st, void* addr) const override; diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 4c0436ad1e2..31f0cc12aa5 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2161,7 +2161,13 @@ void G1CollectedHeap::print_extended_on(outputStream* st) const { } void G1CollectedHeap::print_on_error(outputStream* st) const { - this->CollectedHeap::print_on_error(st); + print_extended_on(st); + st->cr(); + + BarrierSet* bs = BarrierSet::barrier_set(); + if (bs != nullptr) { + bs->print_on(st); + } if (_cm != nullptr) { st->cr(); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index d1e81205cef..8d449ceedc6 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1313,7 +1313,7 @@ private: public: void print_on(outputStream* st) const override; - void print_extended_on(outputStream* st) const override; + void print_extended_on(outputStream* st) const; void print_on_error(outputStream* st) const override; void gc_threads_do(ThreadClosure* tc) const override; diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 24cc30e1918..244094f1acc 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -673,7 +673,13 @@ void ParallelScavengeHeap::print_on(outputStream* st) const { } void ParallelScavengeHeap::print_on_error(outputStream* st) const { - this->CollectedHeap::print_on_error(st); + print_on(st); + st->cr(); + + BarrierSet* bs = BarrierSet::barrier_set(); + if (bs != nullptr) { + bs->print_on(st); + } st->cr(); PSParallelCompact::print_on_error(st); diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index fcf57909a03..ea2b656d4bd 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -810,6 +810,16 @@ void SerialHeap::print_on(outputStream* st) const { MetaspaceUtils::print_on(st); } +void SerialHeap::print_on_error(outputStream* st) const { + print_on(st); + st->cr(); + + BarrierSet* bs = BarrierSet::barrier_set(); + if (bs != nullptr) { + bs->print_on(st); + } +} + void SerialHeap::gc_threads_do(ThreadClosure* tc) const { } diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 754f6741cfe..2ec50814daf 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -207,6 +207,7 @@ public: void verify(VerifyOption option) override; void print_on(outputStream* st) const override; + void print_on_error(outputStream* st) const override; void gc_threads_do(ThreadClosure* tc) const override; void print_tracing_info() const override; diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 2175b58b694..9c55a894ee7 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -188,17 +188,6 @@ void CollectedHeap::print_heap_after_gc() { void CollectedHeap::print() const { print_on(tty); } -void CollectedHeap::print_on_error(outputStream* st) const { - st->print_cr("Heap:"); - print_extended_on(st); - st->cr(); - - BarrierSet* bs = BarrierSet::barrier_set(); - if (bs != nullptr) { - bs->print_on(st); - } -} - void CollectedHeap::trace_heap(GCWhen::Type when, const GCTracer* gc_tracer) { const GCHeapSummary& heap_summary = create_heap_summary(); gc_tracer->report_gc_heap_summary(when, heap_summary); diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 31a224597a0..7b3fbd1a1c4 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -440,15 +440,7 @@ protected: // The default behavior is to call print_on() on tty. virtual void print() const; - // Print more detailed heap information on the given - // outputStream. The default behavior is to call print_on(). It is - // up to each subclass to override it and add any additional output - // it needs. - virtual void print_extended_on(outputStream* st) const { - print_on(st); - } - - virtual void print_on_error(outputStream* st) const; + virtual void print_on_error(outputStream* st) const = 0; // Used to print information about locations in the hs_err file. virtual bool print_location(outputStream* st, void* addr) const = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 32acb42c765..c055a3f9b5a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -649,6 +649,12 @@ void ShenandoahHeap::print_on(outputStream* st) const { } } +void ShenandoahHeap::print_on_error(outputStream* st) const { + print_on(st); + st->cr(); + print_heap_regions_on(st); +} + class ShenandoahInitWorkerGCLABClosure : public ThreadClosure { public: void do_thread(Thread* thread) { @@ -2582,12 +2588,6 @@ void ShenandoahHeap::rebuild_free_set(bool concurrent) { } } -void ShenandoahHeap::print_extended_on(outputStream *st) const { - print_on(st); - st->cr(); - print_heap_regions_on(st); -} - bool ShenandoahHeap::is_bitmap_slice_committed(ShenandoahHeapRegion* r, bool skip_self) { size_t slice = r->index() / _bitmap_regions_per_slice; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index d9508beac20..2bbb590f355 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -203,7 +203,7 @@ public: void initialize_serviceability() override; void print_on(outputStream* st) const override; - void print_extended_on(outputStream *st) const override; + void print_on_error(outputStream *st) const override; void print_tracing_info() const override; void print_heap_regions_on(outputStream* st) const; diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index 29111062529..828e3c9d033 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -359,33 +359,7 @@ void ZCollectedHeap::print_on(outputStream* st) const { } void ZCollectedHeap::print_on_error(outputStream* st) const { - st->print_cr("ZGC Globals:"); - st->print_cr(" Young Collection: %s/%u", ZGeneration::young()->phase_to_string(), ZGeneration::young()->seqnum()); - st->print_cr(" Old Collection: %s/%u", ZGeneration::old()->phase_to_string(), ZGeneration::old()->seqnum()); - st->print_cr(" Offset Max: " EXACTFMT " (" PTR_FORMAT ")", EXACTFMTARGS(ZAddressOffsetMax), ZAddressOffsetMax); - st->print_cr(" Page Size Small: %zuM", ZPageSizeSmall / M); - st->print_cr(" Page Size Medium: %zuM", ZPageSizeMedium / M); - st->cr(); - st->print_cr("ZGC Metadata Bits:"); - st->print_cr(" LoadGood: " PTR_FORMAT, ZPointerLoadGoodMask); - st->print_cr(" LoadBad: " PTR_FORMAT, ZPointerLoadBadMask); - st->print_cr(" MarkGood: " PTR_FORMAT, ZPointerMarkGoodMask); - st->print_cr(" MarkBad: " PTR_FORMAT, ZPointerMarkBadMask); - st->print_cr(" StoreGood: " PTR_FORMAT, ZPointerStoreGoodMask); - st->print_cr(" StoreBad: " PTR_FORMAT, ZPointerStoreBadMask); - st->print_cr(" ------------------- "); - st->print_cr(" Remapped: " PTR_FORMAT, ZPointerRemapped); - st->print_cr(" RemappedYoung: " PTR_FORMAT, ZPointerRemappedYoungMask); - st->print_cr(" RemappedOld: " PTR_FORMAT, ZPointerRemappedOldMask); - st->print_cr(" MarkedYoung: " PTR_FORMAT, ZPointerMarkedYoung); - st->print_cr(" MarkedOld: " PTR_FORMAT, ZPointerMarkedOld); - st->print_cr(" Remembered: " PTR_FORMAT, ZPointerRemembered); - st->cr(); - CollectedHeap::print_on_error(st); -} - -void ZCollectedHeap::print_extended_on(outputStream* st) const { - _heap.print_extended_on(st); + _heap.print_on_error(st); } void ZCollectedHeap::print_tracing_info() const { diff --git a/src/hotspot/share/gc/z/zCollectedHeap.hpp b/src/hotspot/share/gc/z/zCollectedHeap.hpp index 434204e16b8..08aa7d40a3f 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.hpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,7 +117,6 @@ public: void print_on(outputStream* st) const override; void print_on_error(outputStream* st) const override; - void print_extended_on(outputStream* st) const override; void print_tracing_info() const override; bool print_location(outputStream* st, void* addr) const override; diff --git a/src/hotspot/share/gc/z/zHeap.cpp b/src/hotspot/share/gc/z/zHeap.cpp index bca9e2f8c41..e0f4cb65303 100644 --- a/src/hotspot/share/gc/z/zHeap.cpp +++ b/src/hotspot/share/gc/z/zHeap.cpp @@ -326,10 +326,41 @@ void ZHeap::print_on(outputStream* st) const { MetaspaceUtils::print_on(st); } -void ZHeap::print_extended_on(outputStream* st) const { +void ZHeap::print_on_error(outputStream* st) const { print_on(st); st->cr(); + print_globals_on(st); + st->cr(); + + print_page_table_on(st); +} + +void ZHeap::print_globals_on(outputStream* st) const { + st->print_cr("ZGC Globals:"); + st->print_cr(" Young Collection: %s/%u", ZGeneration::young()->phase_to_string(), ZGeneration::young()->seqnum()); + st->print_cr(" Old Collection: %s/%u", ZGeneration::old()->phase_to_string(), ZGeneration::old()->seqnum()); + st->print_cr(" Offset Max: " EXACTFMT " (" PTR_FORMAT ")", EXACTFMTARGS(ZAddressOffsetMax), ZAddressOffsetMax); + st->print_cr(" Page Size Small: %zuM", ZPageSizeSmall / M); + st->print_cr(" Page Size Medium: %zuM", ZPageSizeMedium / M); + st->cr(); + st->print_cr("ZGC Metadata Bits:"); + st->print_cr(" LoadGood: " PTR_FORMAT, ZPointerLoadGoodMask); + st->print_cr(" LoadBad: " PTR_FORMAT, ZPointerLoadBadMask); + st->print_cr(" MarkGood: " PTR_FORMAT, ZPointerMarkGoodMask); + st->print_cr(" MarkBad: " PTR_FORMAT, ZPointerMarkBadMask); + st->print_cr(" StoreGood: " PTR_FORMAT, ZPointerStoreGoodMask); + st->print_cr(" StoreBad: " PTR_FORMAT, ZPointerStoreBadMask); + st->print_cr(" ------------------- "); + st->print_cr(" Remapped: " PTR_FORMAT, ZPointerRemapped); + st->print_cr(" RemappedYoung: " PTR_FORMAT, ZPointerRemappedYoungMask); + st->print_cr(" RemappedOld: " PTR_FORMAT, ZPointerRemappedOldMask); + st->print_cr(" MarkedYoung: " PTR_FORMAT, ZPointerMarkedYoung); + st->print_cr(" MarkedOld: " PTR_FORMAT, ZPointerMarkedOld); + st->print_cr(" Remembered: " PTR_FORMAT, ZPointerRemembered); +} + +void ZHeap::print_page_table_on(outputStream* st) const { // Do not allow pages to be deleted _page_allocator.enable_safe_destroy(); diff --git a/src/hotspot/share/gc/z/zHeap.hpp b/src/hotspot/share/gc/z/zHeap.hpp index 4bf4727c3e3..25cd2209003 100644 --- a/src/hotspot/share/gc/z/zHeap.hpp +++ b/src/hotspot/share/gc/z/zHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,7 +132,9 @@ public: // Printing void print_on(outputStream* st) const; - void print_extended_on(outputStream* st) const; + void print_on_error(outputStream* st) const; + void print_globals_on(outputStream* st) const; + void print_page_table_on(outputStream* st) const; bool print_location(outputStream* st, uintptr_t addr) const; bool print_location(outputStream* st, zaddress addr) const; bool print_location(outputStream* st, zpointer ptr) const; diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index bbf1fcf9d6f..ef04d69ee99 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1191,6 +1191,7 @@ void VMError::report(outputStream* st, bool _verbose) { GCLogPrecious::print_on_error(st); if (Universe::heap() != nullptr) { + st->print_cr("Heap:"); Universe::heap()->print_on_error(st); st->cr(); } @@ -1374,6 +1375,7 @@ void VMError::print_vm_info(outputStream* st) { if (Universe::is_fully_initialized()) { MutexLocker hl(Heap_lock); GCLogPrecious::print_on_error(st); + st->print_cr("Heap:"); Universe::heap()->print_on_error(st); st->cr(); st->print_cr("Polling page: " PTR_FORMAT, p2i(SafepointMechanism::get_polling_page())); From 6ab1647af2d83427215f3a704671f113ba9845e2 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 7 Apr 2025 11:32:16 +0000 Subject: [PATCH 011/843] 8353637: ZGC: Discontiguous memory reservation is broken on Windows Co-authored-by: Axel Boldt-Christmas Reviewed-by: jsikstro, aboldtch, eosterlund --- .../os/posix/gc/z/zVirtualMemory_posix.cpp | 2 +- .../windows/gc/z/zVirtualMemory_windows.cpp | 136 +++++---- src/hotspot/share/gc/z/zArguments.hpp | 2 + src/hotspot/share/gc/z/zInitialize.hpp | 2 + src/hotspot/share/gc/z/zMemory.cpp | 147 ++++++---- src/hotspot/share/gc/z/zMemory.hpp | 27 +- src/hotspot/share/gc/z/zMemory.inline.hpp | 12 + src/hotspot/share/gc/z/zNMT.cpp | 20 ++ src/hotspot/share/gc/z/zNMT.hpp | 2 + src/hotspot/share/gc/z/zPhysicalMemory.cpp | 2 +- src/hotspot/share/gc/z/zVirtualMemory.cpp | 27 +- src/hotspot/share/gc/z/zVirtualMemory.hpp | 7 +- .../gtest/gc/z/test_zMapper_windows.cpp | 153 ++-------- test/hotspot/gtest/gc/z/test_zMemory.cpp | 24 +- .../gtest/gc/z/test_zVirtualMemory.cpp | 4 +- .../gtest/gc/z/test_zVirtualMemoryManager.cpp | 269 ++++++++++++++++++ test/hotspot/gtest/gc/z/zunittest.hpp | 82 ++++++ 17 files changed, 627 insertions(+), 291 deletions(-) create mode 100644 test/hotspot/gtest/gc/z/test_zVirtualMemoryManager.cpp create mode 100644 test/hotspot/gtest/gc/z/zunittest.hpp diff --git a/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp b/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp index a177fe2b636..a103f764c98 100644 --- a/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp +++ b/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp @@ -32,7 +32,7 @@ void ZVirtualMemoryManager::pd_initialize_before_reserve() { // Does nothing } -void ZVirtualMemoryManager::pd_initialize_after_reserve() { +void ZVirtualMemoryManager::pd_register_callbacks(ZMemoryManager* manager) { // Does nothing } diff --git a/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp b/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp index 392b16e38a3..ac5be56a0c0 100644 --- a/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp +++ b/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp @@ -33,7 +33,7 @@ class ZVirtualMemoryManagerImpl : public CHeapObj { public: virtual void initialize_before_reserve() {} - virtual void initialize_after_reserve(ZMemoryManager* manager) {} + virtual void register_callbacks(ZMemoryManager* manager) {} virtual bool reserve(zaddress_unsafe addr, size_t size) = 0; virtual void unreserve(zaddress_unsafe addr, size_t size) = 0; }; @@ -47,7 +47,7 @@ public: class ZVirtualMemoryManagerSmallPages : public ZVirtualMemoryManagerImpl { private: class PlaceholderCallbacks : public AllStatic { - public: + private: static void split_placeholder(zoffset start, size_t size) { ZMapper::split_placeholder(ZOffset::address_unsafe(start), size); } @@ -79,99 +79,93 @@ private: } } - // Called when a memory area is returned to the memory manager but can't - // be merged with an already existing area. Make sure this area is covered - // by a single placeholder. - static void create_callback(const ZMemory* area) { - assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); + // Callback implementations - coalesce_into_one_placeholder(area->start(), area->size()); + // Called when a memory area is going to be handed out to be used. + // + // Splits the memory area into granule-sized placeholders. + static void prepare_for_hand_out_callback(const ZMemory& area) { + assert(is_aligned(area.size(), ZGranuleSize), "Must be granule aligned"); + + split_into_granule_sized_placeholders(area.start(), area.size()); } - // Called when a complete memory area in the memory manager is allocated. - // Create granule sized placeholders for the entire area. - static void destroy_callback(const ZMemory* area) { - assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); + // Called when a memory area is handed back to the memory manager. + // + // Combines the granule-sized placeholders into one placeholder. + static void prepare_for_hand_back_callback(const ZMemory& area) { + assert(is_aligned(area.size(), ZGranuleSize), "Must be granule aligned"); - split_into_granule_sized_placeholders(area->start(), area->size()); + coalesce_into_one_placeholder(area.start(), area.size()); } - // Called when a memory area is allocated at the front of an exising memory area. - // Turn the first part of the memory area into granule sized placeholders. - static void shrink_from_front_callback(const ZMemory* area, size_t size) { - assert(area->size() > size, "Must be larger than what we try to split out"); - assert(is_aligned(size, ZGranuleSize), "Must be granule aligned"); + // Called when inserting a memory area and it can be merged with an + // existing, adjacent memory area. + // + // Coalesces the underlying placeholders into one. + static void grow_callback(const ZMemory& from, const ZMemory& to) { + assert(is_aligned(from.size(), ZGranuleSize), "Must be granule aligned"); + assert(is_aligned(to.size(), ZGranuleSize), "Must be granule aligned"); + assert(from != to, "Must have grown"); + assert(to.contains(from), "Must be within"); + + coalesce_into_one_placeholder(to.start(), to.size()); + } + + // Called when a memory area is removed from the front or back of an existing + // memory area. + // + // Splits the memory into two placeholders. + static void shrink_callback(const ZMemory& from, const ZMemory& to) { + assert(is_aligned(from.size(), ZGranuleSize), "Must be granule aligned"); + assert(is_aligned(to.size(), ZGranuleSize), "Must be granule aligned"); + assert(from != to, "Must have shrunk"); + assert(from.contains(to), "Must be larger than what we try to split out"); + assert(from.start() == to.start() || from.end() == to.end(), + "Only verified to work if we split a placeholder into two placeholders"); // Split the area into two placeholders - split_placeholder(area->start(), size); - - // Split the first part into granule sized placeholders - split_into_granule_sized_placeholders(area->start(), size); + split_placeholder(to.start(), to.size()); } - // Called when a memory area is allocated at the end of an existing memory area. - // Turn the second part of the memory area into granule sized placeholders. - static void shrink_from_back_callback(const ZMemory* area, size_t size) { - assert(area->size() > size, "Must be larger than what we try to split out"); - assert(is_aligned(size, ZGranuleSize), "Must be granule aligned"); - - // Split the area into two placeholders - const zoffset start = to_zoffset(area->end() - size); - split_placeholder(start, size); - - // Split the second part into granule sized placeholders - split_into_granule_sized_placeholders(start, size); - } - - // Called when freeing a memory area and it can be merged at the start of an - // existing area. Coalesce the underlying placeholders into one. - static void grow_from_front_callback(const ZMemory* area, size_t size) { - assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); - - const zoffset start = area->start() - size; - coalesce_into_one_placeholder(start, area->size() + size); - } - - // Called when freeing a memory area and it can be merged at the end of an - // existing area. Coalesce the underlying placeholders into one. - static void grow_from_back_callback(const ZMemory* area, size_t size) { - assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); - - coalesce_into_one_placeholder(area->start(), area->size() + size); - } - - static void register_with(ZMemoryManager* manager) { + public: + static ZMemoryManager::Callbacks callbacks() { // Each reserved virtual memory address area registered in _manager is // exactly covered by a single placeholder. Callbacks are installed so // that whenever a memory area changes, the corresponding placeholder // is adjusted. // - // The create and grow callbacks are called when virtual memory is - // returned to the memory manager. The new memory area is then covered - // by a new single placeholder. + // The prepare_for_hand_out callback is called when virtual memory is + // handed out to callers. The memory area is split into granule-sized + // placeholders. // - // The destroy and shrink callbacks are called when virtual memory is - // allocated from the memory manager. The memory area is then is split - // into granule-sized placeholders. + // The prepare_for_hand_back callback is called when previously handed + // out virtual memory is handed back to the memory manager. The + // returned memory area is then covered by a new single placeholder. + // + // The grow callback is called when a virtual memory area grows. The + // resulting memory area is then covered by a single placeholder. + // + // The shrink callback is called when a virtual memory area is split into + // two parts. The two resulting memory areas are then covered by two + // separate placeholders. // // See comment in zMapper_windows.cpp explaining why placeholders are // split into ZGranuleSize sized placeholders. ZMemoryManager::Callbacks callbacks; - callbacks._create = &create_callback; - callbacks._destroy = &destroy_callback; - callbacks._shrink_from_front = &shrink_from_front_callback; - callbacks._shrink_from_back = &shrink_from_back_callback; - callbacks._grow_from_front = &grow_from_front_callback; - callbacks._grow_from_back = &grow_from_back_callback; + callbacks._prepare_for_hand_out = &prepare_for_hand_out_callback; + callbacks._prepare_for_hand_back = &prepare_for_hand_back_callback; + callbacks._grow = &grow_callback; + callbacks._shrink = &shrink_callback; - manager->register_callbacks(callbacks); + return callbacks; } }; - virtual void initialize_after_reserve(ZMemoryManager* manager) { - PlaceholderCallbacks::register_with(manager); + virtual void register_callbacks(ZMemoryManager* manager) { + manager->register_callbacks(PlaceholderCallbacks::callbacks()); } virtual bool reserve(zaddress_unsafe addr, size_t size) { @@ -220,8 +214,8 @@ void ZVirtualMemoryManager::pd_initialize_before_reserve() { _impl->initialize_before_reserve(); } -void ZVirtualMemoryManager::pd_initialize_after_reserve() { - _impl->initialize_after_reserve(&_manager); +void ZVirtualMemoryManager::pd_register_callbacks(ZMemoryManager* manager) { + _impl->register_callbacks(manager); } bool ZVirtualMemoryManager::pd_reserve(zaddress_unsafe addr, size_t size) { diff --git a/src/hotspot/share/gc/z/zArguments.hpp b/src/hotspot/share/gc/z/zArguments.hpp index 3ed1c8e212e..8bbd88f357c 100644 --- a/src/hotspot/share/gc/z/zArguments.hpp +++ b/src/hotspot/share/gc/z/zArguments.hpp @@ -29,6 +29,8 @@ class CollectedHeap; class ZArguments : public GCArguments { + friend class ZTest; + private: static void select_max_gc_threads(); diff --git a/src/hotspot/share/gc/z/zInitialize.hpp b/src/hotspot/share/gc/z/zInitialize.hpp index ce31912586e..44a286f2182 100644 --- a/src/hotspot/share/gc/z/zInitialize.hpp +++ b/src/hotspot/share/gc/z/zInitialize.hpp @@ -37,6 +37,8 @@ public: }; class ZInitialize : public AllStatic { + friend class ZTest; + private: static constexpr size_t ErrorMessageLength = 256; diff --git a/src/hotspot/share/gc/z/zMemory.cpp b/src/hotspot/share/gc/z/zMemory.cpp index 8ccde9f45a2..35e95888d4d 100644 --- a/src/hotspot/share/gc/z/zMemory.cpp +++ b/src/hotspot/share/gc/z/zMemory.cpp @@ -25,56 +25,47 @@ #include "gc/z/zLock.inline.hpp" #include "gc/z/zMemory.inline.hpp" -ZMemory* ZMemoryManager::create(zoffset start, size_t size) { - ZMemory* const area = new ZMemory(start, size); - if (_callbacks._create != nullptr) { - _callbacks._create(area); - } - return area; -} - -void ZMemoryManager::destroy(ZMemory* area) { - if (_callbacks._destroy != nullptr) { - _callbacks._destroy(area); - } - delete area; -} - void ZMemoryManager::shrink_from_front(ZMemory* area, size_t size) { - if (_callbacks._shrink_from_front != nullptr) { - _callbacks._shrink_from_front(area, size); + if (_callbacks._shrink != nullptr) { + const ZMemory* from = area; + const ZMemory to(area->start() + size, area->size() - size); + _callbacks._shrink(*from, to); } area->shrink_from_front(size); } void ZMemoryManager::shrink_from_back(ZMemory* area, size_t size) { - if (_callbacks._shrink_from_back != nullptr) { - _callbacks._shrink_from_back(area, size); + if (_callbacks._shrink != nullptr) { + const ZMemory* from = area; + const ZMemory to(area->start(), area->size() - size); + _callbacks._shrink(*from, to); } area->shrink_from_back(size); } void ZMemoryManager::grow_from_front(ZMemory* area, size_t size) { - if (_callbacks._grow_from_front != nullptr) { - _callbacks._grow_from_front(area, size); + if (_callbacks._grow != nullptr) { + const ZMemory* from = area; + const ZMemory to(area->start() - size, area->size() + size); + _callbacks._grow(*from, to); } area->grow_from_front(size); } void ZMemoryManager::grow_from_back(ZMemory* area, size_t size) { - if (_callbacks._grow_from_back != nullptr) { - _callbacks._grow_from_back(area, size); + if (_callbacks._grow != nullptr) { + const ZMemory* from = area; + const ZMemory to(area->start(), area->size() + size); + _callbacks._grow(*from, to); } area->grow_from_back(size); } ZMemoryManager::Callbacks::Callbacks() - : _create(nullptr), - _destroy(nullptr), - _shrink_from_front(nullptr), - _shrink_from_back(nullptr), - _grow_from_front(nullptr), - _grow_from_back(nullptr) {} + : _prepare_for_hand_out(nullptr), + _prepare_for_hand_back(nullptr), + _grow(nullptr), + _shrink(nullptr) {} ZMemoryManager::ZMemoryManager() : _freelist(), @@ -118,18 +109,24 @@ zoffset ZMemoryManager::alloc_low_address(size_t size) { ZListIterator iter(&_freelist); for (ZMemory* area; iter.next(&area);) { if (area->size() >= size) { + zoffset start; + if (area->size() == size) { // Exact match, remove area - const zoffset start = area->start(); + start = area->start(); _freelist.remove(area); - destroy(area); - return start; + delete area; } else { // Larger than requested, shrink area - const zoffset start = area->start(); + start = area->start(); shrink_from_front(area, size); - return start; } + + if (_callbacks._prepare_for_hand_out != nullptr) { + _callbacks._prepare_for_hand_out(ZMemory(start, size)); + } + + return start; } } @@ -142,20 +139,24 @@ zoffset ZMemoryManager::alloc_low_address_at_most(size_t size, size_t* allocated ZMemory* const area = _freelist.first(); if (area != nullptr) { + const zoffset start = area->start(); + if (area->size() <= size) { // Smaller than or equal to requested, remove area - const zoffset start = area->start(); - *allocated = area->size(); _freelist.remove(area); - destroy(area); - return start; + *allocated = area->size(); + delete area; } else { // Larger than requested, shrink area - const zoffset start = area->start(); shrink_from_front(area, size); *allocated = size; - return start; } + + if (_callbacks._prepare_for_hand_out != nullptr) { + _callbacks._prepare_for_hand_out(ZMemory(start, *allocated)); + } + + return start; } // Out of memory @@ -169,17 +170,24 @@ zoffset ZMemoryManager::alloc_high_address(size_t size) { ZListReverseIterator iter(&_freelist); for (ZMemory* area; iter.next(&area);) { if (area->size() >= size) { + zoffset start; + if (area->size() == size) { // Exact match, remove area - const zoffset start = area->start(); + start = area->start(); _freelist.remove(area); - destroy(area); - return start; + delete area; } else { // Larger than requested, shrink area shrink_from_back(area, size); - return to_zoffset(area->end()); + start = to_zoffset(area->end()); } + + if (_callbacks._prepare_for_hand_out != nullptr) { + _callbacks._prepare_for_hand_out(ZMemory(start, size)); + } + + return start; } } @@ -187,12 +195,10 @@ zoffset ZMemoryManager::alloc_high_address(size_t size) { return zoffset(UINTPTR_MAX); } -void ZMemoryManager::free(zoffset start, size_t size) { +void ZMemoryManager::move_into(zoffset start, size_t size) { assert(start != zoffset(UINTPTR_MAX), "Invalid address"); const zoffset_end end = to_zoffset_end(start, size); - ZLocker locker(&_lock); - ZListIterator iter(&_freelist); for (ZMemory* area; iter.next(&area);) { if (start < area->start()) { @@ -213,7 +219,7 @@ void ZMemoryManager::free(zoffset start, size_t size) { } else { // Insert new area before current area assert(end < area->start(), "Areas must not overlap"); - ZMemory* const new_area = create(start, size); + ZMemory* const new_area = new ZMemory(start, size); _freelist.insert_before(area, new_area); } @@ -229,7 +235,50 @@ void ZMemoryManager::free(zoffset start, size_t size) { grow_from_back(last, size); } else { // Insert new area last - ZMemory* const new_area = create(start, size); + ZMemory* const new_area = new ZMemory(start, size); _freelist.insert_last(new_area); } } + +void ZMemoryManager::free(zoffset start, size_t size) { + ZLocker locker(&_lock); + + if (_callbacks._prepare_for_hand_back != nullptr) { + _callbacks._prepare_for_hand_back(ZMemory(start, size)); + } + + move_into(start, size); +} + +void ZMemoryManager::register_range(zoffset start, size_t size) { + // Note that there's no need to call the _prepare_for_hand_back when memory + // is added the first time. We don't have to undo the effects of a previous + // _prepare_for_hand_out callback. + + // No need to lock during initialization. + + move_into(start, size); +} + +bool ZMemoryManager::unregister_first(zoffset* start_out, size_t* size_out) { + // Note that this doesn't hand out memory to be used, so we don't call the + // _prepare_for_hand_out callback. + + ZLocker locker(&_lock); + + if (_freelist.is_empty()) { + return false; + } + + // Don't invoke the _prepare_for_hand_out callback + + ZMemory* const area = _freelist.remove_first(); + + // Return the range + *start_out = area->start(); + *size_out = area->size(); + + delete area; + + return true; +} diff --git a/src/hotspot/share/gc/z/zMemory.hpp b/src/hotspot/share/gc/z/zMemory.hpp index 229d5a7c50c..da37596c1c7 100644 --- a/src/hotspot/share/gc/z/zMemory.hpp +++ b/src/hotspot/share/gc/z/zMemory.hpp @@ -44,6 +44,11 @@ public: zoffset_end end() const; size_t size() const; + bool operator==(const ZMemory& other) const; + bool operator!=(const ZMemory& other) const; + + bool contains(const ZMemory& other) const; + void shrink_from_front(size_t size); void shrink_from_back(size_t size); void grow_from_front(size_t size); @@ -51,17 +56,17 @@ public: }; class ZMemoryManager { + friend class ZVirtualMemoryManagerTest; + public: - typedef void (*CreateDestroyCallback)(const ZMemory* area); - typedef void (*ResizeCallback)(const ZMemory* area, size_t size); + typedef void (*CallbackPrepare)(const ZMemory& area); + typedef void (*CallbackResize)(const ZMemory& from, const ZMemory& to); struct Callbacks { - CreateDestroyCallback _create; - CreateDestroyCallback _destroy; - ResizeCallback _shrink_from_front; - ResizeCallback _shrink_from_back; - ResizeCallback _grow_from_front; - ResizeCallback _grow_from_back; + CallbackPrepare _prepare_for_hand_out; + CallbackPrepare _prepare_for_hand_back; + CallbackResize _grow; + CallbackResize _shrink; Callbacks(); }; @@ -71,13 +76,13 @@ private: ZList _freelist; Callbacks _callbacks; - ZMemory* create(zoffset start, size_t size); - void destroy(ZMemory* area); void shrink_from_front(ZMemory* area, size_t size); void shrink_from_back(ZMemory* area, size_t size); void grow_from_front(ZMemory* area, size_t size); void grow_from_back(ZMemory* area, size_t size); + void move_into(zoffset start, size_t size); + public: ZMemoryManager(); @@ -92,6 +97,8 @@ public: zoffset alloc_high_address(size_t size); void free(zoffset start, size_t size); + void register_range(zoffset start, size_t size); + bool unregister_first(zoffset* start_out, size_t* size_out); }; #endif // SHARE_GC_Z_ZMEMORY_HPP diff --git a/src/hotspot/share/gc/z/zMemory.inline.hpp b/src/hotspot/share/gc/z/zMemory.inline.hpp index 154ac6d69f2..39e5b26d856 100644 --- a/src/hotspot/share/gc/z/zMemory.inline.hpp +++ b/src/hotspot/share/gc/z/zMemory.inline.hpp @@ -46,6 +46,18 @@ inline size_t ZMemory::size() const { return end() - start(); } +inline bool ZMemory::operator==(const ZMemory& other) const { + return _start == other._start && _end == other._end; +} + +inline bool ZMemory::operator!=(const ZMemory& other) const { + return !operator==(other); +} + +inline bool ZMemory::contains(const ZMemory& other) const { + return _start <= other._start && other.end() <= end(); +} + inline void ZMemory::shrink_from_front(size_t size) { assert(this->size() > size, "Too small"); _start += size; diff --git a/src/hotspot/share/gc/z/zNMT.cpp b/src/hotspot/share/gc/z/zNMT.cpp index 07ea8df1325..4e1efbf9caf 100644 --- a/src/hotspot/share/gc/z/zNMT.cpp +++ b/src/hotspot/share/gc/z/zNMT.cpp @@ -40,6 +40,26 @@ void ZNMT::reserve(zaddress_unsafe start, size_t size) { MemTracker::record_virtual_memory_reserve((address)untype(start), size, CALLER_PC, mtJavaHeap); } +void ZNMT::unreserve(zaddress_unsafe start, size_t size) { + precond(is_aligned(untype(start), ZGranuleSize)); + precond(is_aligned(size, ZGranuleSize)); + + if (MemTracker::enabled()) { + // We are the owner of the reserved memory, and any failure to unreserve + // are fatal, so so we don't need to hold a lock while unreserving memory. + + MemTracker::NmtVirtualMemoryLocker nvml; + + // The current NMT implementation does not support unreserving a memory + // region that was built up from smaller memory reservations. Workaround + // this problem by splitting the work up into granule-sized chunks, which + // is the smallest unit we ever reserve. + for (size_t i = 0; i < size; i += ZGranuleSize) { + MemTracker::record_virtual_memory_release((address)untype(start + i), ZGranuleSize); + } + } +} + void ZNMT::commit(zoffset offset, size_t size) { MemTracker::allocate_memory_in(ZNMT::_device, untype(offset), size, CALLER_PC, mtJavaHeap); } diff --git a/src/hotspot/share/gc/z/zNMT.hpp b/src/hotspot/share/gc/z/zNMT.hpp index d75b48808d4..bea6a6b62ac 100644 --- a/src/hotspot/share/gc/z/zNMT.hpp +++ b/src/hotspot/share/gc/z/zNMT.hpp @@ -42,6 +42,8 @@ public: static void initialize(); static void reserve(zaddress_unsafe start, size_t size); + static void unreserve(zaddress_unsafe start, size_t size); + static void commit(zoffset offset, size_t size); static void uncommit(zoffset offset, size_t size); diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.cpp b/src/hotspot/share/gc/z/zPhysicalMemory.cpp index 541e60051c3..5b209a4c01c 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp +++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp @@ -238,7 +238,7 @@ ZPhysicalMemory ZPhysicalMemory::split_committed() { ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity) : _backing(max_capacity) { // Make the whole range free - _manager.free(zoffset(0), max_capacity); + _manager.register_range(zoffset(0), max_capacity); } bool ZPhysicalMemoryManager::is_initialized() const { diff --git a/src/hotspot/share/gc/z/zVirtualMemory.cpp b/src/hotspot/share/gc/z/zVirtualMemory.cpp index 21152cf4db6..471fc6f505e 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.cpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.cpp @@ -42,6 +42,9 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity) // Initialize platform specific parts before reserving address space pd_initialize_before_reserve(); + // Register the Windows callbacks + pd_register_callbacks(&_manager); + // Reserve address space if (!reserve(max_capacity)) { ZInitialize::error_d("Failed to reserve enough address space for Java heap"); @@ -51,9 +54,6 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity) // Set ZAddressOffsetMax to the highest address end available after reservation ZAddressOffsetMax = untype(highest_available_address_end()); - // Initialize platform specific parts after reserving address space - pd_initialize_after_reserve(); - // Successfully initialized _initialized = true; } @@ -154,7 +154,7 @@ bool ZVirtualMemoryManager::reserve_contiguous(zoffset start, size_t size) { ZNMT::reserve(addr, size); // Make the address range free - _manager.free(start, size); + _manager.register_range(start, size); return true; } @@ -211,6 +211,25 @@ bool ZVirtualMemoryManager::reserve(size_t max_capacity) { return reserved >= max_capacity; } +void ZVirtualMemoryManager::unreserve(zoffset start, size_t size) { + const zaddress_unsafe addr = ZOffset::address_unsafe(start); + + // Unregister the reserved memory from NMT + ZNMT::unreserve(addr, size); + + // Unreserve address space + pd_unreserve(addr, size); +} + +void ZVirtualMemoryManager::unreserve_all() { + zoffset start; + size_t size; + + while (_manager.unregister_first(&start, &size)) { + unreserve(start, size); + } +} + bool ZVirtualMemoryManager::is_initialized() const { return _initialized; } diff --git a/src/hotspot/share/gc/z/zVirtualMemory.hpp b/src/hotspot/share/gc/z/zVirtualMemory.hpp index 57a377ab61b..f5185549e8a 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.hpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.hpp @@ -48,6 +48,7 @@ public: class ZVirtualMemoryManager { friend class ZMapperTest; + friend class ZVirtualMemoryManagerTest; private: static size_t calculate_min_range(size_t size); @@ -58,7 +59,7 @@ private: // Platform specific implementation void pd_initialize_before_reserve(); - void pd_initialize_after_reserve(); + void pd_register_callbacks(ZMemoryManager* manager); bool pd_reserve(zaddress_unsafe addr, size_t size); void pd_unreserve(zaddress_unsafe addr, size_t size); @@ -68,6 +69,8 @@ private: size_t reserve_discontiguous(size_t size); bool reserve(size_t max_capacity); + void unreserve(zoffset start, size_t size); + DEBUG_ONLY(size_t force_reserve_discontiguous(size_t size);) public: @@ -81,6 +84,8 @@ public: ZVirtualMemory alloc(size_t size, bool force_low_address); void free(const ZVirtualMemory& vmem); + + void unreserve_all(); }; #endif // SHARE_GC_Z_ZVIRTUALMEMORY_HPP diff --git a/test/hotspot/gtest/gc/z/test_zMapper_windows.cpp b/test/hotspot/gtest/gc/z/test_zMapper_windows.cpp index 79ad840b50b..c66bb04668a 100644 --- a/test/hotspot/gtest/gc/z/test_zMapper_windows.cpp +++ b/test/hotspot/gtest/gc/z/test_zMapper_windows.cpp @@ -29,182 +29,71 @@ #include "gc/z/zMapper_windows.hpp" #include "gc/z/zMemory.inline.hpp" #include "gc/z/zSyscall_windows.hpp" -#include "gc/z/zVirtualMemory.hpp" +#include "gc/z/zVirtualMemory.inline.hpp" #include "runtime/os.hpp" -#include "unittest.hpp" +#include "zunittest.hpp" using namespace testing; -#define EXPECT_ALLOC_OK(offset) EXPECT_NE(offset, zoffset(UINTPTR_MAX)) - -class ZMapperTest : public Test { +class ZMapperTest : public ZTest { private: - static constexpr size_t ZMapperTestReservationSize = 32 * M; + static constexpr size_t ReservationSize = 32 * M; - static bool _initialized; - static ZMemoryManager* _va; - - static ZVirtualMemoryManager* _vmm; - - static bool _has_unreserved; + ZVirtualMemoryManager* _vmm; + ZMemoryManager* _va; public: - bool reserve_for_test() { - // Initialize platform specific parts before reserving address space - _vmm->pd_initialize_before_reserve(); - - // Reserve address space - if (!_vmm->pd_reserve(ZOffset::address_unsafe(zoffset(0)), ZMapperTestReservationSize)) { - return false; - } - - // Make the address range free before setting up callbacks below - _va->free(zoffset(0), ZMapperTestReservationSize); - - // Initialize platform specific parts after reserving address space - _vmm->pd_initialize_after_reserve(); - - return true; - } - virtual void SetUp() { // Only run test on supported Windows versions - if (!ZSyscall::is_supported()) { + if (!is_os_supported()) { GTEST_SKIP() << "Requires Windows version 1803 or later"; - return; } - ZSyscall::initialize(); - ZGlobalsPointers::initialize(); - // Fake a ZVirtualMemoryManager _vmm = (ZVirtualMemoryManager*)os::malloc(sizeof(ZVirtualMemoryManager), mtTest); + _vmm = ::new (_vmm) ZVirtualMemoryManager(ReservationSize); // Construct its internal ZMemoryManager _va = new (&_vmm->_manager) ZMemoryManager(); // Reserve address space for the test - if (!reserve_for_test()) { + if (_vmm->reserved() != ReservationSize) { GTEST_SKIP() << "Failed to reserve address space"; - return; } - - _initialized = true; - _has_unreserved = false; } virtual void TearDown() { - if (!ZSyscall::is_supported()) { + if (!is_os_supported()) { // Test skipped, nothing to cleanup return; } - if (_initialized && !_has_unreserved) { - _vmm->pd_unreserve(ZOffset::address_unsafe(zoffset(0)), 0); - } + // Best-effort cleanup + _vmm->unreserve_all(); + _vmm->~ZVirtualMemoryManager(); os::free(_vmm); } - static void test_unreserve() { + void test_unreserve() { zoffset bottom = _va->alloc_low_address(ZGranuleSize); - zoffset top = _va->alloc_high_address(ZGranuleSize); + zoffset middle = _va->alloc_low_address(ZGranuleSize); + zoffset top = _va->alloc_low_address(ZGranuleSize); + + ASSERT_EQ(bottom, zoffset(0)); + ASSERT_EQ(middle, bottom + 1 * ZGranuleSize); + ASSERT_EQ(top, bottom + 2 * ZGranuleSize); // Unreserve the middle part - ZMapper::unreserve(ZOffset::address_unsafe(bottom + ZGranuleSize), ZGranuleSize); + ZMapper::unreserve(ZOffset::address_unsafe(middle), ZGranuleSize); // Make sure that we still can unreserve the memory before and after ZMapper::unreserve(ZOffset::address_unsafe(bottom), ZGranuleSize); ZMapper::unreserve(ZOffset::address_unsafe(top), ZGranuleSize); - - _has_unreserved = true; - } - - static void test_alloc_low_address() { - // Verify that we get placeholder for first granule - zoffset bottom = _va->alloc_low_address(ZGranuleSize); - EXPECT_ALLOC_OK(bottom); - - _va->free(bottom, ZGranuleSize); - - // Alloc something larger than a granule and free it - bottom = _va->alloc_low_address(ZGranuleSize * 3); - EXPECT_ALLOC_OK(bottom); - - _va->free(bottom, ZGranuleSize * 3); - - // Free with more memory allocated - bottom = _va->alloc_low_address(ZGranuleSize); - EXPECT_ALLOC_OK(bottom); - - zoffset next = _va->alloc_low_address(ZGranuleSize); - EXPECT_ALLOC_OK(next); - - _va->free(bottom, ZGranuleSize); - _va->free(next, ZGranuleSize); - } - - static void test_alloc_high_address() { - // Verify that we get placeholder for last granule - zoffset high = _va->alloc_high_address(ZGranuleSize); - EXPECT_ALLOC_OK(high); - - zoffset prev = _va->alloc_high_address(ZGranuleSize); - EXPECT_ALLOC_OK(prev); - - _va->free(high, ZGranuleSize); - _va->free(prev, ZGranuleSize); - - // Alloc something larger than a granule and return it - high = _va->alloc_high_address(ZGranuleSize * 2); - EXPECT_ALLOC_OK(high); - - _va->free(high, ZGranuleSize * 2); - } - - static void test_alloc_whole_area() { - // Alloc the whole reservation - zoffset bottom = _va->alloc_low_address(ZMapperTestReservationSize); - EXPECT_ALLOC_OK(bottom); - - // Free two chunks and then allocate them again - _va->free(bottom, ZGranuleSize * 4); - _va->free(bottom + ZGranuleSize * 6, ZGranuleSize * 6); - - zoffset offset = _va->alloc_low_address(ZGranuleSize * 4); - EXPECT_ALLOC_OK(offset); - - offset = _va->alloc_low_address(ZGranuleSize * 6); - EXPECT_ALLOC_OK(offset); - - // Now free it all, and verify it can be re-allocated - _va->free(bottom, ZMapperTestReservationSize); - - bottom = _va->alloc_low_address(ZMapperTestReservationSize); - EXPECT_ALLOC_OK(bottom); - - _va->free(bottom, ZMapperTestReservationSize); } }; -bool ZMapperTest::_initialized = false; -ZMemoryManager* ZMapperTest::_va = nullptr; -ZVirtualMemoryManager* ZMapperTest::_vmm = nullptr; -bool ZMapperTest::_has_unreserved; - TEST_VM_F(ZMapperTest, test_unreserve) { test_unreserve(); } -TEST_VM_F(ZMapperTest, test_alloc_low_address) { - test_alloc_low_address(); -} - -TEST_VM_F(ZMapperTest, test_alloc_high_address) { - test_alloc_high_address(); -} - -TEST_VM_F(ZMapperTest, test_alloc_whole_area) { - test_alloc_whole_area(); -} - #endif // _WINDOWS diff --git a/test/hotspot/gtest/gc/z/test_zMemory.cpp b/test/hotspot/gtest/gc/z/test_zMemory.cpp index 39b0cc31db1..786a8b3fe32 100644 --- a/test/hotspot/gtest/gc/z/test_zMemory.cpp +++ b/test/hotspot/gtest/gc/z/test_zMemory.cpp @@ -23,28 +23,10 @@ #include "gc/z/zGlobals.hpp" #include "gc/z/zMemory.inline.hpp" -#include "unittest.hpp" - -class ZAddressOffsetMaxSetter { -private: - const size_t _old_max; - const size_t _old_mask; - -public: - ZAddressOffsetMaxSetter() - : _old_max(ZAddressOffsetMax), - _old_mask(ZAddressOffsetMask) { - ZAddressOffsetMax = size_t(16) * G * 1024; - ZAddressOffsetMask = ZAddressOffsetMax - 1; - } - ~ZAddressOffsetMaxSetter() { - ZAddressOffsetMax = _old_max; - ZAddressOffsetMask = _old_mask; - } -}; +#include "zunittest.hpp" TEST(ZMemory, accessors) { - ZAddressOffsetMaxSetter setter; + ZAddressOffsetMaxSetter setter(size_t(16) * G * 1024); { ZMemory mem(zoffset(0), ZGranuleSize); @@ -74,7 +56,7 @@ TEST(ZMemory, accessors) { } TEST(ZMemory, resize) { - ZAddressOffsetMaxSetter setter; + ZAddressOffsetMaxSetter setter(size_t(16) * G * 1024); ZMemory mem(zoffset(ZGranuleSize * 2), ZGranuleSize * 2) ; diff --git a/test/hotspot/gtest/gc/z/test_zVirtualMemory.cpp b/test/hotspot/gtest/gc/z/test_zVirtualMemory.cpp index d09d79f8b1c..facbb14e8a0 100644 --- a/test/hotspot/gtest/gc/z/test_zVirtualMemory.cpp +++ b/test/hotspot/gtest/gc/z/test_zVirtualMemory.cpp @@ -22,9 +22,11 @@ */ #include "gc/z/zVirtualMemory.inline.hpp" -#include "unittest.hpp" +#include "zunittest.hpp" TEST(ZVirtualMemory, split) { + ZAddressOffsetMaxSetter setter(size_t(16) * G * 1024); + ZVirtualMemory vmem(zoffset(0), 10); ZVirtualMemory vmem0 = vmem.split(0); diff --git a/test/hotspot/gtest/gc/z/test_zVirtualMemoryManager.cpp b/test/hotspot/gtest/gc/z/test_zVirtualMemoryManager.cpp new file mode 100644 index 00000000000..1100b1e005e --- /dev/null +++ b/test/hotspot/gtest/gc/z/test_zVirtualMemoryManager.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zArguments.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zInitialize.hpp" +#include "gc/z/zList.inline.hpp" +#include "gc/z/zMemory.inline.hpp" +#include "gc/z/zNUMA.inline.hpp" +#include "gc/z/zValue.inline.hpp" +#include "gc/z/zVirtualMemory.hpp" +#include "runtime/os.hpp" +#include "zunittest.hpp" + +using namespace testing; + +#define ASSERT_ALLOC_OK(offset) ASSERT_NE(offset, zoffset(UINTPTR_MAX)) + +class ZCallbacksResetter { +private: + ZMemoryManager::Callbacks* _callbacks; + ZMemoryManager::Callbacks _saved; + +public: + ZCallbacksResetter(ZMemoryManager::Callbacks* callbacks) + : _callbacks(callbacks), + _saved(*callbacks) { + *_callbacks = {}; + } + ~ZCallbacksResetter() { + *_callbacks = _saved; + } +}; + +class ZVirtualMemoryManagerTest : public ZTest { +private: + static constexpr size_t ReservationSize = 32 * M; + + ZMemoryManager* _va; + ZVirtualMemoryManager* _vmm; + +public: + virtual void SetUp() { + // Only run test on supported Windows versions + if (!is_os_supported()) { + GTEST_SKIP() << "OS not supported"; + } + + void* vmr_mem = os::malloc(sizeof(ZVirtualMemoryManager), mtTest); + _vmm = ::new (vmr_mem) ZVirtualMemoryManager(ReservationSize); + _va = &_vmm->_manager; + } + + virtual void TearDown() { + if (!is_os_supported()) { + // Test skipped, nothing to cleanup + return; + } + + // Best-effort cleanup + _vmm->unreserve_all(); + _vmm->~ZVirtualMemoryManager(); + os::free(_vmm); + } + + void test_reserve_discontiguous_and_coalesce() { + // Start by ensuring that we have 3 unreserved granules, and then let the + // fourth granule be pre-reserved and therefore blocking subsequent requests + // to reserve memory. + // + // +----+----+----+----+ + // ----- pre-reserved - to block contiguous reservation + // --------------- unreserved - to allow reservation of 3 granules + // + // If we then asks for 4 granules starting at the first granule above, + // then we won't be able to allocate 4 consecutive granules and the code + // reverts into the discontiguous mode. This mode uses interval halving + // to find the limits of memory areas that have already been reserved. + // This will lead to the first 2 granules being reserved, then the third + // granule will be reserved. + // + // The problem we had with this is that this would yield two separate + // placeholder reservations, even though they are adjacent. The callbacks + // are supposed to fix that by coalescing the placeholders, *but* the + // callbacks used to be only turned on *after* the reservation call. So, + // we end up with one 3 granule large memory area in the manager, which + // unexpectedly was covered by two placeholders (instead of the expected + // one placeholder). + // + // Later when the callbacks had been installed and we tried to fetch memory + // from the manager, the callbacks would try to split off the placeholder + // to separate the fetched memory from the memory left in the manager. This + // used to fail because the memory was already split into two placeholders. + + if (_vmm->reserved() < 4 * ZGranuleSize || !_va->free_is_contiguous()) { + GTEST_SKIP() << "Fixture failed to reserve adequate memory, reserved " + << (_vmm->reserved() >> ZGranuleSizeShift) << " * ZGranuleSize"; + } + + // Start at the offset we reserved. + const zoffset base_offset = _vmm->lowest_available_address(); + + // Empty the reserved memory in preparation for the rest of the test. + _vmm->unreserve_all(); + + const zaddress_unsafe base = ZOffset::address_unsafe(base_offset); + const zaddress_unsafe blocked = base + 3 * ZGranuleSize; + + // Reserve the memory that is acting as a blocking reservation. + { + char* const result = os::attempt_reserve_memory_at((char*)untype(blocked), ZGranuleSize, !ExecMem, mtTest); + if (uintptr_t(result) != untype(blocked)) { + GTEST_SKIP() << "Failed to reserve requested memory at " << untype(blocked); + } + } + + { + // This ends up reserving 2 granules and then 1 granule adjacent to the + // first. In previous implementations this resulted in two separate + // placeholders (4MB and 2MB). This was a bug, because the manager is + // designed to have one placeholder per memory area. This in turn would + // lead to a subsequent failure when _vmm->alloc tried to split off the + // 4MB that is already covered by its own placeholder. You can't place + // a placeholder over an already existing placeholder. + + // To reproduce this, the test needed to mimic the initializing memory + // reservation code which had the placeholders turned off. This was done + // with this helper: + // + // ZCallbacksResetter resetter(&_va->_callbacks); + // + // After the fix, we always have the callbacks turned on, so we don't + // need this to mimic the initializing memory reservation. + + const size_t reserved = _vmm->reserve_discontiguous(base_offset, 4 * ZGranuleSize, ZGranuleSize); + ASSERT_LE(reserved, 3 * ZGranuleSize); + if (reserved < 3 * ZGranuleSize) { + GTEST_SKIP() << "Failed reserve_discontiguous" + ", expected 3 * ZGranuleSize, got " << (reserved >> ZGranuleSizeShift) + << " * ZGranuleSize"; + } + } + + { + // The test used to crash here because the 3 granule memory area was + // inadvertently covered by two place holders (2 granules + 1 granule). + const ZVirtualMemory vmem = _vmm->alloc(2 * ZGranuleSize, true); + ASSERT_EQ(vmem.start(), base_offset); + ASSERT_EQ(vmem.size(), 2 * ZGranuleSize); + + // Cleanup - Must happen in granule-sizes because of how Windows hands + // out memory in granule-sized placeholder reservations. + _vmm->unreserve(base_offset, ZGranuleSize); + _vmm->unreserve(base_offset + ZGranuleSize, ZGranuleSize); + } + + // Final cleanup + const ZVirtualMemory vmem = _vmm->alloc(ZGranuleSize, true); + ASSERT_EQ(vmem.start(), base_offset + 2 * ZGranuleSize); + ASSERT_EQ(vmem.size(), ZGranuleSize); + _vmm->unreserve(vmem.start(), vmem.size()); + + const bool released = os::release_memory((char*)untype(blocked), ZGranuleSize); + ASSERT_TRUE(released); + } + + void test_alloc_low_address() { + // Verify that we get a placeholder for the first granule + zoffset bottom = _va->alloc_low_address(ZGranuleSize); + ASSERT_ALLOC_OK(bottom); + + _va->free(bottom, ZGranuleSize); + + // Alloc something larger than a granule and free it + bottom = _va->alloc_low_address(ZGranuleSize * 3); + ASSERT_ALLOC_OK(bottom); + + _va->free(bottom, ZGranuleSize * 3); + + // Free with more memory allocated + bottom = _va->alloc_low_address(ZGranuleSize); + ASSERT_ALLOC_OK(bottom); + + zoffset next = _va->alloc_low_address(ZGranuleSize); + ASSERT_ALLOC_OK(next); + + _va->free(bottom, ZGranuleSize); + _va->free(next, ZGranuleSize); + } + + void test_alloc_high_address() { + // Verify that we get a placeholder for the last granule + zoffset high = _va->alloc_high_address(ZGranuleSize); + ASSERT_ALLOC_OK(high); + + zoffset prev = _va->alloc_high_address(ZGranuleSize); + ASSERT_ALLOC_OK(prev); + + _va->free(high, ZGranuleSize); + _va->free(prev, ZGranuleSize); + + // Alloc something larger than a granule and return it + high = _va->alloc_high_address(ZGranuleSize * 2); + ASSERT_ALLOC_OK(high); + + _va->free(high, ZGranuleSize * 2); + } + + void test_alloc_whole_area() { + // Alloc the whole reservation + zoffset bottom = _va->alloc_low_address(ReservationSize); + ASSERT_ALLOC_OK(bottom); + + // Free two chunks and then allocate them again + _va->free(bottom, ZGranuleSize * 4); + _va->free(bottom + ZGranuleSize * 6, ZGranuleSize * 6); + + zoffset offset = _va->alloc_low_address(ZGranuleSize * 4); + ASSERT_ALLOC_OK(offset); + + offset = _va->alloc_low_address(ZGranuleSize * 6); + ASSERT_ALLOC_OK(offset); + + // Now free it all, and verify it can be re-allocated + _va->free(bottom, ReservationSize); + + bottom = _va->alloc_low_address(ReservationSize); + ASSERT_ALLOC_OK(bottom); + + _va->free(bottom, ReservationSize); + } +}; + +TEST_VM_F(ZVirtualMemoryManagerTest, test_reserve_discontiguous_and_coalesce) { + test_reserve_discontiguous_and_coalesce(); +} + +TEST_VM_F(ZVirtualMemoryManagerTest, test_alloc_low_address) { + test_alloc_low_address(); +} + +TEST_VM_F(ZVirtualMemoryManagerTest, test_alloc_high_address) { + test_alloc_high_address(); +} + +TEST_VM_F(ZVirtualMemoryManagerTest, test_alloc_whole_area) { + test_alloc_whole_area(); +} diff --git a/test/hotspot/gtest/gc/z/zunittest.hpp b/test/hotspot/gtest/gc/z/zunittest.hpp new file mode 100644 index 00000000000..610d158c89d --- /dev/null +++ b/test/hotspot/gtest/gc/z/zunittest.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef ZUNITTEST_HPP +#define ZUNITTEST_HPP + +#include "gc/z/zAddress.hpp" +#include "gc/z/zArguments.hpp" +#include "gc/z/zInitialize.hpp" +#include "unittest.hpp" + +class ZAddressOffsetMaxSetter { + friend class ZTest; + +private: + size_t _old_max; + size_t _old_mask; + +public: + ZAddressOffsetMaxSetter(size_t zaddress_offset_max) + : _old_max(ZAddressOffsetMax), + _old_mask(ZAddressOffsetMask) { + ZAddressOffsetMax = zaddress_offset_max; + ZAddressOffsetMask = ZAddressOffsetMax - 1; + } + ~ZAddressOffsetMaxSetter() { + ZAddressOffsetMax = _old_max; + ZAddressOffsetMask = _old_mask; + } +}; + +class ZTest : public testing::Test { +private: + ZAddressOffsetMaxSetter _zaddress_offset_max_setter; + +protected: + ZTest() + : _zaddress_offset_max_setter(ZAddressOffsetMax) { + if (!is_os_supported()) { + // If the OS does not support ZGC do not run initialization, as it may crash the VM. + return; + } + + // Initialize ZGC subsystems for gtests, may only be called once per process. + static bool runs_once = [&]() { + ZInitialize::pd_initialize(); + ZGlobalsPointers::initialize(); + + // ZGlobalsPointers::initialize() sets ZAddressOffsetMax, make sure the + // first test fixture invocation has a correct ZAddressOffsetMaxSetter. + _zaddress_offset_max_setter._old_max = ZAddressOffsetMax; + _zaddress_offset_max_setter._old_mask = ZAddressOffsetMask; + return true; + }(); + } + + bool is_os_supported() { + return ZArguments::is_os_supported(); + } +}; + +#endif // ZUNITTEST_HPP From e8c9e5c6cd3c844765c27c068022a018914fdf4e Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 7 Apr 2025 11:34:23 +0000 Subject: [PATCH 012/843] 8353231: Test com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad still fails intermittently Reviewed-by: dholmes --- .../OperatingSystemMXBean/TEST.properties | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/jdk/com/sun/management/OperatingSystemMXBean/TEST.properties diff --git a/test/jdk/com/sun/management/OperatingSystemMXBean/TEST.properties b/test/jdk/com/sun/management/OperatingSystemMXBean/TEST.properties new file mode 100644 index 00000000000..9ddb06fbbcb --- /dev/null +++ b/test/jdk/com/sun/management/OperatingSystemMXBean/TEST.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +exclusiveAccess.dirs=. From 26bb18378737809542b1153f8f34d55d409ea4e2 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 7 Apr 2025 11:56:53 +0000 Subject: [PATCH 013/843] 8352621: MatchException from backwards incompatible change to switch expressions Reviewed-by: abimpoudis --- .../sun/tools/javac/comp/TransPatterns.java | 9 +- .../com/sun/tools/javac/jvm/Target.java | 9 +- .../NoPrimitivesAsCaseLabelsFor21.java | 166 ++++++++++++++++++ 3 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 test/langtools/tools/javac/patterns/NoPrimitivesAsCaseLabelsFor21.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java index 93c4eaa03ee..58c36a5cf7c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1041,7 +1041,12 @@ public class TransPatterns extends TreeTranslator { private LoadableConstant toLoadableConstant(JCCaseLabel l, Type selector) { if (l.hasTag(Tag.PATTERNCASELABEL)) { Type principalType = principalType(((JCPatternCaseLabel) l).pat); - if (((JCPatternCaseLabel) l).pat.type.isReference()) { + + if (target.switchBootstrapOnlyAllowsReferenceTypesAsCaseLabels()) { + principalType = types.boxedTypeOrType(principalType); + } + + if (principalType.isReference()) { if (types.isSubtype(selector, principalType)) { return (LoadableConstant) selector; } else { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java index 5b207352e6e..eeca1dadc1b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,4 +245,11 @@ public enum Target { public boolean nullCheckOuterThisByDefault() { return compareTo(JDK1_25) >= 0; } + + /** Releases prior to JDK 23 don't allow primitive types as case labels in + * SwitchBootstrap.typeSwitch + */ + public boolean switchBootstrapOnlyAllowsReferenceTypesAsCaseLabels() { + return compareTo(Target.JDK1_23) < 0; + } } diff --git a/test/langtools/tools/javac/patterns/NoPrimitivesAsCaseLabelsFor21.java b/test/langtools/tools/javac/patterns/NoPrimitivesAsCaseLabelsFor21.java new file mode 100644 index 00000000000..bd5f51b644e --- /dev/null +++ b/test/langtools/tools/javac/patterns/NoPrimitivesAsCaseLabelsFor21.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8352621 + * @summary Verify javac does not use primitive types in SwitchBootstraps.typeSwitch + * when compiling with target older than JDK 23 + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask + * @run main NoPrimitivesAsCaseLabelsFor21 +*/ + +import java.io.IOException; +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.constantpool.ClassEntry; +import java.lang.classfile.constantpool.LoadableConstantEntry; +import java.lang.classfile.constantpool.MethodHandleEntry; +import java.lang.constant.DirectMethodHandleDesc; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.atomic.AtomicBoolean; + +import toolbox.JavacTask; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class NoPrimitivesAsCaseLabelsFor21 extends TestRunner { + + ToolBox tb; + + public static void main(String... args) throws Exception { + new NoPrimitivesAsCaseLabelsFor21().runTests(); + } + + NoPrimitivesAsCaseLabelsFor21() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testExhaustiveSealedClasses(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + + tb.writeJavaFiles(src, + """ + package test; + public class Test { + private int test(Object obj) { + return switch (obj) { + case R1(String s1, String s2) when s1.isEmpty() -> 0; + case R1(String s1, String s2) -> 1; + case R2(int i1, int i2) when i1 == 0 -> 2; + case R2(int i1, int i2) -> 3; + default -> 4; + }; + } + record R1(String s1, String s2) {} + record R2(int i1, int i2) {} + } + """); + + Path classes = current.resolve("classes"); + + Files.createDirectories(classes); + + for (String version : new String[] {"23", System.getProperty("java.specification.version")}) { + new JavacTask(tb) + .options("--release", version) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + Path testClassFile = classes.resolve("test").resolve("Test.class"); + String primitivesInBoostrapArgsForNewer = + findPrimitiveBootstrapArguments(testClassFile); + + if (!primitivesInBoostrapArgsForNewer.contains("I-Ljava/lang/Class")) { + throw new AssertionError("Expected primitive types in switch bootstrap arguments: " + primitivesInBoostrapArgsForNewer); + } + } + + for (String version : new String[] {"21", "22"}) { + new JavacTask(tb) + .options("--release", version) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + Path testClassFile = classes.resolve("test").resolve("Test.class"); + String primitivesInBoostrapArgsForOlder = + findPrimitiveBootstrapArguments(testClassFile); + + + if (!primitivesInBoostrapArgsForOlder.isEmpty()) { + throw new AssertionError("Unexpected primitive types in switch bootstrap arguments: " + primitivesInBoostrapArgsForOlder); + } + } + } + + private String findPrimitiveBootstrapArguments(Path forFile) throws IOException { + AtomicBoolean hasTypeSwitchBootStrap = new AtomicBoolean(); + StringBuilder nonClassInTypeSwitchBootStrap = new StringBuilder(); + ClassModel testClassFileModel = ClassFile.of().parse(forFile); + + testClassFileModel.findAttribute(Attributes.bootstrapMethods()) + .orElseThrow() + .bootstrapMethods() + .stream() + .filter(bme -> isTypeSwitchBoostrap(bme.bootstrapMethod())) + .forEach(bme -> { + hasTypeSwitchBootStrap.set(true); + for (LoadableConstantEntry e : bme.arguments()) { + if (!(e instanceof ClassEntry)) { + nonClassInTypeSwitchBootStrap.append(String.valueOf(e)); + } + } + }); + + if (!hasTypeSwitchBootStrap.get()) { + throw new AssertionError("Didn't find any typeSwitch bootstraps!"); + } + + return nonClassInTypeSwitchBootStrap.toString(); + } + + private static boolean isTypeSwitchBoostrap(MethodHandleEntry entry) { + DirectMethodHandleDesc desc = entry.asSymbol(); + return "Ljava/lang/runtime/SwitchBootstraps;".equals(desc.owner().descriptorString()) && + "typeSwitch".equals(desc.methodName()) && + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;".equals(desc.lookupDescriptor()); + } +} From 353e1738f6eb9965571e1de881d209b698492e6e Mon Sep 17 00:00:00 2001 From: Matthew Donovan Date: Mon, 7 Apr 2025 11:58:17 +0000 Subject: [PATCH 014/843] 8219408: Tests should handle ${} in the view of jtreg "smart action" Reviewed-by: mullan --- test/jdk/com/sun/security/auth/login/ConfigFile/TEST.properties | 2 -- .../jdk/java/security/Security/SecurityPropFile/TEST.properties | 2 -- test/jdk/javax/security/auth/login/TEST.properties | 2 -- test/jdk/sun/security/util/Resources/TEST.properties | 2 -- 4 files changed, 8 deletions(-) delete mode 100644 test/jdk/com/sun/security/auth/login/ConfigFile/TEST.properties delete mode 100644 test/jdk/java/security/Security/SecurityPropFile/TEST.properties delete mode 100644 test/jdk/javax/security/auth/login/TEST.properties delete mode 100644 test/jdk/sun/security/util/Resources/TEST.properties diff --git a/test/jdk/com/sun/security/auth/login/ConfigFile/TEST.properties b/test/jdk/com/sun/security/auth/login/ConfigFile/TEST.properties deleted file mode 100644 index 908b451f8ea..00000000000 --- a/test/jdk/com/sun/security/auth/login/ConfigFile/TEST.properties +++ /dev/null @@ -1,2 +0,0 @@ -# disabled till JDK-8219408 is fixed -allowSmartActionArgs=false diff --git a/test/jdk/java/security/Security/SecurityPropFile/TEST.properties b/test/jdk/java/security/Security/SecurityPropFile/TEST.properties deleted file mode 100644 index 908b451f8ea..00000000000 --- a/test/jdk/java/security/Security/SecurityPropFile/TEST.properties +++ /dev/null @@ -1,2 +0,0 @@ -# disabled till JDK-8219408 is fixed -allowSmartActionArgs=false diff --git a/test/jdk/javax/security/auth/login/TEST.properties b/test/jdk/javax/security/auth/login/TEST.properties deleted file mode 100644 index 908b451f8ea..00000000000 --- a/test/jdk/javax/security/auth/login/TEST.properties +++ /dev/null @@ -1,2 +0,0 @@ -# disabled till JDK-8219408 is fixed -allowSmartActionArgs=false diff --git a/test/jdk/sun/security/util/Resources/TEST.properties b/test/jdk/sun/security/util/Resources/TEST.properties deleted file mode 100644 index 908b451f8ea..00000000000 --- a/test/jdk/sun/security/util/Resources/TEST.properties +++ /dev/null @@ -1,2 +0,0 @@ -# disabled till JDK-8219408 is fixed -allowSmartActionArgs=false From 66435c27b3e0a89e4350caf6207e36f5a9b82b7f Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 7 Apr 2025 12:28:41 +0000 Subject: [PATCH 015/843] 8352684: Opensource JInternalFrame tests - series1 Reviewed-by: azvegint --- .../swing/JInternalFrame/bug4131008.java | 86 +++++++++++++++++++ .../swing/JInternalFrame/bug4176136.java | 70 +++++++++++++++ .../swing/JInternalFrame/bug4244536.java | 75 ++++++++++++++++ .../swing/JInternalFrame/bug4305284.java | 73 ++++++++++++++++ 4 files changed, 304 insertions(+) create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4131008.java create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4176136.java create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4244536.java create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4305284.java diff --git a/test/jdk/javax/swing/JInternalFrame/bug4131008.java b/test/jdk/javax/swing/JInternalFrame/bug4131008.java new file mode 100644 index 00000000000..9f45175a785 --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4131008.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4131008 + * @summary JInternalFrame should refresh title after it changing + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4131008 +*/ + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.UIManager; + +public class bug4131008 { + + private static final String INSTRUCTIONS = """ + Press button "Change title" at the internal frame "Old". + If title of this frame will replaced by "New", + then test passed, else test fails."""; + + public static void main(String[] args) throws Exception { + + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + + PassFailJFrame.builder() + .title("bug4131008 Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4131008::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4131008"); + JInternalFrame jif = new JInternalFrame("Old"); + JDesktopPane jdp = new JDesktopPane(); + frame.setContentPane(jdp); + + jif.setSize(150, 100); + jif.setVisible(true); + JButton bt = new JButton("Change title"); + bt.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jif.setTitle("New"); + } + }); + jif.getContentPane().add(bt); + jdp.add(jif); + try { + jif.setSelected(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + frame.setSize(300, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JInternalFrame/bug4176136.java b/test/jdk/javax/swing/JInternalFrame/bug4176136.java new file mode 100644 index 00000000000..019e453750c --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4176136.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4176136 + * @summary Default close operation JInternalFrame.DO_NOTHING_ON_CLOSE works correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4176136 + */ + + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; + +public class bug4176136 { + + private static final String INSTRUCTIONS = """ + Click the close button of the internal frame. + You will see the close button activate, + but nothing else should happen. + If the internal frame closes, the test fails. + If it doesn't close, the test passes."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4176136 Instructions") + .instructions(INSTRUCTIONS) + .columns(25) + .testUI(bug4176136::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4176136"); + JDesktopPane dp = new JDesktopPane(); + frame.add(dp); + JInternalFrame inf = new JInternalFrame(); + dp.add(inf); + inf.setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE); + inf.setSize(100, 100); + inf.setClosable(true); + inf.setVisible(true); + frame.setSize(200, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JInternalFrame/bug4244536.java b/test/jdk/javax/swing/JInternalFrame/bug4244536.java new file mode 100644 index 00000000000..85acb833d2a --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4244536.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4244536 + * @summary Tests that Motif JInternalFrame can be maximized + * after it was iconified. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4244536 + */ + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.UIManager; + +public class bug4244536 { + + private static final String INSTRUCTIONS = """ + Minimize the internal frame using the minimize button. + Then double-click on it to restore its size. + Then press the maximize button. + If the frame gets maximized, test passes. + If its size don't change, test fails."""; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + + PassFailJFrame.builder() + .title("bug4244536 Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4244536::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4244536"); + JDesktopPane desktop = new JDesktopPane(); + JInternalFrame jif = new JInternalFrame("Internal Frame"); + jif.setSize(150, 150); + jif.setMaximizable(true); + jif.setIconifiable(true); + jif.setVisible(true); + desktop.add(jif); + frame.add("Center", desktop); + frame.setSize(300, 300); + return frame; + } + +} diff --git a/test/jdk/javax/swing/JInternalFrame/bug4305284.java b/test/jdk/javax/swing/JInternalFrame/bug4305284.java new file mode 100644 index 00000000000..8801c8c678c --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4305284.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4305284 + * @summary JInternalFrames can't be sized off of the desktop + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4305284 + */ + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; + +public class bug4305284 { + + private static final String INSTRUCTIONS = """ + Try to resize the shown internal frame. + If it can't be sized of the desktop bounds, + then test passes, else test fails."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4305284 Instructions") + .instructions(INSTRUCTIONS) + .columns(25) + .testUI(bug4305284::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4305284"); + JInternalFrame jif = new JInternalFrame("Test", + true, true, true, true); + JDesktopPane dp = new JDesktopPane(); + frame.setContentPane(dp); + dp.add(jif); + + try { + jif.setBounds(50, 50, 200, 200); + jif.setMaximum(false); + jif.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + frame.setSize(300, 300); + return frame; + } + +} From 27c8d9d635eaa0aac722c1b1eba8591fd291c077 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 7 Apr 2025 12:30:55 +0000 Subject: [PATCH 016/843] 8352686: Opensource JInternalFrame tests - series3 Reviewed-by: azvegint --- .../swing/JInternalFrame/bug4151444.java | 84 ++++++++++++ .../swing/JInternalFrame/bug4215380.java | 109 +++++++++++++++ .../swing/JInternalFrame/bug4321312.java | 126 ++++++++++++++++++ .../swing/JInternalFrame/bug4322726.java | 109 +++++++++++++++ 4 files changed, 428 insertions(+) create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4151444.java create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4215380.java create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4321312.java create mode 100644 test/jdk/javax/swing/JInternalFrame/bug4322726.java diff --git a/test/jdk/javax/swing/JInternalFrame/bug4151444.java b/test/jdk/javax/swing/JInternalFrame/bug4151444.java new file mode 100644 index 00000000000..26b64142e28 --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4151444.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4151444 + * @summary The maximize button acts like the restore button + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4151444 +*/ + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLayeredPane; +import javax.swing.UIManager; + + +public class bug4151444 { + + private static JFrame frame; + private static JInternalFrame interFrame; + + private static final String INSTRUCTIONS = """ + - maximize the internal frame + - then minimize the internal frame + - then maximize the internal frame again + - Check whether internal frame is maximized + - Test will fail automatically even if "Pass" is pressed + if internal frame is not maximized."""; + + public static void main(String[] args) throws Exception { + + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + + PassFailJFrame pfj = PassFailJFrame.builder() + .title("bug4151444 Instructions") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(bug4151444::createTestUI) + .build(); + try { + pfj.awaitAndCheck(); + } finally { + if (!interFrame.isMaximum()) { + throw new RuntimeException ("Test failed. The maximize button acts like the restore button"); + } + } + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4151444 frame"); + JDesktopPane desktop = new JDesktopPane(); + frame.setContentPane(desktop); + interFrame = new JInternalFrame( + "Internal frame", true, true, true, true); + desktop.add(interFrame, JLayeredPane.DEFAULT_LAYER); + interFrame.setBounds(0, 0, 200, 100); + interFrame.setVisible(true); + frame.setSize(300, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JInternalFrame/bug4215380.java b/test/jdk/javax/swing/JInternalFrame/bug4215380.java new file mode 100644 index 00000000000..f9cd18dfb75 --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4215380.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4215380 + * @summary Internal Frame should get focus + * @key headful + * @run main bug4215380 + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.InputEvent; +import java.awt.Point; +import java.awt.Robot; + +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +public class bug4215380 { + + private static String button; + private static JButton b; + private static JFrame frame; + private static JInternalFrame jif; + private static volatile Point loc; + private static volatile Dimension size; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4215380"); + JDesktopPane desktop = new JDesktopPane(); + frame.add(desktop, BorderLayout.CENTER); + + jif = iFrame(1); + desktop.add(jif, JLayeredPane.DEFAULT_LAYER); + desktop.add(iFrame(2), JLayeredPane.DEFAULT_LAYER); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + loc = b.getLocationOnScreen(); + size = b.getSize(); + }); + robot.mouseMove(loc.x + size.width / 2, loc.y + size.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(500); + if (!(jif.isSelected()) && !button.equals("Frame 1")) { + throw new RuntimeException("Internal frame \"Frame 1\" should be selected..."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static JInternalFrame iFrame(int i) { + JInternalFrame frame = new JInternalFrame("Frame " + i); + JPanel panel = new JPanel(); + JButton bt = new JButton("Button " + i); + if (i == 1) { + b = bt; + } + bt.addActionListener(e -> button = ((JButton)e.getSource()).getText()); + + panel.add(bt); + + frame.getContentPane().add(panel); + frame.setBounds(10, i * 80 - 70, 120, 90); + frame.setVisible(true); + return frame; + } +} diff --git a/test/jdk/javax/swing/JInternalFrame/bug4321312.java b/test/jdk/javax/swing/JInternalFrame/bug4321312.java new file mode 100644 index 00000000000..1b527acf745 --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4321312.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4321312 + * @summary Verifies no Exception thrown from BasicInternalFrameUI$BorderListener + * @key headful + * @run main bug4321312 + */ + +import java.awt.Dimension; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.Point; +import java.awt.Robot; + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class bug4321312 { + + private static JFrame frame; + private static MyInternalFrame jif; + private static volatile Point loc; + private static volatile Dimension size; + + static boolean fails; + static Exception exc; + + private static synchronized boolean isFails() { + return fails; + } + + private static synchronized void setFails(Exception e) { + fails = true; + exc = e; + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + SwingUtilities.invokeAndWait(() -> { + try { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (ClassNotFoundException | InstantiationException + | UnsupportedLookAndFeelException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + + frame = new JFrame("bug4321312"); + JDesktopPane jdp = new JDesktopPane(); + frame.add(jdp); + + jif = new MyInternalFrame("Internal Frame", true); + jdp.add(jif); + jif.setSize(150, 150); + jif.setVisible(true); + + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + loc = jif.getLocationOnScreen(); + size = jif.getSize(); + }); + robot.mouseMove(loc.x + size.width / 2, loc.y + size.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(200); + if (isFails()) { + throw new RuntimeException(exc); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class MyInternalFrame extends JInternalFrame { + MyInternalFrame(String str, boolean b) { + super(str, b); + } + + protected void processMouseEvent(MouseEvent e) { + try { + super.processMouseEvent(e); + } catch (Exception exc) { + setFails(exc); + } + } + } +} diff --git a/test/jdk/javax/swing/JInternalFrame/bug4322726.java b/test/jdk/javax/swing/JInternalFrame/bug4322726.java new file mode 100644 index 00000000000..861f9357fba --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/bug4322726.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4322726 + * @summary Tests that JInternalFrame throws ArrayIndexOutOfBoundsException when Control-F4 pressed + * @key headful + * @run main bug4322726 + */ + +import java.awt.event.KeyEvent; +import java.awt.Robot; + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import java.beans.PropertyVetoException; + +public class bug4322726 { + + private static JFrame frame; + private static JInternalFrame internalFrame; + private static volatile boolean failed; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4322726"); + frame.setSize(600, 400); + TestDesktopPane desktopPane = new TestDesktopPane(); + frame.setContentPane(desktopPane); + internalFrame = new JInternalFrame(); + internalFrame.setClosable(true); + internalFrame.setMaximizable(true); + internalFrame.setIconifiable(true); + internalFrame.setResizable(true); + internalFrame.setTitle("Internal Frame"); + internalFrame.setSize(300, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setSize(400, 400); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + try { + internalFrame.setSelected(true); + } catch (PropertyVetoException e) { + throw new RuntimeException("PropertyVetoException thrown"); + } + }); + robot.waitForIdle(); + robot.delay(200); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_F4); + robot.keyRelease(KeyEvent.VK_F4); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.waitForIdle(); + robot.delay(200); + if (failed) { + throw new RuntimeException("Failed: index is out of bounds"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class TestDesktopPane extends JDesktopPane { + protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { + try { + return super.processKeyBinding(ks, e, condition, pressed); + } catch (ArrayIndexOutOfBoundsException ex) { + failed = true; + } + return failed; + } + } +} From 9128ec61df430a2eb352f58ec9799d332f7b1a10 Mon Sep 17 00:00:00 2001 From: Joachim Kern Date: Mon, 7 Apr 2025 12:50:43 +0000 Subject: [PATCH 017/843] 8352935: Launcher should not add $JDK/../lib to LD_LIBRARY_PATH Reviewed-by: clanger, ihse, jpai --- src/java.base/unix/native/libjli/java_md.c | 7 ++-- .../tools/launcher/ExecutionEnvironment.java | 1 - test/jdk/tools/launcher/Test7029048.java | 32 ++++++------------- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/java.base/unix/native/libjli/java_md.c b/src/java.base/unix/native/libjli/java_md.c index 2c25a7668c3..0a61971b080 100644 --- a/src/java.base/unix/native/libjli/java_md.c +++ b/src/java.base/unix/native/libjli/java_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -348,7 +348,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv, * * o $JVMPATH (directory portion only) * o $JDK/lib - * o $JDK/../lib * * followed by the user's previous effective LD_LIBRARY_PATH, if * any. @@ -377,10 +376,8 @@ CreateExecutionEnvironment(int *pargc, char ***pargv, snprintf(new_runpath, new_runpath_size, LD_LIBRARY_PATH "=" "%s:" - "%s/lib:" - "%s/../lib", + "%s/lib", new_jvmpath, - jdkroot, jdkroot ); diff --git a/test/jdk/tools/launcher/ExecutionEnvironment.java b/test/jdk/tools/launcher/ExecutionEnvironment.java index 8a10756021e..dbf20fc5bb9 100644 --- a/test/jdk/tools/launcher/ExecutionEnvironment.java +++ b/test/jdk/tools/launcher/ExecutionEnvironment.java @@ -141,7 +141,6 @@ public class ExecutionEnvironment extends TestHelper { String libPath = LD_LIBRARY_PATH + "=" + jvmroot + "/lib/server" + System.getProperty("path.separator") + jvmroot + "/lib" + System.getProperty("path.separator") + - jvmroot + "/../lib" + System.getProperty("path.separator") + LD_LIBRARY_PATH_VALUE; if (!tr.matches(libPath)) { flagError(tr, "FAIL: did not get <" + libPath + ">"); diff --git a/test/jdk/tools/launcher/Test7029048.java b/test/jdk/tools/launcher/Test7029048.java index 4aab158cfc1..f92867044a1 100644 --- a/test/jdk/tools/launcher/Test7029048.java +++ b/test/jdk/tools/launcher/Test7029048.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,21 +26,10 @@ * @bug 7029048 8217340 8217216 * @summary Ensure that the launcher defends against user settings of the * LD_LIBRARY_PATH environment variable on Unixes - * @requires os.family != "windows" & os.family != "mac" & !vm.musl & os.family != "aix" + * @requires os.family != "windows" & os.family != "mac" * @library /test/lib - * @compile -XDignore.symbol.file ExecutionEnvironment.java Test7029048.java - * @run main/othervm -DexpandedLdLibraryPath=false Test7029048 - */ - -/** - * @test - * @bug 7029048 8217340 8217216 - * @summary Ensure that the launcher defends against user settings of the - * LD_LIBRARY_PATH environment variable on Unixes - * @requires os.family == "aix" | vm.musl - * @library /test/lib - * @compile -XDignore.symbol.file ExecutionEnvironment.java Test7029048.java - * @run main/othervm -DexpandedLdLibraryPath=true Test7029048 + * @compile ExecutionEnvironment.java Test7029048.java + * @run main/othervm Test7029048 */ import java.io.File; @@ -51,13 +40,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import jdk.test.lib.Platform; + public class Test7029048 extends TestHelper { private static final String LIBJVM = ExecutionEnvironment.LIBJVM; private static final String LD_LIBRARY_PATH = ExecutionEnvironment.LD_LIBRARY_PATH; - private static final String LD_LIBRARY_PATH_64 = - ExecutionEnvironment.LD_LIBRARY_PATH_64; private static final File libDir = new File(System.getProperty("sun.boot.library.path")); @@ -71,9 +60,6 @@ public class Test7029048 extends TestHelper { private static final File dstClientDir = new File(dstLibDir, "client"); private static final File dstClientLibjvm = new File(dstClientDir, LIBJVM); - static final boolean IS_EXPANDED_LD_LIBRARY_PATH = - Boolean.getBoolean("expandedLdLibraryPath"); - static String getValue(String name, List in) { for (String x : in) { String[] s = x.split("="); @@ -134,7 +120,7 @@ public class Test7029048 extends TestHelper { private static enum TestCase { NO_DIR(0), // Directory does not exist NO_LIBJVM(0), // Directory exists, but no libjvm.so - LIBJVM(3); // Directory exists, with a libjvm.so + LIBJVM(2); // Directory exists, with a libjvm.so private final int value; TestCase(int i) { this.value = i; @@ -170,7 +156,7 @@ public class Test7029048 extends TestHelper { } desc = "LD_LIBRARY_PATH should not be set (no libjvm.so)"; - if (IS_EXPANDED_LD_LIBRARY_PATH) { + if (Platform.isAix() || Platform.isMusl()) { printSkipMessage(desc); continue; } @@ -180,7 +166,7 @@ public class Test7029048 extends TestHelper { recursiveDelete(dstLibDir); } desc = "LD_LIBRARY_PATH should not be set (no directory)"; - if (IS_EXPANDED_LD_LIBRARY_PATH) { + if (Platform.isAix() || Platform.isMusl()) { printSkipMessage(desc); continue; } From 77fff61b864054b0029ee5d38f6293534db10ce1 Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Mon, 7 Apr 2025 13:04:47 +0000 Subject: [PATCH 018/843] 8341095: Possible overflow in os::Posix::print_uptime_info Reviewed-by: dholmes --- src/hotspot/os/posix/os_posix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 6f756fbf648..a36d6b87641 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -551,7 +551,7 @@ void os::Posix::print_uptime_info(outputStream* st) { setutxent(); while ((ent = getutxent())) { if (!strcmp("system boot", ent->ut_line)) { - bootsec = ent->ut_tv.tv_sec; + bootsec = (int)ent->ut_tv.tv_sec; break; } } From 60fbf73fc492ad9fff83fb4540e2d01311406287 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Mon, 7 Apr 2025 13:27:21 +0000 Subject: [PATCH 019/843] 8353709: Debug symbols bundle should contain full debug files when building --with-external-symbols-in-bundles=public Reviewed-by: erikj, mbaesken --- make/Bundles.gmk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/make/Bundles.gmk b/make/Bundles.gmk index 58950b5fb1f..8962b596278 100644 --- a/make/Bundles.gmk +++ b/make/Bundles.gmk @@ -242,7 +242,10 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), ) ) JDK_SYMBOLS_BUNDLE_FILES := \ - $(call FindFiles, $(SYMBOLS_IMAGE_DIR)) + $(filter-out \ + %.stripped.pdb, \ + $(call FindFiles, $(SYMBOLS_IMAGE_DIR)) \ + ) TEST_DEMOS_BUNDLE_FILES := $(filter $(JDK_DEMOS_IMAGE_HOMEDIR)/demo/%, \ $(ALL_JDK_DEMOS_FILES)) From 402103331bcdb1055f89c938fdd6b1df772993b6 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 7 Apr 2025 15:03:30 +0000 Subject: [PATCH 020/843] 8353659: SubmissionPublisherTest::testCap1Submit times out Reviewed-by: dl, alanb --- .../classes/java/util/concurrent/ForkJoinPool.java | 13 ++++++------- .../util/concurrent/tck/ForkJoinPool20Test.java | 7 +++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index ec46f61291d..5c74e653431 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -1278,8 +1278,7 @@ public class ForkJoinPool extends AbstractExecutorService * @param internal if caller owns this queue * @throws RejectedExecutionException if array could not be resized */ - final void push(ForkJoinTask task, ForkJoinPool pool, - boolean internal) { + final void push(ForkJoinTask task, ForkJoinPool pool, boolean internal) { int s = top, b = base, m, cap, room; ForkJoinTask[] a; if ((a = array) != null && (cap = a.length) > 0 && // else disabled task != null) { @@ -1383,8 +1382,7 @@ public class ForkJoinPool extends AbstractExecutorService if (a != null && (cap = a.length) > 0 && U.getReference(a, k = slotOffset((cap - 1) & s)) == task && (internal || tryLockPhase())) { - if (top == p && - U.compareAndSetReference(a, k, task, null)) { + if (top == p && U.compareAndSetReference(a, k, task, null)) { taken = true; updateTop(s); } @@ -2061,8 +2059,9 @@ public class ForkJoinPool extends AbstractExecutorService ((e & SHUTDOWN) != 0L && ac == 0 && quiescent() > 0) || (qs = queues) == null || (n = qs.length) <= 0) return IDLE; // terminating - int k = Math.max(n << 2, SPIN_WAITS << 1); - for (int prechecks = k / n;;) { // reactivation threshold + + for (int prechecks = Math.min(ac, 2), // reactivation threshold + k = Math.max(n + (n << 1), SPIN_WAITS << 1);;) { WorkQueue q; int cap; ForkJoinTask[] a; long c; if (w.phase == activePhase) return activePhase; @@ -2071,7 +2070,7 @@ public class ForkJoinPool extends AbstractExecutorService if ((q = qs[k & (n - 1)]) == null) Thread.onSpinWait(); else if ((a = q.array) != null && (cap = a.length) > 0 && - a[q.base & (cap - 1)] != null && --prechecks <= 0 && + a[q.base & (cap - 1)] != null && --prechecks < 0 && (int)(c = ctl) == activePhase && compareAndSetCtl(c, (sp & LMASK) | ((c + RC_UNIT) & UMASK))) return w.phase = activePhase; // reactivate diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java b/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java index 41dd82300e2..9b60bbae484 100644 --- a/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java @@ -528,6 +528,7 @@ public class ForkJoinPool20Test extends JSR166TestCase { final CountDownLatch delayedDone = new CountDownLatch(1); final CountDownLatch immediateDone = new CountDownLatch(1); final ForkJoinPool p = new ForkJoinPool(2); + p.cancelDelayedTasksOnShutdown(); try (PoolCleaner cleaner = cleaner(p)) { final Runnable delayed = () -> { delayedDone.countDown(); @@ -568,8 +569,8 @@ public class ForkJoinPool20Test extends JSR166TestCase { public Boolean call() throws Exception { Thread.sleep(LONGER_DELAY_MS); return Boolean.TRUE; }}; ForkJoinTask task = p.submitWithTimeout(c, 1, NANOSECONDS, null); - Thread.sleep(timeoutMillis()); - assertTrue(task.isCancelled()); + while(!task.isCancelled()) + Thread.sleep(timeoutMillis()); } static final class SubmitWithTimeoutException extends RuntimeException {} @@ -586,7 +587,6 @@ public class ForkJoinPool20Test extends JSR166TestCase { c, 1, NANOSECONDS, (ForkJoinTask t) -> t.complete(two)); - Thread.sleep(timeoutMillis()); assertEquals(task.join(), two); } @@ -602,7 +602,6 @@ public class ForkJoinPool20Test extends JSR166TestCase { c, 1, NANOSECONDS, (ForkJoinTask t) -> t.completeExceptionally(new SubmitWithTimeoutException())); - Thread.sleep(timeoutMillis()); try { task.join(); shouldThrow(); From 9a391f44e038d6c15a7872164bd3099edad93c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eirik=20Bj=C3=B8rsn=C3=B8s?= Date: Mon, 7 Apr 2025 15:23:18 +0000 Subject: [PATCH 021/843] 8353278: Consolidate local file URL checks in jar: and file: URL schemes Reviewed-by: dfuchs, jpai --- .../share/classes/sun/net/www/ParseUtil.java | 18 +++++++++++++++++- .../net/www/protocol/jar/JarFileFactory.java | 12 +++++++----- .../sun/net/www/protocol/jar/URLJarFile.java | 18 ++---------------- .../sun/net/www/protocol/file/Handler.java | 5 ++--- .../sun/net/www/protocol/file/Handler.java | 6 ++---- 5 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/java.base/share/classes/sun/net/www/ParseUtil.java b/src/java.base/share/classes/sun/net/www/ParseUtil.java index 628eeb948ad..51d1b8398b6 100644 --- a/src/java.base/share/classes/sun/net/www/ParseUtil.java +++ b/src/java.base/share/classes/sun/net/www/ParseUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -507,6 +507,22 @@ public final class ParseUtil { } } + /** + * {@return true if the url is a file: URL for a 'local file' as defined by RFC 8089, Section 2} + * + * For unknown historical reasons, this method deviates from RFC 8089 + * by allowing "~" as an alias for 'localhost' + * + * @param url the URL which may be a local file URL + */ + public static boolean isLocalFileURL(URL url) { + if (url.getProtocol().equalsIgnoreCase("file")) { + String host = url.getHost(); + return host == null || host.isEmpty() || host.equals("~") || + host.equalsIgnoreCase("localhost"); + } + return false; + } // -- Character classes for parsing -- diff --git a/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java b/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java index 9afbea8bf76..4d695c8d4e8 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/src/java.base/share/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import java.util.jar.JarFile; import jdk.internal.util.OperatingSystem; import sun.net.util.URLUtil; +import sun.net.www.ParseUtil; /* A factory for cached JAR file. This class is used to both retrieve * and cache Jar files. @@ -92,7 +93,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { return get(url, false); } URL patched = urlFor(url); - if (!URLJarFile.isFileURL(patched)) { + if (!ParseUtil.isLocalFileURL(patched)) { // A temporary file will be created, we can prepopulate // the cache in this case. return get(url, useCaches); @@ -158,9 +159,10 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { // Deal with UNC pathnames specially. See 4180841 String host = url.getHost(); - if (host != null && !host.isEmpty() && - !host.equalsIgnoreCase("localhost")) { - + // Subtly different from ParseUtil.isLocalFileURL, for historical reasons + boolean isLocalFile = ParseUtil.isLocalFileURL(url) && !"~".equals(host); + // For remote hosts, change 'file://host/folder/data.xml' to 'file:////host/folder/data.xml' + if (!isLocalFile) { @SuppressWarnings("deprecation") var _unused = url = new URL("file", "", "//" + host + url.getPath()); } diff --git a/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java b/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java index b3d4a223196..d30d18df9d6 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java +++ b/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ public class URLJarFile extends JarFile { private Map superEntries; static JarFile getJarFile(URL url, URLJarFileCloseController closeController) throws IOException { - if (isFileURL(url)) { + if (ParseUtil.isLocalFileURL(url)) { Runtime.Version version = "runtime".equals(url.getRef()) ? JarFile.runtimeVersion() : JarFile.baseVersion(); @@ -71,20 +71,6 @@ public class URLJarFile extends JarFile { this.closeController = closeController; } - static boolean isFileURL(URL url) { - if (url.getProtocol().equalsIgnoreCase("file")) { - /* - * Consider this a 'file' only if it's a LOCAL file, because - * 'file:' URLs can be accessible through ftp. - */ - String host = url.getHost(); - if (host == null || host.isEmpty() || host.equals("~") || - host.equalsIgnoreCase("localhost")) - return true; - } - return false; - } - /** * Returns the ZipEntry for the given entry name or * null if not found. diff --git a/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java b/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java index 4b2c110b3e1..efde6a809e9 100644 --- a/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java +++ b/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,8 +64,7 @@ public class Handler extends URLStreamHandler { public URLConnection openConnection(URL u, Proxy p) throws IOException { String host = u.getHost(); - if (host == null || host.isEmpty() || host.equals("~") || - host.equalsIgnoreCase("localhost")) { + if (ParseUtil.isLocalFileURL(u)) { File file = new File(ParseUtil.decode(u.getPath())); return createFileURLConnection(u, file); } diff --git a/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java b/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java index 2865aa32a95..38ad16267e7 100644 --- a/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java +++ b/src/java.base/windows/classes/sun/net/www/protocol/file/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,9 +72,7 @@ public class Handler extends URLStreamHandler { path = path.replace('/', '\\'); path = path.replace('|', ':'); - if ((host == null) || host.isEmpty() || - host.equalsIgnoreCase("localhost") || - host.equals("~")) { + if (ParseUtil.isLocalFileURL(url)) { return createFileURLConnection(url, new File(path)); } From 867a0301893cbf3d5434e4966d27d7f4913afb98 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 7 Apr 2025 16:15:51 +0000 Subject: [PATCH 022/843] 8352971: Increase maximum number of hold counts for ReentrantReadWriteLock Reviewed-by: alanb --- .../locks/ReentrantReadWriteLock.java | 72 +++++++------ .../util/concurrent/tck/JSR166TestCase.java | 1 + .../tck/ReentrantReadWriteLock20Test.java | 100 ++++++++++++++++++ .../tck/ReentrantReadWriteLockTest.java | 2 +- 4 files changed, 140 insertions(+), 35 deletions(-) create mode 100644 test/jdk/java/util/concurrent/tck/ReentrantReadWriteLock20Test.java diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index cc9b75a7e37..a45043e48ee 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -251,25 +251,25 @@ public class ReentrantReadWriteLock * Synchronization implementation for ReentrantReadWriteLock. * Subclassed into fair and nonfair versions. */ - abstract static class Sync extends AbstractQueuedSynchronizer { + abstract static class Sync extends AbstractQueuedLongSynchronizer { private static final long serialVersionUID = 6317671515068378041L; /* * Read vs write count extraction constants and functions. - * Lock state is logically divided into two unsigned shorts: + * Lock state is logically divided into two ints: * The lower one representing the exclusive (writer) lock hold count, * and the upper the shared (reader) hold count. */ - static final int SHARED_SHIFT = 16; - static final int SHARED_UNIT = (1 << SHARED_SHIFT); - static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1; - static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; + static final int SHARED_SHIFT = 32; + static final long SHARED_UNIT = (1L << SHARED_SHIFT); + static final long MAX_COUNT = Integer.MAX_VALUE; + static final long EXCLUSIVE_MASK = (1L << SHARED_SHIFT) - 1; /** Returns the number of shared holds represented in count. */ - static int sharedCount(int c) { return c >>> SHARED_SHIFT; } + static int sharedCount(long c) { return (int)(c >>> SHARED_SHIFT); } /** Returns the number of exclusive holds represented in count. */ - static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; } + static int exclusiveCount(long c) { return (int)(c & EXCLUSIVE_MASK); } /** * A counter for per-thread read hold counts. @@ -367,11 +367,12 @@ public class ReentrantReadWriteLock * both read and write holds that are all released during a * condition wait and re-established in tryAcquire. */ + @Override @ReservedStackAccess - protected final boolean tryRelease(int releases) { + protected final boolean tryRelease(long releases) { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); - int nextc = getState() - releases; + long nextc = getState() - releases; boolean free = exclusiveCount(nextc) == 0; if (free) setExclusiveOwnerThread(null); @@ -379,8 +380,9 @@ public class ReentrantReadWriteLock return free; } + @Override @ReservedStackAccess - protected final boolean tryAcquire(int acquires) { + protected final boolean tryAcquire(long acquires) { /* * Walkthrough: * 1. If read count nonzero or write count nonzero @@ -393,8 +395,8 @@ public class ReentrantReadWriteLock * and set owner. */ Thread current = Thread.currentThread(); - int c = getState(); - int w = exclusiveCount(c); + long c = getState(); + long w = exclusiveCount(c); if (c != 0) { // (Note: if c != 0 and w == 0 then shared count != 0) if (w == 0 || current != getExclusiveOwnerThread()) @@ -412,8 +414,9 @@ public class ReentrantReadWriteLock return true; } + @Override @ReservedStackAccess - protected final boolean tryReleaseShared(int unused) { + protected final boolean tryReleaseShared(long unused) { Thread current = Thread.currentThread(); if (firstReader == current) { // assert firstReaderHoldCount > 0; @@ -435,8 +438,8 @@ public class ReentrantReadWriteLock --rh.count; } for (;;) { - int c = getState(); - int nextc = c - SHARED_UNIT; + long c = getState(); + long nextc = c - SHARED_UNIT; if (compareAndSetState(c, nextc)) // Releasing the read lock has no effect on readers, // but it may allow waiting writers to proceed if @@ -450,8 +453,9 @@ public class ReentrantReadWriteLock "attempt to unlock read lock, not locked by current thread"); } + @Override @ReservedStackAccess - protected final int tryAcquireShared(int unused) { + protected final long tryAcquireShared(long unused) { /* * Walkthrough: * 1. If write lock held by another thread, fail. @@ -468,10 +472,10 @@ public class ReentrantReadWriteLock * saturated, chain to version with full retry loop. */ Thread current = Thread.currentThread(); - int c = getState(); + long c = getState(); if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) - return -1; + return -1L; int r = sharedCount(c); if (!readerShouldBlock() && r < MAX_COUNT && @@ -490,7 +494,7 @@ public class ReentrantReadWriteLock readHolds.set(rh); rh.count++; } - return 1; + return 1L; } return fullTryAcquireShared(current); } @@ -499,7 +503,7 @@ public class ReentrantReadWriteLock * Full version of acquire for reads, that handles CAS misses * and reentrant reads not dealt with in tryAcquireShared. */ - final int fullTryAcquireShared(Thread current) { + final long fullTryAcquireShared(Thread current) { /* * This code is in part redundant with that in * tryAcquireShared but is simpler overall by not @@ -508,7 +512,7 @@ public class ReentrantReadWriteLock */ HoldCounter rh = null; for (;;) { - int c = getState(); + long c = getState(); if (exclusiveCount(c) != 0) { if (getExclusiveOwnerThread() != current) return -1; @@ -529,7 +533,7 @@ public class ReentrantReadWriteLock } } if (rh.count == 0) - return -1; + return -1L; } } if (sharedCount(c) == MAX_COUNT) @@ -551,7 +555,7 @@ public class ReentrantReadWriteLock rh.count++; cachedHoldCounter = rh; // cache for release } - return 1; + return 1L; } } } @@ -564,7 +568,7 @@ public class ReentrantReadWriteLock @ReservedStackAccess final boolean tryWriteLock() { Thread current = Thread.currentThread(); - int c = getState(); + long c = getState(); if (c != 0) { int w = exclusiveCount(c); if (w == 0 || current != getExclusiveOwnerThread()) @@ -587,7 +591,7 @@ public class ReentrantReadWriteLock final boolean tryReadLock() { Thread current = Thread.currentThread(); for (;;) { - int c = getState(); + long c = getState(); if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) return false; @@ -672,7 +676,7 @@ public class ReentrantReadWriteLock setState(0); // reset to unlocked state } - final int getCount() { return getState(); } + final long getCount() { return getState(); } } /** @@ -1431,9 +1435,9 @@ public class ReentrantReadWriteLock public boolean hasWaiters(Condition condition) { if (condition == null) throw new NullPointerException(); - if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) + if (!(condition instanceof AbstractQueuedLongSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); - return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); + return sync.hasWaiters((AbstractQueuedLongSynchronizer.ConditionObject)condition); } /** @@ -1454,9 +1458,9 @@ public class ReentrantReadWriteLock public int getWaitQueueLength(Condition condition) { if (condition == null) throw new NullPointerException(); - if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) + if (!(condition instanceof AbstractQueuedLongSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); - return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition); + return sync.getWaitQueueLength((AbstractQueuedLongSynchronizer.ConditionObject)condition); } /** @@ -1479,9 +1483,9 @@ public class ReentrantReadWriteLock protected Collection getWaitingThreads(Condition condition) { if (condition == null) throw new NullPointerException(); - if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) + if (!(condition instanceof AbstractQueuedLongSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); - return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition); + return sync.getWaitingThreads((AbstractQueuedLongSynchronizer.ConditionObject)condition); } /** @@ -1494,7 +1498,7 @@ public class ReentrantReadWriteLock * @return a string identifying this lock, as well as its lock state */ public String toString() { - int c = sync.getCount(); + long c = sync.getCount(); int w = Sync.exclusiveCount(c); int r = Sync.sharedCount(c); diff --git a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java index 92e2e82362a..18007f72ca8 100644 --- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java +++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java @@ -622,6 +622,7 @@ public class JSR166TestCase extends TestCase { String[] java20TestClassNames = { "ForkJoinPool20Test", "SynchronousQueue20Test", + "ReentrantReadWriteLock20Test" }; addNamedTestClasses(suite, java20TestClassNames); } diff --git a/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLock20Test.java b/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLock20Test.java new file mode 100644 index 00000000000..730e162e7fc --- /dev/null +++ b/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLock20Test.java @@ -0,0 +1,100 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import junit.framework.Test; +import junit.framework.TestSuite; + +import java.util.ArrayDeque; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ReentrantReadWriteLock20Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ReentrantReadWriteLock20Test.class); + } + public void test66kReadersFair() throws InterruptedException { test66kReaders(true); } + public void test66kReadersUnfair() throws InterruptedException { test66kReaders(false); } + + private void test66kReaders(boolean fairness) throws InterruptedException { + final var failure = new AtomicReference(); + final var lock = new ReentrantReadWriteLock(fairness); + final var numThreads = 0x10000; + final var threads = new ArrayDeque(numThreads); + final var latch = new CountDownLatch(1); + try { + for(int i = 0; i < numThreads && failure.get() == null;++i) { + var t = Thread.ofVirtual().unstarted(() -> { + + try { + lock.readLock().lock(); + } catch (Throwable ex) { + failure.compareAndSet(null, ex); + return; + } + + try { + while (latch.getCount() > 0) { + try { + latch.await(); + } catch (InterruptedException ie) { + failure.compareAndSet(null, ie); + } + } + } + finally { + lock.readLock().unlock(); + } + }); + + threads.addLast(t); + t.start(); + } + } finally { + latch.countDown(); // Make sure waiters are signalled + Thread next; + while ((next = threads.pollFirst()) != null) { + while (next.isAlive()) { + next.join(); + } + } + } + + assertEquals(null, failure.get()); + } +} diff --git a/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java b/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java index ccbff0d29ce..64f3d2c58e3 100644 --- a/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java +++ b/test/jdk/java/util/concurrent/tck/ReentrantReadWriteLockTest.java @@ -1720,7 +1720,7 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase { ? "ReentrantReadWriteLock$FairSync" : "ReentrantReadWriteLock$NonfairSync"; final String conditionClassName - = "AbstractQueuedSynchronizer$ConditionObject"; + = "AbstractQueuedLongSynchronizer$ConditionObject"; final Thread.State expectedAcquireState = timedAcquire ? Thread.State.TIMED_WAITING : Thread.State.WAITING; From e08441c03352543f800aef166afabec1dacaf4bf Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 7 Apr 2025 16:40:36 +0000 Subject: [PATCH 023/843] 8353475: Open source two Swing DefaultCaret tests Reviewed-by: honkar --- .../swing/text/DefaultCaret/PaintTest.java | 63 ++++++++++++++++ .../swing/text/DefaultCaret/bug4785160.java | 71 +++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 test/jdk/javax/swing/text/DefaultCaret/PaintTest.java create mode 100644 test/jdk/javax/swing/text/DefaultCaret/bug4785160.java diff --git a/test/jdk/javax/swing/text/DefaultCaret/PaintTest.java b/test/jdk/javax/swing/text/DefaultCaret/PaintTest.java new file mode 100644 index 00000000000..c554764527e --- /dev/null +++ b/test/jdk/javax/swing/text/DefaultCaret/PaintTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4193062 + * @summary Tests that when a TextField first gets focus, if modelToView fails + * (null is returned) that the caret will start to blink again. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PaintTest +*/ + +import java.awt.FlowLayout; +import javax.swing.JFrame; +import javax.swing.JTextField; + +public class PaintTest { + + static final String INSTRUCTIONS = """ + If the test window displays with the text caret flashing (do wait at + least several second for it to start) the test PASSES, otherwise it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("PaintTest Test Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(PaintTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("PaintTest"); + JTextField tf = new JTextField(20); + frame.setLayout(new FlowLayout()); + frame.add(tf); + frame.setSize(300, 300); + return frame; + } +} diff --git a/test/jdk/javax/swing/text/DefaultCaret/bug4785160.java b/test/jdk/javax/swing/text/DefaultCaret/bug4785160.java new file mode 100644 index 00000000000..644becf8ae6 --- /dev/null +++ b/test/jdk/javax/swing/text/DefaultCaret/bug4785160.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4785160 + * @summary Test that the cursor is always visible when typing in JTextArea with JScrollBar + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4785160 +*/ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +public class bug4785160 { + + static final String INSTRUCTIONS = """ + Ensure that the horizontal scrollbar is visible in the JTextArea. + If necessary, reduce the width of the window so that the scrollbar becomes visible. + Scroll all the way to the right so the end of the line is visible. + If necessary, move the text caret in the text area to the end of line. + The test PASSES if the caret is visible at the end of the line. + The test FAILS if the caret disappears when moved to the end of the line. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4785160 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4785160::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("bug4785160"); + JTextArea area = new JTextArea(); + String s = ""; + for (int i = 0; i < 80; i++) { + s += "m"; + } + area.setText(s); + area.getCaret().setDot(area.getText().length() + 1); + frame.add(new JScrollPane(area)); + frame.setSize(300, 300); + return frame; + } +} From 0d4d1558164bb352aa4f7be1fffb7eb2da506944 Mon Sep 17 00:00:00 2001 From: Koushik Thirupattur Date: Mon, 7 Apr 2025 17:29:13 +0000 Subject: [PATCH 024/843] 8349890: Option -Djava.security.debug=x509,ava breaks special chars Reviewed-by: mullan --- .../share/classes/sun/security/x509/AVA.java | 22 ++----- ...X500PrincipalInDebugModeWithAvaOption.java | 61 +++++++++++++++++++ 2 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 test/jdk/sun/security/x509/X500Name/PrintX500PrincipalInDebugModeWithAvaOption.java diff --git a/src/java.base/share/classes/sun/security/x509/AVA.java b/src/java.base/share/classes/sun/security/x509/AVA.java index f5d8008fbb0..915421c76f2 100644 --- a/src/java.base/share/classes/sun/security/x509/AVA.java +++ b/src/java.base/share/classes/sun/security/x509/AVA.java @@ -640,7 +640,7 @@ public class AVA implements DerEncoder { */ public String toString() { return toKeywordValueString - (toKeyword(DEFAULT, Collections.emptyMap())); + (toKeyword(DEFAULT, Collections.emptyMap()), true); } /** @@ -659,7 +659,7 @@ public class AVA implements DerEncoder { * OID/keyword map. */ public String toRFC1779String(Map oidMap) { - return toKeywordValueString(toKeyword(RFC1779, oidMap)); + return toKeywordValueString(toKeyword(RFC1779, oidMap), false); } /** @@ -758,12 +758,6 @@ public class AVA implements DerEncoder { // escape null character sbuffer.append("\\00"); - } else if (debug != null && Debug.isOn("ava")) { - - // embed non-printable/non-escaped char - // as escaped hex pairs for debugging - byte[] valueBytes = Character.toString(c).getBytes(UTF_8); - HexFormat.of().withPrefix("\\").withUpperCase().formatHex(sbuffer, valueBytes); } else { // append non-printable/non-escaped char @@ -888,14 +882,6 @@ public class AVA implements DerEncoder { } } - } else if (debug != null && Debug.isOn("ava")) { - - // embed non-printable/non-escaped char - // as escaped hex pairs for debugging - - previousWhite = false; - byte[] valueBytes = Character.toString(c).getBytes(UTF_8); - HexFormat.of().withPrefix("\\").withUpperCase().formatHex(sbuffer, valueBytes); } else { // append non-printable/non-escaped char @@ -945,7 +931,7 @@ public class AVA implements DerEncoder { return AVAKeyword.hasKeyword(oid, RFC2253); } - private String toKeywordValueString(String keyword) { + private String toKeywordValueString(String keyword, Boolean isFromToString) { /* * Construct the value with as little copying and garbage * production as practical. First the keyword (mandatory), @@ -1019,7 +1005,7 @@ public class AVA implements DerEncoder { sbuffer.append(c); - } else if (debug != null && Debug.isOn("ava")) { + } else if (debug != null && isFromToString && Debug.isOn("ava")) { // embed non-printable/non-escaped char // as escaped hex pairs for debugging diff --git a/test/jdk/sun/security/x509/X500Name/PrintX500PrincipalInDebugModeWithAvaOption.java b/test/jdk/sun/security/x509/X500Name/PrintX500PrincipalInDebugModeWithAvaOption.java new file mode 100644 index 00000000000..88f0b6d15a8 --- /dev/null +++ b/test/jdk/sun/security/x509/X500Name/PrintX500PrincipalInDebugModeWithAvaOption.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8349890 + * @summary Make sure debug with AVA option does not interfere with parsing special characters. + * @library /test/lib + * @run main/othervm -Djava.security.debug=x509:ava PrintX500PrincipalInDebugModeWithAvaOption + */ + +import jdk.test.lib.Asserts; +import javax.security.auth.x500.X500Principal; + +public class PrintX500PrincipalInDebugModeWithAvaOption { + + public static void main(String[] args) throws Exception { + + X500Principal name = new X500Principal("cn=john doe + l=ca\\+lifornia + l =sf, O=Ñ"); + + //Test the name in default String format. This will perform the hex conversion to + //"\\C3\\91" for special character "Ñ" + Asserts.assertTrue(name.toString().contains("\\C3\\91"), + "String does not contain expected value"); + + //Test the name in RFC2253 format. This should skip the hex conversion to return + //"\u00d1" for special character "Ñ" + Asserts.assertTrue(name.getName().contains("\u00d1"), + "String does not contain expected value"); + + //Test the name in canonical name in RFC2253 format. This should skip the hex conversion to return + //"n\u0303" for special character "Ñ" + Asserts.assertTrue(name.getName(X500Principal.CANONICAL).contains("n\u0303"), + "String does not contain expected value"); + + + //Test to print name in RFC1779 format. This should skip the hex conversion to print + //"\u00d1" for special character "Ñ" + Asserts.assertTrue(name.getName(X500Principal.RFC1779).contains("\u00d1"), + "String does not contain expected value"); + } +} From 1b6f6946ae1fa0657d6bd1f63b25a0008ab2acdd Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 7 Apr 2025 18:16:15 +0000 Subject: [PATCH 025/843] 8353304: Open source two JTabbedPane tests Reviewed-by: kizune --- test/jdk/ProblemList.txt | 1 + .../javax/swing/JTabbedPane/bug4499556.java | 280 ++++++++++++++++++ .../javax/swing/JTabbedPane/bug6259533.java | 82 +++++ 3 files changed, 363 insertions(+) create mode 100644 test/jdk/javax/swing/JTabbedPane/bug4499556.java create mode 100644 test/jdk/javax/swing/JTabbedPane/bug6259533.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index b7f1d68a451..ef2c698f198 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -774,6 +774,7 @@ jdk/jfr/jvm/TestWaste.java 8282427 generic- javax/swing/JFileChooser/6698013/bug6698013.java 8024419 macosx-all javax/swing/JColorChooser/8065098/bug8065098.java 8065647 macosx-all +javax/swing/JTabbedPane/bug4499556.java 8267500 macosx-all javax/swing/JTabbedPane/4666224/bug4666224.java 8144124 macosx-all javax/swing/JTabbedPane/TestJTabbedPaneOpaqueColor.java 8345090 windows-all,linux-all javax/swing/SwingUtilities/TestTextPosInPrint.java 8227025 windows-all diff --git a/test/jdk/javax/swing/JTabbedPane/bug4499556.java b/test/jdk/javax/swing/JTabbedPane/bug4499556.java new file mode 100644 index 00000000000..fe9d7dbbfde --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4499556.java @@ -0,0 +1,280 @@ +/* + Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4499556 + * @summary Use arbitrary (J)Components as JTabbedPane tab labels. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4499556 +*/ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4499556 { + + static final String INSTRUCTIONS = """ + The test window contains a tabbedPane with 4 tabs. + + Tab #0 without any tabComponent, just a title. + Tab #1 with a JLabel and a little JButton wrapped into JPanel + Tab #2 with a JButton (Delete #1) as a tabComponent + Tab #3 with a JTextField as a tabComponent + + Check that tabbedPane and all tabComponents are shown properly + for different tabLayout and tabPlacement policies, + (you can change them with help of settings in the right panel), + and for different looks and feels (you can change L&F by using the L&F menu) + + Remove tab #1 by clicking the Button labeled Delete #1 and then re-insert it + by clicking "Insert #1". Check that it works - ie Delete #1 is restored. + + If everything displays and behaves as described, the test PASSES, otherwise it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4499556::createUI) + .build() + .awaitAndCheck(); + } + + static volatile JTabbedPane pane; + + static JFrame createUI() { + JFrame frame = new JFrame("bug4499556"); + pane = getTabbedPane(); + frame.add(pane); + frame.add(getRightPanel(), BorderLayout.EAST); + JMenu menu = new JMenu("L&F Menu"); + JMenuItem platformItem = new JMenuItem("Platform L&F"); + JMenuItem nimbusItem = new JMenuItem("Nimbus L&F"); + JMenuItem metalItem = new JMenuItem("Metal L&F"); + menu.add(platformItem); + menu.add(nimbusItem); + menu.add(metalItem); + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + frame.setJMenuBar(menuBar); + platformItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setPlatformLAF(); + } + }); + metalItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setMetalLAF(); + } + }); + + nimbusItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setNimbusLAF(); + } + }); + frame.setSize(500, 500); + return frame; + } + + static JTabbedPane getTabbedPane() { + final JTabbedPane pane = new JTabbedPane(); + + pane.add("Title", new JLabel("")); + + addCompoundTab(pane); + + pane.add("Title", new JLabel("")); + pane.add("Title", new JLabel("")); + + final JButton button = new JButton("Delete #1"); + pane.setTabComponentAt(2, button); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (pane.getTabCount() == 4) { + pane.remove(1); + button.setText("Insert #1"); + } else { + addCompoundTab(pane); + button.setText("Delete #1"); + } + } + }); + + JTextField tf = new JTextField("JTextField", 7); + pane.setTabComponentAt(3, tf); + + return pane; + } + + static JComponent getRightPanel() { + JComponent ret = new Box(BoxLayout.Y_AXIS); + ret.setBorder(BorderFactory.createTitledBorder("Properties")); + ret.setPreferredSize(new Dimension(100, 0)); + final JCheckBox checkBox = new JCheckBox(); + JPanel temp = new JPanel(); + temp.add(new JLabel("Scrollable")); + temp.add(checkBox); + pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); + checkBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (checkBox.isSelected()) { + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + } else { + pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); + } + } + }); + checkBox.doClick(); + ret.add(temp); + ButtonGroup group = new ButtonGroup(); + temp = new JPanel(); + JRadioButton topRadio = new JRadioButton("Top"); + temp.add(topRadio); + topRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.TOP); + } + }); + ret.add(temp); + temp = new JPanel(); + JRadioButton bottomRadio = new JRadioButton("Bottom"); + temp.add(bottomRadio); + bottomRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.BOTTOM); + } + }); + ret.add(temp); + temp = new JPanel(); + JRadioButton leftRadio = new JRadioButton("Left"); + temp.add(leftRadio); + leftRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.LEFT); + } + }); + ret.add(temp); + temp = new JPanel(); + JRadioButton rightRadio = new JRadioButton("Right"); + temp.add(rightRadio); + rightRadio.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + pane.setTabPlacement(JTabbedPane.RIGHT); + } + }); + ret.add(temp); + group.add(topRadio); + group.add(bottomRadio); + group.add(leftRadio); + group.add(rightRadio); + return ret; + } + + + + static void addCompoundTab(final JTabbedPane pane) { + JLabel label = new JLabel("JLabel"); + label.setOpaque(true); + JPanel testPanel = new JPanel(); + JLabel comp = new JLabel("JLabel"); + testPanel.add(comp); + JButton closeButton = new CloseButton(); + closeButton.setPreferredSize(new Dimension(10, 10)); + testPanel.add(closeButton); + testPanel.setOpaque(false); + pane.insertTab("Test", null, new JLabel(""), "", 1); + pane.setTabComponentAt(1, testPanel); + } + + static class CloseButton extends JButton { + public CloseButton() { + final Object[] options = {"Fine"}; + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showOptionDialog(null, + "How are you ?", "Hello !", JOptionPane.YES_OPTION, + JOptionPane.QUESTION_MESSAGE, null, options, null); + } + }); + } + + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(Color.black); + g.drawLine(0, 0, getWidth()-1, getHeight()-1); + g.drawLine(0, getHeight()-1, getWidth()-1, 0); + } + } + + static boolean setLAF(String laf) { + try { + UIManager.setLookAndFeel(laf); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + SwingUtilities.updateComponentTreeUI(pane); + return true; + } + + static final boolean setPlatformLAF() { + return setLAF(UIManager.getSystemLookAndFeelClassName()); + } + + static final boolean setNimbusLAF() { + return setLAF("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + } + + static final boolean setMetalLAF() { + return setLAF("javax.swing.plaf.metal.MetalLookAndFeel"); + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/bug6259533.java b/test/jdk/javax/swing/JTabbedPane/bug6259533.java new file mode 100644 index 00000000000..7aaa3e591ce --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug6259533.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6259533 + * @requires (os.family == "windows") + * @summary Win L&F : JTabbedPane should move upwards the tabComponent of the selected tab. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6259533 +*/ + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTabbedPane; +import javax.swing.UIManager; + +public class bug6259533 { + + static final String INSTRUCTIONS = """ + This test is for the Windows LaF only. + + You should see a JTabbedPane with two tabs. + The first tab uses a string and the second tab has a JLabel as a tabComponent + + Select each tab and notice that on selection the tab title + is moved upwards slightly in comparison with the unselected tab + + If that is the observed behaviour, press PASS, press FAIL otherwise. + + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug6259533::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + JFrame frame = new JFrame("bug6259533"); + JTabbedPane pane = new JTabbedPane(); + pane.add("String Tab", null); + pane.add("Tab 2", null); + JLabel label = new JLabel("JLabel Tab"); + pane.setTabComponentAt(1, label); + frame.add(pane); + frame.setSize(400, 200); + return frame; + } + +} From 885cf0ff8d1e7816bf409136234d63373d576f9e Mon Sep 17 00:00:00 2001 From: Volodymyr Paprotski Date: Mon, 7 Apr 2025 18:44:04 +0000 Subject: [PATCH 026/843] 8353671: Remove dead code missed in JDK-8350459 Reviewed-by: sviswanathan, mullan --- .../MontgomeryIntegerPolynomialP256.java | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java b/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java index 954713bea5f..1910746fe44 100644 --- a/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/MontgomeryIntegerPolynomialP256.java @@ -547,27 +547,4 @@ public final class MontgomeryIntegerPolynomialP256 extends IntegerPolynomial limbs[i - 5] += (v << 4) & LIMB_MASK; limbs[i - 4] += v >> 48; } - - // Used when limbs a could overflow by one modulus. - @ForceInline - protected void reducePositive(long[] a) { - long aa0 = a[0]; - long aa1 = a[1] + (aa0>>BITS_PER_LIMB); - long aa2 = a[2] + (aa1>>BITS_PER_LIMB); - long aa3 = a[3] + (aa2>>BITS_PER_LIMB); - long aa4 = a[4] + (aa3>>BITS_PER_LIMB); - - long c0 = a[0] - modulus[0]; - long c1 = a[1] - modulus[1] + (c0 >> BITS_PER_LIMB); - long c2 = a[2] - modulus[2] + (c1 >> BITS_PER_LIMB); - long c3 = a[3] - modulus[3] + (c2 >> BITS_PER_LIMB); - long c4 = a[4] - modulus[4] + (c3 >> BITS_PER_LIMB); - long mask = c4 >> BITS_PER_LIMB; // Signed shift! - - a[0] = ((aa0 & mask) | (c0 & ~mask)) & LIMB_MASK; - a[1] = ((aa1 & mask) | (c1 & ~mask)) & LIMB_MASK; - a[2] = ((aa2 & mask) | (c2 & ~mask)) & LIMB_MASK; - a[3] = ((aa3 & mask) | (c3 & ~mask)) & LIMB_MASK; - a[4] = ((aa4 & mask) | (c4 & ~mask)); - } } From 5481021ee64fd457279ea7083be0f977c7ce3e3c Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 7 Apr 2025 18:46:04 +0000 Subject: [PATCH 027/843] 8321591: (fs) Improve String -> Path conversion performance (win) Reviewed-by: alanb --- .../classes/sun/nio/fs/WindowsPathParser.java | 116 +++++++++--------- .../bench/java/nio/file/PathOfString.java | 52 ++++++++ 2 files changed, 113 insertions(+), 55 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/nio/file/PathOfString.java diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsPathParser.java b/src/java.base/windows/classes/sun/nio/fs/WindowsPathParser.java index 6198fbfd5b5..b9986d41f42 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsPathParser.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsPathParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,38 +37,7 @@ class WindowsPathParser { /** * The result of a parse operation */ - static class Result { - private final WindowsPathType type; - private final String root; - private final String path; - - Result(WindowsPathType type, String root, String path) { - this.type = type; - this.root = root; - this.path = path; - } - - /** - * The path type - */ - WindowsPathType type() { - return type; - } - - /** - * The root component - */ - String root() { - return root; - } - - /** - * The normalized path (includes root) - */ - String path() { - return path; - } - } + record Result(WindowsPathType type, String root, String path) {}; /** * Parses the given input as a Windows path @@ -117,7 +86,7 @@ class WindowsPathParser { char c = 0; int next = 2; if (isSlash(c0) && isSlash(c1)) { - // UNC: We keep the first two slash, collapse all the + // UNC: We keep the first two slashes, collapse all the // following, then take the hostname and share name out, // meanwhile collapsing all the redundant slashes. type = WindowsPathType.UNC; @@ -170,9 +139,7 @@ class WindowsPathParser { } if (requireToNormalize) { - StringBuilder sb = new StringBuilder(input.length()); - sb.append(root); - return new Result(type, root, normalize(sb, input, off)); + return new Result(type, root, normalize(root, input, off)); } else { return new Result(type, root, input); } @@ -182,40 +149,62 @@ class WindowsPathParser { * Remove redundant slashes from the rest of the path, forcing all slashes * into the preferred slash. */ - private static String normalize(StringBuilder sb, String path, int off) { - int len = path.length(); - off = nextNonSlash(path, off, len); - int start = off; + private static String normalize(String root, String path, int pathOff) { + + int rootLen = root.length(); + int pathLen = path.length(); + + // the result array will initally contain the characters of root in + // the first rootLen elements followed by the chanacters of path from + // position index pathOff to the end of path + char[] result = new char[rootLen + pathLen - pathOff]; + root.getChars(0, rootLen, result, 0); + path.getChars(pathOff, pathLen, result, rootLen); + + // the portion of array derived from path is normalized by copying + // from position srcPos to position dstPos, and as the invariant + // dstPos <= srcPos holds, no characters can be overwritten + int dstPos = rootLen; + int srcPos = nextNonSlash(result, rootLen, result.length); + + // pathPos is the position in array which is being tested as to + // whether the element at that position is a slash + int pathPos = srcPos; + char lastC = 0; - while (off < len) { - char c = path.charAt(off); + while (pathPos < result.length) { + char c = result[pathPos]; if (isSlash(c)) { if (lastC == ' ') throw new InvalidPathException(path, "Trailing char <" + lastC + ">", - off - 1); - sb.append(path, start, off); - off = nextNonSlash(path, off, len); - if (off != len) //no slash at the end of normalized path - sb.append('\\'); - start = off; + pathPos - 1); + int nchars = pathPos - srcPos; + System.arraycopy(result, srcPos, result, dstPos, nchars); + dstPos += nchars; + pathPos = nextNonSlash(result, pathPos, result.length); + if (pathPos != result.length) //no slash at the end of normalized path + result[dstPos++] = '\\'; + srcPos = pathPos; } else { if (isInvalidPathChar(c)) throw new InvalidPathException(path, "Illegal char <" + c + ">", - off); + pathPos); lastC = c; - off++; + pathPos++; } } - if (start != off) { + if (srcPos != pathPos) { if (lastC == ' ') throw new InvalidPathException(path, "Trailing char <" + lastC + ">", - off - 1); - sb.append(path, start, off); + pathPos - 1); + int nchars = pathPos - srcPos; + System.arraycopy(result, srcPos, result, dstPos, nchars); + dstPos += nchars; } - return sb.toString(); + return new String(result, 0, dstPos); } private static final boolean isSlash(char c) { @@ -227,6 +216,11 @@ class WindowsPathParser { return off; } + private static final int nextNonSlash(char[] path, int off, int end) { + while (off < end && isSlash(path[off])) { off++; } + return off; + } + private static final int nextSlash(String path, int off, int end) { char c; while (off < end && !isSlash(c=path.charAt(off))) { @@ -239,6 +233,18 @@ class WindowsPathParser { return off; } + private static final int nextSlash(char[] path, int off, int end) { + char c; + while (off < end && !isSlash(c=path[off])) { + if (isInvalidPathChar(c)) + throw new InvalidPathException(new String(path), + "Illegal character [" + c + "] in path", + off); + off++; + } + return off; + } + private static final boolean isLetter(char c) { return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')); } diff --git a/test/micro/org/openjdk/bench/java/nio/file/PathOfString.java b/test/micro/org/openjdk/bench/java/nio/file/PathOfString.java new file mode 100644 index 00000000000..662bc0f25e6 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/nio/file/PathOfString.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.nio.file; + +import java.nio.file.Path; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +@State(Scope.Benchmark) +public class PathOfString { + @Param({"C:\\Users\\foo\\bar\\gus.txt", // absolute + "C:\\Users\\\\foo\\\\bar\\gus.txt", // ... with extra '\\'s + "\\\\.\\UNC\\localhost\\C$\\Users\\foo", // UNC + "\\\\.\\UNC\\localhost\\C$\\\\Users\\\\foo", // ... with extra '\\'s + "\\\\?\\C:\\Users\\foo\\bar\\gus.txt", // long path prefix + "\\\\?\\C:\\Users\\\\foo\\bar\\\\gus.txt", // ... with extra '\\'s + ".\\foo\\bar\\gus.txt", // relative + ".\\foo\\\\bar\\\\gus.txt", // ... with extra '\\'s + "\\foo\\bar\\gus.txt", // current drive-relative + "\\foo\\\\bar\\\\gus.txt", // ... with extra '\\'s + "C:foo\\bar\\gus.txt", // drive's current directory-relative + "C:foo\\\\bar\\\\gus.txt"}) // ... with extra '\\'s + + public String path; + + @Benchmark + public Path parse() { + return Path.of(path); + } +} From 05ff557dee6adc679d85bfe8fb49f69053a6aaba Mon Sep 17 00:00:00 2001 From: Renjith Kannath Pariyangad Date: Mon, 7 Apr 2025 19:52:39 +0000 Subject: [PATCH 028/843] 8353138: Screen capture for test TaskbarPositionTest.java, failure case Reviewed-by: aivanov, serb --- .../swing/Popup/TaskbarPositionTest.java | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/test/jdk/javax/swing/Popup/TaskbarPositionTest.java b/test/jdk/javax/swing/Popup/TaskbarPositionTest.java index 5378f61c96f..a6499567483 100644 --- a/test/jdk/javax/swing/Popup/TaskbarPositionTest.java +++ b/test/jdk/javax/swing/Popup/TaskbarPositionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,11 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.JComboBox; import javax.swing.JFrame; @@ -337,11 +341,11 @@ public class TaskbarPositionTest implements ActionListener { } } - try { - // Use Robot to automate the test - Robot robot = new Robot(); - robot.setAutoDelay(50); + // Use Robot to automate the test + Robot robot = new Robot(); + robot.setAutoDelay(50); + try { SwingUtilities.invokeAndWait(TaskbarPositionTest::new); robot.waitForIdle(); @@ -442,6 +446,9 @@ public class TaskbarPositionTest implements ActionListener { hidePopup(robot); robot.waitForIdle(); + } catch (Throwable t) { + saveScreenCapture(robot, screens); + throw t; } finally { SwingUtilities.invokeAndWait(() -> { if (frame != null) { @@ -450,4 +457,17 @@ public class TaskbarPositionTest implements ActionListener { }); } } + + private static void saveScreenCapture(Robot robot, GraphicsDevice[] screens) { + for (int i = 0; i < screens.length; i++) { + Rectangle bounds = screens[i].getDefaultConfiguration() + .getBounds(); + BufferedImage image = robot.createScreenCapture(bounds); + try { + ImageIO.write(image, "png", new File("Screenshot.png")); + } catch (IOException e) { + e.printStackTrace(); + } + } + } } From 3757f660f237408e843584c224f03a64657f7b31 Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Mon, 7 Apr 2025 19:53:36 +0000 Subject: [PATCH 029/843] 8353002: Remove unnecessary Windows version check in WTaskbarPeer Reviewed-by: prr, serb, aivanov --- .../classes/sun/awt/windows/WTaskbarPeer.java | 7 +-- .../java/awt/Dialog/TaskbarFeatureTest.java | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 test/jdk/java/awt/Dialog/TaskbarFeatureTest.java diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WTaskbarPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WTaskbarPeer.java index 98abeff562f..09cafc3bed9 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WTaskbarPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WTaskbarPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,6 @@ import java.awt.Window; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import sun.awt.AWTAccessor; -import sun.awt.OSInfo; import sun.awt.shell.ShellFolder; final class WTaskbarPeer implements TaskbarPeer { @@ -44,9 +43,7 @@ final class WTaskbarPeer implements TaskbarPeer { private static synchronized void init() { if (!initExecuted) { - supported = OSInfo.getWindowsVersion() - .compareTo(OSInfo.WINDOWS_7) >= 0 - && ShellFolder.invoke(() -> nativeInit()); + supported = ShellFolder.invoke(() -> nativeInit()); } initExecuted = true; } diff --git a/test/jdk/java/awt/Dialog/TaskbarFeatureTest.java b/test/jdk/java/awt/Dialog/TaskbarFeatureTest.java new file mode 100644 index 00000000000..5392019d5a3 --- /dev/null +++ b/test/jdk/java/awt/Dialog/TaskbarFeatureTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Taskbar; +import java.awt.Taskbar.Feature; + +/* + * @test + * @bug 8353002 + * @key headful + * @requires (os.family == "windows") + * @summary Verifies that expected taskbar features are supported on Windows. + */ + +public class TaskbarFeatureTest { + + public static void main(String[] args) throws Exception { + Taskbar taskbar = Taskbar.getTaskbar(); + testFeature(taskbar, Feature.ICON_BADGE_IMAGE_WINDOW); + testFeature(taskbar, Feature.PROGRESS_STATE_WINDOW); + testFeature(taskbar, Feature.PROGRESS_VALUE_WINDOW); + testFeature(taskbar, Feature.USER_ATTENTION_WINDOW); + } + + private static void testFeature(Taskbar taskbar, Feature feature) { + if (!taskbar.isSupported(feature)) { + throw new RuntimeException("Feature not supported: " + feature); + } + } +} From cebda921dd49cf05b521f9ab3f731dd44719b027 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 7 Apr 2025 20:32:26 +0000 Subject: [PATCH 030/843] 8311227: Add .editorconfig Co-authored-by: David Briemann Reviewed-by: erikj --- .editorconfig | 7 +++++++ src/hotspot/.editorconfig | 3 +++ 2 files changed, 10 insertions(+) create mode 100644 .editorconfig create mode 100644 src/hotspot/.editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..0e6c17e7674 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*.{cpp,hpp,c,h,java,cc,hh,m,mm,S,md,properties,gmk,m4,ac}] +trim_trailing_whitespace = true + +[Makefile] +trim_trailing_whitespace = true diff --git a/src/hotspot/.editorconfig b/src/hotspot/.editorconfig new file mode 100644 index 00000000000..48e63362b54 --- /dev/null +++ b/src/hotspot/.editorconfig @@ -0,0 +1,3 @@ +[*.{cpp,hpp,c,h}] +indent_style = space +indent_size = 2 From 42dc99eac16c46f1b403cce1dd14c6bda50eae70 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 7 Apr 2025 20:34:30 +0000 Subject: [PATCH 031/843] 8301197: Make sure use of printf is correct and actually needed Reviewed-by: erikj --- make/Docs.gmk | 2 +- make/Init.gmk | 10 +- make/InitSupport.gmk | 23 ++-- make/MainSupport.gmk | 58 ++++---- make/RunTests.gmk | 9 +- make/SourceRevision.gmk | 2 +- make/autoconf/help.m4 | 130 +++++++++--------- make/common/FindTests.gmk | 6 +- make/common/JarArchive.gmk | 2 +- make/common/Modules.gmk | 4 +- make/common/modules/GensrcCommon.gmk | 4 +- make/modules/java.base/Copy.gmk | 2 +- .../modules/java.base/gensrc/GensrcBuffer.gmk | 2 +- .../gensrc/GensrcScopedMemoryAccess.gmk | 2 +- make/scripts/compare.sh | 8 +- test/make/autoconf/test.m4 | 10 +- 16 files changed, 145 insertions(+), 129 deletions(-) diff --git a/make/Docs.gmk b/make/Docs.gmk index 49c97946f75..0948f8ff76c 100644 --- a/make/Docs.gmk +++ b/make/Docs.gmk @@ -264,7 +264,7 @@ define create_overview_file $$($1_OVERVIEW): $$($1_OVERVIEW_VARDEPS_FILE) $$(call LogInfo, Creating overview.html for $1) $$(call MakeDir, $$(@D)) - $$(PRINTF) > $$@ '$$($1_OVERVIEW_TEXT)' + $$(ECHO) -n '$$($1_OVERVIEW_TEXT)' > $$@ endef ################################################################################ diff --git a/make/Init.gmk b/make/Init.gmk index 2a8f6399a18..5dd1a71dd9a 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -137,7 +137,7 @@ main: MAKEOVERRIDES := main: $(INIT_TARGETS) ifneq ($(SEQUENTIAL_TARGETS)$(PARALLEL_TARGETS), ) $(call RotateLogFiles) - $(PRINTF) "Building $(TARGET_DESCRIPTION)\n" $(BUILD_LOG_PIPE_SIMPLE) + $(ECHO) "Building $(TARGET_DESCRIPTION)" $(BUILD_LOG_PIPE_SIMPLE) ifneq ($(SEQUENTIAL_TARGETS), ) # Don't touch build output dir since we might be cleaning. That # means no log pipe. @@ -158,7 +158,8 @@ main: $(INIT_TARGETS) -f make/Main.gmk $(USER_MAKE_VARS) \ $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE) $(BUILD_LOG_PIPE) || \ ( exitcode=$$? && \ - $(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" \ + $(ECHO) "" $(BUILD_LOG_PIPE_SIMPLE) && \ + $(ECHO) "ERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode)" \ $(BUILD_LOG_PIPE_SIMPLE) && \ cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -j 1 -f make/Init.gmk \ on-failure ; \ @@ -170,7 +171,7 @@ main: $(INIT_TARGETS) if test -f $(MAKESUPPORT_OUTPUTDIR)/exit-with-error ; then \ exit 1 ; \ fi - $(PRINTF) "Finished building $(TARGET_DESCRIPTION)\n" $(BUILD_LOG_PIPE_SIMPLE) + $(ECHO) "Finished building $(TARGET_DESCRIPTION)" $(BUILD_LOG_PIPE_SIMPLE) $(call ReportProfileTimes) endif @@ -181,7 +182,8 @@ on-failure: $(call PrintFailureReports) $(call PrintBuildLogFailures) $(call ReportProfileTimes) - $(PRINTF) "HELP: Run 'make doctor' to diagnose build problems.\n\n" + $(ECHO) "HELP: Run 'make doctor' to diagnose build problems." + $(ECHO) "" ifneq ($(COMPARE_BUILD), ) $(call CleanupCompareBuild) endif diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index a9af44e4225..809d1128692 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -173,9 +173,10 @@ define PrintFailureReports $(RM) $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log ; \ $(if $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*.log), \ ( \ - $(PRINTF) "\n=== Output from failing command(s) repeated here ===\n" ; \ + $(ECHO) "" ; \ + $(ECHO) "=== Output from failing command(s) repeated here ===" ; \ $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*.log)), \ - $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" ; \ + $(ECHO) "* For target $(notdir $(basename $(logfile))):" ; \ $(if $(filter all, $(LOG_REPORT)), \ $(GREP) -v -e "^Note: including file:" < $(logfile) || true ; \ , \ @@ -185,8 +186,9 @@ define PrintFailureReports fi ; \ ) \ ) \ - $(PRINTF) "\n* All command lines available in $(MAKESUPPORT_OUTPUTDIR)/failure-logs.\n" ; \ - $(PRINTF) "=== End of repeated output ===\n" ; \ + $(ECHO) "" ; \ + $(ECHO) "* All command lines available in $(MAKESUPPORT_OUTPUTDIR)/failure-logs." ; \ + $(ECHO) "=== End of repeated output ===" ; \ ) >> $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log \ ) \ ) @@ -195,13 +197,16 @@ endef define PrintBuildLogFailures $(if $(filter none, $(LOG_REPORT)), , \ if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then \ - $(PRINTF) "\n=== Make failed targets repeated here ===\n" ; \ + $(ECHO) "" ; \ + $(ECHO) "=== Make failed targets repeated here ===" ; \ $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \ - $(PRINTF) "=== End of repeated output ===\n" ; \ - $(PRINTF) "\nHELP: Try searching the build log for the name of the first failed target.\n" ; \ + $(ECHO) "=== End of repeated output ===" ; \ + $(ECHO) "" ; \ + $(ECHO) "HELP: Try searching the build log for the name of the first failed target." ; \ else \ - $(PRINTF) "\nNo indication of failed target found.\n" ; \ - $(PRINTF) "HELP: Try searching the build log for '] Error'.\n" ; \ + $(ECHO) "" ; \ + $(ECHO) "No indication of failed target found." ; \ + $(ECHO) "HELP: Try searching the build log for '] Error'." ; \ fi >> $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log ; \ $(CAT) $(MAKESUPPORT_OUTPUTDIR)/failure-summary.log \ ) diff --git a/make/MainSupport.gmk b/make/MainSupport.gmk index f7ba4de2d53..ae4858c35af 100644 --- a/make/MainSupport.gmk +++ b/make/MainSupport.gmk @@ -57,77 +57,77 @@ define SetupTargetBody endef define CleanDocs - @$(PRINTF) "Cleaning docs ..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning docs ..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(SUPPORT_OUTPUTDIR)/docs $(RM) -r $(SUPPORT_OUTPUTDIR)/javadoc $(RM) -r $(IMAGES_OUTPUTDIR)/docs - @$(PRINTF) " done\n" + @$(ECHO) " done" endef # Cleans the dir given as $1 define CleanDir - @$(PRINTF) "Cleaning $(strip $1) build artifacts ..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning $(strip $1) build artifacts ..." + @$(ECHO) "" $(LOG_DEBUG) ($(CD) $(OUTPUTDIR) && $(RM) -r $1) - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define CleanSupportDir - @$(PRINTF) "Cleaning $(strip $1) build artifacts ..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning$(strip $1) build artifacts ..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(SUPPORT_OUTPUTDIR)/$(strip $1) - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define CleanMakeSupportDir - @$(PRINTF) "Cleaning $(strip $1) make support artifacts ..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning $(strip $1) make support artifacts ..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(MAKESUPPORT_OUTPUTDIR)/$(strip $1) - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define CleanTest - @$(PRINTF) "Cleaning test $(strip $1) ..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning test $(strip $1) ..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(SUPPORT_OUTPUTDIR)/test/$(strip $(subst -,/,$1)) # Remove as much of the test directory structure as is empty $(RMDIR) -p $(dir $(SUPPORT_OUTPUTDIR)/test/$(strip $(subst -,/,$1))) 2> /dev/null || true - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define Clean-gensrc - @$(PRINTF) "Cleaning gensrc $(if $1,for $(strip $1) )..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning gensrc $(if $1,for $(strip $1) )..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(SUPPORT_OUTPUTDIR)/gensrc/$(strip $1) - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define Clean-java - @$(PRINTF) "Cleaning java $(if $1,for $(strip $1) )..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning java $(if $1,for $(strip $1) )..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(JDK_OUTPUTDIR)/modules/$(strip $1) $(RM) -r $(SUPPORT_OUTPUTDIR)/special_classes/$(strip $1) - $(PRINTF) " done\n" - $(PRINTF) "Cleaning headers $(if $1,for $(strip $1)) ..." + $(ECHO) " done" + $(ECHO) -n "Cleaning headers $(if $1,for $(strip $1) )..." $(RM) -r $(SUPPORT_OUTPUTDIR)/headers/$(strip $1) - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define Clean-native - @$(PRINTF) "Cleaning native $(if $1,for $(strip $1) )..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning native $(if $1,for $(strip $1) )..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(SUPPORT_OUTPUTDIR)/native/$(strip $1) $(RM) -r $(SUPPORT_OUTPUTDIR)/modules_libs/$(strip $1) $(RM) -r $(SUPPORT_OUTPUTDIR)/modules_cmds/$(strip $1) - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define Clean-include - @$(PRINTF) "Cleaning include $(if $1,for $(strip $1) )..." - @$(PRINTF) "\n" $(LOG_DEBUG) + @$(ECHO) -n "Cleaning include $(if $1,for $(strip $1) )..." + @$(ECHO) "" $(LOG_DEBUG) $(RM) -r $(SUPPORT_OUTPUTDIR)/modules_include/$(strip $1) - @$(PRINTF) " done\n" + @$(ECHO) " done" endef define CleanModule diff --git a/make/RunTests.gmk b/make/RunTests.gmk index b9fd3e755d1..7aa0082e0ae 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -1017,7 +1017,8 @@ define SetupRunJtregTestBody $1_COMMAND_LINE := \ for i in {0..$$(JTREG_RETRY_COUNT)}; do \ if [ "$$$$i" != 0 ]; then \ - $$(PRINTF) "\nRetrying Jtreg run. Attempt: $$$$i\n"; \ + $$(ECHO) ""; \ + $$(ECHO) "Retrying Jtreg run. Attempt: $$$$i"; \ fi; \ $$($1_COMMAND_LINE); \ if [ "`$$(CAT) $$($1_EXITCODE)`" = "0" ]; then \ @@ -1030,10 +1031,12 @@ define SetupRunJtregTestBody ifneq ($$(JTREG_REPEAT_COUNT), 0) $1_COMMAND_LINE := \ for i in {1..$$(JTREG_REPEAT_COUNT)}; do \ - $$(PRINTF) "\nRepeating Jtreg run: $$$$i out of $$(JTREG_REPEAT_COUNT)\n"; \ + $$(ECHO) ""; \ + $$(ECHO) "Repeating Jtreg run: $$$$i out of $$(JTREG_REPEAT_COUNT)"; \ $$($1_COMMAND_LINE); \ if [ "`$$(CAT) $$($1_EXITCODE)`" != "0" ]; then \ - $$(PRINTF) "\nFailures detected, no more repeats.\n"; \ + $$(ECHO) ""; \ + $$(ECHO) "Failures detected, no more repeats."; \ break; \ fi; \ done diff --git a/make/SourceRevision.gmk b/make/SourceRevision.gmk index 285aaae17b5..15399527e6a 100644 --- a/make/SourceRevision.gmk +++ b/make/SourceRevision.gmk @@ -55,7 +55,7 @@ ifneq ($(and $(GIT), $(wildcard $(TOPDIR)/.git)), ) SCM_DIR := .git ID_COMMAND := $(PRINTF) "git:%s%s\n" \ "$$($(GIT) log -n1 --format=%H | cut -c1-12)" \ - "$$(if test -n "$$($(GIT) status --porcelain)"; then printf '+'; fi)" + "$$(if test -n "$$($(GIT) status --porcelain)"; then $(PRINTF) '+'; fi)" endif ifeq ($(USE_SCM), true) diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index 400acf11a63..93796d27f06 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -228,19 +228,19 @@ AC_DEFUN_ONCE([HELP_PRINT_ADDITIONAL_HELP_AND_EXIT], if test "x$CONFIGURE_PRINT_ADDITIONAL_HELP" != x; then # Print available toolchains - $PRINTF "The following toolchains are valid as arguments to --with-toolchain-type.\n" - $PRINTF "Which are available to use depends on the build platform.\n" + $ECHO "The following toolchains are valid as arguments to --with-toolchain-type." + $ECHO "Which are available to use depends on the build platform." for toolchain in $VALID_TOOLCHAINS_all; do # Use indirect variable referencing toolchain_var_name=TOOLCHAIN_DESCRIPTION_$toolchain TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} $PRINTF " %-22s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done - $PRINTF "\n" + $ECHO "" # Print available JVM features - $PRINTF "The following JVM features are valid as arguments to --with-jvm-features.\n" - $PRINTF "Which are available to use depends on the environment and JVM variant.\n" + $ECHO "The following JVM features are valid as arguments to --with-jvm-features." + $ECHO "Which are available to use depends on the environment and JVM variant." m4_foreach(FEATURE, m4_split(jvm_features_valid), [ # Create an m4 variable containing the description for FEATURE. m4_define(FEATURE_DESCRIPTION, [jvm_feature_desc_]m4_translit(FEATURE, -, _)) @@ -257,115 +257,117 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], [ # Finally output some useful information to the user - printf "\n" - printf "====================================================\n" + $ECHO "" + $ECHO "====================================================" if test "x$no_create" != "xyes"; then if test "x$IS_RECONFIGURE" != "xyes"; then - printf "A new configuration has been successfully created in\n%s\n" "$OUTPUTDIR" + $ECHO "A new configuration has been successfully created in" + $ECHO "$OUTPUTDIR" else - printf "The existing configuration has been successfully updated in\n%s\n" "$OUTPUTDIR" + $ECHO "The existing configuration has been successfully updated in" + $ECHO "$OUTPUTDIR" fi else if test "x$IS_RECONFIGURE" != "xyes"; then - printf "A configuration has been successfully checked but not created\n" + $ECHO "A configuration has been successfully checked but not created" else - printf "The existing configuration has been successfully checked in\n%s\n" "$OUTPUTDIR" + $ECHO "The existing configuration has been successfully checked in" + $ECHO "$OUTPUTDIR" fi fi if test "x$CONFIGURE_COMMAND_LINE" != x; then - printf "using configure arguments '$CONFIGURE_COMMAND_LINE'.\n" + $ECHO "using configure arguments '$CONFIGURE_COMMAND_LINE'." else - printf "using default settings.\n" + $ECHO "using default settings." fi if test "x$REAL_CONFIGURE_COMMAND_EXEC_FULL" != x; then - printf "\n" - printf "The original configure invocation was '$REAL_CONFIGURE_COMMAND_EXEC_SHORT $REAL_CONFIGURE_COMMAND_LINE'.\n" + $ECHO "" + $ECHO "The original configure invocation was '$REAL_CONFIGURE_COMMAND_EXEC_SHORT $REAL_CONFIGURE_COMMAND_LINE'." fi - printf "\n" - printf "Configuration summary:\n" - printf "* Name: $CONF_NAME\n" - printf "* Debug level: $DEBUG_LEVEL\n" - printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n" - printf "* JVM variants: $JVM_VARIANTS\n" - printf "* JVM features: " + $ECHO "" + $ECHO "Configuration summary:" + $ECHO "* Name: $CONF_NAME" + $ECHO "* Debug level: $DEBUG_LEVEL" + $ECHO "* HS debug level: $HOTSPOT_DEBUG_LEVEL" + $ECHO "* JVM variants: $JVM_VARIANTS" + $ECHO -n "* JVM features: " for variant in $JVM_VARIANTS; do features_var_name=JVM_FEATURES_$variant JVM_FEATURES_FOR_VARIANT=${!features_var_name} - printf "$variant: \'$JVM_FEATURES_FOR_VARIANT\' " + $ECHO -n "$variant: '$JVM_FEATURES_FOR_VARIANT' " done - printf "\n" + $ECHO "" - printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" - printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" + $ECHO "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS" + $ECHO "* Version string: $VERSION_STRING ($VERSION_SHORT)" if test "x$SOURCE_DATE" != xupdated; then source_date_info="$SOURCE_DATE ($SOURCE_DATE_ISO_8601)" else source_date_info="Determined at build time" fi - printf "* Source date: $source_date_info\n" + $ECHO "* Source date: $source_date_info" - printf "\n" - printf "Tools summary:\n" + $ECHO "" + $ECHO "Tools summary:" if test "x$OPENJDK_BUILD_OS" = "xwindows"; then - printf "* Environment: %s version %s; windows version %s; prefix \"%s\"; root \"%s\"\n" \ - "$WINENV_VENDOR" "$WINENV_VERSION" "$WINDOWS_VERSION" "$WINENV_PREFIX" "$WINENV_ROOT" + $ECHO "* Environment: $WINENV_VENDOR version $WINENV_VERSION; windows version $WINDOWS_VERSION; prefix \"$WINENV_PREFIX\"; root \"$WINENV_ROOT\"" fi - printf "* Boot JDK: $BOOT_JDK_VERSION (at $BOOT_JDK)\n" - printf "* Toolchain: $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION)\n" + $ECHO "* Boot JDK: $BOOT_JDK_VERSION (at $BOOT_JDK)" + $ECHO "* Toolchain: $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION)" if test "x$DEVKIT_NAME" != x; then - printf "* Devkit: $DEVKIT_NAME ($DEVKIT_ROOT)\n" + $ECHO "* Devkit: $DEVKIT_NAME ($DEVKIT_ROOT)" elif test "x$DEVKIT_ROOT" != x; then - printf "* Devkit: $DEVKIT_ROOT\n" + $ECHO "* Devkit: $DEVKIT_ROOT" elif test "x$SYSROOT" != x; then - printf "* Sysroot: $SYSROOT\n" + $ECHO "* Sysroot: $SYSROOT" fi - printf "* C Compiler: Version $CC_VERSION_NUMBER (at ${CC#"$FIXPATH "})\n" - printf "* C++ Compiler: Version $CXX_VERSION_NUMBER (at ${CXX#"$FIXPATH "})\n" + $ECHO "* C Compiler: Version $CC_VERSION_NUMBER (at ${CC#"$FIXPATH "})" + $ECHO "* C++ Compiler: Version $CXX_VERSION_NUMBER (at ${CXX#"$FIXPATH "})" - printf "\n" - printf "Build performance summary:\n" - printf "* Build jobs: $JOBS\n" - printf "* Memory limit: $MEMORY_SIZE MB\n" + $ECHO "" + $ECHO "Build performance summary:" + $ECHO "* Build jobs: $JOBS" + $ECHO "* Memory limit: $MEMORY_SIZE MB" if test "x$CCACHE_STATUS" != "x"; then - printf "* ccache status: $CCACHE_STATUS\n" + $ECHO "* ccache status: $CCACHE_STATUS" fi - printf "\n" + $ECHO "" if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xtrue"; then - printf "NOTE: You have requested to build more than one version of the JVM, which\n" - printf "will result in longer build times.\n" - printf "\n" + $ECHO "NOTE: You have requested to build more than one version of the JVM, which" + $ECHO "will result in longer build times." + $ECHO "" fi if test "x$OUTPUT_DIR_IS_LOCAL" != "xyes"; then - printf "WARNING: Your build output directory is not on a local disk.\n" - printf "This will severely degrade build performance!\n" - printf "It is recommended that you create an output directory on a local disk,\n" - printf "and run the configure script again from that directory.\n" - printf "\n" + $ECHO "WARNING: Your build output directory is not on a local disk." + $ECHO "This will severely degrade build performance!" + $ECHO "It is recommended that you create an output directory on a local disk," + $ECHO "and run the configure script again from that directory." + $ECHO "" fi if test "x$IS_RECONFIGURE" = "xyes" && test "x$no_create" != "xyes"; then - printf "WARNING: The result of this configuration has overridden an older\n" - printf "configuration. You *should* run 'make clean' to make sure you get a\n" - printf "proper build. Failure to do so might result in strange build problems.\n" - printf "\n" + $ECHO "WARNING: The result of this configuration has overridden an older" + $ECHO "configuration. You *should* run 'make clean' to make sure you get a" + $ECHO "proper build. Failure to do so might result in strange build problems." + $ECHO "" fi if test "x$IS_RECONFIGURE" != "xyes" && test "x$no_create" = "xyes"; then - printf "WARNING: The result of this configuration was not saved.\n" - printf "You should run without '--no-create | -n' to create the configuration.\n" - printf "\n" + $ECHO "WARNING: The result of this configuration was not saved." + $ECHO "You should run without '--no-create | -n' to create the configuration." + $ECHO "" fi if test "x$UNSUPPORTED_TOOLCHAIN_VERSION" = "xyes"; then - printf "WARNING: The toolchain version used is known to have issues. Please\n" - printf "consider using a supported version unless you know what you are doing.\n" - printf "\n" + $ECHO "WARNING: The toolchain version used is known to have issues. Please" + $ECHO "consider using a supported version unless you know what you are doing." + $ECHO "" fi ]) @@ -381,10 +383,10 @@ AC_DEFUN_ONCE([HELP_REPEAT_WARNINGS], if test -e "$CONFIG_LOG_PATH/config.log"; then $GREP '^configure:.*: WARNING:' "$CONFIG_LOG_PATH/config.log" > /dev/null 2>&1 if test $? -eq 0; then - printf "The following warnings were produced. Repeated here for convenience:\n" + $ECHO "The following warnings were produced. Repeated here for convenience:" # We must quote sed expression (using []) to stop m4 from eating the []. $GREP '^configure:.*: WARNING:' "$CONFIG_LOG_PATH/config.log" | $SED -e [ 's/^configure:[0-9]*: //' ] - printf "\n" + $ECHO "" fi fi ]) diff --git a/make/common/FindTests.gmk b/make/common/FindTests.gmk index 1f3a70b3035..41cf08d9e48 100644 --- a/make/common/FindTests.gmk +++ b/make/common/FindTests.gmk @@ -58,13 +58,15 @@ ifeq ($(GENERATE_FIND_TESTS_FILE), true) $(TOPDIR)/test/make/TestMake.gmk $(call MakeTargetDir) ( $(foreach root, $(JTREG_TESTROOTS), \ - $(PRINTF) "\n$(root)_JTREG_TEST_GROUPS := " ; \ + $(ECHO) ""; \ + $(ECHO) -n "$(root)_JTREG_TEST_GROUPS := "; \ $(SED) -n -e 's/^\#.*//g' -e 's/\([^ ]*\)\w*=.*/\1/gp' \ $($(root)_JTREG_GROUP_FILES) \ | $(SORT) -u | $(TR) '\n' ' ' ; \ ) \ ) > $@ - $(PRINTF) "\nMAKE_TEST_TARGETS := " >> $@ + $(ECHO) "" >> $@ + $(ECHO) -n "MAKE_TEST_TARGETS := " >> $@ $(MAKE) -s --no-print-directory $(MAKE_ARGS) \ SPEC=$(SPEC) -f $(TOPDIR)/test/make/TestMake.gmk print-targets \ TARGETS_FILE=$@ diff --git a/make/common/JarArchive.gmk b/make/common/JarArchive.gmk index 1f8ed1bc002..26a98f28949 100644 --- a/make/common/JarArchive.gmk +++ b/make/common/JarArchive.gmk @@ -256,7 +256,7 @@ define SetupJarArchiveBody $$(if $$($1_JARMAIN), \ $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \ $$(if $$($1_EXTRA_MANIFEST_ATTR), \ - $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \ + $(ECHO) "$$($1_EXTRA_MANIFEST_ATTR)" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \ $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \ $$($1_JAR_CMD) --create $$($1_JAR_OPTIONS) --file $$@ --manifest $$($1_MANIFEST_FILE) $$(NEWLINE) \ $$($1_SCAPTURE_CONTENTS) \ diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index f4f815c740d..663e9075cf8 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -180,7 +180,7 @@ ifeq ($(GENERATE_MODULE_DEPS_FILE), true) $(call MakeTargetDir) $(RM) $@ $(foreach m, $(MODULE_INFOS), \ - ( $(PRINTF) "DEPS_$(call GetModuleNameFromModuleInfo, $m) := " && \ + ( $(ECHO) -n "DEPS_$(call GetModuleNameFromModuleInfo, $m) := " && \ $(AWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) ' \ BEGIN { if (MODULE != "java.base") printf(" java.base"); } \ /^ *requires/ { sub(/;/, ""); \ @@ -194,7 +194,7 @@ ifeq ($(GENERATE_MODULE_DEPS_FILE), true) gsub(/\r/, ""); \ printf(" %s", $$0) } \ END { printf("\n") }' $m && \ - $(PRINTF) "TRANSITIVE_MODULES_$(call GetModuleNameFromModuleInfo, $m) := " && \ + $(ECHO) -n "TRANSITIVE_MODULES_$(call GetModuleNameFromModuleInfo, $m) := " && \ $(AWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) ' \ BEGIN { if (MODULE != "java.base") printf(" java.base"); } \ /^ *requires *transitive/ { \ diff --git a/make/common/modules/GensrcCommon.gmk b/make/common/modules/GensrcCommon.gmk index 64d1f71d82e..2a94c3f9a42 100644 --- a/make/common/modules/GensrcCommon.gmk +++ b/make/common/modules/GensrcCommon.gmk @@ -41,8 +41,8 @@ include $(TOPDIR)/make/ToolsJdk.gmk define SetupVersionProperties $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/$$(strip $2): $$(call MakeTargetDir) - $(PRINTF) "jdk=$(VERSION_NUMBER)\nfull=$(VERSION_STRING)\nrelease=$(VERSION_SHORT)\n" \ - > $$@ + $(PRINTF) "jdk=%s\nfull=%s\nrelease=%s\n" \ + $(VERSION_NUMBER) $(VERSION_STRING) $(VERSION_SHORT) > $$@ $$(strip $1) += $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/$$(strip $2) endef diff --git a/make/modules/java.base/Copy.gmk b/make/modules/java.base/Copy.gmk index e33676529cd..4625c1f7dbc 100644 --- a/make/modules/java.base/Copy.gmk +++ b/make/modules/java.base/Copy.gmk @@ -99,7 +99,7 @@ JVMCFG := $(LIB_DST_DIR)/jvm.cfg define print-cfg-line $(call LogInfo, Adding -$1 $2 to jvm.cfg) - $(PRINTF) -- "-$1 $2\n" >> $@ $(NEWLINE) + $(ECHO) "-$1 $2" >> $@ $(NEWLINE) endef $(JVMCFG): $(call DependOnVariable, ORDERED_CFG_VARIANTS) diff --git a/make/modules/java.base/gensrc/GensrcBuffer.gmk b/make/modules/java.base/gensrc/GensrcBuffer.gmk index f769a8e61e0..dd91c8c870a 100644 --- a/make/modules/java.base/gensrc/GensrcBuffer.gmk +++ b/make/modules/java.base/gensrc/GensrcBuffer.gmk @@ -272,7 +272,7 @@ define SetupGenBuffer $$($1_long_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp $$($1_float_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp $$($1_double_CMD) -i$$($1_SRC_BIN) -o$$($1_DST).tmp - $(PRINTF) "}\n" >> $$($1_DST).tmp + $(ECHO) "}" >> $$($1_DST).tmp mv $$($1_DST).tmp $$($1_DST) endif diff --git a/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk b/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk index 00fba64394b..ea51e4fd4ee 100644 --- a/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk +++ b/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk @@ -163,7 +163,7 @@ $(SCOPED_MEMORY_ACCESS_DEST): $(BUILD_TOOLS_JDK) $(SCOPED_MEMORY_ACCESS_TEMPLATE $(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \ $(TOOL_SPP) -nel -K$(BIN_$t_type) -Dtype=$(BIN_$t_type) -DType=$(BIN_$t_Type) $(BIN_$t_ARGS) \ -i$(SCOPED_MEMORY_ACCESS_BIN_TEMPLATE) -o$(SCOPED_MEMORY_ACCESS_DEST) ;) - $(PRINTF) "}\n" >> $(SCOPED_MEMORY_ACCESS_DEST) + $(ECHO) "}" >> $(SCOPED_MEMORY_ACCESS_DEST) TARGETS += $(SCOPED_MEMORY_ACCESS_DEST) diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh index cc2f4adf2ed..250b5a37b9f 100644 --- a/make/scripts/compare.sh +++ b/make/scripts/compare.sh @@ -203,12 +203,12 @@ compare_permissions() { do if [ ! -f ${OTHER_DIR}/$f ]; then continue; fi if [ ! -f ${THIS_DIR}/$f ]; then continue; fi - OP=`ls -l ${OTHER_DIR}/$f | awk '{printf("%.10s\n", $1);}'` - TP=`ls -l ${THIS_DIR}/$f | awk '{printf("%.10s\n", $1);}'` + OP=`ls -l ${OTHER_DIR}/$f | $AWK '{printf("%.10s\n", $1);}'` + TP=`ls -l ${THIS_DIR}/$f | $AWK '{printf("%.10s\n", $1);}'` if [ "$OP" != "$TP" ] then if [ -z "$found" ]; then echo ; found="yes"; fi - $PRINTF "\tother: ${OP} this: ${TP}\t$f\n" + $PRINTF "\tother: %s this: %s\t%s\n" "${OP}" "${TP}" "$f" fi done if [ -z "$found" ]; then @@ -260,7 +260,7 @@ compare_file_types() { continue else if [ -z "$found" ]; then echo ; found="yes"; fi - $PRINTF "\tother: ${OF}\n\tthis : ${TF}\n" + $PRINTF "\tother: %s\n\tthis : %s\n" "${OF}" "${TF}" fi fi done diff --git a/test/make/autoconf/test.m4 b/test/make/autoconf/test.m4 index 07fb91f6ff7..0aa002ef9bf 100644 --- a/test/make/autoconf/test.m4 +++ b/test/make/autoconf/test.m4 @@ -92,14 +92,16 @@ AC_DEFUN([TEST_ARG_ENABLE], # Use the CUSTOM_EARLY_HOOK to inject our test after basic init is done. AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK], [ - $PRINTF "\nStarting configure tests\n" - $PRINTF "==============================\n" + $ECHO "" + $ECHO "Starting configure tests" + $ECHO "==============================" TEST_STRING_OPS TEST_ARG_ENABLE # If no assertions failed, report success - $PRINTF "==============================\n" - $PRINTF "Configure tests finished successfully\n\n" + $ECHO "==============================" + $ECHO "Configure tests finished successfully" + $ECHO "" exit 0 ]) From a8dfcf55849775a7ac4822a8b7661f20f1b33bb0 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Mon, 7 Apr 2025 20:45:51 +0000 Subject: [PATCH 032/843] 8353322: Specification of ChoiceFormat#parse(String, ParsePosition) is inadequate Reviewed-by: naoto --- .../share/classes/java/text/ChoiceFormat.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/text/ChoiceFormat.java b/src/java.base/share/classes/java/text/ChoiceFormat.java index cf951ebf81f..560f3017824 100644 --- a/src/java.base/share/classes/java/text/ChoiceFormat.java +++ b/src/java.base/share/classes/java/text/ChoiceFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -558,7 +558,20 @@ public class ChoiceFormat extends NumberFormat { } /** - * Parses a Number from the input text. + * Parses the input text starting at the index given by the {@code ParsePosition} + * as a {@code Double}. The value returned is the {@code limit} corresponding + * to the {@code format} that is the longest substring of the input text. + * Matching is done in ascending order, when multiple {@code format}s match + * the text equivalently in strength, the first matching {@code limit} is + * returned. If there is no match, {@code Double.NaN} is returned. + *

+ * For example, + * {@snippet lang=java : + * var fmt = new ChoiceFormat("0#foo|1#bar|2#baz"); + * fmt.parse("baz", new ParsePosition(0)); // returns 2.0 + * fmt.parse("quux", new ParsePosition(0)); // returns NaN + * } + * * @param text the source text. * @param status an input-output parameter. On input, the * status.index field indicates the first character of the @@ -567,7 +580,8 @@ public class ChoiceFormat extends NumberFormat { * in the source text. On exit, if an error did occur, * status.index is unchanged and status.errorIndex is set to the * first index of the character that caused the parse to fail. - * @return A Number representing the value of the number parsed. + * @return A Number which represents the {@code limit} corresponding to the + * {@code format} parsed, or {@code Double.NaN} if the parse fails. * @throws NullPointerException if {@code status} is {@code null} * or if {@code text} is {@code null} and the list of * choice strings is not empty. From e266eba40131bb97c392c8c87551d28e74c4764a Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Mon, 7 Apr 2025 20:50:41 +0000 Subject: [PATCH 033/843] 8352972: PPC64: Intrinsify Unsafe::setMemory Reviewed-by: lucy --- src/hotspot/cpu/ppc/stubGenerator_ppc.cpp | 100 ++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index fa356ec13ac..939c3d3094a 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -2383,6 +2383,105 @@ class StubGenerator: public StubCodeGenerator { } + // Helper for generate_unsafe_setmemory + // + // Atomically fill an array of memory using 1-, 2-, 4-, or 8-byte chunks and return. + static void do_setmemory_atomic_loop(int elem_size, Register dest, Register size, Register byteVal, + MacroAssembler *_masm) { + + Label L_Loop, L_Tail; // 2x unrolled loop + + // Propagate byte to required width + if (elem_size > 1) __ rldimi(byteVal, byteVal, 8, 64 - 2 * 8); + if (elem_size > 2) __ rldimi(byteVal, byteVal, 16, 64 - 2 * 16); + if (elem_size > 4) __ rldimi(byteVal, byteVal, 32, 64 - 2 * 32); + + __ srwi_(R0, size, exact_log2(2 * elem_size)); // size is a 32 bit value + __ beq(CR0, L_Tail); + __ mtctr(R0); + + __ align(32); // loop alignment + __ bind(L_Loop); + __ store_sized_value(byteVal, 0, dest, elem_size); + __ store_sized_value(byteVal, elem_size, dest, elem_size); + __ addi(dest, dest, 2 * elem_size); + __ bdnz(L_Loop); + + __ bind(L_Tail); + __ andi_(R0, size, elem_size); + __ bclr(Assembler::bcondCRbiIs1, Assembler::bi0(CR0, Assembler::equal), Assembler::bhintbhBCLRisReturn); + __ store_sized_value(byteVal, 0, dest, elem_size); + __ blr(); + } + + // + // Generate 'unsafe' set memory stub + // Though just as safe as the other stubs, it takes an unscaled + // size_t (# bytes) argument instead of an element count. + // + // Input: + // R3_ARG1 - destination array address + // R4_ARG2 - byte count (size_t) + // R5_ARG3 - byte value + // + address generate_unsafe_setmemory(address unsafe_byte_fill) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, StubGenStubId::unsafe_setmemory_id); + address start = __ function_entry(); + + // bump this on entry, not on exit: + // inc_counter_np(SharedRuntime::_unsafe_set_memory_ctr); + + { + Label L_fill8Bytes, L_fill4Bytes, L_fillBytes; + + const Register dest = R3_ARG1; + const Register size = R4_ARG2; + const Register byteVal = R5_ARG3; + const Register rScratch1 = R6; + + // fill_to_memory_atomic(unsigned char*, unsigned long, unsigned char) + + // Check for pointer & size alignment + __ orr(rScratch1, dest, size); + + __ andi_(R0, rScratch1, 7); + __ beq(CR0, L_fill8Bytes); + + __ andi_(R0, rScratch1, 3); + __ beq(CR0, L_fill4Bytes); + + __ andi_(R0, rScratch1, 1); + __ bne(CR0, L_fillBytes); + + // Mark remaining code as such which performs Unsafe accesses. + UnsafeMemoryAccessMark umam(this, true, false); + + // At this point, we know the lower bit of size is zero and a + // multiple of 2 + do_setmemory_atomic_loop(2, dest, size, byteVal, _masm); + + __ align(32); + __ bind(L_fill8Bytes); + // At this point, we know the lower 3 bits of size are zero and a + // multiple of 8 + do_setmemory_atomic_loop(8, dest, size, byteVal, _masm); + + __ align(32); + __ bind(L_fill4Bytes); + // At this point, we know the lower 2 bits of size are zero and a + // multiple of 4 + do_setmemory_atomic_loop(4, dest, size, byteVal, _masm); + + __ align(32); + __ bind(L_fillBytes); + do_setmemory_atomic_loop(1, dest, size, byteVal, _masm); + } + + return start; + } + + // // Generate generic array copy stubs // @@ -3207,6 +3306,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_arrayof_jshort_fill = generate_fill(StubGenStubId::arrayof_jshort_fill_id); StubRoutines::_arrayof_jint_fill = generate_fill(StubGenStubId::arrayof_jint_fill_id); } + StubRoutines::_unsafe_setmemory = generate_unsafe_setmemory(StubRoutines::_jbyte_fill); #endif } From fd2734e97d3ef505473938109746ae59d5fefca6 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Mon, 7 Apr 2025 21:52:57 +0000 Subject: [PATCH 034/843] 8353585: Provide ChoiceFormat#parse(String, ParsePosition) tests Reviewed-by: naoto --- .../text/Format/ChoiceFormat/ParseTest.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 test/jdk/java/text/Format/ChoiceFormat/ParseTest.java diff --git a/test/jdk/java/text/Format/ChoiceFormat/ParseTest.java b/test/jdk/java/text/Format/ChoiceFormat/ParseTest.java new file mode 100644 index 00000000000..17ead8f450c --- /dev/null +++ b/test/jdk/java/text/Format/ChoiceFormat/ParseTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8353585 + * @summary Basic parse tests. Enforce regular behavior, no match, and multi match. + * @run junit ParseTest + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.text.ChoiceFormat; +import java.text.ParsePosition; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ParseTest { + + // Ensure that the parsed text produces the expected number + // i.e. return limit corresponding to format matched + @ParameterizedTest + @MethodSource + void parseTest(String pattern, String text, Double expected, int index) { + var pp = new ParsePosition(index); + var fmt = new ChoiceFormat(pattern); + assertEquals(expected, fmt.parse(text, pp), "Incorrect limit returned"); + if (expected.equals(Double.NaN)) { // AKA failed parse + assertEquals(index, pp.getErrorIndex(), + "Failed parse produced incorrect error index"); + } else { + assertEquals(-1, pp.getErrorIndex(), + "Error index should remain -1 on match"); + } + } + + private static Stream parseTest() { + return Stream.of( + Arguments.of("1#foo", "foo", Double.NaN, -1), + Arguments.of("1#baz", "foo bar baz", Double.NaN, 20), + Arguments.of("1#baz", "foo bar baz", 1d, 8), + Arguments.of("1#baz", "foo baz quux", Double.NaN, 8), + Arguments.of("1#a", "", Double.NaN, 0), + Arguments.of("1#a", "a", 1d, 0), + Arguments.of("1# ", " ", 1d, 0), + Arguments.of("1#a|2#a", "a", 1d, 0), + Arguments.of("1#a|2#aa", "aa", 2d, 0), + Arguments.of("1#a|2#aa", "aabb", 2d, 0), + Arguments.of("1#a|2#aa", "bbaa", Double.NaN, 0), + Arguments.of("1#aa|2#aaa", "a", Double.NaN, 0) + ); + } +} From 3951a8e01945d262cdd6ebbe4e1548ddf8e3c02a Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 7 Apr 2025 23:36:04 +0000 Subject: [PATCH 035/843] 8353365: TOUCH_ASSERT_POISON clears GetLastError() Reviewed-by: kbarrett, stuefe, jwaters --- src/hotspot/os/windows/os_windows.cpp | 1 + test/hotspot/gtest/utilities/test_vmerror.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 06fe8a826cd..ec03a45594c 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2600,6 +2600,7 @@ static inline void report_error(Thread* t, DWORD exception_code, //----------------------------------------------------------------------------- JNIEXPORT LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { + PreserveLastError ple; if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD exception_record = exceptionInfo->ExceptionRecord; DWORD exception_code = exception_record->ExceptionCode; diff --git a/test/hotspot/gtest/utilities/test_vmerror.cpp b/test/hotspot/gtest/utilities/test_vmerror.cpp index a779133b711..ad2f2c3004f 100644 --- a/test/hotspot/gtest/utilities/test_vmerror.cpp +++ b/test/hotspot/gtest/utilities/test_vmerror.cpp @@ -28,6 +28,17 @@ #ifdef ASSERT +#ifdef _WINDOWS + +#include + +TEST_VM_ASSERT_MSG(vmErrorTest, fatalWithError, + "fatal error: GetLastError should be 6 - actually: 6") { + SetLastError(6); + fatal("GetLastError should be 6 - actually: %lu", GetLastError()); +} +#endif // WINDOWS + TEST_VM_ASSERT_MSG(vmErrorTest, resourceMark, "fatal error: memory leak: allocating without ResourceMark") { From edaeb4b2da7c7a49ea3f3baebc7a072b56088e34 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 8 Apr 2025 00:33:36 +0000 Subject: [PATCH 036/843] 8352895: UserCookie.java runs wrong test class Reviewed-by: dfuchs --- test/jdk/sun/net/www/protocol/http/UserCookie.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/sun/net/www/protocol/http/UserCookie.java b/test/jdk/sun/net/www/protocol/http/UserCookie.java index 29261112ece..7867523719b 100644 --- a/test/jdk/sun/net/www/protocol/http/UserCookie.java +++ b/test/jdk/sun/net/www/protocol/http/UserCookie.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,9 @@ /* * @test * @bug 6439651 - * @modules jdk.httpserver - * @run main/othervm UserAuth * @summary Sending "Cookie" header with JRE 1.5.0_07 doesn't work anymore + * @modules jdk.httpserver + * @run main/othervm UserCookie */ import java.net.*; From b64cdc28132c889ca8e21dc9534590ba2a778bcd Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 8 Apr 2025 00:35:33 +0000 Subject: [PATCH 037/843] 8353787: Increased number of SHA-384-Digest java.util.jar.Attributes$Name instances leading to higher memory footprint Reviewed-by: mullan, lancea --- src/java.base/share/classes/java/util/jar/Attributes.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/jar/Attributes.java b/src/java.base/share/classes/java/util/jar/Attributes.java index 149bf38f67c..9322bb9acac 100644 --- a/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/src/java.base/share/classes/java/util/jar/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -727,6 +727,7 @@ public class Attributes implements Map, Cloneable { addName(names, new Name("Created-By")); addName(names, new Name("SHA1-Digest")); addName(names, new Name("SHA-256-Digest")); + addName(names, new Name("SHA-384-Digest")); KNOWN_NAMES = Map.copyOf(names); } else { // Even if KNOWN_NAMES was read from archive, we still need From 80ff7b9c9406c7845ecb3bc40910e92ccdd23ff2 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Tue, 8 Apr 2025 01:37:29 +0000 Subject: [PATCH 038/843] 8353695: RISC-V: compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java is failing with Zvkn Reviewed-by: fjiang, mli --- .../cpuflags/TestAESIntrinsicsOnSupportedConfig.java | 2 +- .../cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java | 2 +- .../compiler/lib/ir_framework/test/IREncodingPrinter.java | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java index b710ebcd283..4956b149574 100644 --- a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java +++ b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java @@ -26,7 +26,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.cpu.features ~= ".*aes.*" & !vm.graal.enabled + * @requires (vm.cpu.features ~= ".*aes.*" | vm.cpu.features ~= ".*zvkn.*") & !vm.graal.enabled * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/timeout=600 -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java index 26ad906095f..ef947c4e057 100644 --- a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java +++ b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java @@ -28,7 +28,7 @@ * java.management * * @build jdk.test.whitebox.WhiteBox - * @requires !(vm.cpu.features ~= ".*aes.*") + * @requires !(vm.cpu.features ~= ".*aes.*" | vm.cpu.features ~= ".*zvkn.*") * @requires vm.compiler1.enabled | !vm.graal.enabled * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 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 c9904404e90..7d229cae152 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -109,12 +109,13 @@ public class IREncodingPrinter { "asimd", "sve", "sve2", - // Riscv64 + // RISCV64 "rvv", "zbkb", "zfh", "zvbb", - "zvfh" + "zvfh", + "zvkn" )); public IREncodingPrinter() { From fb955bcb153b7008b45e9080c0817fcce7b5463e Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 8 Apr 2025 06:03:16 +0000 Subject: [PATCH 039/843] 8353267: jmod create finds the wrong set of packages when class file are in non-package location Reviewed-by: rriggs --- .../jlink/internal/ResourcePoolManager.java | 17 ++- .../classes/jdk/tools/jmod/JmodTask.java | 61 +++++---- test/jdk/tools/jlink/ClassFileInMetaInfo.java | 120 ++++++++++++++++++ test/jdk/tools/jmod/JmodTest.java | 44 ++++++- 4 files changed, 208 insertions(+), 34 deletions(-) create mode 100644 test/jdk/tools/jlink/ClassFileInMetaInfo.java diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java index 028bca2ecac..ba04b9db014 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Stream; import jdk.internal.jimage.decompressor.CompressedResourceHeader; -import jdk.internal.module.Resources; +import jdk.internal.module.Checks; import jdk.internal.module.ModuleInfo; import jdk.internal.module.ModuleInfo.Attributes; import jdk.internal.module.ModuleTarget; @@ -67,11 +67,16 @@ public class ResourcePoolManager { } /** - * Returns true if a resource has an effective package. + * Returns true if a resource is located in a named package. */ - public static boolean isNamedPackageResource(String path) { - return (path.endsWith(".class") && !path.endsWith("module-info.class")) || - Resources.canEncapsulate(path); + public static boolean isNamedPackageResource(String name) { + int index = name.lastIndexOf("/"); + if (index == -1) { + return false; + } else { + String pn = name.substring(0, index).replace('/', '.'); + return Checks.isPackageName(pn); + } } static class ResourcePoolModuleImpl implements ResourcePoolModule { diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index ed1620ec0f0..5345ee4253c 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -87,7 +87,7 @@ import jdk.internal.module.ModuleInfoExtender; import jdk.internal.module.ModulePath; import jdk.internal.module.ModuleResolution; import jdk.internal.module.ModuleTarget; -import jdk.internal.module.Resources; +import jdk.internal.module.Checks; import jdk.tools.jlink.internal.Utils; import static java.util.stream.Collectors.joining; @@ -689,7 +689,6 @@ public class JmodTask { (path, attrs) -> attrs.isRegularFile(), FileVisitOption.FOLLOW_LINKS)) { return stream.map(dir::relativize) - .filter(path -> isResource(path.toString())) .map(path -> toPackageName(path)) .filter(pkg -> pkg.length() > 0) .collect(Collectors.toSet()); @@ -703,46 +702,58 @@ public class JmodTask { */ Set findPackages(JarFile jf) { return jf.stream() - .filter(e -> !e.isDirectory() && isResource(e.getName())) + .filter(e -> !e.isDirectory()) .map(e -> toPackageName(e)) .filter(pkg -> pkg.length() > 0) .collect(Collectors.toSet()); } /** - * Returns true if it's a .class or a resource with an effective - * package name. + * Maps the given relative file path to a package name. + * @throws UncheckedIOException for a class file in a top-level directory */ - boolean isResource(String name) { - name = name.replace(File.separatorChar, '/'); - return name.endsWith(".class") || Resources.canEncapsulate(name); - } + private String toPackageName(Path path) { + assert path.getRoot() == null; - - String toPackageName(Path path) { - String name = path.toString(); - int index = name.lastIndexOf(File.separatorChar); - if (index != -1) - return name.substring(0, index).replace(File.separatorChar, '.'); - - if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { - IOException e = new IOException(name + " in the unnamed package"); - throw new UncheckedIOException(e); + Path parent = path.getParent(); + if (parent != null) { + String sep = path.getFileSystem().getSeparator(); + String pn = parent.toString().replace(sep, "."); + return Checks.isPackageName(pn) ? pn : ""; + } else { + // file in top-level directory + ensureNotClassFile(path.toString()); + return ""; } - return ""; } - String toPackageName(ZipEntry entry) { + /** + * Maps the name of a JAR file entry to a package name. + * @throws UncheckedIOException for a class file in a top-level directory + */ + private String toPackageName(ZipEntry entry) { String name = entry.getName(); - int index = name.lastIndexOf("/"); - if (index != -1) - return name.substring(0, index).replace('/', '.'); + assert !name.endsWith("/"); + int index = name.lastIndexOf("/"); + if (index != -1) { + String pn = name.substring(0, index).replace('/', '.'); + return Checks.isPackageName(pn) ? pn : ""; + } else { + // entry in top-level directory + ensureNotClassFile(name); + return ""; + } + } + + /** + * Throws IOException for a .class file that is not module-info.class. + */ + private void ensureNotClassFile(String name) { if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { IOException e = new IOException(name + " in the unnamed package"); throw new UncheckedIOException(e); } - return ""; } void processClasses(JmodOutputStream out, List classpaths) diff --git a/test/jdk/tools/jlink/ClassFileInMetaInfo.java b/test/jdk/tools/jlink/ClassFileInMetaInfo.java new file mode 100644 index 00000000000..028da2cbe50 --- /dev/null +++ b/test/jdk/tools/jlink/ClassFileInMetaInfo.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8353267 + * @summary Test jlink with a module containing a class file in its META-INF directory + * @library /test/lib + * @modules java.base/jdk.internal.module + * jdk.jlink + * jdk.jartool + * @run junit ClassFileInMetaInfo + */ + +import java.lang.module.ModuleDescriptor; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.spi.ToolProvider; + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.ModuleInfoWriter; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import static org.junit.jupiter.api.Assertions.*; + +class ClassFileInMetaInfo { + private static PrintStream out; + private static String moduleName; + private static String classesDir; + + @BeforeAll + static void setup() throws Exception { + out = System.err; // inline with Junit + + // Create module foo containing + // module-info.class + // p/C.class + // META-INF/extra/q/C.class + moduleName = "foo"; + ModuleDescriptor descriptor = ModuleDescriptor.newModule(moduleName).build(); + byte[] moduleInfo = ModuleInfoWriter.toBytes(descriptor); + Path dir = Files.createTempDirectory(Path.of("."), moduleName); + Files.write(dir.resolve("module-info.class"), moduleInfo); + Files.createFile(Files.createDirectory(dir.resolve("p")).resolve("C.class")); + Path extraClasses = dir.resolve("META-INF/extra/"); + Files.createFile(Files.createDirectories(extraClasses.resolve("q")).resolve("C.class")); + classesDir = dir.toString(); + } + + @Test + void testExplodedModule() throws Exception { + test(classesDir); + } + + @Test + void testModularJar() throws Exception { + String jarFile = "foo.jar"; + ToolProvider jarTool = ToolProvider.findFirst("jar").orElseThrow(); + int res = jarTool.run(out, out, "cf", jarFile, "-C", classesDir, "."); + assertEquals(0, res); + test(jarFile); + } + + @Test + void testJmod() throws Exception { + String jmodFile = "foo.jmod"; + ToolProvider jmodTool = ToolProvider.findFirst("jmod").orElseThrow(); + int res = jmodTool.run(out, out, "create", "--class-path", classesDir, jmodFile); + assertEquals(0, res); + test(jmodFile); + } + + /** + * jlink --module-path .. --add-modules foo --ouptut image + * image/bin/java --describe-module foo + */ + private void test(String modulePath) throws Exception { + Path dir = Files.createTempDirectory(Path.of("."), "image"); + Files.delete(dir); + String image = dir.toString(); + + ToolProvider jlinkTool = ToolProvider.findFirst("jlink").orElseThrow(); + int res = jlinkTool.run(out, out, + "--module-path", modulePath, + "--add-modules", moduleName, + "--output", image); + assertEquals(0, res); + + var pb = new ProcessBuilder(image + "/bin/java", "--describe-module", moduleName); + ProcessTools.executeProcess(pb) + .outputTo(out) + .errorTo(out) + .shouldHaveExitValue(0) + .shouldContain(moduleName) + .shouldContain("contains p") + .shouldNotContain("META-INF"); + } +} \ No newline at end of file diff --git a/test/jdk/tools/jmod/JmodTest.java b/test/jdk/tools/jmod/JmodTest.java index d75b31cef23..9cf81e6dcaf 100644 --- a/test/jdk/tools/jmod/JmodTest.java +++ b/test/jdk/tools/jmod/JmodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,12 @@ /* * @test - * @bug 8142968 8166568 8166286 8170618 8168149 8240910 8276764 8276766 + * @bug 8142968 8166568 8166286 8170618 8168149 8240910 8276764 8276766 8353267 * @summary Basic test for jmod * @library /test/lib * @modules jdk.compiler * jdk.jlink + * java.base/jdk.internal.module * @build jdk.test.lib.compiler.CompilerUtils * jdk.test.lib.util.FileUtils * jdk.test.lib.Platform @@ -45,6 +46,7 @@ import java.util.spi.ToolProvider; import java.util.stream.Stream; import jdk.test.lib.compiler.CompilerUtils; import jdk.test.lib.util.FileUtils; +import jdk.test.lib.util.ModuleInfoWriter; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @@ -682,7 +684,43 @@ public class JmodTest { Set pkgs = getModuleDescriptor(jmod).packages(); assertEquals(pkgs, expectedPackages); }); - } + } + + /** + * Test class files is the META-INF directory. + */ + @Test + public void testClassInMetaInf() throws IOException { + Path jmod = MODS_DIR.resolve("baz.jmod"); + FileUtils.deleteFileIfExistsWithRetry(jmod); + + ModuleDescriptor descriptor = ModuleDescriptor.newModule("baz").build(); + byte[] moduleInfo = ModuleInfoWriter.toBytes(descriptor); + + Path dir = Files.createTempDirectory(Path.of("."), "baz"); + Files.write(dir.resolve("module-info.class"), moduleInfo); + Files.createFile(Files.createDirectory(dir.resolve("p")).resolve("C.class")); + + // META-INF/extra/q/C.class + Path extraClasses = dir.resolve("META-INF/extra/"); + Files.createFile(Files.createDirectories(extraClasses.resolve("q")).resolve("C.class")); + + Set expectedPackages = Set.of("p"); + Set expectedContent = Set.of( + CLASSES_PREFIX + "module-info.class", + CLASSES_PREFIX + "p/C.class", + CLASSES_PREFIX + "META-INF/extra/q/C.class"); + + jmod("create", + "--class-path", dir.toString(), + jmod.toString()) + .assertSuccess() + .resultChecker(r -> { + Set pkgs = getModuleDescriptor(jmod).packages(); + assertEquals(pkgs, expectedPackages); + assertJmodContent(jmod, expectedContent); + }); + } @Test public void testVersion() { From 9844c1c52b9b7b6959d4e5cc626495c83f4aa9d4 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 8 Apr 2025 06:07:44 +0000 Subject: [PATCH 040/843] 8066583: DeflaterInput/OutputStream and InflaterInput/OutputStream should explain responsibility for freeing resources Reviewed-by: liach, alanb, lancea --- .../java/util/zip/DeflaterInputStream.java | 39 ++++++- .../java/util/zip/DeflaterOutputStream.java | 57 ++++++++-- .../java/util/zip/InflaterInputStream.java | 41 ++++++- .../java/util/zip/InflaterOutputStream.java | 35 +++++- .../java/util/zip/DeflateIn_InflateOut.java | 84 +++++++++++++- .../java/util/zip/InflateIn_DeflateOut.java | 104 ++++++++++++++++++ 6 files changed, 344 insertions(+), 16 deletions(-) diff --git a/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java index cb3f534cd5e..59364980598 100644 --- a/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java +++ b/src/java.base/share/classes/java/util/zip/DeflaterInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,20 @@ import java.util.Objects; * Implements an input stream filter for compressing data in the "deflate" * compression format. * + *

Compressor Usage

+ * A {@code DeflaterInputStream} created without + * specifying a {@linkplain Deflater compressor} will create a compressor + * at construction time, and close the compressor when the input stream + * is {@linkplain #close closed}. + *

+ * If a compressor is specified when creating a {@code DeflaterInputStream}, it is the + * responsibility of the caller to {@linkplain Deflater#close close} the + * compressor after closing the input stream. + * + * @apiNote + * The {@link #close} method should be called to release resources used by this + * stream, either directly, or with the {@code try}-with-resources statement. + * * @since 1.6 * @author David R Tribble (david@tribble.com) * @@ -68,8 +82,11 @@ public class DeflaterInputStream extends FilterInputStream { } /** - * Creates a new input stream with a default compressor and buffer - * size. + * Creates a new input stream and compressor with the + * default compression level and a default buffer size. + *

+ * The compressor will be closed when this input stream + * is {@linkplain #close() closed}. * * @param in input stream to read the uncompressed data to * @throws NullPointerException if {@code in} is null @@ -82,6 +99,10 @@ public class DeflaterInputStream extends FilterInputStream { /** * Creates a new input stream with the specified compressor and a * default buffer size. + *

+ * {@linkplain #close() Closing} this input stream + * {@linkplain ##compressor-usage will not close} the given + * {@linkplain Deflater compressor}. * * @param in input stream to read the uncompressed data to * @param defl compressor ("deflater") for this stream @@ -94,6 +115,10 @@ public class DeflaterInputStream extends FilterInputStream { /** * Creates a new input stream with the specified compressor and buffer * size. + *

+ * {@linkplain #close() Closing} this input stream + * {@linkplain ##compressor-usage will not close} the given + * {@linkplain Deflater compressor}. * * @param in input stream to read the uncompressed data to * @param defl compressor ("deflater") for this stream @@ -123,6 +148,7 @@ public class DeflaterInputStream extends FilterInputStream { * * @throws IOException if an I/O error occurs */ + @Override public void close() throws IOException { if (in != null) { try { @@ -147,6 +173,7 @@ public class DeflaterInputStream extends FilterInputStream { * @throws IOException if an I/O error occurs or if this stream is * already closed */ + @Override public int read() throws IOException { // Read a single byte of compressed data int len = read(rbuf, 0, 1); @@ -169,6 +196,7 @@ public class DeflaterInputStream extends FilterInputStream { * @throws IOException if an I/O error occurs or if this input stream is * already closed */ + @Override public int read(byte[] b, int off, int len) throws IOException { // Sanity checks ensureOpen(); @@ -224,6 +252,7 @@ public class DeflaterInputStream extends FilterInputStream { * already closed * @throws IllegalArgumentException if {@code n < 0} */ + @Override public long skip(long n) throws IOException { if (n < 0) { throw new IllegalArgumentException("negative skip length"); @@ -259,6 +288,7 @@ public class DeflaterInputStream extends FilterInputStream { * @throws IOException if an I/O error occurs or if this stream is * already closed */ + @Override public int available() throws IOException { ensureOpen(); if (reachEOF) { @@ -273,6 +303,7 @@ public class DeflaterInputStream extends FilterInputStream { * * @return false, always */ + @Override public boolean markSupported() { return false; } @@ -282,6 +313,7 @@ public class DeflaterInputStream extends FilterInputStream { * * @param limit maximum bytes that can be read before invalidating the position marker */ + @Override public void mark(int limit) { // Operation not supported } @@ -291,6 +323,7 @@ public class DeflaterInputStream extends FilterInputStream { * * @throws IOException always thrown */ + @Override public void reset() throws IOException { throw new IOException("mark/reset not supported"); } diff --git a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java index 66630d5adf0..3fca6a1b759 100644 --- a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,20 @@ import java.io.IOException; * or method in this class will cause a {@link NullPointerException} to be * thrown. * + *

Compressor Usage

+ * A {@code DeflaterOutputStream} created without + * specifying a {@linkplain Deflater compressor} will create a compressor + * at construction time, and close the compressor when the output stream + * is {@linkplain #close closed}. + *

+ * If a compressor is specified when creating a {@code DeflaterOutputStream}, it is the + * responsibility of the caller to {@linkplain Deflater#close close} the + * compressor after closing the output stream. + * + * @apiNote + * The {@link #close} method should be called to release resources used by this + * stream, either directly, or with the {@code try}-with-resources statement. + * * @see Deflater * @author David Connelly * @since 1.1 @@ -63,6 +77,10 @@ public class DeflaterOutputStream extends FilterOutputStream { /** * Creates a new output stream with the specified compressor, * buffer size and flush mode. + *

+ * {@linkplain #close() Closing} this output stream + * {@linkplain ##compressor-usage will not close} the given + * {@linkplain Deflater compressor}. * * @param out the output stream * @param def the compressor ("deflater") @@ -98,7 +116,11 @@ public class DeflaterOutputStream extends FilterOutputStream { * buffer size. * *

The new output stream instance is created as if by invoking - * the 4-argument constructor DeflaterOutputStream(out, def, size, false). + * the 4-argument constructor {@code DeflaterOutputStream(out, def, size, false)}. + *

+ * {@linkplain #close() Closing} this output stream + * {@linkplain ##compressor-usage will not close} the given + * {@linkplain Deflater compressor}. * * @param out the output stream * @param def the compressor ("deflater") @@ -112,6 +134,10 @@ public class DeflaterOutputStream extends FilterOutputStream { /** * Creates a new output stream with the specified compressor, flush * mode and a default buffer size. + *

+ * {@linkplain #close() Closing} this output stream + * {@linkplain ##compressor-usage will not close} the given + * {@linkplain Deflater compressor}. * * @param out the output stream * @param def the compressor ("deflater") @@ -135,7 +161,11 @@ public class DeflaterOutputStream extends FilterOutputStream { * a default buffer size. * *

The new output stream instance is created as if by invoking - * the 3-argument constructor DeflaterOutputStream(out, def, false). + * the 3-argument constructor {@code DeflaterOutputStream(out, def, false)}. + *

+ * {@linkplain #close() Closing} this output stream + * {@linkplain ##compressor-usage will not close} the given + * {@linkplain Deflater compressor}. * * @param out the output stream * @param def the compressor ("deflater") @@ -148,8 +178,12 @@ public class DeflaterOutputStream extends FilterOutputStream { /** - * Creates a new output stream with a default compressor, a default - * buffer size and the specified flush mode. + * Creates a new output stream and compressor with the + * default compression level, a default buffer size and + * the specified flush mode. + *

+ * The compressor will be closed when this output stream + * is {@linkplain #close() closed}. * * @param out the output stream * @param syncFlush @@ -166,10 +200,14 @@ public class DeflaterOutputStream extends FilterOutputStream { } /** - * Creates a new output stream with a default compressor and buffer size. + * Creates a new output stream and compressor with the + * default compression level and a default buffer size. * *

The new output stream instance is created as if by invoking - * the 2-argument constructor DeflaterOutputStream(out, false). + * the 2-argument constructor {@code DeflaterOutputStream(out, false)}. + *

+ * The compressor will be closed when this output stream + * is {@linkplain #close() closed}. * * @param out the output stream */ @@ -184,6 +222,7 @@ public class DeflaterOutputStream extends FilterOutputStream { * @param b the byte to be written * @throws IOException if an I/O error has occurred */ + @Override public void write(int b) throws IOException { byte[] buf = new byte[1]; buf[0] = (byte)(b & 0xff); @@ -198,6 +237,7 @@ public class DeflaterOutputStream extends FilterOutputStream { * @param len the length of the data * @throws IOException if an I/O error has occurred */ + @Override public void write(byte[] b, int off, int len) throws IOException { if (def.finished()) { throw new IOException("write beyond end of stream"); @@ -239,8 +279,10 @@ public class DeflaterOutputStream extends FilterOutputStream { /** * Writes remaining compressed data to the output stream and closes the * underlying stream. + * * @throws IOException if an I/O error has occurred */ + @Override public void close() throws IOException { if (!closed) { closed = true; @@ -296,6 +338,7 @@ public class DeflaterOutputStream extends FilterOutputStream { * * @since 1.7 */ + @Override public void flush() throws IOException { if (syncFlush && !def.finished()) { int len = 0; diff --git a/src/java.base/share/classes/java/util/zip/InflaterInputStream.java b/src/java.base/share/classes/java/util/zip/InflaterInputStream.java index f13b5915a84..81dcf8246e0 100644 --- a/src/java.base/share/classes/java/util/zip/InflaterInputStream.java +++ b/src/java.base/share/classes/java/util/zip/InflaterInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,21 @@ import java.util.Objects; *

Unless otherwise noted, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be * thrown. + * + *

Decompressor Usage

+ * An {@code InflaterInputStream} created without + * specifying a {@linkplain Inflater decompressor} will create a decompressor + * at construction time, and close the decompressor when the input stream + * is {@linkplain #close closed}. + *

+ * If a decompressor is specified when creating a {@code InflaterInputStream}, it is the + * responsibility of the caller to {@linkplain Inflater#close close} the + * decompressor after closing the input stream. + * + * @apiNote + * The {@link #close} method should be called to release resources used by this + * stream, either directly, or with the {@code try}-with-resources statement. + * * @see Inflater * @author David Connelly * @since 1.1 @@ -75,6 +90,11 @@ public class InflaterInputStream extends FilterInputStream { /** * Creates a new input stream with the specified decompressor and * buffer size. + *

+ * {@linkplain #close() Closing} this input stream + * {@linkplain ##decompressor-usage will not close} the given + * {@linkplain Inflater decompressor}. + * * @param in the input stream * @param inf the decompressor ("inflater") * @param size the input buffer size @@ -94,6 +114,11 @@ public class InflaterInputStream extends FilterInputStream { /** * Creates a new input stream with the specified decompressor and a * default buffer size. + *

+ * {@linkplain #close() Closing} this input stream + * {@linkplain ##decompressor-usage will not close} the given + * {@linkplain Inflater decompressor}. + * * @param in the input stream * @param inf the decompressor ("inflater") */ @@ -104,7 +129,12 @@ public class InflaterInputStream extends FilterInputStream { boolean usesDefaultInflater = false; /** - * Creates a new input stream with a default decompressor and buffer size. + * Creates a new input stream and decompressor with a + * default buffer size. + *

+ * The decompressor will be closed when this input stream + * is {@linkplain #close() closed}. + * * @param in the input stream */ public InflaterInputStream(InputStream in) { @@ -120,6 +150,7 @@ public class InflaterInputStream extends FilterInputStream { * @return the byte read, or -1 if end of compressed input is reached * @throws IOException if an I/O error has occurred */ + @Override public int read() throws IOException { ensureOpen(); return read(singleByteBuf, 0, 1) == -1 ? -1 : Byte.toUnsignedInt(singleByteBuf[0]); @@ -151,6 +182,7 @@ public class InflaterInputStream extends FilterInputStream { * @throws ZipException if a ZIP format error has occurred * @throws IOException if an I/O error has occurred */ + @Override public int read(byte[] b, int off, int len) throws IOException { ensureOpen(); if (b == null) { @@ -193,6 +225,7 @@ public class InflaterInputStream extends FilterInputStream { * @throws IOException if an I/O error occurs. * */ + @Override public int available() throws IOException { ensureOpen(); if (reachEOF) { @@ -220,6 +253,7 @@ public class InflaterInputStream extends FilterInputStream { * already closed * @throws IllegalArgumentException if {@code n < 0} */ + @Override public long skip(long n) throws IOException { if (n < 0) { throw new IllegalArgumentException("negative skip length"); @@ -246,8 +280,10 @@ public class InflaterInputStream extends FilterInputStream { /** * Closes this input stream and releases any system resources associated * with the stream. + * * @throws IOException if an I/O error has occurred */ + @Override public void close() throws IOException { if (!closed) { if (usesDefaultInflater) @@ -287,6 +323,7 @@ public class InflaterInputStream extends FilterInputStream { * @see java.io.InputStream#mark(int) * @see java.io.InputStream#reset() */ + @Override public boolean markSupported() { return false; } diff --git a/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java index 7b08d5b4538..31c51509a76 100644 --- a/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/InflaterOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,20 @@ import java.util.Objects; * Implements an output stream filter for uncompressing data stored in the * "deflate" compression format. * + *

Decompressor Usage

+ * An {@code InflaterOutputStream} created without + * specifying a {@linkplain Inflater decompressor} will create a decompressor + * at construction time, and close the decompressor when the output stream + * is {@linkplain #close closed}. + *

+ * If a decompressor is specified when creating a {@code InflaterOutputStream}, it is the + * responsibility of the caller to {@linkplain Inflater#close close} the + * decompressor after closing the output stream. + * + * @apiNote + * The {@link #close} method should be called to release resources used by this + * stream, either directly, or with the {@code try}-with-resources statement. + * * @since 1.6 * @author David R Tribble (david@tribble.com) * @@ -68,8 +82,11 @@ public class InflaterOutputStream extends FilterOutputStream { } /** - * Creates a new output stream with a default decompressor and buffer - * size. + * Creates a new output stream and decompressor with a + * default buffer size. + *

+ * The decompressor will be closed when this output stream + * is {@linkplain #close() closed}. * * @param out output stream to write the uncompressed data to * @throws NullPointerException if {@code out} is null @@ -82,6 +99,10 @@ public class InflaterOutputStream extends FilterOutputStream { /** * Creates a new output stream with the specified decompressor and a * default buffer size. + *

+ * {@linkplain #close() Closing} this output stream + * {@linkplain ##decompressor-usage will not close} the given + * {@linkplain Inflater decompressor}. * * @param out output stream to write the uncompressed data to * @param infl decompressor ("inflater") for this stream @@ -94,6 +115,10 @@ public class InflaterOutputStream extends FilterOutputStream { /** * Creates a new output stream with the specified decompressor and * buffer size. + *

+ * {@linkplain #close() Closing} this output stream + * {@linkplain ##decompressor-usage will not close} the given + * {@linkplain Inflater decompressor}. * * @param out output stream to write the uncompressed data to * @param infl decompressor ("inflater") for this stream @@ -123,6 +148,7 @@ public class InflaterOutputStream extends FilterOutputStream { * * @throws IOException if an I/O error occurs */ + @Override public void close() throws IOException { if (!closed) { // Complete the uncompressed output @@ -142,6 +168,7 @@ public class InflaterOutputStream extends FilterOutputStream { * @throws IOException if an I/O error occurs or this stream is already * closed */ + @Override public void flush() throws IOException { ensureOpen(); @@ -199,6 +226,7 @@ public class InflaterOutputStream extends FilterOutputStream { * closed * @throws ZipException if a compression (ZIP) format error occurs */ + @Override public void write(int b) throws IOException { // Write a single byte of data wbuf[0] = (byte) b; @@ -219,6 +247,7 @@ public class InflaterOutputStream extends FilterOutputStream { * @throws NullPointerException if {@code b} is null * @throws ZipException if a compression (ZIP) format error occurs */ + @Override public void write(byte[] b, int off, int len) throws IOException { // Sanity checks ensureOpen(); diff --git a/test/jdk/java/util/zip/DeflateIn_InflateOut.java b/test/jdk/java/util/zip/DeflateIn_InflateOut.java index 68ad0eaa036..d0b23e6b811 100644 --- a/test/jdk/java/util/zip/DeflateIn_InflateOut.java +++ b/test/jdk/java/util/zip/DeflateIn_InflateOut.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ */ import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.zip.*; @@ -270,6 +271,83 @@ public class DeflateIn_InflateOut { check(Arrays.equals(data, baos.toByteArray())); } + /** + * Verifies that when a DeflaterInputStream is constructed + * by passing a Deflater instance, then closing the DeflaterInputStream + * will not close the passed Deflater instance. + */ + private static void deflaterInputStreamDeflaterNotClosed() throws Throwable { + // some arbitrary content + final byte[] original = "foo".repeat(1024).getBytes(StandardCharsets.US_ASCII); + // run the DeflaterInputStream tests + try (final Deflater def = new Deflater()) { + try (ByteArrayInputStream bis = new ByteArrayInputStream(original); + DeflaterInputStream iis = new DeflaterInputStream(bis, def)) { + iis.readAllBytes(); + } + // verify the deflater wasn't closed - reset() will throw IllegalStateException if + // the deflater is closed + def.reset(); + + // repeat the test with the other constructor + try (ByteArrayInputStream bis = new ByteArrayInputStream(original); + DeflaterInputStream iis = new DeflaterInputStream(bis, def, 1024)) { + iis.readAllBytes(); + } + // verify the deflater wasn't closed - reset() will throw IllegalStateException if + // the deflater is closed + def.reset(); + } + } + + private static byte[] deflate(final byte[] original) { + final ByteArrayOutputStream compressedBaos = new ByteArrayOutputStream(); + try (Deflater compressor = new Deflater()) { + compressor.setInput(original); + compressor.finish(); + while (!compressor.finished()) { + byte[] tmpBuffer = new byte[1024]; + int numCompressed = compressor.deflate(tmpBuffer); + compressedBaos.write(tmpBuffer, 0, numCompressed); + } + } + return compressedBaos.toByteArray(); + } + + /** + * Verifies that when a InflaterOutputStream is constructed + * by passing a Inflater instance, then closing the InflaterOutputStream + * will not close the passed Inflater instance. + */ + private static void inflaterOutputStreamInflaterNotClosed() throws Throwable { + // some arbitrary content + final byte[] original = "bar".repeat(1024).getBytes(StandardCharsets.US_ASCII); + // deflate it + final byte[] deflated = deflate(original); + try (final Inflater infl = new Inflater()) { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + InflaterOutputStream dos = new InflaterOutputStream(bos, infl)) { + dos.write(deflated); + dos.flush(); + check(Arrays.equals(original, bos.toByteArray())); + } + // verify the inflater wasn't closed - reset() will throw IllegalStateException if + // the inflater is closed + infl.reset(); + + // repeat the test with the other constructor + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + InflaterOutputStream dos = new InflaterOutputStream(bos, infl, 1024)) { + dos.write(deflated); + dos.flush(); + check(Arrays.equals(original, bos.toByteArray())); + } + // verify the inflater wasn't closed - reset() will throw IllegalStateException if + // the inflater is closed + infl.reset(); + } + } + public static void realMain(String[] args) throws Throwable { new Random(new Date().getTime()).nextBytes(data); @@ -284,6 +362,10 @@ public class DeflateIn_InflateOut { SkipBytes(); NeedsDictionary(); + + deflaterInputStreamDeflaterNotClosed(); + + inflaterOutputStreamInflaterNotClosed(); } //--------------------- Infrastructure --------------------------- diff --git a/test/jdk/java/util/zip/InflateIn_DeflateOut.java b/test/jdk/java/util/zip/InflateIn_DeflateOut.java index e9c9c59e24e..31cdf73aaae 100644 --- a/test/jdk/java/util/zip/InflateIn_DeflateOut.java +++ b/test/jdk/java/util/zip/InflateIn_DeflateOut.java @@ -1,5 +1,6 @@ /* * Copyright 2009 Google, Inc. All Rights Reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +31,7 @@ */ import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.zip.*; @@ -293,6 +295,106 @@ public class InflateIn_DeflateOut { checkLOP(gis, gos); } + private static byte[] deflate(final byte[] original) { + final ByteArrayOutputStream compressedBaos = new ByteArrayOutputStream(); + try (Deflater compressor = new Deflater()) { + compressor.setInput(original); + compressor.finish(); + while (!compressor.finished()) { + byte[] tmpBuffer = new byte[1024]; + int numCompressed = compressor.deflate(tmpBuffer); + compressedBaos.write(tmpBuffer, 0, numCompressed); + } + } + return compressedBaos.toByteArray(); + } + + /** + * Verifies that when a InflaterInputStream is constructed + * by passing a Inflater instance, then closing the InflaterInputStream + * will not close the passed Inflater instance. + */ + private static void inflaterInputStreamInflaterNotClosed() throws Throwable { + // some arbitrary content + final byte[] original = "foo".repeat(1024).getBytes(StandardCharsets.US_ASCII); + // deflate it + final byte[] deflated = deflate(original); + // run the InflaterInputStream tests + try (final Inflater infl = new Inflater()) { + try (ByteArrayInputStream bis = new ByteArrayInputStream(deflated); + InflaterInputStream iis = new InflaterInputStream(bis, infl)) { + final byte[] inflated = iis.readAllBytes(); + check(Arrays.equals(original, inflated)); + } + // verify the inflater wasn't closed - reset() will throw IllegalStateException if + // the inflater is closed + infl.reset(); + + // repeat the test with the other constructor + try (ByteArrayInputStream bis = new ByteArrayInputStream(deflated); + InflaterInputStream iis = new InflaterInputStream(bis, infl, 1024)) { + final byte[] inflated = iis.readAllBytes(); + check(Arrays.equals(original, inflated)); + } + // verify the inflater wasn't closed - reset() will throw IllegalStateException if + // the inflater is closed + infl.reset(); + } + } + + /** + * Verifies that when a DeflaterOutputStream is constructed + * by passing a Deflater instance, then closing the DeflaterOutputStream + * will not close the passed Deflater instance. + */ + private static void deflaterOutputStreamDeflaterNotClosed() throws Throwable { + // some arbitrary content + final byte[] data = "bar".repeat(1024).getBytes(StandardCharsets.US_ASCII); + // run the InflaterInputStream tests + try (final Deflater def = new Deflater()) { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DeflaterOutputStream dos = new DeflaterOutputStream(bos, def)) { + dos.write(data); + } + // verify the deflater wasn't closed - reset() will throw IllegalStateException if + // the deflater is closed + def.reset(); + + // repeat the test with the other constructor + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DeflaterOutputStream dos = new DeflaterOutputStream(bos, def, 1024)) { + dos.write(data); + } + // verify the deflater wasn't closed - reset() will throw IllegalStateException if + // the deflater is closed + def.reset(); + + // repeat the test with the other constructor + for (boolean syncFlush : new boolean[] {false, true}) { + System.out.println("testing with syncFlush = " + syncFlush); + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DeflaterOutputStream dos = new DeflaterOutputStream(bos, def, syncFlush)) { + dos.write(data); + } + // verify the deflater wasn't closed - reset() will throw IllegalStateException if + // the deflater is closed + def.reset(); + } + + // repeat the test with the other constructor + for (boolean syncFlush : new boolean[] {false, true}) { + System.out.println("testing with syncFlush = " + syncFlush); + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DeflaterOutputStream dos = new DeflaterOutputStream(bos, def, 1024, syncFlush)) { + dos.write(data); + } + // verify the deflater wasn't closed - reset() will throw IllegalStateException if + // the deflater is closed + def.reset(); + } + } + } + public static void realMain(String[] args) throws Throwable { WriteCloseRead(); WriteFlushRead(); @@ -300,6 +402,8 @@ public class InflateIn_DeflateOut { GZWriteFlushRead(); GZLineOrientedProtocol(); TestFlushableGZIPOutputStream(); + inflaterInputStreamInflaterNotClosed(); + deflaterOutputStreamDeflaterNotClosed(); } //--------------------- Infrastructure --------------------------- From ea07e719ca255d0da1966118c464ee23f4dc44da Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 8 Apr 2025 08:12:59 +0000 Subject: [PATCH 041/843] 8352256: ObjectSynchronizer::quick_notify misses JFR event notification path Reviewed-by: dholmes, coleenp, mgronlun --- src/hotspot/share/runtime/objectMonitor.cpp | 12 ++++++++++++ src/hotspot/share/runtime/objectMonitor.hpp | 2 ++ src/hotspot/share/runtime/synchronizer.cpp | 10 +++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index e280de6baf1..03228d0cb12 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -2058,6 +2058,12 @@ void ObjectMonitor::notify(TRAPS) { return; } + quick_notify(current); +} + +void ObjectMonitor::quick_notify(JavaThread* current) { + assert(has_owner(current), "Precondition"); + EventJavaMonitorNotify event; DTRACE_MONITOR_PROBE(notify, this, object(), current); int tally = notify_internal(current) ? 1 : 0; @@ -2080,6 +2086,12 @@ void ObjectMonitor::notifyAll(TRAPS) { return; } + quick_notifyAll(current); +} + +void ObjectMonitor::quick_notifyAll(JavaThread* current) { + assert(has_owner(current), "Precondition"); + EventJavaMonitorNotify event; DTRACE_MONITOR_PROBE(notifyAll, this, object(), current); int tally = 0; diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index d24201fafe4..729316811c2 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -385,6 +385,8 @@ class ObjectMonitor : public CHeapObj { void wait(jlong millis, bool interruptible, TRAPS); void notify(TRAPS); void notifyAll(TRAPS); + void quick_notify(JavaThread* current); + void quick_notifyAll(JavaThread* current); void print() const; #ifdef ASSERT diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 73dd9d5330e..d608ffbdc02 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -368,16 +368,12 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool al if (mon->first_waiter() != nullptr) { // We have one or more waiters. Since this is an inflated monitor - // that we own, we can transfer one or more threads from the waitset - // to the entry_list here and now, avoiding the slow-path. + // that we own, we quickly notify them here and now, avoiding the slow-path. if (all) { - DTRACE_MONITOR_PROBE(notifyAll, mon, obj, current); + mon->quick_notifyAll(current); } else { - DTRACE_MONITOR_PROBE(notify, mon, obj, current); + mon->quick_notify(current); } - do { - mon->notify_internal(current); - } while (mon->first_waiter() != nullptr && all); } return true; } From fda5eecd6717eb6e1db56be3e41b65deae6e683e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Casta=C3=B1eda=20Lozano?= Date: Tue, 8 Apr 2025 08:27:00 +0000 Subject: [PATCH 042/843] 8353669: IGV: dump OOP maps for MachSafePoint nodes Reviewed-by: chagedorn, thartmann --- src/hotspot/share/opto/idealGraphPrinter.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index f6ec1a72506..47cc66c4cf0 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -667,6 +667,15 @@ void IdealGraphPrinter::visit_node(Node* n, bool edges) { print_prop("lrg", lrg_id); } + if (node->is_MachSafePoint()) { + const OopMap* oopmap = node->as_MachSafePoint()->oop_map(); + if (oopmap != nullptr) { + stringStream oopmap_stream; + oopmap->print_on(&oopmap_stream); + print_prop("oopmap", oopmap_stream.freeze()); + } + } + Compile::current()->_in_dump_cnt--; tail(PROPERTIES_ELEMENT); From 9088afc4f16b6265e640bf176d8ca8e3ac6ca45c Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 8 Apr 2025 09:25:23 +0000 Subject: [PATCH 043/843] 8353332: Test jdk/jshell/ToolProviderTest.java failed in relation to enable-preview Reviewed-by: jpai, asotona --- .../jshell/tool/JShellToolProvider.java | 18 +++++--- .../jdk/jshell/ToolProviderTest.java | 46 +++++++++++++++---- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolProvider.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolProvider.java index f858eb6a406..ebc02ecd93c 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolProvider.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.io.PrintStream; import java.util.Collections; import java.util.EnumSet; import java.util.Set; +import java.util.function.Function; import javax.lang.model.SourceVersion; import javax.tools.Tool; import jdk.jshell.tool.JavaShellToolBuilder; @@ -40,6 +41,10 @@ import jdk.jshell.tool.JavaShellToolBuilder; */ public class JShellToolProvider implements Tool { + //for tests, so that they can tweak the builder (typically set persistence): + private static Function augmentToolBuilder = + builder -> builder; + /** * Returns the name of this Java shell tool provider. * @@ -86,11 +91,12 @@ public class JShellToolProvider implements Tool { ? (PrintStream) err : new PrintStream(err); try { - return JavaShellToolBuilder - .builder() - .in(xin, null) - .out(xout) - .err(xerr) + return augmentToolBuilder.apply( + JavaShellToolBuilder + .builder() + .in(xin, null) + .out(xout) + .err(xerr)) .start(arguments); } catch (Throwable ex) { xerr.println(ex.getMessage()); diff --git a/test/langtools/jdk/jshell/ToolProviderTest.java b/test/langtools/jdk/jshell/ToolProviderTest.java index ada5f34d8c0..67038c878ab 100644 --- a/test/langtools/jdk/jshell/ToolProviderTest.java +++ b/test/langtools/jdk/jshell/ToolProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,20 +21,25 @@ * questions. */ +import java.lang.reflect.Field; +import java.util.HashMap; import java.util.ServiceLoader; import java.util.function.Consumer; +import java.util.function.Function; import javax.tools.Tool; +import jdk.internal.jshell.tool.JShellToolProvider; +import jdk.jshell.tool.JavaShellToolBuilder; import org.testng.annotations.Test; import static org.testng.Assert.assertTrue; /* * @test - * @bug 8170044 8171343 8179856 8185840 8190383 + * @bug 8170044 8171343 8179856 8185840 8190383 8353332 * @summary Test ServiceLoader launching of jshell tool * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.jdeps/com.sun.tools.javap - * jdk.jshell/jdk.internal.jshell.tool + * jdk.jshell/jdk.internal.jshell.tool:+open * @library /tools/lib * @build Compiler toolbox.ToolBox * @run testng ToolProviderTest @@ -68,13 +73,20 @@ public class ToolProviderTest extends StartOptionTest { @Override protected int runShell(String... args) { - ServiceLoader sl = ServiceLoader.load(Tool.class); - for (Tool provider : sl) { - if (provider.name().equals("jshell")) { - return provider.run(cmdInStream, cmdout, cmderr, args); + //make sure the JShell running during the test is not using persisted preferences from the machine: + Function prevAugmentedToolBuilder = + getAndSetAugmentedToolBuilder(builder -> builder.persistence(new HashMap<>())); + try { + ServiceLoader sl = ServiceLoader.load(Tool.class); + for (Tool provider : sl) { + if (provider.name().equals("jshell")) { + return provider.run(cmdInStream, cmdout, cmderr, args); + } } + throw new AssertionError("Repl tool not found by ServiceLoader: " + sl); + } finally { + getAndSetAugmentedToolBuilder(prevAugmentedToolBuilder); } - throw new AssertionError("Repl tool not found by ServiceLoader: " + sl); } // Test --show-version @@ -87,4 +99,22 @@ public class ToolProviderTest extends StartOptionTest { }, "--show-version"); } + + private Function getAndSetAugmentedToolBuilder + (Function augmentToolBuilder) { + try { + Field f = JShellToolProvider.class.getDeclaredField("augmentToolBuilder"); + + f.setAccessible(true); + + Function prev = + (Function) f.get(null); + + f.set(null, augmentToolBuilder); + + return prev; + } catch (ReflectiveOperationException ex) { + throw new IllegalStateException(ex); + } + } } From d8bed1304713b17286d4ed614f95d0ef6e59a95b Mon Sep 17 00:00:00 2001 From: Koushik Thirupattur Date: Tue, 8 Apr 2025 11:50:59 +0000 Subject: [PATCH 044/843] 8353945: Test javax/security/auth/x500/X500Principal/NameFormat.java fails after JDK-8349890 Reviewed-by: mullan --- .../auth/x500/X500Principal/NameFormat.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java b/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java index 2503b36f30c..3f0422ff933 100644 --- a/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java +++ b/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java @@ -118,22 +118,23 @@ public class NameFormat { testName("CN=Before\\0dAfter,DC=example,DC=net", "toString", "CN=Before\\0DAfter, DC=example, DC=net", 22); testName("CN=Before\\0dAfter,DC=example,DC=net", "RFC1779", - "CN=Before\\0DAfter, " + + "CN=Before\r" + "After, " + "OID.0.9.2342.19200300.100.1.25=example, " + "OID.0.9.2342.19200300.100.1.25=net", 23); + testName("CN=Before\\0dAfter,DC=example,DC=net", "RFC2253", - "CN=Before\\0DAfter,DC=example,DC=net", 24); + "CN=Before\r" + "After,DC=example,DC=net", 24); testName("CN=Before\\0dAfter,DC=example,DC=net", "CANONICAL", - "cn=before\\0dafter,dc=#16076578616d706c65,dc=#16036e6574", 25); + "cn=before\r" + "after,dc=#16076578616d706c65,dc=#16036e6574", 25); testName("CN=Lu\\C4\\8Di\\C4\\87", "toString", "CN=Lu\\C4\\8Di\\C4\\87", 26); testName("CN=Lu\\C4\\8Di\\C4\\87", "RFC1779", - "CN=Lu\\C4\\8Di\\C4\\87", 27); + "CN=Lu\u010di\u0107", 27); testName("CN=Lu\\C4\\8Di\\C4\\87", "RFC2253", - "CN=Lu\\C4\\8Di\\C4\\87", 28); + "CN=Lu\u010di\u0107", 28); testName("CN=Lu\\C4\\8Di\\C4\\87", "CANONICAL", - "cn=lu\\c4\\8di\\c4\\87", 29); + "cn=luc\u030cic\u0301", 29); try { p = new X500Principal("cn=\\gg"); From 3d24f1a38280fd7f40148399c1ae2f3bd20763e5 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Tue, 8 Apr 2025 12:40:10 +0000 Subject: [PATCH 045/843] 8353580: libjpeg is not found if not installed in system directories Reviewed-by: erikj --- make/autoconf/lib-bundled.m4 | 22 ++++++++++++++++------ make/autoconf/spec.gmk.template | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/make/autoconf/lib-bundled.m4 b/make/autoconf/lib-bundled.m4 index 091f01cadb5..2b0d4f2f23f 100644 --- a/make/autoconf/lib-bundled.m4 +++ b/make/autoconf/lib-bundled.m4 @@ -62,19 +62,29 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBJPEG], if test "x${with_libjpeg}" = "xbundled"; then USE_EXTERNAL_LIBJPEG=false + LIBJPEG_CFLAGS="" + LIBJPEG_LIBS="" elif test "x${with_libjpeg}" = "xsystem"; then - AC_CHECK_HEADER(jpeglib.h, [], - [ AC_MSG_ERROR([--with-libjpeg=system specified, but jpeglib.h not found!])]) - AC_CHECK_LIB(jpeg, jpeg_CreateDecompress, [], - [ AC_MSG_ERROR([--with-libjpeg=system specified, but no libjpeg found])]) + PKG_CHECK_MODULES(LIBJPEG, libjpeg, [LIBJPEG_FOUND=yes], [LIBJPEG_FOUND=no]) + if test "x${LIBJPEG_FOUND}" = "xyes"; then + # PKG_CHECK_MODULES will set LIBJPEG_CFLAGS and LIBJPEG_LIBS + USE_EXTERNAL_LIBJPEG=true + else + AC_CHECK_HEADER(jpeglib.h, [], + [ AC_MSG_ERROR([--with-libjpeg=system specified, but jpeglib.h not found!])]) + AC_CHECK_LIB(jpeg, jpeg_CreateDecompress, [], + [ AC_MSG_ERROR([--with-libjpeg=system specified, but no libjpeg found])]) - USE_EXTERNAL_LIBJPEG=true - LIBJPEG_LIBS="-ljpeg" + USE_EXTERNAL_LIBJPEG=true + LIBJPEG_CFLAGS="" + LIBJPEG_LIBS="-ljpeg" + fi else AC_MSG_ERROR([Invalid use of --with-libjpeg: ${with_libjpeg}, use 'system' or 'bundled']) fi AC_SUBST(USE_EXTERNAL_LIBJPEG) + AC_SUBST(LIBJPEG_CFLAGS) AC_SUBST(LIBJPEG_LIBS) ]) diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template index 80c6dfc2ba2..d433ead98a7 100644 --- a/make/autoconf/spec.gmk.template +++ b/make/autoconf/spec.gmk.template @@ -800,6 +800,7 @@ TAR_SUPPORTS_TRANSFORM := @TAR_SUPPORTS_TRANSFORM@ # Build setup USE_EXTERNAL_LIBJPEG := @USE_EXTERNAL_LIBJPEG@ +LIBJPEG_CFLAGS := @LIBJPEG_CFLAGS@ LIBJPEG_LIBS := @LIBJPEG_LIBS@ USE_EXTERNAL_LIBGIF := @USE_EXTERNAL_LIBGIF@ GIFLIB_LIBS := @GIFLIB_LIBS@ From b3751b90f6f5406fb78f0f9a01f0337a64021dfc Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Tue, 8 Apr 2025 12:40:54 +0000 Subject: [PATCH 046/843] 8353573: System giflib not found by configure if it's not in system directories Reviewed-by: erikj --- make/autoconf/lib-bundled.m4 | 42 +++++++++++++++++++++++++++++---- make/autoconf/spec.gmk.template | 1 + 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/make/autoconf/lib-bundled.m4 b/make/autoconf/lib-bundled.m4 index 2b0d4f2f23f..3246697663c 100644 --- a/make/autoconf/lib-bundled.m4 +++ b/make/autoconf/lib-bundled.m4 @@ -95,6 +95,10 @@ AC_DEFUN_ONCE([LIB_SETUP_GIFLIB], [ AC_ARG_WITH(giflib, [AS_HELP_STRING([--with-giflib], [use giflib from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])]) + AC_ARG_WITH(giflib-include, [AS_HELP_STRING([--with-giflib-include], + [specify directory for the system giflib include files])]) + AC_ARG_WITH(giflib-lib, [AS_HELP_STRING([--with-giflib-lib], + [specify directory for the system giflib library])]) AC_MSG_CHECKING([for which giflib to use]) # default is bundled @@ -107,11 +111,40 @@ AC_DEFUN_ONCE([LIB_SETUP_GIFLIB], if test "x${with_giflib}" = "xbundled"; then USE_EXTERNAL_LIBGIF=false + GIFLIB_CFLAGS="" + GIFLIB_LIBS="" elif test "x${with_giflib}" = "xsystem"; then - AC_CHECK_HEADER(gif_lib.h, [], - [ AC_MSG_ERROR([--with-giflib=system specified, but gif_lib.h not found!])]) - AC_CHECK_LIB(gif, DGifGetCode, [], - [ AC_MSG_ERROR([--with-giflib=system specified, but no giflib found!])]) + GIFLIB_H_FOUND=no + if test "x${with_giflib_include}" != x; then + GIFLIB_CFLAGS="-I${with_giflib_include}" + GIFLIB_H_FOUND=yes + fi + if test "x$GIFLIB_H_FOUND" = xno; then + AC_CHECK_HEADER(gif_lib.h, + [ + GIFLIB_CFLAGS="" + GIFLIB_H_FOUND=yes + ]) + fi + if test "x$GIFLIB_H_FOUND" = xno; then + AC_MSG_ERROR([--with-giflib=system specified, but gif_lib.h not found!]) + fi + + GIFLIB_LIB_FOUND=no + if test "x${with_giflib_lib}" != x; then + GIFLIB_LIBS="-L${with_giflib_lib} -lgif" + GIFLIB_LIB_FOUND=yes + fi + if test "x$GIFLIB_LIB_FOUND" = xno; then + AC_CHECK_LIB(gif, DGifGetCode, + [ + GIFLIB_LIBS="-lgif" + GIFLIB_LIB_FOUND=yes + ]) + fi + if test "x$GIFLIB_LIB_FOUND" = xno; then + AC_MSG_ERROR([--with-giflib=system specified, but no giflib found!]) + fi USE_EXTERNAL_LIBGIF=true GIFLIB_LIBS=-lgif @@ -120,6 +153,7 @@ AC_DEFUN_ONCE([LIB_SETUP_GIFLIB], fi AC_SUBST(USE_EXTERNAL_LIBGIF) + AC_SUBST(GIFLIB_CFLAGS) AC_SUBST(GIFLIB_LIBS) ]) diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template index d433ead98a7..17a913a2d90 100644 --- a/make/autoconf/spec.gmk.template +++ b/make/autoconf/spec.gmk.template @@ -803,6 +803,7 @@ USE_EXTERNAL_LIBJPEG := @USE_EXTERNAL_LIBJPEG@ LIBJPEG_CFLAGS := @LIBJPEG_CFLAGS@ LIBJPEG_LIBS := @LIBJPEG_LIBS@ USE_EXTERNAL_LIBGIF := @USE_EXTERNAL_LIBGIF@ +GIFLIB_CFLAGS := @GIFLIB_CFLAGS@ GIFLIB_LIBS := @GIFLIB_LIBS@ USE_EXTERNAL_LIBZ := @USE_EXTERNAL_LIBZ@ LIBZ_CFLAGS := @LIBZ_CFLAGS@ From 21db0fdbfb019b9a7c6613e190ad457278f29582 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Tue, 8 Apr 2025 12:59:36 +0000 Subject: [PATCH 047/843] 8353665: RISC-V: IR verification fails in TestSubNodeFloatDoubleNegation.java Reviewed-by: thartmann, luhenry --- .../floatingpoint/TestSubNodeFloatDoubleNegation.java | 4 +++- .../jtreg/compiler/lib/ir_framework/TestFramework.java | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java b/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java index 66292e37b1c..e6695081841 100644 --- a/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java +++ b/test/hotspot/jtreg/compiler/floatingpoint/TestSubNodeFloatDoubleNegation.java @@ -55,7 +55,9 @@ public class TestSubNodeFloatDoubleNegation { @Test // Match a generic SubNode, because scalar Float16 operations are often // performed as float operations. - @IR(counts = { IRNode.SUB, "2" }) + @IR(counts = { IRNode.SUB, "2" }, applyIfPlatform = {"riscv64", "false"}) + @IR(counts = { IRNode.SUB, "2" }, applyIfCPUFeature = {"zfh", "false"}) + @IR(counts = { IRNode.SUB_HF, "2" }, applyIfCPUFeature = {"zfh", "true"}) // Checks that the subtractions in 0 - (0 - hf) do not get eliminiated public static Float16 testHalfFloat(Float16 hf) { return Float16.subtract( diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 79c99352a32..8f70ad9b7d0 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -139,11 +139,14 @@ public class TestFramework { "UseAVX", "UseSSE", "UseSVE", - "UseZbb", - "UseRVV", "Xlog", "LogCompilation", - "UseCompactObjectHeaders" + "UseCompactObjectHeaders", + // Riscv + "UseRVV", + "UseZbb", + "UseZfh", + "UseZvbb" ) ); From cc5e9388d8c55178fd32eabce0f24d5ab8e76fdd Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Tue, 8 Apr 2025 13:00:07 +0000 Subject: [PATCH 048/843] 8353600: RISC-V: compiler/vectorization/TestRotateByteAndShortVector.java is failing with Zvbb Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/riscv_v.ad | 25 ++------- .../TestRotateByteAndShortVector.java | 51 ++++++++++--------- 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index cd9d2107b79..1e99b2ece29 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -80,8 +80,12 @@ source %{ case Op_PopCountVI: case Op_ReverseBytesV: case Op_ReverseV: + return UseZvbb; case Op_RotateLeftV: case Op_RotateRightV: + if (bt != T_INT && bt != T_LONG) { + return false; + } return UseZvbb; case Op_LoadVectorGather: case Op_LoadVectorGatherMasked: @@ -3413,27 +3417,6 @@ instruct vshiftcnt(vReg dst, iRegIorL2I cnt) %{ %} // --------------------------------- Vector Rotation ---------------------------------- -// -// Following rotate instruct's are shared by vectorization (in SLP, superword.cpp) and Vector API. -// -// Rotate behaviour in vectorization is defined by java API, which includes: -// 1. Integer.rorateRight, Integer.rorateLeft. -// `rotation by any multiple of 32 is a no-op, so all but the last five bits of the rotation distance can be ignored`. -// 2. Long.rorateRight, Long.rorateLeft. -// `rotation by any multiple of 64 is a no-op, so all but the last six bits of the rotation distance can be ignored`. -// -// Rotate behaviour in Vector API is defined as below, e.g. -// 1. For Byte ROR, `a ROR b` is: (byte)(((((byte)a) & 0xFF) >>> (b & 7)) | ((((byte)a) & 0xFF) << (8 - (b & 7)))) -// 2. For Short ROR, `a ROR b` is: (short)(((((short)a) & 0xFFFF) >>> (b & 15)) | ((((short)a) & 0xFFFF) << (16 - (b & 15)))) -// 3. For Integer ROR, `a ROR b` is: Integer.rotateRight(a, ((int)b)) -// 4. For Long ROR, `a ROR b` is: Long.rotateRight(a, ((int)b)) -// -// Basically, the behaviour between vectorization and Vector API is the same for Long and Integer, except that Vector API -// also supports Byte and Short rotation. But we can still share the intrinsics between vectorization and Vector API. -// -// NOTE: As vror.vi encodes 6-bits immediate rotate amount, which is different from other vector-immediate instructions, -// implementation of vector rotation for long and other types can be unified. - // Rotate right instruct vrotate_right(vReg dst, vReg src, vReg shift) %{ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java b/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java index 08e69485d56..e130fc0ba6c 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestRotateByteAndShortVector.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2022, Loongson Technology Co. Ltd. All rights reserved. + * Copyright (c) 2022, 2025 Loongson Technology Co. Ltd. All rights reserved. + * Copyright (c) 2025, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,15 +24,16 @@ /** * @test - * @bug 8286847 + * @bug 8286847 8353600 * @key randomness * @summary Test vectorization of rotate byte and short - * @library /test/lib - * @run main/othervm -XX:-TieredCompilation -XX:CompileCommand=compileonly,TestRotateByteAndShortVector::testRotate* -Xbatch TestRotateByteAndShortVector + * @library /test/lib / + * @run main/othervm TestRotateByteAndShortVector */ import java.util.Random; import jdk.test.lib.Utils; +import compiler.lib.ir_framework.*; public class TestRotateByteAndShortVector { private static final Random random = Utils.getRandomInstance(); @@ -49,27 +51,7 @@ public class TestRotateByteAndShortVector { private static short resShort = 0; public static void main(String[] args) { - System.out.println("warmup"); - warmup(); - - System.out.println("Testing..."); - runRotateLeftByteTest(); - runRotateRightByteTest(); - runRotateLeftShortTest(); - runRotateRightShortTest(); - - System.out.println("PASSED"); - } - - static void warmup() { - random.nextBytes(arrByte); - randomShorts(); - for (int i = 0; i < ITERS; i++) { - testRotateLeftByte(rolByte, arrByte, i); - testRotateRightByte(rorByte, arrByte, i); - testRotateLeftShort(rolShort, arrShort, i); - testRotateRightShort(rorShort, arrShort, i); - } + TestFramework.run(); } static void randomShorts() { @@ -78,6 +60,7 @@ public class TestRotateByteAndShortVector { } } + @Run(test = { "testRotateLeftByte" }) static void runRotateLeftByteTest() { for (int shift = 0; shift < 64; shift++) { random.nextBytes(arrByte); @@ -91,6 +74,7 @@ public class TestRotateByteAndShortVector { } } + @Run(test = { "testRotateRightByte" }) static void runRotateRightByteTest() { for (int shift = 0; shift < 64; shift++) { random.nextBytes(arrByte); @@ -104,6 +88,7 @@ public class TestRotateByteAndShortVector { } } + @Run(test = { "testRotateLeftShort" }) static void runRotateLeftShortTest() { for (int shift = 0; shift < 64; shift++) { randomShorts(); @@ -117,6 +102,7 @@ public class TestRotateByteAndShortVector { } } + @Run(test = { "testRotateRightShort" }) static void runRotateRightShortTest() { for (int shift = 0; shift < 64; shift++) { randomShorts(); @@ -130,24 +116,39 @@ public class TestRotateByteAndShortVector { } } + // NOTE: currently, there is no platform supporting RotateLeftV/RotateRightV intrinsic. + // If there is some implementation, it could probably in a wrong way which is different + // from what java language spec expects. + @Test + @IR(failOn = { IRNode.ROTATE_LEFT_V }) + @IR(failOn = { IRNode.ROTATE_RIGHT_V }) static void testRotateLeftByte(byte[] test, byte[] arr, int shift) { for (int i = 0; i < ARRLEN; i++) { test[i] = (byte) ((arr[i] << shift) | (arr[i] >>> -shift)); } } + @Test + @IR(failOn = { IRNode.ROTATE_LEFT_V }) + @IR(failOn = { IRNode.ROTATE_RIGHT_V }) static void testRotateRightByte(byte[] test, byte[] arr, int shift) { for (int i = 0; i < ARRLEN; i++) { test[i] = (byte) ((arr[i] >>> shift) | (arr[i] << -shift)); } } + @Test + @IR(failOn = { IRNode.ROTATE_LEFT_V }) + @IR(failOn = { IRNode.ROTATE_RIGHT_V }) static void testRotateLeftShort(short[] test, short[] arr, int shift) { for (int i = 0; i < ARRLEN; i++) { test[i] = (short) ((arr[i] << shift) | (arr[i] >>> -shift)); } } + @Test + @IR(failOn = { IRNode.ROTATE_LEFT_V }) + @IR(failOn = { IRNode.ROTATE_RIGHT_V }) static void testRotateRightShort(short[] test, short[] arr, int shift) { for (int i = 0; i < ARRLEN; i++) { test[i] = (short) ((arr[i] >>> shift) | (arr[i] << -shift)); From dfa79c373097d17a347b7c17103c57e12f59dc67 Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Tue, 8 Apr 2025 13:02:50 +0000 Subject: [PATCH 049/843] 8340321: Disable SHA-1 in TLS/DTLS 1.2 handshake signatures Reviewed-by: mullan --- .../sun/security/ssl/SignatureScheme.java | 5 +- .../share/conf/security/java.security | 3 +- ...DisableSHA1inHandshakeSignatureDTLS12.java | 54 ++++++++ .../DisableSHA1inHandshakeSignatureTLS12.java | 120 ++++++++++++++++++ .../DisableSHA1inHandshakeSignatureTLS13.java | 70 ++++++++++ 5 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureDTLS12.java create mode 100644 test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS12.java create mode 100644 test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS13.java diff --git a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java index 00b6b0593f5..b817cc3fb9d 100644 --- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java +++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java @@ -132,8 +132,9 @@ enum SignatureScheme { "DSA", ProtocolVersion.PROTOCOLS_TO_12), ECDSA_SHA1 (0x0203, "ecdsa_sha1", "SHA1withECDSA", - "EC", - ProtocolVersion.PROTOCOLS_TO_13), + "EC", null, null, -1, + ProtocolVersion.PROTOCOLS_TO_13, + ProtocolVersion.PROTOCOLS_TO_12), RSA_PKCS1_SHA1 (0x0201, "rsa_pkcs1_sha1", "SHA1withRSA", "RSA", null, null, 511, ProtocolVersion.PROTOCOLS_TO_13, diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 82a57dfed6f..b115d479838 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -768,7 +768,8 @@ http.auth.digest.disabledAlgorithms = MD5, SHA-1 # rsa_pkcs1_sha1, secp224r1, TLS_RSA_* jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ - ECDH, TLS_RSA_* + ECDH, TLS_RSA_*, rsa_pkcs1_sha1 usage HandshakeSignature, \ + ecdsa_sha1 usage HandshakeSignature, dsa_sha1 usage HandshakeSignature # # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) diff --git a/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureDTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureDTLS12.java new file mode 100644 index 00000000000..6c597cd2576 --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureDTLS12.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8340321 + * @summary Disable SHA-1 in TLS/DTLS 1.2 signatures. + * This test only covers DTLS 1.2. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSHA1inHandshakeSignatureDTLS12 + */ + +public class DisableSHA1inHandshakeSignatureDTLS12 extends + DisableSHA1inHandshakeSignatureTLS12 { + + protected DisableSHA1inHandshakeSignatureDTLS12() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + new DisableSHA1inHandshakeSignatureDTLS12().run(); + } + + @Override + protected String getProtocol() { + return "DTLSv1.2"; + } + + // No CertificateRequest in DTLS server flight. + @Override + protected void checkCertificateRequest() { + } +} diff --git a/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS12.java new file mode 100644 index 00000000000..0389740b7fe --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS12.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8340321 + * @summary Disable SHA-1 in TLS/DTLS 1.2 signatures. + * This test only covers TLS 1.2. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSHA1inHandshakeSignatureTLS12 + */ + +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertTrue; + +import java.util.List; + +public class DisableSHA1inHandshakeSignatureTLS12 extends + AbstractCheckSignatureSchemes { + + protected DisableSHA1inHandshakeSignatureTLS12() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + new DisableSHA1inHandshakeSignatureTLS12().run(); + } + + @Override + protected String getProtocol() { + return "TLSv1.2"; + } + + // Run things in TLS handshake order. + protected void run() throws Exception { + + // Produce client_hello + clientEngine.wrap(clientOut, cTOs); + cTOs.flip(); + + checkClientHello(); + + // Consume client_hello. + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + // Produce server_hello. + serverEngine.wrap(serverOut, sTOc); + sTOc.flip(); + + checkCertificateRequest(); + } + + // Returns SHA-1 signature schemes supported for TLSv1.2 handshake + protected List getDisabledSignatureSchemes() { + return List.of( + "ecdsa_sha1", + "rsa_pkcs1_sha1", + "dsa_sha1" + ); + } + + protected void checkClientHello() throws Exception { + // Get signature_algorithms extension signature schemes. + List sigAlgsSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_EXT); + + // Should not be present in signature_algorithms extension. + getDisabledSignatureSchemes().forEach(ss -> + assertFalse(sigAlgsSS.contains(ss), + "Signature Scheme " + ss + + " present in ClientHello's signature_algorithms extension")); + + // Get signature_algorithms_cert extension signature schemes. + List sigAlgsCertSS = getSigSchemesCliHello( + extractHandshakeMsg(cTOs, TLS_HS_CLI_HELLO), + SIG_ALGS_CERT_EXT); + + // Should be present in signature_algorithms_cert extension. + getDisabledSignatureSchemes().forEach(ss -> + assertTrue(sigAlgsCertSS.contains(ss), + "Signature Scheme " + ss + + " isn't present in ClientHello's" + + " signature_algorithms extension")); + } + + protected void checkCertificateRequest() throws Exception { + // Get CertificateRequest message signature schemes. + List sigAlgsCertSS = getSigSchemesCertReq( + extractHandshakeMsg(sTOc, TLS_HS_CERT_REQ)); + + // Should not be present in CertificateRequest message. + getDisabledSignatureSchemes().forEach(ss -> + assertFalse(sigAlgsCertSS.contains(ss), + "Signature Scheme " + ss + + " present in CertificateRequest")); + } +} diff --git a/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS13.java b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS13.java new file mode 100644 index 00000000000..55f619460d4 --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/DisableSHA1inHandshakeSignatureTLS13.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8340321 + * @summary Disable SHA-1 in TLS/DTLS 1.2 signatures. + * This test only covers TLS 1.3. + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm DisableSHA1inHandshakeSignatureTLS13 + */ + +import java.security.Security; +import java.util.List; + +public class DisableSHA1inHandshakeSignatureTLS13 extends + DisableSHA1inHandshakeSignatureTLS12 { + + protected DisableSHA1inHandshakeSignatureTLS13() throws Exception { + super(); + } + + public static void main(String[] args) throws Exception { + // SHA-1 algorithm MUST NOT be used in any TLSv1.3 handshake signatures. + // This is regardless of jdk.tls.disabledAlgorithms configuration. + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + new DisableSHA1inHandshakeSignatureTLS13().run(); + } + + @Override + protected String getProtocol() { + return "TLSv1.3"; + } + + // Returns SHA-1 signature schemes NOT supported for TLSv1.3 handshake + // signatures, but supported for TLSv1.3 certificate signatures. + @Override + protected List getDisabledSignatureSchemes() { + return List.of("ecdsa_sha1", "rsa_pkcs1_sha1"); + } + + // TLSv1.3 sends CertificateRequest signature schemes in + // signature_algorithms and signature_algorithms_cert extensions. Same as + // ClientHello, but they are encrypted. So we skip CertificateRequest + // signature schemes verification for TLSv1.3. + @Override + protected void checkCertificateRequest() { + } +} From d9f2e6921558b4919889d81871b699971fb4f3ba Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Tue, 8 Apr 2025 13:05:15 +0000 Subject: [PATCH 050/843] 8352963: [REDO] Missing late inline cleanup causes compiler/vectorapi/VectorLogicalOpIdentityTest.java IR failure Reviewed-by: vlivanov, thartmann --- src/hotspot/share/opto/callGenerator.cpp | 6 +- src/hotspot/share/opto/callnode.cpp | 113 +++++++++++------- src/hotspot/share/opto/callnode.hpp | 1 + src/hotspot/share/opto/compile.cpp | 11 ++ test/hotspot/jtreg/ProblemList.txt | 1 - .../VectorGatherMaskFoldingTest.java | 11 +- .../VectorLogicalOpIdentityTest.java | 5 +- 7 files changed, 95 insertions(+), 53 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index ec7117e3568..e0ad2f00ab5 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -470,7 +470,7 @@ class LateInlineVirtualCallGenerator : public VirtualCallGenerator { virtual void do_late_inline(); virtual void set_callee_method(ciMethod* m) { - assert(_callee == nullptr, "repeated inlining attempt"); + assert(_callee == nullptr || _callee == m, "repeated inline attempt with different callee"); _callee = m; } @@ -987,8 +987,8 @@ CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* c Compile* C = Compile::current(); bool should_delay = C->should_delay_inlining(); if (cg != nullptr) { - if (should_delay) { - return CallGenerator::for_late_inline(callee, cg); + if (should_delay && IncrementalInlineMH) { + return CallGenerator::for_mh_late_inline(caller, callee, input_not_const); } else { return cg; } diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 68efabea15c..bb30dcb2976 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1091,6 +1091,15 @@ void CallJavaNode::dump_compact_spec(outputStream* st) const { } #endif +void CallJavaNode::register_for_late_inline() { + if (generator() != nullptr) { + Compile::current()->prepend_late_inline(generator()); + set_generator(nullptr); + } else { + assert(false, "repeated inline attempt"); + } +} + //============================================================================= uint CallStaticJavaNode::size_of() const { return sizeof(*this); } bool CallStaticJavaNode::cmp( const Node &n ) const { @@ -1101,26 +1110,35 @@ bool CallStaticJavaNode::cmp( const Node &n ) const { Node* CallStaticJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) { CallGenerator* cg = generator(); if (can_reshape && cg != nullptr) { - assert(IncrementalInlineMH, "required"); - assert(cg->call_node() == this, "mismatch"); - assert(cg->is_mh_late_inline(), "not virtual"); + if (cg->is_mh_late_inline()) { + assert(IncrementalInlineMH, "required"); + assert(cg->call_node() == this, "mismatch"); + assert(cg->method()->is_method_handle_intrinsic(), "required"); - // Check whether this MH handle call becomes a candidate for inlining. - ciMethod* callee = cg->method(); - vmIntrinsics::ID iid = callee->intrinsic_id(); - if (iid == vmIntrinsics::_invokeBasic) { - if (in(TypeFunc::Parms)->Opcode() == Op_ConP) { - phase->C->prepend_late_inline(cg); - set_generator(nullptr); + // Check whether this MH handle call becomes a candidate for inlining. + ciMethod* callee = cg->method(); + vmIntrinsics::ID iid = callee->intrinsic_id(); + if (iid == vmIntrinsics::_invokeBasic) { + if (in(TypeFunc::Parms)->Opcode() == Op_ConP) { + register_for_late_inline(); + } + } else if (iid == vmIntrinsics::_linkToNative) { + // never retry + } else { + assert(callee->has_member_arg(), "wrong type of call?"); + if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) { + register_for_late_inline(); + phase->C->inc_number_of_mh_late_inlines(); + } } - } else if (iid == vmIntrinsics::_linkToNative) { - // never retry } else { - assert(callee->has_member_arg(), "wrong type of call?"); - if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) { - phase->C->prepend_late_inline(cg); - set_generator(nullptr); + assert(IncrementalInline, "required"); + assert(!cg->method()->is_method_handle_intrinsic(), "required"); + if (phase->C->print_inlining()) { + phase->C->inline_printer()->record(cg->method(), cg->call_node()->jvms(), InliningResult::FAILURE, + "static call node changed: trying again"); } + register_for_late_inline(); } } return CallNode::Ideal(phase, can_reshape); @@ -1189,39 +1207,46 @@ bool CallDynamicJavaNode::cmp( const Node &n ) const { Node* CallDynamicJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) { CallGenerator* cg = generator(); if (can_reshape && cg != nullptr) { - assert(IncrementalInlineVirtual, "required"); - assert(cg->call_node() == this, "mismatch"); - assert(cg->is_virtual_late_inline(), "not virtual"); + if (cg->is_virtual_late_inline()) { + assert(IncrementalInlineVirtual, "required"); + assert(cg->call_node() == this, "mismatch"); - // Recover symbolic info for method resolution. - ciMethod* caller = jvms()->method(); - ciBytecodeStream iter(caller); - iter.force_bci(jvms()->bci()); + // Recover symbolic info for method resolution. + ciMethod* caller = jvms()->method(); + ciBytecodeStream iter(caller); + iter.force_bci(jvms()->bci()); - bool not_used1; - ciSignature* not_used2; - ciMethod* orig_callee = iter.get_method(not_used1, ¬_used2); // callee in the bytecode - ciKlass* holder = iter.get_declared_method_holder(); - if (orig_callee->is_method_handle_intrinsic()) { - assert(_override_symbolic_info, "required"); - orig_callee = method(); - holder = method()->holder(); - } + bool not_used1; + ciSignature* not_used2; + ciMethod* orig_callee = iter.get_method(not_used1, ¬_used2); // callee in the bytecode + ciKlass* holder = iter.get_declared_method_holder(); + if (orig_callee->is_method_handle_intrinsic()) { + assert(_override_symbolic_info, "required"); + orig_callee = method(); + holder = method()->holder(); + } - ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); + ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); - Node* receiver_node = in(TypeFunc::Parms); - const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr(); + Node* receiver_node = in(TypeFunc::Parms); + const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr(); - int not_used3; - bool call_does_dispatch; - ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/, - call_does_dispatch, not_used3); // out-parameters - if (!call_does_dispatch) { - // Register for late inlining. - cg->set_callee_method(callee); - phase->C->prepend_late_inline(cg); // MH late inlining prepends to the list, so do the same - set_generator(nullptr); + int not_used3; + bool call_does_dispatch; + ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/, + call_does_dispatch, not_used3); // out-parameters + if (!call_does_dispatch) { + // Register for late inlining. + cg->set_callee_method(callee); + register_for_late_inline(); // MH late inlining prepends to the list, so do the same + } + } else { + assert(IncrementalInline, "required"); + if (phase->C->print_inlining()) { + phase->C->inline_printer()->record(cg->method(), cg->call_node()->jvms(), InliningResult::FAILURE, + "dynamic call node changed: trying again"); + } + register_for_late_inline(); } } return CallNode::Ideal(phase, can_reshape); diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index fc03ab5163b..db857d4c6d1 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -790,6 +790,7 @@ public: void set_arg_escape(bool f) { _arg_escape = f; } bool arg_escape() const { return _arg_escape; } void copy_call_debug_info(PhaseIterGVN* phase, SafePointNode *sfpt); + void register_for_late_inline(); DEBUG_ONLY( bool validate_symbolic_info() const; ) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 56f57793fbb..8a059d0852f 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -2085,6 +2085,7 @@ bool Compile::inline_incrementally_one() { for (int i = 0; i < _late_inlines.length(); i++) { _late_inlines_pos = i+1; CallGenerator* cg = _late_inlines.at(i); + bool is_scheduled_for_igvn_before = C->igvn_worklist()->member(cg->call_node()); bool does_dispatch = cg->is_virtual_late_inline() || cg->is_mh_late_inline(); if (inlining_incrementally() || does_dispatch) { // a call can be either inlined or strength-reduced to a direct call cg->do_late_inline(); @@ -2095,6 +2096,16 @@ bool Compile::inline_incrementally_one() { _late_inlines_pos = i+1; // restore the position in case new elements were inserted print_method(PHASE_INCREMENTAL_INLINE_STEP, 3, cg->call_node()); break; // process one call site at a time + } else { + bool is_scheduled_for_igvn_after = C->igvn_worklist()->member(cg->call_node()); + if (!is_scheduled_for_igvn_before && is_scheduled_for_igvn_after) { + // Avoid potential infinite loop if node already in the IGVN list + assert(false, "scheduled for IGVN during inlining attempt"); + } else { + // Ensure call node has not disappeared from IGVN worklist during a failed inlining attempt + assert(!is_scheduled_for_igvn_before || is_scheduled_for_igvn_after, "call node removed from IGVN list during inlining pass"); + cg->call_node()->set_generator(cg); + } } } else { // Ignore late inline direct calls when inlining is not allowed. diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 6dd35997cac..d76f4b2d95b 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -56,7 +56,6 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897,8348519 aix-ppc64,linux-ppc64le,linux-s390x -compiler/vectorapi/VectorLogicalOpIdentityTest.java 8302459 linux-x64,windows-x64 compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorGatherMaskFoldingTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorGatherMaskFoldingTest.java index 88175baf8e4..7e16c5e5e86 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorGatherMaskFoldingTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorGatherMaskFoldingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import java.nio.ByteOrder; /** * @test - * @bug 8325520 + * @bug 8325520 8302459 * @library /test/lib / * @summary Don't allow folding of Load/Store vectors when using incompatible indices or masks * @modules jdk.incubator.vector @@ -1398,7 +1398,12 @@ public class VectorGatherMaskFoldingTest { public static void main(String[] args) { TestFramework testFramework = new TestFramework(); testFramework.setDefaultWarmup(10000) - .addFlags("--add-modules=jdk.incubator.vector", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+IncrementalInlineForceCleanup") + .addFlags("--add-modules=jdk.incubator.vector") .start(); + testFramework = new TestFramework(); + testFramework.setDefaultWarmup(10000) + .addFlags("--add-modules=jdk.incubator.vector", "-XX:-TieredCompilation") + .start(); + } } diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java index 426dec67019..1a2402222ed 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ import jdk.test.lib.Utils; /** * @test - * @bug 8288294 + * @bug 8288294 8302459 * @key randomness * @library /test/lib / * @summary Add identity transformations for vector logic operations @@ -761,5 +761,6 @@ public class VectorLogicalOpIdentityTest { public static void main(String[] args) { TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:-TieredCompilation"); } } From 250437e557c56ba66a74ab759cfd1071a510e184 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 8 Apr 2025 13:12:28 +0000 Subject: [PATCH 051/843] 8351654: Agent transformer bytecodes should be verified Reviewed-by: dholmes, lmesnik --- .../share/classfile/classFileParser.cpp | 3 +- .../share/classfile/classFileStream.cpp | 9 +- .../share/classfile/classFileStream.hpp | 11 +- src/hotspot/share/classfile/klassFactory.cpp | 8 +- .../PatchModuleJavaBaseVerify.java | 63 +++++++ .../runtime/verifier/CFLH/TestChecker.java | 41 +++++ .../runtime/verifier/CFLH/TestVerify.java | 174 ++++++++++++++++++ 7 files changed, 300 insertions(+), 9 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleJavaBaseVerify.java create mode 100644 test/hotspot/jtreg/runtime/verifier/CFLH/TestChecker.java create mode 100644 test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index ae66ee22511..3e6246d4aee 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -5333,7 +5333,8 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, assert(0 == _access_flags.as_unsigned_short(), "invariant"); // Figure out whether we can skip format checking (matching classic VM behavior) - _need_verify = Verifier::should_verify_for(_loader_data->class_loader()); + // Always verify CFLH bytes from the user agents. + _need_verify = stream->from_class_file_load_hook() ? true : Verifier::should_verify_for(_loader_data->class_loader()); // synch back verification state to stream to check for truncation. stream->set_need_verify(_need_verify); diff --git a/src/hotspot/share/classfile/classFileStream.cpp b/src/hotspot/share/classfile/classFileStream.cpp index 0fc3e5b390c..382bd58af2b 100644 --- a/src/hotspot/share/classfile/classFileStream.cpp +++ b/src/hotspot/share/classfile/classFileStream.cpp @@ -34,13 +34,15 @@ void ClassFileStream::truncated_file_error(TRAPS) const { ClassFileStream::ClassFileStream(const u1* buffer, int length, const char* source, - bool from_boot_loader_modules_image) : + bool from_boot_loader_modules_image, + bool from_class_file_load_hook) : _buffer_start(buffer), _buffer_end(buffer + length), _current(buffer), _source(source), _need_verify(true), // may be reset by ClassFileParser when this stream is parsed. - _from_boot_loader_modules_image(from_boot_loader_modules_image) { + _from_boot_loader_modules_image(from_boot_loader_modules_image), + _from_class_file_load_hook(from_class_file_load_hook) { assert(buffer != nullptr, "caller should throw NPE"); } @@ -68,5 +70,6 @@ const ClassFileStream* ClassFileStream::clone() const { return new ClassFileStream(new_buffer_start, length(), clone_source(), - from_boot_loader_modules_image()); + from_boot_loader_modules_image(), + from_class_file_load_hook()); } diff --git a/src/hotspot/share/classfile/classFileStream.hpp b/src/hotspot/share/classfile/classFileStream.hpp index 67d66bb74a1..135a34bdeee 100644 --- a/src/hotspot/share/classfile/classFileStream.hpp +++ b/src/hotspot/share/classfile/classFileStream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,9 @@ class ClassFileStream: public ResourceObj { const char* const _source; // Source of stream (directory name, ZIP/JAR archive name) bool _need_verify; // True if we need to verify and check truncation of stream bytes. bool _from_boot_loader_modules_image; // True if this was created by ClassPathImageEntry. - void truncated_file_error(TRAPS) const ; + bool _from_class_file_load_hook; // True if this is from CFLH (needs verification) + + void truncated_file_error(TRAPS) const; protected: const u1* clone_buffer() const; @@ -55,7 +57,8 @@ class ClassFileStream: public ResourceObj { ClassFileStream(const u1* buffer, int length, const char* source, - bool from_boot_loader_modules_image = false); + bool from_boot_loader_modules_image = false, + bool from_class_file_load_hook = false); virtual const ClassFileStream* clone() const; @@ -154,6 +157,8 @@ class ClassFileStream: public ResourceObj { bool at_eos() const { return _current == _buffer_end; } uint64_t compute_fingerprint() const; + + bool from_class_file_load_hook() const { return _from_class_file_load_hook; } }; #endif // SHARE_CLASSFILE_CLASSFILESTREAM_HPP diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp index 52da747d8b6..28bb176ed0a 100644 --- a/src/hotspot/share/classfile/klassFactory.cpp +++ b/src/hotspot/share/classfile/klassFactory.cpp @@ -76,7 +76,9 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook( s2 path_index = ik->shared_classpath_index(); ClassFileStream* stream = new ClassFileStream(ptr, pointer_delta_as_int(end_ptr, ptr), - cfs->source()); + cfs->source(), + /* from_boot_loader_modules_image */ false, + /* from_class_file_load_hook */ true); ClassLoadInfo cl_info(protection_domain); ClassFileParser parser(stream, class_name, @@ -155,7 +157,9 @@ static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream, // Set new class file stream using JVMTI agent modified class file data. stream = new ClassFileStream(ptr, pointer_delta_as_int(end_ptr, ptr), - stream->source()); + stream->source(), + /* from_boot_loader_modules_image */ false, + /* from_class_file_load_hook */ true); } } diff --git a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleJavaBaseVerify.java b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleJavaBaseVerify.java new file mode 100644 index 00000000000..5dd7e6bf005 --- /dev/null +++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleJavaBaseVerify.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8351654 + * @summary Show that --patch-module for java.base does not verify the classfile. + * @requires vm.flagless + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @compile PatchModuleMain.java + * @run driver PatchModuleJavaBaseVerify + */ + +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class PatchModuleJavaBaseVerify { + + public static void main(String[] args) throws Exception { + String source = "package java.lang; " + + "public class NewClass { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("java/lang/NewClass", + InMemoryJavaCompiler.compile("java.lang.NewClass", source, "--patch-module=java.base"), + "mods/java.base"); + + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("--patch-module=java.base=mods/java.base", + "-Xlog:verification", "PatchModuleMain", "java.lang.NewClass"); + + new OutputAnalyzer(pb.start()) + .shouldContain("I pass!") + .shouldContain("End class verification for: PatchModuleMain") + .shouldNotContain("End class verification for: java.lang.NewClass") + .shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/verifier/CFLH/TestChecker.java b/test/hotspot/jtreg/runtime/verifier/CFLH/TestChecker.java new file mode 100644 index 00000000000..0d990549c2f --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/CFLH/TestChecker.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package checker; + +public interface TestChecker { + void check(Integer i); + + static TestChecker instance() { + return TestCheckerImpl.instance; + } + + class TestCheckerImpl implements TestChecker { + private static final TestCheckerImpl instance = new TestCheckerImpl(); + + @Override + public void check(Integer i) { + System.out.println("Checking: " + i); + } + } +} diff --git a/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java b/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java new file mode 100644 index 00000000000..214751863ea --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/CFLH/TestVerify.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Verifier should verify ClassFileLoadHook bytes even if on bootclasspath + * @bug 8351654 + * @requires vm.jvmti + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * @compile TestChecker.java + * @run driver jdk.test.lib.helpers.ClassFileInstaller checker/TestChecker + * @run main TestVerify buildAgent + * @run main/othervm --patch-module=java.base=. -Dagent.retransform=false -javaagent:redefineagent.jar TestVerify + * @run main/othervm --patch-module=java.base=. -Dagent.retransform=true -javaagent:redefineagent.jar TestVerify + */ + +import java.lang.invoke.MethodHandles; +import java.time.Duration; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.MethodTransform; +import java.lang.classfile.constantpool.InterfaceMethodRefEntry; +import java.lang.classfile.instruction.ReturnInstruction; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.ProtectionDomain; + +import java.io.PrintWriter; +import jdk.test.lib.helpers.ClassFileInstaller; +import java.io.FileNotFoundException; + +public class TestVerify { + + private static final String CLASS_TO_BREAK = "java.time.Duration"; + private static final String INTERNAL_CLASS_TO_BREAK = CLASS_TO_BREAK.replace('.', '/'); + private static final boolean DEBUG = false; + + private static class BadTransformer implements ClassFileTransformer { + + @Override + public byte[] transform(Module module, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { + + if (className.equals(INTERNAL_CLASS_TO_BREAK)) { + System.out.println("Instrumenting modular class " + INTERNAL_CLASS_TO_BREAK); + + var methodTransform = MethodTransform.transformingCode((builder, element) -> { + if (element instanceof ReturnInstruction) { + System.out.println("Injecting bug"); + // THE BUG! insert broken function call + + var checkerDesc = ClassDesc.of("checker", "TestChecker"); + builder.invokestatic(checkerDesc, "instance", MethodTypeDesc.of(checkerDesc), true); + + // dup the instance ref, this is just to get a bad argument to the next method call + builder.dup(); + + // then call a check method that doesn't take that type, but we have the wrong desc + builder.invokeinterface(checkerDesc, "check", MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_Integer)); + + System.out.println("Done injecting bug"); + } + builder.with(element); + }); + var classTransform = ClassTransform.transformingMethods(mm -> mm.methodName().stringValue().equals("getSeconds"), methodTransform); + + byte[] bytes; + try { + var cf = ClassFile.of(); + var existingClass = cf.parse(classfileBuffer); + bytes = cf.transformClass(existingClass, classTransform); + + if (DEBUG) Files.write(Path.of("bad.class"), bytes); + } catch (Throwable e) { + throw new AssertionError(e); + } + return bytes; + } + return null; + } + } + + static Instrumentation inst = null; + + public static void premain(String args, Instrumentation instrumentation) throws Exception { + System.out.println("Premain"); + inst = instrumentation; + } + + private static void buildAgent() { + try { + ClassFileInstaller.main("TestVerify"); + } catch (Exception e) { + throw new RuntimeException("Could not write agent classfile", e); + } + + try { + PrintWriter pw = new PrintWriter("MANIFEST.MF"); + pw.println("Premain-Class: TestVerify"); + pw.println("Agent-Class: TestVerify"); + pw.println("Can-Retransform-Classes: true"); + pw.println("Can-Redefine-Classes: true"); + pw.close(); + } catch (FileNotFoundException e) { + throw new RuntimeException("Could not write manifest file for the agent", e); + } + + sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); + if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "TestVerify.class" })) { + throw new RuntimeException("Could not write the agent jar file"); + } + } + + public static void main(String argv[]) throws Exception { + if (argv.length == 1 && argv[0].equals("buildAgent")) { + buildAgent(); + return; + } + + // double check our class hasn't been loaded yet + for (Class clazz : inst.getAllLoadedClasses()) { + if (clazz.getName().equals(CLASS_TO_BREAK)) { + throw new AssertionError("Oops! Class " + CLASS_TO_BREAK + " is already loaded, the test can't work"); + } + } + + boolean retransform = Boolean.getBoolean("agent.retransform"); + + try { + if (retransform) { + // Retransform the class for the VerifyError. + var clazz = Class.forName(CLASS_TO_BREAK); + inst.addTransformer(new BadTransformer(), true); + inst.retransformClasses(clazz); + } else { + // Load the class instrumented with CFLH for the VerifyError. + inst.addTransformer(new BadTransformer()); + System.out.println("1 hour is " + Duration.ofHours(1).getSeconds() + " seconds"); + } + throw new RuntimeException("Failed: Did not throw VerifyError"); + } catch (VerifyError e) { + System.out.println("Passed: VerifyError " + e.getMessage()); + } + } +} From 676cfae91c8bd4799adfedff2ad59a9aab953ece Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 8 Apr 2025 13:49:15 +0000 Subject: [PATCH 052/843] 8354016: Update ReentrantReadWriteLock documentation to reflect its new max capacity Reviewed-by: alanb --- .../java/util/concurrent/locks/ReentrantReadWriteLock.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index a45043e48ee..3e0b293380f 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -207,8 +207,8 @@ import jdk.internal.vm.annotation.ReservedStackAccess; * *

Implementation Notes

* - *

This lock supports a maximum of 65535 recursive write locks - * and 65535 read locks. Attempts to exceed these limits result in + *

This lock supports a maximum of {@link Integer#MAX_VALUE} recursive write locks + * and {@link Integer#MAX_VALUE} read locks. Attempts to exceed these limits result in * {@link Error} throws from locking methods. * * @since 1.5 From 58ff36f3bdefe2e883dc871a4e7fcaa81e8eef5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Tue, 8 Apr 2025 15:19:32 +0000 Subject: [PATCH 053/843] 8350705: [JMH] test security.SSLHandshake failed for 2 threads configuration Reviewed-by: hchao, mullan --- .../bench/java/security/SSLHandshake.java | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/test/micro/org/openjdk/bench/java/security/SSLHandshake.java b/test/micro/org/openjdk/bench/java/security/SSLHandshake.java index 5a4529059a5..d8773781b58 100644 --- a/test/micro/org/openjdk/bench/java/security/SSLHandshake.java +++ b/test/micro/org/openjdk/bench/java/security/SSLHandshake.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,6 @@ import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import java.nio.ByteBuffer; @@ -50,13 +49,17 @@ import javax.net.ssl.TrustManagerFactory; @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) +@State(Scope.Thread) @Warmup(iterations = 5, time = 5) @Measurement(iterations = 5, time = 5) @Fork(value = 3) public class SSLHandshake { - private SSLContext sslc; + // one global server context + private static final SSLContext sslServerCtx = getServerContext(); + + // per-thread client contexts + private SSLContext sslClientCtx; private SSLEngine clientEngine; private ByteBuffer clientOut = ByteBuffer.allocate(5); @@ -75,22 +78,33 @@ public class SSLHandshake { @Param({"TLSv1.2", "TLS"}) String tlsVersion; + private static SSLContext getServerContext() { + try { + KeyStore ks = TestCertificates.getKeyStore(); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance( + KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, new char[0]); + + SSLContext sslCtx = SSLContext.getInstance("TLS"); + sslCtx.init(kmf.getKeyManagers(), null, null); + return sslCtx; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @Setup(Level.Trial) public void init() throws Exception { - KeyStore ks = TestCertificates.getKeyStore(); KeyStore ts = TestCertificates.getTrustStore(); - KeyManagerFactory kmf = KeyManagerFactory.getInstance( - KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, new char[0]); - TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ts); SSLContext sslCtx = SSLContext.getInstance(tlsVersion); - sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - sslc = sslCtx; + sslCtx.init(null, tmf.getTrustManagers(), null); + sslClientCtx = sslCtx; } private HandshakeStatus checkResult(SSLEngine engine, SSLEngineResult result) { @@ -173,13 +187,13 @@ public class SSLHandshake { * Configure the serverEngine to act as a server in the SSL/TLS * handshake. */ - serverEngine = sslc.createSSLEngine(); + serverEngine = sslServerCtx.createSSLEngine(); serverEngine.setUseClientMode(false); /* * Similar to above, but using client mode instead. */ - clientEngine = sslc.createSSLEngine("client", 80); + clientEngine = sslClientCtx.createSSLEngine("client", 80); clientEngine.setUseClientMode(true); } } From 4645ddbb6be6b4456cc4d9f58188b0561a8e593d Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Tue, 8 Apr 2025 15:52:05 +0000 Subject: [PATCH 054/843] 8341976: C2: use_mem_state != load->find_exact_control(load->in(0)) assert failure Reviewed-by: chagedorn, dfenacci --- src/hotspot/share/opto/arraycopynode.cpp | 23 ++++--- src/hotspot/share/opto/arraycopynode.hpp | 2 +- src/hotspot/share/opto/macro.hpp | 4 +- src/hotspot/share/opto/macroArrayCopy.cpp | 55 ++++++++++------ src/hotspot/share/opto/memnode.hpp | 6 +- .../arraycopy/TestSunkLoadAntiDependency.java | 66 +++++++++++++++++++ 6 files changed, 117 insertions(+), 39 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/arraycopy/TestSunkLoadAntiDependency.java diff --git a/src/hotspot/share/opto/arraycopynode.cpp b/src/hotspot/share/opto/arraycopynode.cpp index 23a6ee31fff..85b6bd21aec 100644 --- a/src/hotspot/share/opto/arraycopynode.cpp +++ b/src/hotspot/share/opto/arraycopynode.cpp @@ -681,18 +681,21 @@ bool ArrayCopyNode::may_modify(const TypeOopPtr* t_oop, PhaseValues* phase) { return CallNode::may_modify_arraycopy_helper(dest_t, t_oop, phase); } -bool ArrayCopyNode::may_modify_helper(const TypeOopPtr* t_oop, Node* n, PhaseValues* phase, CallNode*& call) { +bool ArrayCopyNode::may_modify_helper(const TypeOopPtr* t_oop, Node* n, PhaseValues* phase, ArrayCopyNode*& ac) { if (n != nullptr && - n->is_Call() && - n->as_Call()->may_modify(t_oop, phase) && - (n->as_Call()->is_ArrayCopy() || n->as_Call()->is_call_to_arraycopystub())) { - call = n->as_Call(); + n->is_ArrayCopy() && + n->as_ArrayCopy()->may_modify(t_oop, phase)) { + ac = n->as_ArrayCopy(); return true; } return false; } bool ArrayCopyNode::may_modify(const TypeOopPtr* t_oop, MemBarNode* mb, PhaseValues* phase, ArrayCopyNode*& ac) { + if (mb->trailing_expanded_array_copy()) { + return true; + } + Node* c = mb->in(0); BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); @@ -705,23 +708,19 @@ bool ArrayCopyNode::may_modify(const TypeOopPtr* t_oop, MemBarNode* mb, PhaseVal for (uint i = 1; i < c->req(); i++) { if (c->in(i) != nullptr) { Node* n = c->in(i)->in(0); - if (may_modify_helper(t_oop, n, phase, call)) { - ac = call->isa_ArrayCopy(); + if (may_modify_helper(t_oop, n, phase, ac)) { assert(c == mb->in(0), "only for clone"); return true; } } } - } else if (may_modify_helper(t_oop, c->in(0), phase, call)) { - ac = call->isa_ArrayCopy(); + } else if (may_modify_helper(t_oop, c->in(0), phase, ac)) { #ifdef ASSERT bool use_ReduceInitialCardMarks = BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && static_cast(bs)->use_ReduceInitialCardMarks(); - assert(c == mb->in(0) || (ac != nullptr && ac->is_clonebasic() && !use_ReduceInitialCardMarks), "only for clone"); + assert(c == mb->in(0) || (ac->is_clonebasic() && !use_ReduceInitialCardMarks), "only for clone"); #endif return true; - } else if (mb->trailing_partial_array_copy()) { - return true; } return false; diff --git a/src/hotspot/share/opto/arraycopynode.hpp b/src/hotspot/share/opto/arraycopynode.hpp index f792722068f..13e739fc2c7 100644 --- a/src/hotspot/share/opto/arraycopynode.hpp +++ b/src/hotspot/share/opto/arraycopynode.hpp @@ -121,7 +121,7 @@ private: BasicType copy_type, const Type* value_type, int count); bool finish_transform(PhaseGVN *phase, bool can_reshape, Node* ctl, Node *mem); - static bool may_modify_helper(const TypeOopPtr* t_oop, Node* n, PhaseValues* phase, CallNode*& call); + static bool may_modify_helper(const TypeOopPtr* t_oop, Node* n, PhaseValues* phase, ArrayCopyNode*& ac); public: static Node* load(BarrierSetC2* bs, PhaseGVN *phase, Node*& ctl, MergeMemNode* mem, Node* addr, const TypePtr* adr_type, const Type *type, BasicType bt); private: diff --git a/src/hotspot/share/opto/macro.hpp b/src/hotspot/share/opto/macro.hpp index e10326e9d87..0e2326fd9d4 100644 --- a/src/hotspot/share/opto/macro.hpp +++ b/src/hotspot/share/opto/macro.hpp @@ -111,7 +111,7 @@ private: void expand_unlock_node(UnlockNode *unlock); // More helper methods modeled after GraphKit for array copy - void insert_mem_bar(Node** ctrl, Node** mem, int opcode, Node* precedent = nullptr); + void insert_mem_bar(Node** ctrl, Node** mem, int opcode, int alias_idx, Node* precedent = nullptr); Node* array_element_address(Node* ary, Node* idx, BasicType elembt); Node* ConvI2L(Node* offset); @@ -171,7 +171,7 @@ private: Node* src, Node* src_offset, Node* dest, Node* dest_offset, Node* copy_length, bool dest_uninitialized); - bool generate_unchecked_arraycopy(Node** ctrl, MergeMemNode** mem, + void generate_unchecked_arraycopy(Node** ctrl, MergeMemNode** mem, const TypePtr* adr_type, BasicType basic_elem_type, bool disjoint_bases, diff --git a/src/hotspot/share/opto/macroArrayCopy.cpp b/src/hotspot/share/opto/macroArrayCopy.cpp index e37c961e88d..e2209fddbdf 100644 --- a/src/hotspot/share/opto/macroArrayCopy.cpp +++ b/src/hotspot/share/opto/macroArrayCopy.cpp @@ -36,8 +36,8 @@ #include "utilities/align.hpp" #include "utilities/powerOfTwo.hpp" -void PhaseMacroExpand::insert_mem_bar(Node** ctrl, Node** mem, int opcode, Node* precedent) { - MemBarNode* mb = MemBarNode::make(C, opcode, Compile::AliasIdxBot, precedent); +void PhaseMacroExpand::insert_mem_bar(Node** ctrl, Node** mem, int opcode, int alias_idx, Node* precedent) { + MemBarNode* mb = MemBarNode::make(C, opcode, alias_idx, precedent); mb->init_req(TypeFunc::Control, *ctrl); mb->init_req(TypeFunc::Memory, *mem); transform_later(mb); @@ -45,7 +45,14 @@ void PhaseMacroExpand::insert_mem_bar(Node** ctrl, Node** mem, int opcode, Node* transform_later(*ctrl); Node* mem_proj = new ProjNode(mb,TypeFunc::Memory); transform_later(mem_proj); - *mem = mem_proj; + if (alias_idx == Compile::AliasIdxBot) { + *mem = mem_proj; + } else { + MergeMemNode* mm = (*mem)->clone()->as_MergeMem(); + mm->set_memory_at(alias_idx, mem_proj); + transform_later(mm); + *mem = mm; + } } Node* PhaseMacroExpand::array_element_address(Node* ary, Node* idx, BasicType elembt) { @@ -667,16 +674,15 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode* } } - bool is_partial_array_copy = false; if (!(*ctrl)->is_top()) { // Generate the fast path, if possible. Node* local_ctrl = *ctrl; MergeMemNode* local_mem = MergeMemNode::make(mem); transform_later(local_mem); - is_partial_array_copy = generate_unchecked_arraycopy(&local_ctrl, &local_mem, - adr_type, copy_type, disjoint_bases, - src, src_offset, dest, dest_offset, - ConvI2X(copy_length), acopy_to_uninitialized); + generate_unchecked_arraycopy(&local_ctrl, &local_mem, + adr_type, copy_type, disjoint_bases, + src, src_offset, dest, dest_offset, + ConvI2X(copy_length), acopy_to_uninitialized); // Present the results of the fast call. result_region->init_req(fast_path, local_ctrl); @@ -818,16 +824,23 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode* // Do not let stores that initialize this object be reordered with // a subsequent store that would make this object accessible by // other threads. - insert_mem_bar(ctrl, &out_mem, Op_MemBarStoreStore); + assert(ac->_dest_type == TypeOopPtr::BOTTOM, "non escaping destination shouldn't have narrow slice"); + insert_mem_bar(ctrl, &out_mem, Op_MemBarStoreStore, Compile::AliasIdxBot); } else { - insert_mem_bar(ctrl, &out_mem, Op_MemBarCPUOrder); + int mem_bar_alias_idx = Compile::AliasIdxBot; + if (ac->_dest_type != TypeOopPtr::BOTTOM) { + // The graph was transformed under the assumption the ArrayCopy node only had an effect on a narrow slice. We can't + // insert a wide membar now that it's being expanded: a load that uses the input memory state of the ArrayCopy + // could then become anti dependent on the membar when it was not anti dependent on the ArrayCopy leading to a + // broken graph. + mem_bar_alias_idx = C->get_alias_index(ac->_dest_type->add_offset(Type::OffsetBot)->is_ptr()); + } + insert_mem_bar(ctrl, &out_mem, Op_MemBarCPUOrder, mem_bar_alias_idx); } - if (is_partial_array_copy) { - assert((*ctrl)->is_Proj(), "MemBar control projection"); - assert((*ctrl)->in(0)->isa_MemBar(), "MemBar node"); - (*ctrl)->in(0)->isa_MemBar()->set_trailing_partial_array_copy(); - } + assert((*ctrl)->is_Proj(), "MemBar control projection"); + assert((*ctrl)->in(0)->isa_MemBar(), "MemBar node"); + (*ctrl)->in(0)->isa_MemBar()->set_trailing_expanded_array_copy(); _igvn.replace_node(_callprojs.fallthrough_memproj, out_mem); if (_callprojs.fallthrough_ioproj != nullptr) { @@ -837,7 +850,7 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode* #ifdef ASSERT const TypeOopPtr* dest_t = _igvn.type(dest)->is_oopptr(); - if (dest_t->is_known_instance() && !is_partial_array_copy) { + if (dest_t->is_known_instance()) { ArrayCopyNode* ac = nullptr; assert(ArrayCopyNode::may_modify(dest_t, (*ctrl)->in(0)->as_MemBar(), &_igvn, ac), "dependency on arraycopy lost"); assert(ac == nullptr, "no arraycopy anymore"); @@ -1174,14 +1187,16 @@ Node* PhaseMacroExpand::generate_generic_arraycopy(Node** ctrl, MergeMemNode** m } // Helper function; generates the fast out-of-line call to an arraycopy stub. -bool PhaseMacroExpand::generate_unchecked_arraycopy(Node** ctrl, MergeMemNode** mem, +void PhaseMacroExpand::generate_unchecked_arraycopy(Node** ctrl, MergeMemNode** mem, const TypePtr* adr_type, BasicType basic_elem_type, bool disjoint_bases, Node* src, Node* src_offset, Node* dest, Node* dest_offset, Node* copy_length, bool dest_uninitialized) { - if ((*ctrl)->is_top()) return false; + if ((*ctrl)->is_top()) { + return; + } Node* src_start = src; Node* dest_start = dest; @@ -1226,9 +1241,7 @@ bool PhaseMacroExpand::generate_unchecked_arraycopy(Node** ctrl, MergeMemNode** } transform_later(*mem); *ctrl = exit_block; - return true; } - return false; } #undef XTOP @@ -1311,7 +1324,7 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) { // Do not let writes into the source float below the arraycopy. { Node* mem = ac->in(TypeFunc::Memory); - insert_mem_bar(&ctrl, &mem, Op_MemBarCPUOrder); + insert_mem_bar(&ctrl, &mem, Op_MemBarCPUOrder, Compile::AliasIdxBot); merge_mem = MergeMemNode::make(mem); transform_later(merge_mem); diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index eca891bebbb..f17db05e683 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -1132,7 +1132,7 @@ class MemBarNode: public MultiNode { LeadingStore, TrailingLoadStore, LeadingLoadStore, - TrailingPartialArrayCopy + TrailingExpandedArrayCopy } _kind; #ifdef ASSERT @@ -1169,8 +1169,8 @@ public: bool trailing() const { return _kind == TrailingLoad || _kind == TrailingStore || _kind == TrailingLoadStore; } bool leading() const { return _kind == LeadingStore || _kind == LeadingLoadStore; } bool standalone() const { return _kind == Standalone; } - void set_trailing_partial_array_copy() { _kind = TrailingPartialArrayCopy; } - bool trailing_partial_array_copy() const { return _kind == TrailingPartialArrayCopy; } + void set_trailing_expanded_array_copy() { _kind = TrailingExpandedArrayCopy; } + bool trailing_expanded_array_copy() const { return _kind == TrailingExpandedArrayCopy; } static void set_store_pair(MemBarNode* leading, MemBarNode* trailing); static void set_load_store_pair(MemBarNode* leading, MemBarNode* trailing); diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestSunkLoadAntiDependency.java b/test/hotspot/jtreg/compiler/arraycopy/TestSunkLoadAntiDependency.java new file mode 100644 index 00000000000..2cb185f58bf --- /dev/null +++ b/test/hotspot/jtreg/compiler/arraycopy/TestSunkLoadAntiDependency.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341976 + * @summary C2: use_mem_state != load->find_exact_control(load->in(0)) assert failure + * @run main/othervm -XX:-BackgroundCompilation TestSunkLoadAntiDependency + * @run main TestSunkLoadAntiDependency + */ + +public class TestSunkLoadAntiDependency { + private static volatile int volatileField; + + public static void main(String[] args) { + int[] array = new int[100]; + for (int i = 0; i < 20_000; i++) { + test1(array, 2); + inlined1(array, 100, 0, 100, array); + } + } + + private static int test1(int[] src, int length) { + length = Integer.max(1, length); + int[] dst = new int[2]; + int stop; + for (stop = 0; stop < 10; stop++) { + for (int i = 0; i < 10; i++) { + } + } + int start; + for (start = 0; start < 9; start++) { + for (int i = 0; i < 10; i++) { + } + } + inlined1(src, length, start, stop, dst); + return dst[0] + dst[1]; + } + + private static void inlined1(int[] src, int length, int start, int stop, int[] dst) { + for (int i = start; i < stop; i++) { + volatileField = 42; + System.arraycopy(src, 0, dst, 0, length); + } + } +} From 3cbe686d6203043e95604b3d6c96d6ed9d5364c3 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Tue, 8 Apr 2025 16:13:43 +0000 Subject: [PATCH 055/843] 8348967: Deprecate security permission classes for removal Reviewed-by: rriggs, iris --- src/java.base/share/classes/java/security/Permissions.java | 3 +++ .../share/classes/java/security/SecurityPermission.java | 5 +++-- .../share/classes/java/security/UnresolvedPermission.java | 6 +++++- .../java/security/UnresolvedPermissionCollection.java | 3 ++- .../share/classes/javax/net/ssl/SSLPermission.java | 5 +++-- .../share/classes/javax/security/auth/AuthPermission.java | 5 +++-- .../javax/security/auth/PrivateCredentialPermission.java | 5 +++-- .../javax/security/auth/kerberos/DelegationPermission.java | 7 +++++-- .../javax/security/auth/kerberos/ServicePermission.java | 7 +++++-- .../org/apache/xml/internal/security/utils/JavaUtils.java | 1 + .../com/sun/security/jgss/InquireSecContextPermission.java | 5 +++-- 11 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/java.base/share/classes/java/security/Permissions.java b/src/java.base/share/classes/java/security/Permissions.java index ecb18aca8bb..269c988ebee 100644 --- a/src/java.base/share/classes/java/security/Permissions.java +++ b/src/java.base/share/classes/java/security/Permissions.java @@ -125,6 +125,7 @@ implements Serializable * @see PermissionCollection#isReadOnly() */ @Override + @SuppressWarnings("removal") public void add(Permission permission) { if (isReadOnly()) throw new SecurityException( @@ -288,6 +289,7 @@ implements Serializable * or {@code null} if there were no unresolved permissions of type p. * */ + @SuppressWarnings("removal") private PermissionCollection getUnresolvedPermissions(Permission p) { UnresolvedPermissionCollection uc = @@ -392,6 +394,7 @@ implements Serializable * permsMap field. Reads in allPermission. */ @java.io.Serial + @SuppressWarnings("removal") private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // Don't call defaultReadObject() diff --git a/src/java.base/share/classes/java/security/SecurityPermission.java b/src/java.base/share/classes/java/security/SecurityPermission.java index c378953095c..7fee76417a6 100644 --- a/src/java.base/share/classes/java/security/SecurityPermission.java +++ b/src/java.base/share/classes/java/security/SecurityPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ package java.security; *

* The target name is the name of a security configuration parameter. * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * @@ -47,6 +47,7 @@ package java.security; * @since 1.2 */ +@Deprecated(since="25", forRemoval=true) public final class SecurityPermission extends BasicPermission { @java.io.Serial diff --git a/src/java.base/share/classes/java/security/UnresolvedPermission.java b/src/java.base/share/classes/java/security/UnresolvedPermission.java index 07c30e2668d..8a9b51396bd 100644 --- a/src/java.base/share/classes/java/security/UnresolvedPermission.java +++ b/src/java.base/share/classes/java/security/UnresolvedPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,8 +49,12 @@ import java.util.Objects; * * @author Roland Schemers * @since 1.2 + * + * @deprecated This permission cannot be used for controlling access to + * resources as the Security Manager is no longer supported. */ +@Deprecated(since="25", forRemoval=true) public final class UnresolvedPermission extends Permission implements java.io.Serializable { diff --git a/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java b/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java index c0bdf5fc2a1..93e09251a02 100644 --- a/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java +++ b/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,7 @@ import java.util.concurrent.CopyOnWriteArrayList; * @serial include */ +@SuppressWarnings("removal") final class UnresolvedPermissionCollection extends PermissionCollection implements java.io.Serializable diff --git a/src/java.base/share/classes/javax/net/ssl/SSLPermission.java b/src/java.base/share/classes/javax/net/ssl/SSLPermission.java index 2f8e06d2ee6..72467089510 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLPermission.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ import java.security.*; * signify a wildcard match. For example: "foo.*" and "*" signify a wildcard * match, while "*foo" and "a*b" do not. * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * @@ -55,6 +55,7 @@ import java.security.*; * @author Roland Schemers */ +@Deprecated(since="25", forRemoval=true) public final class SSLPermission extends BasicPermission { @java.io.Serial diff --git a/src/java.base/share/classes/javax/security/auth/AuthPermission.java b/src/java.base/share/classes/javax/security/auth/AuthPermission.java index 7ad61db21cf..d45aea5fbaf 100644 --- a/src/java.base/share/classes/javax/security/auth/AuthPermission.java +++ b/src/java.base/share/classes/javax/security/auth/AuthPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,12 +30,13 @@ package javax.security.auth; * contains a name (also referred to as a "target name") but no actions * list; you either have the named permission or you don't. * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * * @since 1.4 */ +@Deprecated(since="25", forRemoval=true) public final class AuthPermission extends java.security.BasicPermission { diff --git a/src/java.base/share/classes/javax/security/auth/PrivateCredentialPermission.java b/src/java.base/share/classes/javax/security/auth/PrivateCredentialPermission.java index d25a5a81d9d..5d1688f17d6 100644 --- a/src/java.base/share/classes/javax/security/auth/PrivateCredentialPermission.java +++ b/src/java.base/share/classes/javax/security/auth/PrivateCredentialPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,12 +47,13 @@ import sun.security.util.ResourcesMgr; * CredentialClass {PrincipalClass "PrincipalName"}* * * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * * @since 1.4 */ +@Deprecated(since="25", forRemoval=true) public final class PrivateCredentialPermission extends Permission { @java.io.Serial diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java index b2a14bf6164..310e05bf45f 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,13 +43,14 @@ import java.util.concurrent.ConcurrentHashMap; * latter service principal is specified to restrict the use of a * proxiable ticket. * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * * @since 1.4 */ +@Deprecated(since="25", forRemoval=true) public final class DelegationPermission extends BasicPermission implements java.io.Serializable { @@ -249,6 +250,7 @@ final class KrbDelegationPermissionCollection extends PermissionCollection * the collection, false if not. */ @Override + @SuppressWarnings("removal") public boolean implies(Permission permission) { if (! (permission instanceof DelegationPermission)) return false; @@ -270,6 +272,7 @@ final class KrbDelegationPermissionCollection extends PermissionCollection * has been marked readonly */ @Override + @SuppressWarnings("removal") public void add(Permission permission) { if (! (permission instanceof DelegationPermission)) throw new IllegalArgumentException("invalid permission: "+ diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java index df45b4c72da..616e6be1d51 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,13 +54,14 @@ import java.util.concurrent.ConcurrentHashMap; * principal. * * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * * @since 1.4 */ +@Deprecated(since="25", forRemoval=true) public final class ServicePermission extends Permission implements java.io.Serializable { @@ -433,6 +434,7 @@ final class KrbServicePermissionCollection extends PermissionCollection * the collection, false if not. */ @Override + @SuppressWarnings("removal") public boolean implies(Permission permission) { if (! (permission instanceof ServicePermission np)) return false; @@ -480,6 +482,7 @@ final class KrbServicePermissionCollection extends PermissionCollection * has been marked readonly */ @Override + @SuppressWarnings("removal") public void add(Permission permission) { if (! (permission instanceof ServicePermission sp)) throw new IllegalArgumentException("invalid permission: "+ diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java index 647675ae61c..53396553bb6 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java @@ -39,6 +39,7 @@ public final class JavaUtils { private static final com.sun.org.slf4j.internal.Logger LOG = com.sun.org.slf4j.internal.LoggerFactory.getLogger(JavaUtils.class); + @SuppressWarnings("removal") private static final SecurityPermission REGISTER_PERMISSION = new SecurityPermission("com.sun.org.apache.xml.internal.security.register"); diff --git a/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java index 641edec9c38..fce26e077fc 100644 --- a/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,12 +32,13 @@ import java.security.BasicPermission; * *

The target name is the {@link InquireType} allowed. * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * * @since 1.7 */ +@Deprecated(since="25", forRemoval=true) public final class InquireSecContextPermission extends BasicPermission { private static final long serialVersionUID = -7131173349668647297L; From b98d6aebdd897959785ea27ee7855d26c9ed35d7 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 8 Apr 2025 16:34:20 +0000 Subject: [PATCH 056/843] 8339527: Adjust threshold for MemorySegment::fill native invocation Reviewed-by: jvernee --- .../classes/jdk/internal/foreign/SegmentBulkOperations.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java b/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java index 068db1bf593..5f0794c81d9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,9 +53,7 @@ public final class SegmentBulkOperations { // All the threshold values below MUST be a power of two and should preferably be // greater or equal to 2^3. - - // Update the FILL value for Aarch64 once 8338975 is fixed. - private static final int NATIVE_THRESHOLD_FILL = powerOfPropertyOr("fill", Architecture.isAARCH64() ? 10 : 5); + private static final int NATIVE_THRESHOLD_FILL = powerOfPropertyOr("fill", Architecture.isAARCH64() ? 18 : 5); private static final int NATIVE_THRESHOLD_MISMATCH = powerOfPropertyOr("mismatch", 6); private static final int NATIVE_THRESHOLD_COPY = powerOfPropertyOr("copy", 6); From bd73a0641615d743663ef652bc1f27305af1517b Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 8 Apr 2025 16:55:48 +0000 Subject: [PATCH 057/843] 8300339: Run jtreg in the work dir Reviewed-by: erikj --- make/RunTests.gmk | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 7aa0082e0ae..ebae510fc07 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -995,24 +995,27 @@ define SetupRunJtregTestBody $$(RM) -r $$($1_TEST_SUPPORT_DIR) $$(RM) -r $$($1_TEST_RESULTS_DIR) + $1_JTREG_ARGUMENTS := \ + $$($1_JTREG_LAUNCHER_OPTIONS) \ + -Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \ + $$($1_JTREG_BASIC_OPTIONS) \ + -testjdk:$$(JDK_UNDER_TEST) \ + -dir:$$(JTREG_TOPDIR) \ + -reportDir:$$($1_TEST_RESULTS_DIR) \ + -workDir:$$($1_TEST_SUPPORT_DIR) \ + -report:$${JTREG_REPORT} \ + $$$${JTREG_STATUS} \ + $$(JTREG_OPTIONS) \ + $$(JTREG_FAILURE_HANDLER_OPTIONS) \ + $$(JTREG_COV_OPTIONS) \ + $$($1_TEST_NAME) \ + # + $1_COMMAND_LINE := \ - $$(JTREG_JAVA) $$($1_JTREG_LAUNCHER_OPTIONS) \ - -Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \ - $$($1_JTREG_BASIC_OPTIONS) \ - -testjdk:$$(JDK_UNDER_TEST) \ - -dir:$$(JTREG_TOPDIR) \ - -reportDir:$$($1_TEST_RESULTS_DIR) \ - -workDir:$$($1_TEST_SUPPORT_DIR) \ - -report:$${JTREG_REPORT} \ - $$$${JTREG_STATUS} \ - $$(JTREG_OPTIONS) \ - $$(JTREG_FAILURE_HANDLER_OPTIONS) \ - $$(JTREG_COV_OPTIONS) \ - $$($1_TEST_NAME) \ + cd $$($1_TEST_SUPPORT_DIR) && $$(JTREG_JAVA) $$($1_JTREG_ARGUMENTS) \ && $$(ECHO) $$$$? > $$($1_EXITCODE) \ || $$(ECHO) $$$$? > $$($1_EXITCODE) - ifneq ($$(JTREG_RETRY_COUNT), 0) $1_COMMAND_LINE := \ for i in {0..$$(JTREG_RETRY_COUNT)}; do \ From e1a4a6beb61c70228c3aa54ddf2d9310fd5020e2 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 8 Apr 2025 16:57:00 +0000 Subject: [PATCH 058/843] 8340185: Use make -k on GHA to catch more build errors Reviewed-by: shade --- .github/actions/do-build/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/do-build/action.yml b/.github/actions/do-build/action.yml index 252105f29fd..6f2c2ce0218 100644 --- a/.github/actions/do-build/action.yml +++ b/.github/actions/do-build/action.yml @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ runs: - name: 'Build' id: build run: > - make LOG=info ${{ inputs.make-target }} + make -k LOG=info ${{ inputs.make-target }} || bash ./.github/scripts/gen-build-failure-report.sh "$GITHUB_STEP_SUMMARY" shell: bash From 5cac579619164b9a664327a4f71c4de7e7575276 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Tue, 8 Apr 2025 17:37:13 +0000 Subject: [PATCH 059/843] 8353713: Improve Currency.getInstance exception handling Reviewed-by: naoto --- .../share/classes/java/util/Currency.java | 24 ++++++------ test/jdk/java/util/Currency/CurrencyTest.java | 38 ++++++++++++------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/java.base/share/classes/java/util/Currency.java b/src/java.base/share/classes/java/util/Currency.java index bc13eff2a60..3aa966e83e8 100644 --- a/src/java.base/share/classes/java/util/Currency.java +++ b/src/java.base/share/classes/java/util/Currency.java @@ -314,8 +314,8 @@ public final class Currency implements Serializable { // or in the list of other currencies. boolean found = false; if (currencyCode.length() != 3) { - throw new IllegalArgumentException("The input currency code must " + - "have a length of 3 characters"); + throw new IllegalArgumentException( + "The input currency code: \"%s\" must have a length of 3 characters".formatted(currencyCode)); } char char1 = currencyCode.charAt(0); char char2 = currencyCode.charAt(1); @@ -338,8 +338,8 @@ public final class Currency implements Serializable { if (!found) { OtherCurrencyEntry ocEntry = OtherCurrencyEntry.findEntry(currencyCode); if (ocEntry == null) { - throw new IllegalArgumentException("The input currency code" + - " is not a valid ISO 4217 code"); + throw new IllegalArgumentException( + "The input currency code: \"%s\" is not a valid ISO 4217 code".formatted(currencyCode)); } defaultFractionDigits = ocEntry.fraction; numericCode = ocEntry.numericCode; @@ -394,8 +394,8 @@ public final class Currency implements Serializable { String country = CalendarDataUtility.findRegionOverride(locale).getCountry(); if (country == null || !country.matches("^[a-zA-Z]{2}$")) { - throw new IllegalArgumentException("The country of the input locale" + - " is not a valid ISO 3166 country code"); + throw new IllegalArgumentException( + "The country of the input locale: \"%s\" is not a valid ISO 3166 country code".formatted(locale)); } char char1 = country.charAt(0); @@ -412,8 +412,8 @@ public final class Currency implements Serializable { } else { // special cases if (tableEntry == INVALID_COUNTRY_ENTRY) { - throw new IllegalArgumentException("The country of the input locale" + - " is not a valid ISO 3166 country code"); + throw new IllegalArgumentException( + "The country of the input locale: \"%s\" is not a valid ISO 3166 country code".formatted(locale)); } if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) { return null; @@ -698,8 +698,8 @@ public final class Currency implements Serializable { */ private static int getMainTableEntry(char char1, char char2) { if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') { - throw new IllegalArgumentException("The country code is not a " + - "valid ISO 3166 code"); + throw new IllegalArgumentException( + "The country code: \"%c%c\" is not a valid ISO 3166 code".formatted(char1, char2)); } return mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')]; } @@ -710,8 +710,8 @@ public final class Currency implements Serializable { */ private static void setMainTableEntry(char char1, char char2, int entry) { if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') { - throw new IllegalArgumentException("The country code is not a " + - "valid ISO 3166 code"); + throw new IllegalArgumentException( + "The country code: \"%c%c\" is not a valid ISO 3166 code".formatted(char1, char2)); } mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')] = entry; } diff --git a/test/jdk/java/util/Currency/CurrencyTest.java b/test/jdk/java/util/Currency/CurrencyTest.java index c8dfb5013bd..7e4155eb65c 100644 --- a/test/jdk/java/util/Currency/CurrencyTest.java +++ b/test/jdk/java/util/Currency/CurrencyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531 * 6488442 7036905 8008577 8039317 8074350 8074351 8150324 8167143 - * 8264792 8334653 + * 8264792 8334653 8353713 * @summary Basic tests for Currency class. * @modules java.base/java.util:open * jdk.localedata @@ -84,14 +84,24 @@ public class CurrencyTest { public void invalidCurrencyTest(String currencyCode) { IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> Currency.getInstance(currencyCode), "getInstance() did not throw IAE"); - assertEquals("The input currency code is not a" + - " valid ISO 4217 code", ex.getMessage()); + assertEquals("The input currency code: \"%s\" is not a valid ISO 4217 code" + .formatted(currencyCode), ex.getMessage()); } private static Stream non4217Currencies() { return Stream.of("AQD", "US$"); } + // Provide 3 length code, but first 2 chars should not be able to index + // the main table, thus resulting as incorrect country code + @Test + void invalidCountryInCodeTest() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> + Currency.getInstance("..A"), "getInstance() did not throw IAE"); + assertEquals("The country code: \"%s\" is not a valid ISO 3166 code" + .formatted(".."), ex.getMessage()); + } + // Calling getInstance() with a currency code not 3 characters long should throw // an IAE @ParameterizedTest @@ -99,8 +109,8 @@ public class CurrencyTest { public void invalidCurrencyLengthTest(String currencyCode) { IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> Currency.getInstance(currencyCode), "getInstance() did not throw IAE"); - assertEquals("The input currency code must have a length of 3" + - " characters", ex.getMessage()); + assertEquals("The input currency code: \"%s\" must have a length of 3 characters" + .formatted(currencyCode), ex.getMessage()); } private static Stream invalidLengthCurrencies() { @@ -163,8 +173,8 @@ public class CurrencyTest { "AC|CP|DG|EA|EU|FX|IC|SU|TA|UK")) { // exceptional reservation codes IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> Currency.getInstance(locale), "Did not throw IAE"); - assertEquals("The country of the input locale is not a" + - " valid ISO 3166 country code", ex.getMessage()); + assertEquals("The country of the input locale: \"%s\" is not a valid ISO 3166 country code" + .formatted(locale), ex.getMessage()); } else { goodCountries++; Currency currency = Currency.getInstance(locale); @@ -180,13 +190,15 @@ public class CurrencyTest { } } - // Check an invalid country code + // Check an invalid country code supplied via the region override @Test - public void invalidCountryTest() { + public void invalidCountryRegionOverrideTest() { + // Override US with nonsensical country + var loc = Locale.forLanguageTag("en-US-u-rg-XXzzzz"); IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, - ()-> Currency.getInstance(Locale.of("", "EU")), "Did not throw IAE"); - assertEquals("The country of the input locale is not a valid" + - " ISO 3166 country code", ex.getMessage()); + ()-> Currency.getInstance(loc), "Did not throw IAE"); + assertEquals("The country of the input locale: \"%s\" is not a valid ISO 3166 country code" + .formatted(loc), ex.getMessage()); } // Ensure a selection of countries have the expected currency From 689d73a30d0701693ad86be164e4406effa11f2e Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 8 Apr 2025 17:39:59 +0000 Subject: [PATCH 060/843] 8317012: Explicitly check for 32-bit word size for using libatomic with zero Reviewed-by: erikj, shade --- make/autoconf/libraries.m4 | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index b946be97d96..bf697928f1b 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -98,13 +98,7 @@ AC_DEFUN([LIB_SETUP_JVM_LIBS], # 32-bit platforms needs fallback library for 8-byte atomic ops on Zero if HOTSPOT_CHECK_JVM_VARIANT(zero); then if test "x$OPENJDK_$1_OS" = xlinux && - (test "x$OPENJDK_$1_CPU" = xarm || - test "x$OPENJDK_$1_CPU" = xm68k || - test "x$OPENJDK_$1_CPU" = xmips || - test "x$OPENJDK_$1_CPU" = xmipsel || - test "x$OPENJDK_$1_CPU" = xppc || - test "x$OPENJDK_$1_CPU" = xsh || - test "x$OPENJDK_$1_CPU" = xriscv32); then + test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then BASIC_JVM_LIBS_$1="$BASIC_JVM_LIBS_$1 -latomic" fi fi From 257f817c7fca1e8cdb0fec0e18ab9c07b19b1d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 8 Apr 2025 18:41:10 +0000 Subject: [PATCH 061/843] 8353431: JFR: Sets to use hashmap instead of binary search as backend Reviewed-by: egahlin --- .../checkpoint/objectSampleCheckpoint.cpp | 84 +++++++++--- .../checkpoint/objectSampleCheckpoint.hpp | 1 + .../recorder/checkpoint/types/jfrTypeSet.cpp | 3 - .../checkpoint/types/jfrTypeSetUtils.cpp | 11 +- .../jfr/recorder/stacktrace/jfrStackTrace.hpp | 3 +- .../stacktrace/jfrStackTraceRepository.cpp | 38 +----- .../stacktrace/jfrStackTraceRepository.hpp | 8 +- .../jfrStackTraceRepository.inline.hpp | 42 ++++++ .../jfr/support/jfrDeprecationManager.cpp | 1 - .../share/jfr/support/jfrKlassUnloading.cpp | 58 ++++----- .../share/jfr/support/jfrKlassUnloading.hpp | 3 +- src/hotspot/share/jfr/utilities/jfrSet.hpp | 123 ++++++++++++++++++ 12 files changed, 265 insertions(+), 110 deletions(-) create mode 100644 src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.inline.hpp create mode 100644 src/hotspot/share/jfr/utilities/jfrSet.hpp diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp index bd3ab03045f..5ce2723391a 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp @@ -34,12 +34,12 @@ #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" -#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" +#include "jfr/recorder/stacktrace/jfrStackTraceRepository.inline.hpp" #include "jfr/recorder/storage/jfrReferenceCountedStorage.hpp" #include "jfr/support/jfrKlassUnloading.hpp" #include "jfr/support/jfrMethodLookup.hpp" #include "jfr/utilities/jfrHashtable.hpp" -#include "jfr/utilities/jfrPredicate.hpp" +#include "jfr/utilities/jfrSet.hpp" #include "jfr/utilities/jfrRelation.hpp" #include "memory/resourceArea.inline.hpp" #include "oops/instanceKlass.inline.hpp" @@ -48,14 +48,13 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" -const int initial_array_size = 64; +const unsigned int initial_size = 431; -template -static GrowableArray* c_heap_allocate_array(int size = initial_array_size) { - return new (mtTracing) GrowableArray(size, mtTracing); +static JfrCHeapTraceIdSet* c_heap_allocate_set(int size = initial_size) { + return new JfrCHeapTraceIdSet(size); } -static GrowableArray* unloaded_thread_id_set = nullptr; +static JfrCHeapTraceIdSet* unloaded_thread_id_set = nullptr; class ThreadIdExclusiveAccess : public StackObj { private: @@ -73,15 +72,15 @@ static bool has_thread_exited(traceid tid) { return false; } ThreadIdExclusiveAccess lock; - return JfrPredicate::test(unloaded_thread_id_set, tid); + return unloaded_thread_id_set->contains(tid); } static void add_to_unloaded_thread_set(traceid tid) { ThreadIdExclusiveAccess lock; if (unloaded_thread_id_set == nullptr) { - unloaded_thread_id_set = c_heap_allocate_array(); + unloaded_thread_id_set = c_heap_allocate_set(); } - JfrMutablePredicate::test(unloaded_thread_id_set, tid); + unloaded_thread_id_set->add(tid); } void ObjectSampleCheckpoint::on_thread_exit(traceid tid) { @@ -194,10 +193,10 @@ inline void BlobCache::on_unlink(BlobEntry* entry) const { assert(entry != nullptr, "invariant"); } -static GrowableArray* id_set = nullptr; +static JfrResourceAreaTraceIdSet* id_set = nullptr; static void prepare_for_resolution() { - id_set = new GrowableArray(JfrOptionSet::old_object_queue_size()); + id_set = new JfrResourceAreaTraceIdSet(initial_size); } static bool stack_trace_precondition(const ObjectSample* sample) { @@ -267,7 +266,6 @@ static void install_stack_traces(const ObjectSampler* sampler) { assert(last != nullptr, "invariant"); assert(last != sampler->last_resolved(), "invariant"); ResourceMark rm; - JfrKlassUnloading::sort(); StackTraceBlobInstaller installer; iterate_samples(installer); } @@ -317,7 +315,7 @@ static bool is_klass_unloaded(traceid klass_id) { static bool is_processed(traceid method_id) { assert(method_id != 0, "invariant"); assert(id_set != nullptr, "invariant"); - return JfrMutablePredicate::test(id_set, method_id); + return !id_set->add(method_id); } void ObjectSampleCheckpoint::add_to_leakp_set(const InstanceKlass* ik, traceid method_id) { @@ -362,17 +360,57 @@ static void write_thread_blob(const ObjectSample* sample, JfrCheckpointWriter& w } } -static GrowableArray* _stacktrace_ids = nullptr; +static JfrResourceAreaTraceIdSet* _stacktrace_id_set = nullptr; + +static inline bool should_write(const JfrStackTrace* stacktrace) { + assert(stacktrace != nullptr, "invariant"); + assert(_stacktrace_id_set != nullptr, "invariant"); + return stacktrace->should_write() && _stacktrace_id_set->contains(stacktrace->id()); +} + +class LeakProfilerStackTraceWriter { + private: + JfrCheckpointWriter& _writer; + int _count; + public: + LeakProfilerStackTraceWriter(JfrCheckpointWriter& writer) : _writer(writer), _count(0) { + assert(_stacktrace_id_set != nullptr, "invariant"); + } + + int count() const { return _count; } + + void operator()(const JfrStackTrace* stacktrace) { + if (should_write(stacktrace)) { + stacktrace->write(_writer); + ++_count; + } + } +}; + +void ObjectSampleCheckpoint::write_stacktraces(Thread* thread) { + assert(_stacktrace_id_set != nullptr, "invariant"); + assert(_stacktrace_id_set->is_nonempty(), "invariant"); + + JfrCheckpointWriter writer(thread); + writer.write_type(TYPE_STACKTRACE); + const int64_t count_offset = writer.reserve(sizeof(u4)); // Don't know how many yet + + LeakProfilerStackTraceWriter lpstw(writer); + JfrStackTraceRepository::iterate_leakprofiler(lpstw); + assert(lpstw.count() == _stacktrace_id_set->size(), "invariant"); + writer.write_count(lpstw.count(), count_offset); +} static void write_stacktrace_blob(const ObjectSample* sample, JfrCheckpointWriter& writer) { - assert(_stacktrace_ids != nullptr, "invariant"); + assert(sample != nullptr, "invariant"); + assert(_stacktrace_id_set != nullptr, "invariant"); if (sample->has_stacktrace()) { write_blob(sample->stacktrace(), writer); return; } const traceid stacktrace_id = sample->stack_trace_id(); if (stacktrace_id != 0) { - _stacktrace_ids->append(stacktrace_id); + _stacktrace_id_set->add(stacktrace_id); } } @@ -406,17 +444,21 @@ static void write_sample_blobs(const ObjectSampler* sampler, bool emit_all, Thre iterate_samples(cbw, true); } +static inline unsigned int set_size() { + const unsigned int queue_size = static_cast(JfrOptionSet::old_object_queue_size()); + return queue_size > initial_size ? queue_size : initial_size; +} + void ObjectSampleCheckpoint::write(const ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread) { assert(sampler != nullptr, "invariant"); assert(edge_store != nullptr, "invariant"); assert(thread != nullptr, "invariant"); { ResourceMark rm(thread); - _stacktrace_ids = new GrowableArray(JfrOptionSet::old_object_queue_size()); + _stacktrace_id_set = new JfrResourceAreaTraceIdSet(set_size()); write_sample_blobs(sampler, emit_all, thread); - if (_stacktrace_ids->is_nonempty()) { - _stacktrace_ids->sort(sort_traceid); - JfrStackTraceRepository::write_leak_profiler(_stacktrace_ids, thread); + if (_stacktrace_id_set->is_nonempty()) { + write_stacktraces(thread); } } // write reference chains diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp index bf1965b13b5..2ab2e12302f 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp @@ -47,6 +47,7 @@ class ObjectSampleCheckpoint : AllStatic { static void add_to_leakp_set(const InstanceKlass* ik, traceid method_id); static int save_mark_words(const ObjectSampler* sampler, ObjectSampleMarker& marker, bool emit_all); static void write_stacktrace(const JfrStackTrace* trace, JfrCheckpointWriter& writer); + static void write_stacktraces(Thread* thread); static void write(const ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread); static void clear(); public: diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index b9dcd7a3694..a1b10e8cfb8 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -1225,9 +1225,6 @@ static void setup(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer } else { _artifacts->initialize(class_unload); } - if (!_class_unload) { - JfrKlassUnloading::sort(previous_epoch()); - } assert(_artifacts != nullptr, "invariant"); assert(!_artifacts->has_klass_entries(), "invariant"); } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp index 5e70fdcb941..d213ecd7d75 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp @@ -37,7 +37,7 @@ JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_table(nullptr), assert(_klass_list != nullptr, "invariant"); } -static const size_t initial_klass_list_size = 256; +static const size_t initial_klass_list_size = 4096; const int initial_klass_loader_set_size = 64; void JfrArtifactSet::initialize(bool class_unload) { @@ -49,10 +49,10 @@ void JfrArtifactSet::initialize(bool class_unload) { assert(_symbol_table != nullptr, "invariant"); _symbol_table->set_class_unload(class_unload); _total_count = 0; - // resource allocation - _klass_list = new GrowableArray(initial_klass_list_size); - _klass_loader_set = new GrowableArray(initial_klass_loader_set_size); + // Resource allocations. Keep in this allocation order. _klass_loader_leakp_set = new GrowableArray(initial_klass_loader_set_size); + _klass_loader_set = new GrowableArray(initial_klass_loader_set_size); + _klass_list = new GrowableArray(initial_klass_list_size); } void JfrArtifactSet::clear() { @@ -63,7 +63,8 @@ void JfrArtifactSet::clear() { JfrArtifactSet::~JfrArtifactSet() { delete _symbol_table; - // _klass_list and _klass_loader_list will be cleared by a ResourceMark + // _klass_loader_set, _klass_loader_leakp_set and + // _klass_list will be cleared by a ResourceMark } traceid JfrArtifactSet::bootstrap_name(bool leakp) { diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.hpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.hpp index 6a7b750752c..101dae21681 100644 --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.hpp +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,7 @@ class JfrStackFrame { class JfrStackTrace : public JfrCHeapObj { friend class JfrNativeSamplerCallback; friend class JfrStackTraceRepository; + friend class LeakProfilerStackTraceWriter; friend class ObjectSampleCheckpoint; friend class ObjectSampler; friend class OSThreadSampler; diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp index b75ac95e27f..99d26c4689e 100644 --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp @@ -27,10 +27,7 @@ #include "jfr/recorder/repository/jfrChunkWriter.hpp" #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" #include "jfr/support/jfrThreadLocal.hpp" -#include "jfr/utilities/jfrPredicate.hpp" -#include "jfr/utilities/jfrRelation.hpp" #include "runtime/mutexLocker.hpp" -#include "utilities/growableArray.hpp" /* * There are two separate repository instances. @@ -48,7 +45,7 @@ JfrStackTraceRepository& JfrStackTraceRepository::instance() { return *_instance; } -static JfrStackTraceRepository& leak_profiler_instance() { +JfrStackTraceRepository& JfrStackTraceRepository::leak_profiler_instance() { assert(_leak_profiler_instance != nullptr, "invariant"); return *_leak_profiler_instance; } @@ -245,36 +242,3 @@ traceid JfrStackTraceRepository::next_id() { MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag); return ++_next_id; } - -static inline bool should_write(const JfrStackTrace* stacktrace, GrowableArray* leakp_set) { - assert(stacktrace != nullptr, "invariant"); - return stacktrace->should_write() && JfrPredicate::test(leakp_set, stacktrace->id()); -} - -void JfrStackTraceRepository::write_leak_profiler(GrowableArray* leakp_set, Thread* t) { - assert(leakp_set != nullptr, "invariant"); - assert(leakp_set->is_nonempty(), "invariant"); - assert(t != nullptr, "invariant"); - - JfrCheckpointWriter writer(t); - writer.write_type(TYPE_STACKTRACE); - const int64_t count_offset = writer.reserve(sizeof(u4)); // Don't know how many yet - - int count = 0; - const JfrStackTraceRepository& repo = leak_profiler_instance(); - - for (u4 i = 0; i < TABLE_SIZE; ++i) { - const JfrStackTrace* stacktrace = repo._table[i]; - while (stacktrace != nullptr) { - if (should_write(stacktrace, leakp_set)) { - stacktrace->write(writer); - ++count; - } - stacktrace = stacktrace->next(); - } - } - - assert(count > 0, "invariant"); - assert(count <= leakp_set->length(), "invariant"); - writer.write_count(count, count_offset); -} diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp index 427aff0eb9a..5aa382944e2 100644 --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp @@ -32,9 +32,6 @@ class JavaThread; class JfrChunkWriter; -template -class GrowableArray; - class JfrStackTraceRepository : public JfrCHeapObj { friend class JfrDeprecatedEdge; friend class JfrRecorder; @@ -54,6 +51,7 @@ class JfrStackTraceRepository : public JfrCHeapObj { JfrStackTraceRepository(); static JfrStackTraceRepository& instance(); + static JfrStackTraceRepository& leak_profiler_instance(); static JfrStackTraceRepository* create(); static void destroy(); bool initialize(); @@ -64,9 +62,11 @@ class JfrStackTraceRepository : public JfrCHeapObj { static const JfrStackTrace* lookup_for_leak_profiler(traceid hash, traceid id); static void record_for_leak_profiler(JavaThread* thread, int skip = 0); - static void write_leak_profiler(GrowableArray* leakp_set, Thread* t); static void clear_leak_profiler(); + template + static void iterate_leakprofiler(Callback& cb); + static traceid next_id(); traceid add_trace(const JfrStackTrace& stacktrace); diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.inline.hpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.inline.hpp new file mode 100644 index 00000000000..5b30216ecca --- /dev/null +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.inline.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_INLINE_HPP +#define SHARE_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_INLINE_HPP + +#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" + +template +inline void JfrStackTraceRepository::iterate_leakprofiler(Callback& cb) { + JfrStackTraceRepository& repo = leak_profiler_instance(); + for (u4 i = 0; i < TABLE_SIZE; ++i) { + const JfrStackTrace* stacktrace = repo._table[i]; + while (stacktrace != nullptr) { + cb(stacktrace); + stacktrace = stacktrace->next(); + } + } +} + +#endif // SHARE_JFR_RECORDER_STACKTRACE_JFRSTACKTRACEREPOSITORY_INLINE_HPP diff --git a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp index ef1f25c84b3..4eb8662c209 100644 --- a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp +++ b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp @@ -354,7 +354,6 @@ static void reset_type_set_blobs() { void JfrDeprecationManager::prepare_type_set(JavaThread* jt) { reset_type_set_blobs(); if (_pending_list.is_nonempty()) { - JfrKlassUnloading::sort(true); JfrCheckpointWriter writer(true /* prev epoch */, jt, false /* header */); PendingListProcessor plp(writer, jt); _pending_list.iterate(plp); diff --git a/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp b/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp index 31eb83e1667..ce5de54ed16 100644 --- a/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp +++ b/src/hotspot/share/jfr/support/jfrKlassUnloading.cpp @@ -26,56 +26,48 @@ #include "jfr/periodic/jfrFinalizerStatisticsEvent.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/support/jfrKlassUnloading.hpp" -#include "jfr/utilities/jfrPredicate.hpp" -#include "jfr/utilities/jfrRelation.hpp" +#include "jfr/utilities/jfrSet.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/macros.hpp" -static const int initial_array_size = 64; +static const int initial_size = 1009; -template -static GrowableArray* c_heap_allocate_array(int size = initial_array_size) { - return new (mtTracing) GrowableArray(size, mtTracing); +static JfrCHeapTraceIdSet* c_heap_allocate_set(int size = initial_size) { + return new JfrCHeapTraceIdSet(size); } // Track the set of unloaded klasses during a chunk / epoch. -static GrowableArray* _unload_set_epoch_0 = nullptr; -static GrowableArray* _unload_set_epoch_1 = nullptr; +static JfrCHeapTraceIdSet* _unload_set_epoch_0 = nullptr; +static JfrCHeapTraceIdSet* _unload_set_epoch_1 = nullptr; static s8 event_klass_unloaded_count = 0; -static GrowableArray* unload_set_epoch_0() { +static JfrCHeapTraceIdSet* unload_set_epoch_0() { if (_unload_set_epoch_0 == nullptr) { - _unload_set_epoch_0 = c_heap_allocate_array(initial_array_size); + _unload_set_epoch_0 = c_heap_allocate_set(); } return _unload_set_epoch_0; } -static GrowableArray* unload_set_epoch_1() { +static JfrCHeapTraceIdSet* unload_set_epoch_1() { if (_unload_set_epoch_1 == nullptr) { - _unload_set_epoch_1 = c_heap_allocate_array(initial_array_size); + _unload_set_epoch_1 = c_heap_allocate_set(); } return _unload_set_epoch_1; } -static GrowableArray* get_unload_set(u1 epoch) { +static JfrCHeapTraceIdSet* get_unload_set(u1 epoch) { return epoch == 0 ? unload_set_epoch_0() : unload_set_epoch_1(); } -static GrowableArray* get_unload_set() { +static JfrCHeapTraceIdSet* get_unload_set() { return get_unload_set(JfrTraceIdEpoch::current()); } -static GrowableArray* get_unload_set_previous_epoch() { +static JfrCHeapTraceIdSet* get_unload_set_previous_epoch() { return get_unload_set(JfrTraceIdEpoch::previous()); } -static void sort_set(GrowableArray* set) { - assert(set != nullptr, "invariant"); - assert(set->is_nonempty(), "invariant"); - set->sort(sort_traceid); -} - static bool is_nonempty_set(u1 epoch) { if (epoch == 0) { return _unload_set_epoch_0 != nullptr && _unload_set_epoch_0->is_nonempty(); @@ -83,16 +75,6 @@ static bool is_nonempty_set(u1 epoch) { return _unload_set_epoch_1 != nullptr && _unload_set_epoch_1->is_nonempty(); } -void JfrKlassUnloading::sort(bool previous_epoch) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - if (is_nonempty_set(JfrTraceIdEpoch::current())) { - sort_set(get_unload_set()); - } - if (previous_epoch && is_nonempty_set(JfrTraceIdEpoch::previous())) { - sort_set(get_unload_set_previous_epoch()); - } -} - void JfrKlassUnloading::clear() { assert_locked_or_safepoint(ClassLoaderDataGraph_lock); if (is_nonempty_set(JfrTraceIdEpoch::previous())) { @@ -102,10 +84,9 @@ void JfrKlassUnloading::clear() { static void add_to_unloaded_klass_set(traceid klass_id) { assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - GrowableArray* const unload_set = get_unload_set(); + JfrCHeapTraceIdSet* const unload_set = get_unload_set(); assert(unload_set != nullptr, "invariant"); - assert(unload_set->find(klass_id) == -1, "invariant"); - unload_set->append(klass_id); + unload_set->add(klass_id); } #if INCLUDE_MANAGEMENT @@ -131,14 +112,19 @@ bool JfrKlassUnloading::on_unload(const Klass* k) { return USED_THIS_EPOCH(k); } +static inline bool is_unloaded(const JfrCHeapTraceIdSet* set, const traceid& id) { + assert(set != nullptr, "invariant"); + return set->contains(id); +} + bool JfrKlassUnloading::is_unloaded(traceid klass_id, bool previous_epoch /* false */) { assert_locked_or_safepoint(ClassLoaderDataGraph_lock); if (previous_epoch) { - if (JfrPredicate::test(get_unload_set_previous_epoch(), klass_id)) { + if (::is_unloaded(get_unload_set_previous_epoch(), klass_id)) { return true; } } - return JfrPredicate::test(get_unload_set(), klass_id); + return ::is_unloaded(get_unload_set(), klass_id); } int64_t JfrKlassUnloading::event_class_count() { diff --git a/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp b/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp index 5d380df436c..25ff820fc09 100644 --- a/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp +++ b/src/hotspot/share/jfr/support/jfrKlassUnloading.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ class JfrKlassUnloading : AllStatic { static bool on_unload(const Klass* k); static int64_t event_class_count(); static bool is_unloaded(traceid klass_id, bool previous_epoch = false); - static void sort(bool previous_epoch = false); static void clear(); }; diff --git a/src/hotspot/share/jfr/utilities/jfrSet.hpp b/src/hotspot/share/jfr/utilities/jfrSet.hpp new file mode 100644 index 00000000000..b4dfc4f6240 --- /dev/null +++ b/src/hotspot/share/jfr/utilities/jfrSet.hpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_JFR_UTILITIES_JFRSET_HPP +#define SHARE_JFR_UTILITIES_JFRSET_HPP + +#include "jfr/utilities/jfrAllocation.hpp" +#include "jfr/utilities/jfrTypes.hpp" +#include "utilities/resizeableResourceHash.hpp" + +template +class ConfigTraceID : public AllStatic { + public: + typedef AllocPolicy STORAGE; + typedef traceid TYPE; + + constexpr static AnyObj::allocation_type alloc_type() { + return AllocType; + } + + constexpr static MemTag memory_tag() { + return memtag; + } + + // Knuth multiplicative hashing. + static uint32_t hash(const TYPE& id) { + const uint32_t v = static_cast(id); + return v * UINT32_C(2654435761); + } + + static bool cmp(const TYPE& lhs, const TYPE& rhs) { + return lhs == rhs; + } +}; + +constexpr static unsigned int MAX_TABLE_SIZE = 0x3fffffff; + +template +class JfrSet : public CONFIG::STORAGE { + public: + typedef typename CONFIG::TYPE TYPE; + typedef ResizeableResourceHashtable HashMap; + + constexpr static bool is_cheap() { + return CONFIG::alloc_type() == AnyObj::C_HEAP; + } + + JfrSet(unsigned int initial_size, unsigned int max_size = MAX_TABLE_SIZE) : + _map(is_cheap() ? new (CONFIG::memory_tag()) HashMap(initial_size, max_size) : new HashMap(initial_size, max_size)) {} + + ~JfrSet() { + if (is_cheap()) { + delete _map; + } + } + + bool add(const TYPE& k) { + bool inserted; + _map->put_if_absent(k, &inserted); + return inserted; + } + + bool remove(const TYPE& k) { + return _map->remove(k); + } + + bool contains(const TYPE& k) const { + return _map->contains(k); + } + + bool is_empty() const { + return _map->number_of_entries() == 0; + } + + bool is_nonempty() const { + return !is_empty(); + } + + int size() const { + return _map->number_of_entries(); + } + + void clear() { + if (is_nonempty()) { + _map->unlink(this); + } + assert(is_empty(), "invariant"); + } + + // Callback for node deletion, used by clear(). + bool do_entry(const TYPE& k, const TYPE& v) { + return true; + } + + private: + HashMap* _map; +}; + +typedef JfrSet > JfrCHeapTraceIdSet; +typedef JfrSet > JfrResourceAreaTraceIdSet; + +#endif // SHARE_JFR_UTILITIES_JFRSET_HPP From 24ff96afe41b62275fe8635e477ecc04bff93123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Tue, 8 Apr 2025 18:45:53 +0000 Subject: [PATCH 062/843] 8352389: Remove incidental whitespace in pre/code content Reviewed-by: liach --- .../tools/javac/parser/DocCommentParser.java | 129 ++++++++++++++ .../formats/html/resources/stylesheet.css | 2 +- .../TestLiteralCodeInPre.java | 11 +- .../doclet/testPreCode/TestPreCode.java | 165 ++++++++++++++++++ .../tools/javac/doctree/CodeTest.java | 4 +- .../tools/javac/doctree/DocCommentTester.java | 4 +- .../tools/javac/doctree/InPreTest.java | 46 ++++- 7 files changed, 349 insertions(+), 12 deletions(-) create mode 100644 test/langtools/jdk/javadoc/doclet/testPreCode/TestPreCode.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java index 017c39b3c54..cf545a8f520 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java @@ -34,8 +34,12 @@ import java.util.regex.Pattern; import com.sun.source.doctree.AttributeTree.ValueKind; import com.sun.source.doctree.DocTree; import com.sun.source.doctree.ErroneousTree; +import com.sun.source.doctree.LiteralTree; +import com.sun.source.doctree.StartElementTree; +import com.sun.source.doctree.TextTree; import com.sun.source.doctree.UnknownBlockTagTree; import com.sun.source.doctree.UnknownInlineTagTree; +import com.sun.source.util.SimpleDocTreeVisitor; import com.sun.tools.javac.parser.Tokens.Comment; import com.sun.tools.javac.tree.DCTree; import com.sun.tools.javac.tree.DCTree.DCAttribute; @@ -126,6 +130,9 @@ public class DocCommentParser { private int lastNonWhite = -1; private boolean newline = true; + /** Used for whitespace normalization in pre/code/literal tags. */ + private boolean inPre = false; + private final Map tagParsers; /** @@ -281,6 +288,7 @@ public class DocCommentParser { */ protected List content(Phase phase) { ListBuffer trees = new ListBuffer<>(); + ListBuffer mainTrees = null; textStart = -1; int depth = 1; // only used when phase is INLINE @@ -349,6 +357,18 @@ public class DocCommentParser { addPendingText(trees, bp - 1); trees.add(html()); + // Create new list for

 content which is merged into main list when element is closed.
+                            if (inPre) {
+                                if (mainTrees == null) {
+                                    mainTrees = trees;
+                                    trees = new ListBuffer<>();
+                                }
+                            } else if (mainTrees != null) {
+                                mainTrees.addAll(normalizePreContent(trees));
+                                trees = mainTrees;
+                                mainTrees = null;
+                            }
+
                             if (phase == Phase.PREAMBLE || phase == Phase.POSTAMBLE) {
                                 break; // Ignore newlines after html tags, in the meta content
                             }
@@ -476,6 +496,13 @@ public class DocCommentParser {
         if (lastNonWhite != -1)
             addPendingText(trees, lastNonWhite);
 
+        // Happens with unclosed 
 element. Add content without normalizing.
+        if (mainTrees != null) {
+            mainTrees.addAll(trees);
+            trees = mainTrees;
+            mainTrees = null;
+        }
+
         return (phase == Phase.INLINE)
                 ? List.of(erroneous("dc.unterminated.inline.tag", pos))
                 : trees.toList();
@@ -1054,6 +1081,9 @@ public class DocCommentParser {
                 }
                 if (ch == '>') {
                     nextChar();
+                    if ("pre".equalsIgnoreCase(name.toString())) {
+                        inPre = true;
+                    }
                     return m.at(p).newStartElementTree(name, attrs, selfClosing).setEndPos(bp);
                 }
             }
@@ -1064,6 +1094,9 @@ public class DocCommentParser {
                 skipWhitespace();
                 if (ch == '>') {
                     nextChar();
+                    if ("pre".equalsIgnoreCase(name.toString())) {
+                        inPre = false;
+                    }
                     return m.at(p).newEndElementTree(name).setEndPos(bp);
                 }
             }
@@ -1186,6 +1219,102 @@ public class DocCommentParser {
         return attrs.toList();
     }
 
+    /*
+     * Removes a newline character following a , {@code or {@literal tag at the
+     * beginning of 
 element content, as well as any space/tabs between the pre
+     * and code tags. The operation is only performed on traditional doc comments.
+     * If conditions are not met the list is returned unchanged.
+     */
+    ListBuffer normalizePreContent(ListBuffer trees) {
+        // Do nothing if comment is not eligible for whitespace normalization.
+        if (textKind == DocTree.Kind.MARKDOWN || isHtmlFile) {
+            return trees;
+        }
+
+        enum State {
+            BEFORE_CODE, // at beginning of 
 content, or after leading horizontal whitespace
+            AFTER_CODE,  // after  start tag (not used for {@code} tag)
+            SUCCEEDED,   // normalization succeeded, add remaining trees
+            FAILED;      // normalization failed, return original trees
+        }
+
+        class Context {
+            State state = State.BEFORE_CODE;
+
+            // Called when an unexpected tree is encountered. Set state to
+            // FAILED unless normalization already terminated successfully.
+            void unexpectedTree() {
+                if (state != State.SUCCEEDED) {
+                    state = State.FAILED;
+                }
+            }
+        }
+
+        var visitor = new SimpleDocTreeVisitor() {
+            @Override
+            public DCTree visitText(TextTree text, Context cx) {
+                if (cx.state == State.BEFORE_CODE && text.getBody().matches("[ \t]+")) {
+                    // 
  ...
+                    return null;
+                } else if (cx.state == State.AFTER_CODE && text.getBody().startsWith("\n")) {
+                    // 
\n...
+                    cx.state = State.SUCCEEDED;
+                    return m.at(((DCText) text).pos + 1).newTextTree(text.getBody().substring(1));
+                }
+                cx.unexpectedTree();
+                return (DCTree) text;
+            }
+
+            @Override
+            public DCTree visitLiteral(LiteralTree literal, Context cx) {
+                if (cx.state == State.BEFORE_CODE && literal.getBody().getBody().startsWith("\n")) {
+                    // 
{@code\n...
+                    cx.state = State.SUCCEEDED;
+                    DCText oldBody = (DCText) literal.getBody();
+                    DCText newBody = m.at(oldBody.pos + 1).newTextTree(oldBody.getBody().substring(1));
+                    m.at(((DCTree) literal).pos);
+                    return literal.getKind() == DocTree.Kind.CODE
+                            ? m.newCodeTree(newBody)
+                            : m.newLiteralTree(newBody);
+                }
+                cx.unexpectedTree();
+                return (DCTree) literal;
+            }
+
+            @Override
+            public DCTree visitStartElement(StartElementTree node, Context cx) {
+                if (cx.state == State.BEFORE_CODE && node.getName().toString().equalsIgnoreCase("code")) {
+                    cx.state = State.AFTER_CODE;
+                } else {
+                    cx.unexpectedTree();
+                }
+                return (DCTree) node;
+            }
+
+            @Override
+            protected DCTree defaultAction(DocTree node, Context cx) {
+                cx.unexpectedTree();
+                return (DCTree) node;
+            }
+        };
+
+        Context cx = new Context();
+        var normalized = new ListBuffer();
+
+        for (var tree : trees) {
+            var visited = visitor.visit(tree, cx);
+            // null return value means the tree should be dropped
+            if (visited != null) {
+                normalized.add(visited);
+            }
+            if (cx.state == State.FAILED) {
+                return trees;
+            }
+        }
+
+        return cx.state == State.SUCCEEDED ? normalized : trees;
+    }
+
     protected void attrValueChar(ListBuffer list) {
         switch (ch) {
             case '&' -> entity(list);
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css
index ac393e8a762..54c7c5cbe21 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css
@@ -133,7 +133,7 @@ pre {
     line-height: var(--code-line-height);
     background-color: var(--pre-background-color);
     color: var(--pre-text-color);
-    padding: 8px;
+    padding: 10px;
     overflow-x:auto;
 }
 h1 {
diff --git a/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java b/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java
index ac5259686f1..1a96da79fb3 100644
--- a/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java
+++ b/test/langtools/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      8002387 8014636 8078320 8175200 8186332 8352249
+ * @bug      8002387 8014636 8078320 8175200 8186332 8352249 8352389
  * @summary  Improve rendered HTML formatting for {@code}
  * @library  ../../lib
  * @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -70,8 +70,7 @@ public class TestLiteralCodeInPre extends JavadocTester {
                 """
                     typical_usage_code()
                     
Lorem ipsum dolor sit amet, consectetur adipiscing elit. - Example:

-                      line 0 @Override
+                    Example:  
  line 0 @Override
                       line 1 <T> void m(T t) {
                       line 2     // do something with T
                       line 3 }
@@ -80,8 +79,7 @@ public class TestLiteralCodeInPre extends JavadocTester {
                 """
                     typical_usage_literal()
Lorem ipsum dolor sit amet, consectetur adipiscing elit. - Example:
-                      line 0 @Override
+                    Example:  
  line 0 @Override
                       line 1 <T> void m(T t) {
                       line 2     // do something with T
                       line 3 }
@@ -90,8 +88,7 @@ public class TestLiteralCodeInPre extends JavadocTester {
                 """
                     recommended_usage_literal()
Lorem ipsum dolor sit amet, consectetur adipiscing elit. - Example:
-                      line 0 @Override
+                    Example:  
  line 0 @Override
                       line 1 <T> void m(T t) {
                       line 2     // do something with T
                       line 3 } 
diff --git a/test/langtools/jdk/javadoc/doclet/testPreCode/TestPreCode.java b/test/langtools/jdk/javadoc/doclet/testPreCode/TestPreCode.java new file mode 100644 index 00000000000..c3614126aae --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testPreCode/TestPreCode.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8352389 + * @summary Remove incidental whitespace in pre/code content + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build javadoc.tester.* toolbox.ToolBox builder.ClassBuilder + * @run main TestPreCode + */ + + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import builder.AbstractBuilder; +import builder.ClassBuilder; +import toolbox.ToolBox; + +import javadoc.tester.JavadocTester; + +public class TestPreCode extends JavadocTester { + + final ToolBox tb; + + public static void main(String... args) throws Exception { + var tester = new TestPreCode(); + tester.runTests(); + } + + TestPreCode() { + tb = new ToolBox(); + } + + @Test + public void testWhitespace(Path base) throws Exception { + Path srcDir = base.resolve("src"); + Path outDir = base.resolve("out"); + + new ClassBuilder(tb, "pkg.A") + .setComments(""" + Class A. +
 \t
+                      first line
+                      second line
+                    
""") + .setModifiers("public", "class") + .addMembers(ClassBuilder.MethodBuilder.parse("public void m0() {}") + .setComments(""" + Method m0. +
 {@code
+                                  first line
+                                  second line
+                                }
"""), + ClassBuilder.MethodBuilder.parse("public void m1() {}") + .setComments(""" + Method m1. +
  first line
+                                  second line
+                                
"""), + ClassBuilder.MethodBuilder.parse("public void m2() {}") + .setComments(""" + Method m2. +
 {@code\s
+                                  first line
+                                  second line
+                                }
"""), + ClassBuilder.MethodBuilder.parse("public void m3() {}") + .setComments(""" + Method m3. +
  .
+                                  second line
+                                
""")) + .write(srcDir); + + javadoc("-d", outDir.toString(), + "-sourcepath", srcDir.toString(), + "pkg"); + + checkExit(Exit.OK); + + checkOrder("pkg/A.html", + """ + Class A. +
  first line
+                      second line
+                    
""", + """ + Method m0. +
  first line
+                      second line
+                    
""", + """ + Method m1. +
  first line
+                      second line
+                    
""", + """ + Method m2. +
  first line
+                      second line
+                    
""", + """ + Method m3. +
  .
+                      second line
+                    
"""); + } + + @Test + public void testUnclosed(Path base) throws Exception { + Path srcDir = base.resolve("src"); + Path outDir = base.resolve("out"); + + new ClassBuilder(tb, "pkg.A") + .setComments(""" + Class A. +

+                      first line
+                      second line
+                    """)
+                .setModifiers("public", "class")
+                .write(srcDir);
+
+        javadoc("-d", outDir.toString(),
+                "-sourcepath", srcDir.toString(),
+                "pkg");
+
+        checkExit(Exit.ERROR);
+
+        // No whitespace normalization for unclosed 
 element
+        checkOrder("pkg/A.html",
+                """
+                    Class A.
+                    

+                      first line
+                      second line
+                    
"""); + } + +} diff --git a/test/langtools/tools/javac/doctree/CodeTest.java b/test/langtools/tools/javac/doctree/CodeTest.java index b7770122715..7623c41497d 100644 --- a/test/langtools/tools/javac/doctree/CodeTest.java +++ b/test/langtools/tools/javac/doctree/CodeTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7021614 8241780 8273244 8284908 8352249 + * @bug 7021614 8241780 8273244 8284908 8352249 8352389 * @summary extend com.sun.source API to support parsing javadoc comments * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file @@ -128,7 +128,7 @@ DocComment[DOC_COMMENT, pos:0 name:pre attributes: empty ] - Literal[CODE, pos:5, |____@Override|____void_m()_{_}|] + Literal[CODE, pos:5, ____@Override|____void_m()_{_}|] body: 1 EndElement[END_ELEMENT, pos:44, pre] block tags: empty diff --git a/test/langtools/tools/javac/doctree/DocCommentTester.java b/test/langtools/tools/javac/doctree/DocCommentTester.java index 3591fcbca2d..1d723a2b625 100644 --- a/test/langtools/tools/javac/doctree/DocCommentTester.java +++ b/test/langtools/tools/javac/doctree/DocCommentTester.java @@ -1023,7 +1023,9 @@ public class DocCommentTester { .replaceFirst("\\.\\s*\\n *@(?![@*])", ".\n@") // Between block tags .replaceAll("\n[ \t]+@(?!([@*]|(dummy|Override)))", "\n@") .replaceAll("(?i)\\{@([a-z][a-z0-9.:-]*)\\s+}", "{@$1}") - .replaceAll("(\\{@value\\s+[^}]+)\\s+(})", "$1$2"); + .replaceAll("(\\{@value\\s+[^}]+)\\s+(})", "$1$2") + .replaceAll("
 *\\{@code\\n", "
{@code ")
+                    .replaceAll("
 *\\n", "
");
         }
     }
 
diff --git a/test/langtools/tools/javac/doctree/InPreTest.java b/test/langtools/tools/javac/doctree/InPreTest.java
index 9203f56a0f2..8f7a705c75a 100644
--- a/test/langtools/tools/javac/doctree/InPreTest.java
+++ b/test/langtools/tools/javac/doctree/InPreTest.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8078320 8273244 8284908 8352249
+ * @bug 8078320 8273244 8284908 8352249 8352389
  * @summary extend com.sun.source API to support parsing javadoc comments
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
@@ -163,6 +163,50 @@ DocComment[DOC_COMMENT, pos:1
     EndElement[END_ELEMENT, pos:26, pre]
   block tags: empty
 ]
+*/
+    /**
+     * 
 {@code
+     * abc  }
+     * def
+ */ + public void in_pre_with_space_at_code_nl() { } +/* +DocComment[DOC_COMMENT, pos:0 + firstSentence: 3 + StartElement[START_ELEMENT, pos:0 + name:pre + attributes: empty + ] + Literal[CODE, pos:6, abc__] + Text[TEXT, pos:19, |def] + body: 1 + EndElement[END_ELEMENT, pos:23, pre] + block tags: empty +] +*/ + /** + *
 
+     *   abc
+     * 
+ */ + public void in_pre_with_space_code_nl() { } +/* +DocComment[DOC_COMMENT, pos:0 + firstSentence: 4 + StartElement[START_ELEMENT, pos:0 + name:pre + attributes: empty + ] + StartElement[START_ELEMENT, pos:6 + name:code + attributes: empty + ] + Text[TEXT, pos:13, __abc|] + EndElement[END_ELEMENT, pos:19, code] + body: 1 + EndElement[END_ELEMENT, pos:26, pre] + block tags: empty +] */ /** * abc {@code From 5b42c46b48363acd00ee4a183edca9a48cdc16c8 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Tue, 8 Apr 2025 20:04:44 +0000 Subject: [PATCH 063/843] 8353757: Log class should have a proper clear() method Reviewed-by: vromero, mcimadamore --- .../com/sun/tools/javac/api/JavacTaskPool.java | 12 +++++------- .../classes/com/sun/tools/javac/util/Log.java | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java index 1ce4cf50ada..87bc64c4e19 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -267,7 +267,7 @@ public class JavacTaskPool { if (ht.get(Log.logKey) instanceof ReusableLog) { //log already inited - not first round - ((ReusableLog)Log.instance(this)).clear(); + Log.instance(this).clear(); Enter.instance(this).newRound(); ((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear(); Types.instance(this).newRound(); @@ -395,11 +395,9 @@ public class JavacTaskPool { this.context = context; } - void clear() { - recorded.clear(); - sourceMap.clear(); - nerrors = 0; - nwarnings = 0; + @Override + public void clear() { + super.clear(); //Set a fake listener that will lazily lookup the context for the 'real' listener. Since //this field is never updated when a new task is created, we cannot simply reset the field //or keep old value. This is a hack to workaround the limitations in the current infrastructure. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java index 56ee413ea07..2167f471104 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java @@ -689,6 +689,20 @@ public class Log extends AbstractLog { diagnosticHandler.report(diagnostic); } + /** + * Reset the state of this instance. + */ + public void clear() { + recorded.clear(); + sourceMap.clear(); + nerrors = 0; + nwarnings = 0; + nsuppressederrors = 0; + nsuppressedwarns = 0; + while (diagnosticHandler.prev != null) + popDiagnosticHandler(diagnosticHandler); + } + /** * Common diagnostic handling. * The diagnostic is counted, and depending on the options and how many diagnostics have been From 63fa255c06a273b00f99d4e8649dab618cbf5773 Mon Sep 17 00:00:00 2001 From: Koushik Thirupattur Date: Tue, 8 Apr 2025 21:58:21 +0000 Subject: [PATCH 064/843] 8354061: Update copyright in NameFormat.java fix after JDK-8349890 Reviewed-by: mullan --- test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java b/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java index 3f0422ff933..6962465e9fc 100644 --- a/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java +++ b/test/jdk/javax/security/auth/x500/X500Principal/NameFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From b4ab964b72c631632511e6f01cdd5a47fb2e31fa Mon Sep 17 00:00:00 2001 From: William Kemper Date: Tue, 8 Apr 2025 22:00:58 +0000 Subject: [PATCH 065/843] 8353218: Shenandoah: Out of date comment references Brooks pointers Reviewed-by: ysr, kdnilsen --- src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 2bbb590f355..db7d62c9ba4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -122,9 +122,9 @@ typedef ShenandoahLock ShenandoahHeapLock; typedef ShenandoahLocker ShenandoahHeapLocker; typedef Stack ShenandoahScanObjectStack; -// Shenandoah GC is low-pause concurrent GC that uses Brooks forwarding pointers -// to encode forwarding data. See BrooksPointer for details on forwarding data encoding. -// See ShenandoahControlThread for GC cycle structure. +// Shenandoah GC is low-pause concurrent GC that uses a load reference barrier +// for concurent evacuation and a snapshot-at-the-beginning write barrier for +// concurrent marking. See ShenandoahControlThread for GC cycle structure. // class ShenandoahHeap : public CollectedHeap { friend class ShenandoahAsserts; From aec1fe0a17fa6801e26a517d4d21656353409f7c Mon Sep 17 00:00:00 2001 From: Xiaolong Peng Date: Wed, 9 Apr 2025 01:00:02 +0000 Subject: [PATCH 066/843] 8351091: Shenandoah: global marking context completeness is not accurately maintained Reviewed-by: ysr, wkemper --- .../shenandoahGenerationalHeuristics.cpp | 2 +- .../heuristics/shenandoahHeuristics.cpp | 4 +--- .../share/gc/shenandoah/shenandoahFreeSet.cpp | 2 +- .../share/gc/shenandoah/shenandoahFullGC.cpp | 16 +++++++-------- .../gc/shenandoah/shenandoahGeneration.cpp | 4 ---- .../gc/shenandoah/shenandoahGeneration.hpp | 2 +- .../shenandoahGenerationalEvacuationTask.cpp | 3 ++- .../shenandoahGenerationalFullGC.cpp | 4 ++-- .../share/gc/shenandoah/shenandoahHeap.cpp | 2 -- .../share/gc/shenandoah/shenandoahHeap.hpp | 2 +- .../gc/shenandoah/shenandoahHeap.inline.hpp | 5 ----- .../gc/shenandoah/shenandoahHeapRegion.cpp | 4 +--- .../shenandoah/shenandoahMarkingContext.cpp | 14 ++----------- .../shenandoah/shenandoahMarkingContext.hpp | 6 ------ .../shenandoahReferenceProcessor.cpp | 9 +++++---- .../share/gc/shenandoah/shenandoahUnload.cpp | 2 +- .../gc/shenandoah/shenandoahVerifier.cpp | 20 ++++++++++--------- 17 files changed, 37 insertions(+), 64 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index 0568d9b4fff..afc9abc496e 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -131,7 +131,7 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio // Reclaim humongous regions here, and count them as the immediate garbage #ifdef ASSERT bool reg_live = region->has_live(); - bool bm_live = heap->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); + bool bm_live = heap->active_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); assert(reg_live == bm_live, "Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu", BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words()); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp index 0f570078150..4c7ed07b2a0 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp @@ -96,8 +96,6 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec size_t free = 0; size_t free_regions = 0; - ShenandoahMarkingContext* const ctx = heap->complete_marking_context(); - for (size_t i = 0; i < num_regions; i++) { ShenandoahHeapRegion* region = heap->get_region(i); @@ -122,7 +120,7 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec // Reclaim humongous regions here, and count them as the immediate garbage #ifdef ASSERT bool reg_live = region->has_live(); - bool bm_live = ctx->is_marked(cast_to_oop(region->bottom())); + bool bm_live = heap->gc_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); assert(reg_live == bm_live, "Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu", BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 9fa4978dfe7..e87c771dec4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -1030,7 +1030,7 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah _heap->generation_for(r->affiliation())->increment_affiliated_region_count(); #ifdef ASSERT - ShenandoahMarkingContext* const ctx = _heap->complete_marking_context(); + ShenandoahMarkingContext* const ctx = _heap->marking_context(); assert(ctx->top_at_mark_start(r) == r->bottom(), "Newly established allocation region starts with TAMS equal to bottom"); assert(ctx->is_bitmap_range_within_region_clear(ctx->top_bitmap(r), r->end()), "Bitmap above top_bitmap() must be clear"); #endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index 621a7233606..9436f09cbe0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -348,8 +348,8 @@ public: void do_object(oop p) { assert(_from_region != nullptr, "must set before work"); - assert(_heap->complete_marking_context()->is_marked(p), "must be marked"); - assert(!_heap->complete_marking_context()->allocated_after_mark_start(p), "must be truly marked"); + assert(_heap->gc_generation()->complete_marking_context()->is_marked(p), "must be marked"); + assert(!_heap->gc_generation()->complete_marking_context()->allocated_after_mark_start(p), "must be truly marked"); size_t obj_size = p->size(); if (_compact_point + obj_size > _to_region->end()) { @@ -551,7 +551,7 @@ private: public: ShenandoahTrashImmediateGarbageClosure() : _heap(ShenandoahHeap::heap()), - _ctx(ShenandoahHeap::heap()->complete_marking_context()) {} + _ctx(ShenandoahHeap::heap()->global_generation()->complete_marking_context()) {} void heap_region_do(ShenandoahHeapRegion* r) override { if (r->is_humongous_start()) { @@ -775,7 +775,7 @@ private: public: ShenandoahAdjustPointersClosure() : _heap(ShenandoahHeap::heap()), - _ctx(ShenandoahHeap::heap()->complete_marking_context()) {} + _ctx(ShenandoahHeap::heap()->gc_generation()->complete_marking_context()) {} void do_oop(oop* p) { do_oop_work(p); } void do_oop(narrowOop* p) { do_oop_work(p); } @@ -793,7 +793,7 @@ public: _heap(ShenandoahHeap::heap()) { } void do_object(oop p) { - assert(_heap->complete_marking_context()->is_marked(p), "must be marked"); + assert(_heap->gc_generation()->complete_marking_context()->is_marked(p), "must be marked"); p->oop_iterate(&_cl); } }; @@ -877,7 +877,7 @@ public: _heap(ShenandoahHeap::heap()), _worker_id(worker_id) {} void do_object(oop p) { - assert(_heap->complete_marking_context()->is_marked(p), "must be marked"); + assert(_heap->gc_generation()->complete_marking_context()->is_marked(p), "must be marked"); size_t size = p->size(); if (FullGCForwarding::is_forwarded(p)) { HeapWord* compact_from = cast_from_oop(p); @@ -950,7 +950,7 @@ public: // NOTE: See blurb at ShenandoahMCResetCompleteBitmapTask on why we need to skip // pinned regions. if (!r->is_pinned()) { - _heap->complete_marking_context()->reset_top_at_mark_start(r); + _heap->gc_generation()->complete_marking_context()->reset_top_at_mark_start(r); } size_t live = r->used(); @@ -1091,7 +1091,7 @@ public: ShenandoahParallelWorkerSession worker_session(worker_id); ShenandoahHeapRegion* region = _regions.next(); ShenandoahHeap* heap = ShenandoahHeap::heap(); - ShenandoahMarkingContext* const ctx = heap->complete_marking_context(); + ShenandoahMarkingContext* const ctx = heap->gc_generation()->complete_marking_context(); while (region != nullptr) { if (heap->is_bitmap_slice_committed(region) && !region->is_pinned() && region->has_live()) { ctx->clear_bitmap(region); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index 48e30ed585f..ad91119ddad 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -775,10 +775,6 @@ bool ShenandoahGeneration::is_bitmap_clear() { return true; } -bool ShenandoahGeneration::is_mark_complete() { - return _is_marking_complete.is_set(); -} - void ShenandoahGeneration::set_mark_complete() { _is_marking_complete.set(); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index fddc71d153e..31c86985c6f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -201,7 +201,7 @@ private: bool is_bitmap_clear(); // We need to track the status of marking for different generations. - bool is_mark_complete(); + bool is_mark_complete() { return _is_marking_complete.is_set(); } virtual void set_mark_complete(); virtual void set_mark_incomplete(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp index 5672463799a..6a845afa4fd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp @@ -169,7 +169,8 @@ void ShenandoahGenerationalEvacuationTask::maybe_promote_region(ShenandoahHeapRe // We identify the entirety of the region as DIRTY to force the next remembered set scan to identify the "interesting pointers" // contained herein. void ShenandoahGenerationalEvacuationTask::promote_in_place(ShenandoahHeapRegion* region) { - ShenandoahMarkingContext* const marking_context = _heap->complete_marking_context(); + assert(!_heap->gc_generation()->is_old(), "Sanity check"); + ShenandoahMarkingContext* const marking_context = _heap->young_generation()->complete_marking_context(); HeapWord* const tams = marking_context->top_at_mark_start(region); { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index 98028b67c7b..3387ed9d7a8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -275,8 +275,8 @@ void ShenandoahPrepareForGenerationalCompactionObjectClosure::do_object(oop p) { assert(_from_region != nullptr, "must set before work"); assert((_from_region->bottom() <= cast_from_oop(p)) && (cast_from_oop(p) < _from_region->top()), "Object must reside in _from_region"); - assert(_heap->complete_marking_context()->is_marked(p), "must be marked"); - assert(!_heap->complete_marking_context()->allocated_after_mark_start(p), "must be truly marked"); + assert(_heap->global_generation()->complete_marking_context()->is_marked(p), "must be marked"); + assert(!_heap->global_generation()->complete_marking_context()->allocated_after_mark_start(p), "must be truly marked"); size_t obj_size = p->size(); uint from_region_age = _from_region->age(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index c055a3f9b5a..045f485090d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -424,8 +424,6 @@ jint ShenandoahHeap::initialize() { _affiliations[i] = ShenandoahAffiliation::FREE; } - // Initialize to complete - _marking_context->mark_complete(); size_t young_cset_regions, old_cset_regions; // We are initializing free set. We ignore cset region tallies. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index db7d62c9ba4..46f8a134051 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -742,7 +742,7 @@ private: ShenandoahLiveData** _liveness_cache; public: - inline ShenandoahMarkingContext* complete_marking_context() const; + // Return the marking context regardless of the completeness status. inline ShenandoahMarkingContext* marking_context() const; template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index 13c203d423c..f4ef186743c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -643,11 +643,6 @@ inline ShenandoahHeapRegion* ShenandoahHeap::get_region(size_t region_idx) const } } -inline ShenandoahMarkingContext* ShenandoahHeap::complete_marking_context() const { - assert (_marking_context->is_complete()," sanity"); - return _marking_context; -} - inline ShenandoahMarkingContext* ShenandoahHeap::marking_context() const { return _marking_context; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index 2c70cecf705..a25e2dfd88f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -855,8 +855,8 @@ void ShenandoahHeapRegion::set_affiliation(ShenandoahAffiliation new_affiliation ShenandoahHeap* heap = ShenandoahHeap::heap(); ShenandoahAffiliation region_affiliation = heap->region_affiliation(this); + ShenandoahMarkingContext* const ctx = heap->marking_context(); { - ShenandoahMarkingContext* const ctx = heap->complete_marking_context(); log_debug(gc)("Setting affiliation of Region %zu from %s to %s, top: " PTR_FORMAT ", TAMS: " PTR_FORMAT ", watermark: " PTR_FORMAT ", top_bitmap: " PTR_FORMAT, index(), shenandoah_affiliation_name(region_affiliation), shenandoah_affiliation_name(new_affiliation), @@ -865,8 +865,6 @@ void ShenandoahHeapRegion::set_affiliation(ShenandoahAffiliation new_affiliation #ifdef ASSERT { - // During full gc, heap->complete_marking_context() is not valid, may equal nullptr. - ShenandoahMarkingContext* const ctx = heap->complete_marking_context(); size_t idx = this->index(); HeapWord* top_bitmap = ctx->top_bitmap(this); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 4fa006e60fb..399db525cf9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -28,6 +28,8 @@ #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.hpp" +#include "shenandoahGlobalGeneration.hpp" + ShenandoahMarkingContext::ShenandoahMarkingContext(MemRegion heap_region, MemRegion bitmap_region, size_t num_regions) : _mark_bit_map(heap_region, bitmap_region), _top_bitmaps(NEW_C_HEAP_ARRAY(HeapWord*, num_regions, mtGC)), @@ -96,15 +98,3 @@ void ShenandoahMarkingContext::clear_bitmap(ShenandoahHeapRegion* r) { assert(is_bitmap_range_within_region_clear(bottom, r->end()), "Region %zu should have no marks in bitmap", r->index()); } - -bool ShenandoahMarkingContext::is_complete() { - return _is_complete.is_set(); -} - -void ShenandoahMarkingContext::mark_complete() { - _is_complete.set(); -} - -void ShenandoahMarkingContext::mark_incomplete() { - _is_complete.unset(); -} diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp index 854f42f2604..8a52042e513 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp @@ -47,8 +47,6 @@ private: HeapWord** const _top_at_mark_starts_base; HeapWord** const _top_at_mark_starts; - ShenandoahSharedFlag _is_complete; - public: ShenandoahMarkingContext(MemRegion heap_region, MemRegion bitmap_region, size_t num_regions); @@ -86,10 +84,6 @@ public: bool is_bitmap_clear() const; bool is_bitmap_range_within_region_clear(const HeapWord* start, const HeapWord* end) const; - - bool is_complete(); - void mark_complete(); - void mark_incomplete(); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHMARKINGCONTEXT_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index 04d38d97f61..0e10e8c819f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -328,12 +328,13 @@ bool ShenandoahReferenceProcessor::should_drop(oop reference, ReferenceType type return true; } + ShenandoahHeap* heap = ShenandoahHeap::heap(); // Check if the referent is still alive, in which case we should // drop the reference. if (type == REF_PHANTOM) { - return ShenandoahHeap::heap()->complete_marking_context()->is_marked(raw_referent); + return heap->active_generation()->complete_marking_context()->is_marked(raw_referent); } else { - return ShenandoahHeap::heap()->complete_marking_context()->is_marked_strong(raw_referent); + return heap->active_generation()->complete_marking_context()->is_marked_strong(raw_referent); } } @@ -345,7 +346,7 @@ void ShenandoahReferenceProcessor::make_inactive(oop reference, ReferenceType ty // next field. An application can't call FinalReference.enqueue(), so there is // no race to worry about when setting the next field. assert(reference_next(reference) == nullptr, "Already inactive"); - assert(ShenandoahHeap::heap()->marking_context()->is_marked(reference_referent_raw(reference)), "only make inactive final refs with alive referents"); + assert(ShenandoahHeap::heap()->active_generation()->complete_marking_context()->is_marked(reference_referent_raw(reference)), "only make inactive final refs with alive referents"); reference_set_next(reference, reference); } else { // Clear referent @@ -435,7 +436,7 @@ oop ShenandoahReferenceProcessor::drop(oop reference, ReferenceType type) { HeapWord* raw_referent = reference_referent_raw(reference); #ifdef ASSERT - assert(raw_referent == nullptr || ShenandoahHeap::heap()->marking_context()->is_marked(raw_referent), + assert(raw_referent == nullptr || ShenandoahHeap::heap()->active_generation()->complete_marking_context()->is_marked(raw_referent), "only drop references with alive referents"); #endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp index 24fb56b8037..6bd50154b4f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp @@ -50,7 +50,7 @@ private: public: ShenandoahIsUnloadingOopClosure() : - _marking_context(ShenandoahHeap::heap()->complete_marking_context()), + _marking_context(ShenandoahHeap::heap()->global_generation()->complete_marking_context()), _is_unloading(false) { } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 1d9895b700b..37951c311ed 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -268,12 +268,12 @@ private: "Must be marked in incomplete bitmap"); break; case ShenandoahVerifier::_verify_marked_complete: - check(ShenandoahAsserts::_safe_all, obj, _heap->complete_marking_context()->is_marked(obj), + check(ShenandoahAsserts::_safe_all, obj, _heap->gc_generation()->complete_marking_context()->is_marked(obj), "Must be marked in complete bitmap"); break; case ShenandoahVerifier::_verify_marked_complete_except_references: case ShenandoahVerifier::_verify_marked_complete_satb_empty: - check(ShenandoahAsserts::_safe_all, obj, _heap->complete_marking_context()->is_marked(obj), + check(ShenandoahAsserts::_safe_all, obj, _heap->gc_generation()->complete_marking_context()->is_marked(obj), "Must be marked in complete bitmap, except j.l.r.Reference referents"); break; default: @@ -701,7 +701,7 @@ public: virtual void work_humongous(ShenandoahHeapRegion *r, ShenandoahVerifierStack& stack, ShenandoahVerifyOopClosure& cl) { size_t processed = 0; HeapWord* obj = r->bottom(); - if (_heap->complete_marking_context()->is_marked(cast_to_oop(obj))) { + if (_heap->gc_generation()->complete_marking_context()->is_marked(cast_to_oop(obj))) { verify_and_follow(obj, stack, cl, &processed); } Atomic::add(&_processed, processed, memory_order_relaxed); @@ -709,7 +709,7 @@ public: virtual void work_regular(ShenandoahHeapRegion *r, ShenandoahVerifierStack &stack, ShenandoahVerifyOopClosure &cl) { size_t processed = 0; - ShenandoahMarkingContext* ctx = _heap->complete_marking_context(); + ShenandoahMarkingContext* ctx = _heap->gc_generation()->complete_marking_context(); HeapWord* tams = ctx->top_at_mark_start(r); // Bitmaps, before TAMS @@ -788,9 +788,11 @@ public: void ShenandoahVerifier::verify_at_safepoint(const char* label, VerifyRememberedSet remembered, - VerifyForwarded forwarded, VerifyMarked marked, + VerifyForwarded forwarded, + VerifyMarked marked, VerifyCollectionSet cset, - VerifyLiveness liveness, VerifyRegions regions, + VerifyLiveness liveness, + VerifyRegions regions, VerifySize sizeness, VerifyGCState gcstate) { guarantee(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "only when nothing else happens"); @@ -989,7 +991,7 @@ void ShenandoahVerifier::verify_at_safepoint(const char* label, (marked == _verify_marked_complete || marked == _verify_marked_complete_except_references || marked == _verify_marked_complete_satb_empty)) { - guarantee(_heap->marking_context()->is_complete(), "Marking context should be complete"); + guarantee(_heap->gc_generation()->is_mark_complete(), "Marking context should be complete"); ShenandoahVerifierMarkedRegionTask task(_verification_bit_map, ld, label, options); _heap->workers()->run_task(&task); count_marked = task.processed(); @@ -1186,7 +1188,7 @@ void ShenandoahVerifier::verify_after_fullgc() { "After Full GC", _verify_remembered_after_full_gc, // verify read-write remembered set _verify_forwarded_none, // all objects are non-forwarded - _verify_marked_complete, // all objects are marked in complete bitmap + _verify_marked_incomplete, // all objects are marked in incomplete bitmap _verify_cset_none, // no cset references _verify_liveness_disable, // no reliable liveness data anymore _verify_regions_notrash_nocset, // no trash, no cset @@ -1294,7 +1296,7 @@ void ShenandoahVerifier::help_verify_region_rem_set(Scanner* scanner, Shenandoah ShenandoahOldGeneration* old_gen = _heap->old_generation(); assert(old_gen->is_mark_complete() || old_gen->is_parsable(), "Sanity"); - ShenandoahMarkingContext* ctx = old_gen->is_mark_complete() ?old_gen->complete_marking_context() : nullptr; + ShenandoahMarkingContext* ctx = old_gen->is_mark_complete() ? old_gen->complete_marking_context() : nullptr; ShenandoahVerifyRemSetClosure check_interesting_pointers(scanner, message); HeapWord* from = r->bottom(); HeapWord* obj_addr = from; From c26c5758679b803489f401fbb23e8153ca10e19f Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 9 Apr 2025 01:15:40 +0000 Subject: [PATCH 067/843] 8353014: Exclude AOT tooling classes from AOT cache Reviewed-by: vlivanov, kvn --- src/hotspot/share/cds/aotArtifactFinder.cpp | 9 +- src/hotspot/share/cds/aotClassFilter.cpp | 55 ++++++++++++ src/hotspot/share/cds/aotClassFilter.hpp | 60 +++++++++++++ src/hotspot/share/cds/cdsConfig.cpp | 18 ++++ src/hotspot/share/cds/cdsConfig.hpp | 1 + src/hotspot/share/cds/dumpTimeClassInfo.hpp | 17 +++- src/hotspot/share/cds/dynamicArchive.cpp | 39 +++++---- src/hotspot/share/cds/dynamicArchive.hpp | 3 +- src/hotspot/share/cds/lambdaFormInvokers.cpp | 55 ++++++++---- .../share/cds/lambdaProxyClassDictionary.cpp | 5 ++ src/hotspot/share/cds/metaspaceShared.cpp | 86 +++++++++++-------- src/hotspot/share/cds/metaspaceShared.hpp | 3 +- .../classfile/systemDictionaryShared.cpp | 12 +-- .../classfile/systemDictionaryShared.hpp | 2 +- 14 files changed, 280 insertions(+), 85 deletions(-) create mode 100644 src/hotspot/share/cds/aotClassFilter.cpp create mode 100644 src/hotspot/share/cds/aotClassFilter.hpp diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp index e644a5e6f5f..6a7faee5133 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.cpp +++ b/src/hotspot/share/cds/aotArtifactFinder.cpp @@ -109,7 +109,10 @@ void AOTArtifactFinder::find_artifacts() { // Add all the InstanceKlasses (and their array classes) that are always included. SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* ik, DumpTimeClassInfo& info) { - if (!info.is_excluded()) { + // Skip "AOT tooling classes" in this block. They will be included in the AOT cache only if + // - One of their subtypes is included + // - One of their instances is found by HeapShared. + if (!info.is_excluded() && !info.is_aot_tooling_class()) { bool add = false; if (!ik->is_hidden()) { // All non-hidden classes are always included into the AOT cache @@ -149,10 +152,10 @@ void AOTArtifactFinder::find_artifacts() { SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* k, DumpTimeClassInfo& info) { if (!info.is_excluded() && _seen_classes->get(k) == nullptr) { info.set_excluded(); - assert(k->is_hidden(), "must be"); if (log_is_enabled(Info, cds)) { ResourceMark rm; - log_info(cds)("Skipping %s: Hidden class", k->name()->as_C_string()); + log_info(cds)("Skipping %s: %s class", k->name()->as_C_string(), + k->is_hidden() ? "Hidden" : "AOT tooling"); } } }); diff --git a/src/hotspot/share/cds/aotClassFilter.cpp b/src/hotspot/share/cds/aotClassFilter.cpp new file mode 100644 index 00000000000..959bea6a623 --- /dev/null +++ b/src/hotspot/share/cds/aotClassFilter.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "cds/aotClassFilter.hpp" +#include "runtime/javaThread.hpp" +#include "runtime/mutexLocker.hpp" + +AOTClassFilter::FilterMark* AOTClassFilter::_current_mark = nullptr; +Thread* AOTClassFilter::_filtering_thread = nullptr; + +AOTClassFilter::FilterMark::FilterMark() { + MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); + assert(_current_mark == nullptr &&_filtering_thread == nullptr, + "impl note: we support only a single AOTClassFilter used by a single thread"); + _current_mark = this; + _filtering_thread = Thread::current(); +} + +AOTClassFilter::FilterMark::~FilterMark() { + MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); + assert(_current_mark == this && _filtering_thread == Thread::current(), "sanity"); + _current_mark = nullptr; + _filtering_thread = nullptr; +} + +// Is called only from SystemDictionaryShared::init_dumptime_info(), which holds DumpTimeTable_lock +bool AOTClassFilter::is_aot_tooling_class(InstanceKlass* ik) { + assert_lock_strong(DumpTimeTable_lock); + if (_current_mark == nullptr || _filtering_thread != Thread::current()) { + return false; + } else { + return _current_mark->is_aot_tooling_class(ik); + } +} diff --git a/src/hotspot/share/cds/aotClassFilter.hpp b/src/hotspot/share/cds/aotClassFilter.hpp new file mode 100644 index 00000000000..b85b83c3a32 --- /dev/null +++ b/src/hotspot/share/cds/aotClassFilter.hpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_CDS_AOTCLASSFILTER_HPP +#define SHARE_CDS_AOTCLASSFILTER_HPP + +#include "memory/allStatic.hpp" +#include "utilities/debug.hpp" + +class InstanceKlass; +class Thread; + +// Used by SystemDictionaryShared/AOTArtifactFinder to filter out classes that +// shouldn't be included into the AOT cache -- for example, classes that are used only +// in the training/assembly phases for building contents in the AOT cache. +// +// The only use case today is in lambdaFormInvokers.cpp. +class AOTClassFilter : AllStatic { +public: + + // Filters should be defined using RAII pattern + class FilterMark { + public: + FilterMark(); + ~FilterMark(); + virtual bool is_aot_tooling_class(InstanceKlass* ik) = 0; + }; + + // Called when ik is being loaded. Return true iff this class is loaded + // only because it's used by the AOT tooling code. + static bool is_aot_tooling_class(InstanceKlass* ik); + +private: + // For the time being, we allow at most one filter. + static FilterMark* _current_mark; + static Thread* _filtering_thread; +}; + +#endif // SHARE_CDS_AOTCLASSFILTER_HPP diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 055b84ed284..47613e09008 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -573,6 +573,24 @@ bool CDSConfig::is_logging_lambda_form_invokers() { return ClassListWriter::is_enabled() || is_dumping_dynamic_archive(); } +bool CDSConfig::is_dumping_regenerated_lambdaform_invokers() { + if (is_dumping_final_static_archive()) { + // No need to regenerate -- the lambda form invokers should have been regenerated + // in the preimage archive (if allowed) + return false; + } else if (is_dumping_dynamic_archive() && is_using_aot_linked_classes()) { + // The base archive has aot-linked classes that may have AOT-resolved CP references + // that point to the lambda form invokers in the base archive. Such pointers will + // be invalid if lambda form invokers are regenerated in the dynamic archive. + return false; + } else if (CDSConfig::is_dumping_method_handles()) { + // Work around JDK-8310831, as some methods in lambda form holder classes may not get generated. + return false; + } else { + return is_dumping_archive(); + } +} + void CDSConfig::stop_using_optimized_module_handling() { _is_using_optimized_module_handling = false; _is_dumping_full_module_graph = false; // This requires is_using_optimized_module_handling() diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index 8a3a060e3c3..f02258eb6fe 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -139,6 +139,7 @@ public: static void stop_using_optimized_module_handling() NOT_CDS_RETURN; static bool is_logging_lambda_form_invokers() NOT_CDS_RETURN_(false); + static bool is_dumping_regenerated_lambdaform_invokers() NOT_CDS_RETURN_(false); static bool is_dumping_aot_linked_classes() NOT_CDS_JAVA_HEAP_RETURN_(false); static bool is_using_aot_linked_classes() NOT_CDS_JAVA_HEAP_RETURN_(false); diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.hpp index 79ede224bb6..0bb60dfbb29 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.hpp @@ -39,9 +39,11 @@ class Method; class Symbol; class DumpTimeClassInfo: public CHeapObj { - bool _excluded; - bool _is_early_klass; - bool _has_checked_exclusion; + bool _excluded; + bool _is_aot_tooling_class; + bool _is_early_klass; + bool _has_checked_exclusion; + class DTLoaderConstraint { Symbol* _name; char _loader_type1; @@ -140,6 +142,7 @@ public: _clsfile_size = -1; _clsfile_crc32 = -1; _excluded = false; + _is_aot_tooling_class = false; _is_early_klass = JvmtiExport::is_early_phase(); _verifier_constraints = nullptr; _verifier_constraint_flags = nullptr; @@ -199,6 +202,14 @@ public: return _excluded || _failed_verification; } + bool is_aot_tooling_class() { + return _is_aot_tooling_class; + } + + void set_is_aot_tooling_class() { + _is_aot_tooling_class = true; + } + // Was this class loaded while JvmtiExport::is_early_phase()==true bool is_early_klass() { return _is_early_klass; diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index 3cf1019d9ea..c3a6db9e9b9 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -32,6 +32,8 @@ #include "cds/cdsConfig.hpp" #include "cds/dynamicArchive.hpp" #include "cds/lambdaProxyClassDictionary.hpp" +#include "cds/lambdaFormInvokers.hpp" +#include "cds/metaspaceShared.hpp" #include "cds/regeneratedClasses.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" @@ -495,6 +497,16 @@ void DynamicArchive::check_for_dynamic_dump() { } } +void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAPS) { + MetaspaceShared::link_shared_classes(CHECK); + if (!jcmd_request && CDSConfig::is_dumping_regenerated_lambdaform_invokers()) { + LambdaFormInvokers::regenerate_holder_classes(CHECK); + } + + VM_PopulateDynamicDumpSharedSpace op(archive_name); + VMThread::execute(&op); +} + void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) { ExceptionMark em(current); ResourceMark rm(current); @@ -507,20 +519,16 @@ void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) log_info(cds, dynamic)("Preparing for dynamic dump at exit in thread %s", current->name()); JavaThread* THREAD = current; // For TRAPS processing related to link_shared_classes - MetaspaceShared::link_shared_classes(false/*not from jcmd*/, THREAD); - if (!HAS_PENDING_EXCEPTION) { - VM_PopulateDynamicDumpSharedSpace op(archive_name); - VMThread::execute(&op); - return; + dump_impl(/*jcmd_request=*/false, archive_name, THREAD); + if (HAS_PENDING_EXCEPTION) { + // One of the prepatory steps failed + oop ex = current->pending_exception(); + log_error(cds)("Dynamic dump has failed"); + log_error(cds)("%s: %s", ex->klass()->external_name(), + java_lang_String::as_utf8_string(java_lang_Throwable::message(ex))); + CLEAR_PENDING_EXCEPTION; + CDSConfig::disable_dumping_dynamic_archive(); // Just for good measure } - - // One of the prepatory steps failed - oop ex = current->pending_exception(); - log_error(cds)("Dynamic dump has failed"); - log_error(cds)("%s: %s", ex->klass()->external_name(), - java_lang_String::as_utf8_string(java_lang_Throwable::message(ex))); - CLEAR_PENDING_EXCEPTION; - CDSConfig::disable_dumping_dynamic_archive(); // Just for good measure } // This is called by "jcmd VM.cds dynamic_dump" @@ -529,10 +537,7 @@ void DynamicArchive::dump_for_jcmd(const char* archive_name, TRAPS) { assert(CDSConfig::is_using_archive() && RecordDynamicDumpInfo, "already checked in arguments.cpp"); assert(ArchiveClassesAtExit == nullptr, "already checked in arguments.cpp"); assert(CDSConfig::is_dumping_dynamic_archive(), "already checked by check_for_dynamic_dump() during VM startup"); - MetaspaceShared::link_shared_classes(true/*from jcmd*/, CHECK); - // copy shared path table to saved. - VM_PopulateDynamicDumpSharedSpace op(archive_name); - VMThread::execute(&op); + dump_impl(/*jcmd_request=*/true, archive_name, CHECK); } bool DynamicArchive::validate(FileMapInfo* dynamic_info) { diff --git a/src/hotspot/share/cds/dynamicArchive.hpp b/src/hotspot/share/cds/dynamicArchive.hpp index eb5fd5f9aba..905c511c4e0 100644 --- a/src/hotspot/share/cds/dynamicArchive.hpp +++ b/src/hotspot/share/cds/dynamicArchive.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,6 +66,7 @@ public: static void check_for_dynamic_dump(); static void dump_for_jcmd(const char* archive_name, TRAPS); static void dump_at_exit(JavaThread* current, const char* archive_name); + static void dump_impl(bool jcmd_request, const char* archive_name, TRAPS); static bool is_mapped() { return FileMapInfo::dynamic_info() != nullptr; } static bool validate(FileMapInfo* dynamic_info); static void dump_array_klasses(); diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index ab22b4775b7..7832de8c6cc 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -22,8 +22,10 @@ * */ +#include "cds/aotClassFilter.hpp" #include "cds/archiveBuilder.hpp" -#include "cds/lambdaFormInvokers.hpp" +#include "cds/cdsConfig.hpp" +#include "cds/lambdaFormInvokers.inline.hpp" #include "cds/metaspaceShared.hpp" #include "cds/regeneratedClasses.hpp" #include "classfile/classFileStream.hpp" @@ -88,30 +90,39 @@ class PrintLambdaFormMessage { } }; +class LambdaFormInvokersClassFilterMark : public AOTClassFilter::FilterMark { +public: + bool is_aot_tooling_class(InstanceKlass* ik) { + if (ik->name()->index_of_at(0, "$Species_", 9) > 0) { + // Classes like java.lang.invoke.BoundMethodHandle$Species_L should be included in AOT cache + return false; + } + if (LambdaFormInvokers::may_be_regenerated_class(ik->name())) { + // Regenerated holder classes should be included in AOT cache. + return false; + } + // Treat all other classes loaded during LambdaFormInvokers::regenerate_holder_classes() as + // "AOT tooling classes". + return true; + } +}; + void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { + if (!CDSConfig::is_dumping_regenerated_lambdaform_invokers()) { + return; + } + PrintLambdaFormMessage plm; if (_lambdaform_lines == nullptr || _lambdaform_lines->length() == 0) { log_info(cds)("Nothing to regenerate for holder classes"); return; } - if (CDSConfig::is_dumping_static_archive() && CDSConfig::is_dumping_method_handles()) { - // Work around JDK-8310831, as some methods in lambda form holder classes may not get generated. - log_info(cds)("Archived MethodHandles may refer to lambda form holder classes. Cannot regenerate."); - return; - } - - if (CDSConfig::is_dumping_dynamic_archive() && CDSConfig::is_dumping_aot_linked_classes() && - CDSConfig::is_using_aot_linked_classes()) { - // The base archive may have some pre-resolved CP entries that point to the lambda form holder - // classes in the base archive. If we generate new versions of these classes, those CP entries - // will be pointing to invalid classes. - log_info(cds)("Base archive already has aot-linked lambda form holder classes. Cannot regenerate."); - return; - } - ResourceMark rm(THREAD); + // Filter out AOT tooling classes like java.lang.invoke.GenerateJLIClassesHelper, etc. + LambdaFormInvokersClassFilterMark filter_mark; + Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS(); Klass* cds_klass = SystemDictionary::resolve_or_null(cds_name, THREAD); guarantee(cds_klass != nullptr, "jdk/internal/misc/CDS must exist!"); @@ -245,7 +256,7 @@ void LambdaFormInvokers::dump_static_archive_invokers() { } assert(index == count, "Should match"); } - log_debug(cds)("Total LF lines stored into static archive: %d", count); + log_debug(cds)("Total LF lines stored into %s: %d", CDSConfig::type_of_archive_being_written(), count); } } @@ -257,14 +268,20 @@ void LambdaFormInvokers::read_static_archive_invokers() { char* str = line->adr_at(0); append(str); } - log_debug(cds)("Total LF lines read from static archive: %d", _static_archive_invokers->length()); + log_debug(cds)("Total LF lines read from %s: %d", CDSConfig::type_of_archive_being_loaded(), _static_archive_invokers->length()); } } void LambdaFormInvokers::serialize(SerializeClosure* soc) { soc->do_ptr(&_static_archive_invokers); if (soc->reading() && CDSConfig::is_dumping_final_static_archive()) { - LambdaFormInvokers::read_static_archive_invokers(); + if (!CDSConfig::is_dumping_aot_linked_classes()) { + // See CDSConfig::is_dumping_regenerated_lambdaform_invokers() -- a dynamic archive can + // regenerate lambda form invokers only if the base archive does not contain aot-linked classes. + // If so, we copy the contents of _static_archive_invokers (from the preimage) into + //_lambdaform_lines, which will be written as _static_archive_invokers into final static archive. + LambdaFormInvokers::read_static_archive_invokers(); + } _static_archive_invokers = nullptr; } } diff --git a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp index c0e31eea399..6b2e432d559 100644 --- a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp +++ b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp @@ -22,6 +22,7 @@ * */ +#include "cds/aotClassFilter.hpp" #include "cds/archiveBuilder.hpp" #include "cds/cdsConfig.hpp" #include "cds/cdsProtectionDomain.hpp" @@ -390,6 +391,10 @@ void LambdaProxyClassDictionary::add_to_dumptime_table(LambdaProxyClassKey& key, InstanceKlass* proxy_klass) { assert_lock_strong(DumpTimeTable_lock); + if (AOTClassFilter::is_aot_tooling_class(proxy_klass)) { + return; + } + bool created; DumpTimeLambdaProxyClassInfo* info = _dumptime_table->put_if_absent(key, &created); info->add_proxy_klass(proxy_klass); diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 277c6ce90e7..85916ced3cf 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -97,6 +97,8 @@ #include "utilities/ostream.hpp" #include "utilities/resourceHash.hpp" +#include + ReservedSpace MetaspaceShared::_symbol_rs; VirtualSpace MetaspaceShared::_symbol_vs; bool MetaspaceShared::_archive_loading_failed = false; @@ -696,6 +698,16 @@ class CollectClassesForLinking : public KlassClosure { GrowableArray _mirrors; public: + CollectClassesForLinking() : _mirrors() { + // ClassLoaderDataGraph::loaded_classes_do_keepalive() requires ClassLoaderDataGraph_lock. + // We cannot link the classes while holding this lock (or else we may run into deadlock). + // Therefore, we need to first collect all the classes, keeping them alive by + // holding onto their java_mirrors in global OopHandles. We then link the classes after + // releasing the lock. + MutexLocker lock(ClassLoaderDataGraph_lock); + ClassLoaderDataGraph::loaded_classes_do_keepalive(this); + } + ~CollectClassesForLinking() { for (int i = 0; i < _mirrors.length(); i++) { _mirrors.at(i).release(Universe::vm_global()); @@ -736,43 +748,20 @@ bool MetaspaceShared::may_be_eagerly_linked(InstanceKlass* ik) { return true; } -bool MetaspaceShared::link_class_for_cds(InstanceKlass* ik, TRAPS) { - // Link the class to cause the bytecodes to be rewritten and the - // cpcache to be created. Class verification is done according - // to -Xverify setting. - bool res = MetaspaceShared::try_link_class(THREAD, ik); - AOTConstantPoolResolver::dumptime_resolve_constants(ik, CHECK_(false)); - return res; -} - -void MetaspaceShared::link_shared_classes(bool jcmd_request, TRAPS) { +void MetaspaceShared::link_shared_classes(TRAPS) { AOTClassLinker::initialize(); AOTClassInitializer::init_test_class(CHECK); - if (!jcmd_request && !CDSConfig::is_dumping_final_static_archive()) { - LambdaFormInvokers::regenerate_holder_classes(CHECK); - } - - while (true) { + ResourceMark rm(THREAD); CollectClassesForLinking collect_classes; - { - // ClassLoaderDataGraph::loaded_classes_do_keepalive() requires ClassLoaderDataGraph_lock. - // We cannot link the classes while holding this lock (or else we may run into deadlock). - // Therefore, we need to first collect all the classes, keeping them alive by - // holding onto their java_mirrors in global OopHandles. We then link the classes after - // releasing the lock. - MutexLocker lock(ClassLoaderDataGraph_lock); - ClassLoaderDataGraph::loaded_classes_do_keepalive(&collect_classes); - } - bool has_linked = false; const GrowableArray* mirrors = collect_classes.mirrors(); for (int i = 0; i < mirrors->length(); i++) { OopHandle mirror = mirrors->at(i); InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve())); if (may_be_eagerly_linked(ik)) { - has_linked |= link_class_for_cds(ik, CHECK); + has_linked |= try_link_class(THREAD, ik); } } @@ -783,6 +772,18 @@ void MetaspaceShared::link_shared_classes(bool jcmd_request, TRAPS) { // Keep scanning until we have linked no more classes. } + // Resolve constant pool entries -- we don't load any new classes during this stage + { + ResourceMark rm(THREAD); + CollectClassesForLinking collect_classes; + const GrowableArray* mirrors = collect_classes.mirrors(); + for (int i = 0; i < mirrors->length(); i++) { + OopHandle mirror = mirrors->at(i); + InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve())); + AOTConstantPoolResolver::dumptime_resolve_constants(ik, CHECK); + } + } + if (CDSConfig::is_dumping_final_static_archive()) { FinalImageRecipes::apply_recipes(CHECK); } @@ -823,8 +824,14 @@ void MetaspaceShared::preload_and_dump(TRAPS) { // When the new -XX:AOTMode=create flag is used, we can't return // to the JLI launcher, as the launcher will fail when trying to // run the main class, which is not what we want. - tty->print_cr("AOTCache creation is complete: %s", AOTCache); - vm_exit(0); + struct stat st; + if (os::stat(AOTCache, &st) != 0) { + tty->print_cr("AOTCache creation failed: %s", AOTCache); + vm_exit(0); + } else { + tty->print_cr("AOTCache creation is complete: %s " INT64_FORMAT " bytes", AOTCache, (int64_t)(st.st_size)); + vm_exit(0); + } } } } @@ -926,6 +933,18 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS } } +#if INCLUDE_CDS_JAVA_HEAP + if (CDSConfig::is_dumping_heap()) { + assert(CDSConfig::allow_only_single_java_thread(), "Required"); + if (!HeapShared::is_archived_boot_layer_available(THREAD)) { + log_info(cds)("archivedBootLayer not available, disabling full module graph"); + CDSConfig::stop_dumping_full_module_graph(); + } + // Do this before link_shared_classes(), as the following line may load new classes. + HeapShared::init_for_dumping(CHECK); + } +#endif + if (CDSConfig::is_dumping_final_static_archive()) { if (ExtraSharedClassListFile) { log_info(cds)("Loading extra classes from %s ...", ExtraSharedClassListFile); @@ -941,16 +960,15 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS // were not explicitly specified in the classlist. E.g., if an interface implemented by class K // fails verification, all other interfaces that were not specified in the classlist but // are implemented by K are not verified. - link_shared_classes(false/*not from jcmd*/, CHECK); + link_shared_classes(CHECK); log_info(cds)("Rewriting and linking classes: done"); + if (CDSConfig::is_dumping_regenerated_lambdaform_invokers()) { + LambdaFormInvokers::regenerate_holder_classes(CHECK); + } + #if INCLUDE_CDS_JAVA_HEAP if (CDSConfig::is_dumping_heap()) { - if (!HeapShared::is_archived_boot_layer_available(THREAD)) { - log_info(cds)("archivedBootLayer not available, disabling full module graph"); - CDSConfig::stop_dumping_full_module_graph(); - } - HeapShared::init_for_dumping(CHECK); ArchiveHeapWriter::init(); if (CDSConfig::is_dumping_full_module_graph()) { ClassLoaderDataShared::ensure_module_entry_tables_exist(); diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index 27df816833c..8881dc6d6fd 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -131,8 +131,7 @@ public: } static bool try_link_class(JavaThread* current, InstanceKlass* ik); - static void link_shared_classes(bool jcmd_request, TRAPS) NOT_CDS_RETURN; - static bool link_class_for_cds(InstanceKlass* ik, TRAPS) NOT_CDS_RETURN_(false); + static void link_shared_classes(TRAPS) NOT_CDS_RETURN; static bool may_be_eagerly_linked(InstanceKlass* ik) NOT_CDS_RETURN_(false); #if INCLUDE_CDS diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index c4e061b8fa9..2fbee502b93 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -22,6 +22,7 @@ * */ +#include "cds/aotClassFilter.hpp" #include "cds/aotClassLocation.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveUtils.hpp" @@ -34,6 +35,7 @@ #include "cds/filemap.hpp" #include "cds/heapShared.hpp" #include "cds/lambdaProxyClassDictionary.hpp" +#include "cds/lambdaFormInvokers.inline.hpp" #include "cds/metaspaceShared.hpp" #include "cds/runTimeClassInfo.hpp" #include "cds/unregisteredClasses.hpp" @@ -484,7 +486,10 @@ void SystemDictionaryShared::initialize() { void SystemDictionaryShared::init_dumptime_info(InstanceKlass* k) { MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); assert(SystemDictionaryShared::class_loading_may_happen(), "sanity"); - _dumptime_table->allocate_info(k); + DumpTimeClassInfo* info = _dumptime_table->allocate_info(k); + if (AOTClassFilter::is_aot_tooling_class(k)) { + info->set_is_aot_tooling_class(); + } } void SystemDictionaryShared::remove_dumptime_info(InstanceKlass* k) { @@ -1056,10 +1061,7 @@ SystemDictionaryShared::find_record(RunTimeSharedDictionary* static_dict, RunTim if (DynamicArchive::is_mapped()) { // Use the regenerated holder classes in the dynamic archive as they // have more methods than those in the base archive. - if (name == vmSymbols::java_lang_invoke_Invokers_Holder() || - name == vmSymbols::java_lang_invoke_DirectMethodHandle_Holder() || - name == vmSymbols::java_lang_invoke_LambdaForm_Holder() || - name == vmSymbols::java_lang_invoke_DelegatingMethodHandle_Holder()) { + if (LambdaFormInvokers::may_be_regenerated_class(name)) { record = dynamic_dict->lookup(name, hash, 0); if (record != nullptr) { return record; diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index 671eb69b8c6..e910bfb5d47 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -244,7 +244,7 @@ public: static bool check_linking_constraints(Thread* current, InstanceKlass* klass) NOT_CDS_RETURN_(false); static void record_linking_constraint(Symbol* name, InstanceKlass* klass, Handle loader1, Handle loader2) NOT_CDS_RETURN; - static bool is_builtin(InstanceKlass* k) { + static bool is_builtin(const InstanceKlass* k) { return (k->shared_classpath_index() != UNREGISTERED_INDEX); } static bool add_unregistered_class(Thread* current, InstanceKlass* k); From 73bb647218ac4c9742cb974d23c5f223bbd56c0a Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Wed, 9 Apr 2025 01:44:46 +0000 Subject: [PATCH 068/843] 8353829: RISC-V: Auto-enable several more extensions for debug builds Reviewed-by: rehn, fjiang --- src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index 8572d54716b..06d6aaf109f 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -223,6 +223,16 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFA)) { VM_Version::ext_Zfa.enable_feature(); } +#endif +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZTSO)) { + VM_Version::ext_Ztso.enable_feature(); + } +#endif +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZACAS)) { + VM_Version::ext_Zacas.enable_feature(); + } #endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) { VM_Version::ext_Zicond.enable_feature(); From 2a0cf8353ae0528a8417407d5719df0dadceadcf Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 9 Apr 2025 03:03:14 +0000 Subject: [PATCH 069/843] 8354088: [BACKOUT] Run jtreg in the work dir Reviewed-by: darcy, iris --- make/RunTests.gmk | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index ebae510fc07..7aa0082e0ae 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -995,27 +995,24 @@ define SetupRunJtregTestBody $$(RM) -r $$($1_TEST_SUPPORT_DIR) $$(RM) -r $$($1_TEST_RESULTS_DIR) - $1_JTREG_ARGUMENTS := \ - $$($1_JTREG_LAUNCHER_OPTIONS) \ - -Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \ - $$($1_JTREG_BASIC_OPTIONS) \ - -testjdk:$$(JDK_UNDER_TEST) \ - -dir:$$(JTREG_TOPDIR) \ - -reportDir:$$($1_TEST_RESULTS_DIR) \ - -workDir:$$($1_TEST_SUPPORT_DIR) \ - -report:$${JTREG_REPORT} \ - $$$${JTREG_STATUS} \ - $$(JTREG_OPTIONS) \ - $$(JTREG_FAILURE_HANDLER_OPTIONS) \ - $$(JTREG_COV_OPTIONS) \ - $$($1_TEST_NAME) \ - # - $1_COMMAND_LINE := \ - cd $$($1_TEST_SUPPORT_DIR) && $$(JTREG_JAVA) $$($1_JTREG_ARGUMENTS) \ + $$(JTREG_JAVA) $$($1_JTREG_LAUNCHER_OPTIONS) \ + -Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \ + $$($1_JTREG_BASIC_OPTIONS) \ + -testjdk:$$(JDK_UNDER_TEST) \ + -dir:$$(JTREG_TOPDIR) \ + -reportDir:$$($1_TEST_RESULTS_DIR) \ + -workDir:$$($1_TEST_SUPPORT_DIR) \ + -report:$${JTREG_REPORT} \ + $$$${JTREG_STATUS} \ + $$(JTREG_OPTIONS) \ + $$(JTREG_FAILURE_HANDLER_OPTIONS) \ + $$(JTREG_COV_OPTIONS) \ + $$($1_TEST_NAME) \ && $$(ECHO) $$$$? > $$($1_EXITCODE) \ || $$(ECHO) $$$$? > $$($1_EXITCODE) + ifneq ($$(JTREG_RETRY_COUNT), 0) $1_COMMAND_LINE := \ for i in {0..$$(JTREG_RETRY_COUNT)}; do \ From 743d1c64c29118b15897b3c676919353ced467f5 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 9 Apr 2025 05:08:51 +0000 Subject: [PATCH 070/843] 8353273: Reduce number of oop map entries in instances Reviewed-by: lmesnik, fparain, jsjolen --- .../share/classfile/fieldLayoutBuilder.cpp | 46 +++- .../share/classfile/fieldLayoutBuilder.hpp | 7 +- src/hotspot/share/oops/instanceKlass.cpp | 2 +- .../FieldLayout/TestOopMapSizeMinimal.java | 257 ++++++++++++++++++ 4 files changed, 297 insertions(+), 15 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp index 1af9bb83361..b6007923907 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp @@ -126,17 +126,19 @@ void FieldLayout::initialize_static_layout() { } } -void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass) { +void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass, bool& super_ends_with_oop) { if (super_klass == nullptr) { + super_ends_with_oop = false; _blocks = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX); _blocks->set_offset(0); _last = _blocks; _start = _blocks; insert(first_empty_block(), new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes())); } else { - bool has_fields = reconstruct_layout(super_klass); + bool super_has_instance_fields = false; + reconstruct_layout(super_klass, super_has_instance_fields, super_ends_with_oop); fill_holes(super_klass); - if (!super_klass->has_contended_annotations() || !has_fields) { + if (!super_klass->has_contended_annotations() || !super_has_instance_fields) { _start = _blocks; // start allocating fields from the first empty block } else { _start = _last; // append fields at the end of the reconstructed layout @@ -293,15 +295,21 @@ LayoutRawBlock* FieldLayout::insert_field_block(LayoutRawBlock* slot, LayoutRawB return block; } -bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) { - bool has_instance_fields = false; +void FieldLayout::reconstruct_layout(const InstanceKlass* ik, bool& has_instance_fields, bool& ends_with_oop) { + has_instance_fields = ends_with_oop = false; GrowableArray* all_fields = new GrowableArray(32); + BasicType last_type; + int last_offset = -1; while (ik != nullptr) { for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) { BasicType type = Signature::basic_type(fs.signature()); // distinction between static and non-static fields is missing if (fs.access_flags().is_static()) continue; has_instance_fields = true; + if (fs.offset() > last_offset) { + last_offset = fs.offset(); + last_type = type; + } int size = type2aelembytes(type); // INHERITED blocks are marked as non-reference because oop_maps are handled by their holder class LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::INHERITED, size, size, false); @@ -310,6 +318,11 @@ bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) { } ik = ik->super() == nullptr ? nullptr : InstanceKlass::cast(ik->super()); } + assert(last_offset == -1 || last_offset > 0, "Sanity"); + if (last_offset > 0 && + (last_type == BasicType::T_ARRAY || last_type == BasicType::T_OBJECT)) { + ends_with_oop = true; + } all_fields->sort(LayoutRawBlock::compare_offset); _blocks = new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes()); @@ -323,7 +336,6 @@ bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) { _last = b; } _start = _blocks; - return has_instance_fields; } // Called during the reconstruction of a layout, after fields from super @@ -516,7 +528,7 @@ FieldGroup* FieldLayoutBuilder::get_or_create_contended_group(int g) { void FieldLayoutBuilder::prologue() { _layout = new FieldLayout(_field_info, _constant_pool); const InstanceKlass* super_klass = _super_klass; - _layout->initialize_instance_layout(super_klass); + _layout->initialize_instance_layout(super_klass, _super_ends_with_oop); if (super_klass != nullptr) { _has_nonstatic_fields = super_klass->has_nonstatic_fields(); } @@ -594,8 +606,14 @@ void FieldLayoutBuilder::insert_contended_padding(LayoutRawBlock* slot) { // Computation of regular classes layout is an evolution of the previous default layout // (FieldAllocationStyle 1): // - primitive fields are allocated first (from the biggest to the smallest) -// - then oop fields are allocated, either in existing gaps or at the end of -// the layout +// - oop fields are allocated, either in existing gaps or at the end of +// the layout. We allocate oops in a single block to have a single oop map entry. +// - if the super class ended with an oop, we lead with oops. That will cause the +// trailing oop map entry of the super class and the oop map entry of this class +// to be folded into a single entry later. Correspondingly, if the super class +// ends with a primitive field, we gain nothing by leading with oops; therefore +// we let oop fields trail, thus giving future derived classes the chance to apply +// the same trick. void FieldLayoutBuilder::compute_regular_layout() { bool need_tail_padding = false; prologue(); @@ -608,8 +626,14 @@ void FieldLayoutBuilder::compute_regular_layout() { insert_contended_padding(_layout->start()); need_tail_padding = true; } - _layout->add(_root_group->primitive_fields()); - _layout->add(_root_group->oop_fields()); + + if (_super_ends_with_oop) { + _layout->add(_root_group->oop_fields()); + _layout->add(_root_group->primitive_fields()); + } else { + _layout->add(_root_group->primitive_fields()); + _layout->add(_root_group->oop_fields()); + } if (!_contended_groups.is_empty()) { for (int i = 0; i < _contended_groups.length(); i++) { diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp index 9b0d80b2a55..82bbaefc623 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.hpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,7 @@ class FieldLayout : public ResourceObj { public: FieldLayout(GrowableArray* field_info, ConstantPool* cp); void initialize_static_layout(); - void initialize_instance_layout(const InstanceKlass* ik); + void initialize_instance_layout(const InstanceKlass* ik, bool& super_ends_with_oop); LayoutRawBlock* first_empty_block() { LayoutRawBlock* block = _start; @@ -188,7 +188,7 @@ class FieldLayout : public ResourceObj { void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = nullptr); void add_contiguously(GrowableArray* list, LayoutRawBlock* start = nullptr); LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block); - bool reconstruct_layout(const InstanceKlass* ik); + void reconstruct_layout(const InstanceKlass* ik, bool& has_instance_fields, bool& ends_with_oop); void fill_holes(const InstanceKlass* ik); LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block); void remove(LayoutRawBlock* block); @@ -237,6 +237,7 @@ class FieldLayoutBuilder : public ResourceObj { int _alignment; bool _has_nonstatic_fields; bool _is_contended; // is a contended class? + bool _super_ends_with_oop; public: FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool, diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index a5afcb68299..31a74dd6423 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3763,7 +3763,7 @@ void InstanceKlass::print_on(outputStream* st) const { InstanceKlass* ik = const_cast(this); ik->print_nonstatic_fields(&print_nonstatic_field); - st->print(BULLET"non-static oop maps: "); + st->print(BULLET"non-static oop maps (%d entries): ", nonstatic_oop_map_count()); OopMapBlock* map = start_of_nonstatic_oop_maps(); OopMapBlock* end_map = map + nonstatic_oop_map_count(); while (map < end_map) { diff --git a/test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java b/test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java new file mode 100644 index 00000000000..861f1aa3d1b --- /dev/null +++ b/test/hotspot/jtreg/runtime/FieldLayout/TestOopMapSizeMinimal.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.internal.misc.Unsafe; +import jdk.test.whitebox.WhiteBox; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/* + * @test id=no_coops_no_ccptr_no_coh + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal + */ + +/* + * @test id=coops_no_ccptr_no_coh + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal + */ + +/* + * @test id=no_coops_ccptr_no_coh + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal + */ + +/* + * @test id=coops_ccptr_no_coh + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders TestOopMapSizeMinimal + */ + +/* + * @test id=no_coops_ccptr_coh + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompactObjectHeaders TestOopMapSizeMinimal + */ + +public class TestOopMapSizeMinimal { + + public static int OOP_SIZE_IN_BYTES = -1; + public static int HEADER_SIZE_IN_BYTES = -1; + + static { + WhiteBox WB = WhiteBox.getWhiteBox(); + boolean is_64_bit = System.getProperty("sun.arch.data.model").equals("64"); + if (is_64_bit) { + if (System.getProperty("java.vm.compressedOopsMode") == null) { + OOP_SIZE_IN_BYTES = 8; + } else { + OOP_SIZE_IN_BYTES = 4; + } + } else { + OOP_SIZE_IN_BYTES = 4; + } + if (is_64_bit) { + if (WB.getBooleanVMFlag("UseCompactObjectHeaders")) { + HEADER_SIZE_IN_BYTES = 8; + } else if (WB.getBooleanVMFlag("UseCompressedClassPointers")) { + HEADER_SIZE_IN_BYTES = 12; + } else { + HEADER_SIZE_IN_BYTES = 16; + } + } else { + HEADER_SIZE_IN_BYTES = 8; + } + } + + public static long alignUp(long value, long alignment) { + return (value + alignment - 1) & ~(alignment - 1); + } + + public static long alignForOop(long position) { + return alignUp(position, OOP_SIZE_IN_BYTES); + } + + private static final Unsafe U = Unsafe.getUnsafe(); + + public static class BASE { + int i1; + Object o1; + } + + public static class DERIVED1 extends BASE { + int i2; + Object o2; + } + + public static class DERIVED2 extends DERIVED1 { + int i3; + Object o3; + } + + public static class DERIVED3 extends DERIVED2 { + int i4; + Object o4; + } + + static boolean mismatch = false; + + private static void checkOffset(Field f, long expectedOffset) { + long realOffset = U.objectFieldOffset(f); + System.out.println("Offset for field " + f.getName() + + ": expected " + expectedOffset + ", got " + realOffset + "."); + if (U.objectFieldOffset(f) != expectedOffset) { + mismatch = true; + System.out.println(" ... mimatch"); + } + } + + private static List allFieldsOf(Class c) { + ArrayList l = new ArrayList<>(); + while (c != null) { + for (Field f : c.getDeclaredFields()) { + l.add(f); + } + c = c.getSuperclass(); + } + return l; + } + + public static void main(String[] args) throws Exception { + + System.out.println("HEADER_SIZE_IN_BYTES " + HEADER_SIZE_IN_BYTES + ", OOP_SIZE_IN_BYTES " + OOP_SIZE_IN_BYTES); + + long i1_loc_expected; + long o1_loc_expected; + long o2_loc_expected; + long i2_loc_expected; + long i3_loc_expected; + long o3_loc_expected; + long o4_loc_expected; + long i4_loc_expected; + + // We expect the layouter to reverse order of oop- and non-oop fields + // when it is useful to minimize the number of oop map entries. + // + // If we have no gaps, this should be the layout: + // BASE i1 + // o1 oopmap entry 1 + // DERIVED1 o2 oopmap entry 1 (reversed order) + // i2 + // DERIVED3 i3 + // o3 oopmap entry 2 + // DERIVED4 o4 oopmap entry 2 (reversed order) + // i4 + + // There are two combinations that have gaps: + // -UseCompressedOops + +COH, and -UseCompressedOops + -UseCompressedClassPointers. + // In both cases there is a gap following i1, and i2 will therefore nestle into that gap. + // Otherwise the same logic applies. + + if (OOP_SIZE_IN_BYTES == 4 || // oop size == int size + (OOP_SIZE_IN_BYTES == 8 && HEADER_SIZE_IN_BYTES == 12) + ) { + // No gaps + + // Expected layout for BASE: int, object + i1_loc_expected = HEADER_SIZE_IN_BYTES; + o1_loc_expected = i1_loc_expected + 4; + + // Expected layout for DERIVED1: object, int (to make o2 border o1) + o2_loc_expected = o1_loc_expected + OOP_SIZE_IN_BYTES; + i2_loc_expected = o2_loc_expected + OOP_SIZE_IN_BYTES; + + // Expected layout for DERIVED2: int, object (to trail with oops, for derived classes to nestle against) + i3_loc_expected = i2_loc_expected + 4; + o3_loc_expected = i3_loc_expected + 4; + + // Expected layout for DERIVED3: object, int (to make o4 border o3) + o4_loc_expected = o3_loc_expected + OOP_SIZE_IN_BYTES; + i4_loc_expected = o4_loc_expected + OOP_SIZE_IN_BYTES; + + } else if (OOP_SIZE_IN_BYTES == 8) { + + // gap after i1 + + i1_loc_expected = HEADER_SIZE_IN_BYTES; + o1_loc_expected = i1_loc_expected + 4 + 4; // + alignment gap + + o2_loc_expected = o1_loc_expected + OOP_SIZE_IN_BYTES; + i2_loc_expected = i1_loc_expected + 4; // into gap following i1 + + o3_loc_expected = o2_loc_expected + OOP_SIZE_IN_BYTES; + i3_loc_expected = o3_loc_expected + OOP_SIZE_IN_BYTES; + + i4_loc_expected = i3_loc_expected + 4; + o4_loc_expected = i4_loc_expected + 4; + } else { + throw new RuntimeException("Unexpected"); + } + + List l = allFieldsOf(DERIVED3.class); + for (Field f : l) { + switch (f.getName()) { + case "i1" : checkOffset(f, i1_loc_expected); break; + case "o1" : checkOffset(f, o1_loc_expected); break; + case "i2" : checkOffset(f, i2_loc_expected); break; + case "o2" : checkOffset(f, o2_loc_expected); break; + case "i3" : checkOffset(f, i3_loc_expected); break; + case "o3" : checkOffset(f, o3_loc_expected); break; + case "i4" : checkOffset(f, i4_loc_expected); break; + case "o4" : checkOffset(f, o4_loc_expected); break; + default: throw new RuntimeException("Unexpected"); + } + } + if (mismatch) { + throw new RuntimeException("Mismatch!"); + } + System.out.println("All good."); + } + +} + From 473251dbb308016ccda6c88fd36bd10c81e65865 Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Wed, 9 Apr 2025 05:09:30 +0000 Subject: [PATCH 071/843] 8353593: MethodData "mileage_*" methods and fields aren't used and can be removed Reviewed-by: phh, thartmann --- src/hotspot/share/oops/methodData.cpp | 6 ------ src/hotspot/share/oops/methodData.hpp | 11 ++--------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index 2d366168f08..280a69df583 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -1257,7 +1257,6 @@ void MethodData::initialize() { ResourceMark rm(thread); init(); - set_creation_mileage(mileage_of(method())); // Go through the bytecodes and allocate and initialize the // corresponding data cells. @@ -1364,11 +1363,6 @@ void MethodData::init() { clear_escape_info(); } -// Get a measure of how much mileage the method has on it. -int MethodData::mileage_of(Method* method) { - return MAX2(method->invocation_count(), method->backedge_count()); -} - bool MethodData::is_mature() const { return CompilationPolicy::is_mature(_method); } diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index 8375552a911..7870d6e459f 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -56,8 +56,7 @@ class BytecodeStream; // counter overflow, multiprocessor races during data collection, space // limitations, missing MDO blocks, etc. Bad or missing data will degrade // optimization quality but will not affect correctness. Also, each MDO -// is marked with its birth-date ("creation_mileage") which can be used -// to assess the quality ("maturity") of its data. +// can be checked for its "maturity" by calling is_mature(). // // Short (<32-bit) counters are designed to overflow to a known "saturated" // state. Also, certain recorded per-BCI events are given one-bit counters @@ -2061,8 +2060,6 @@ private: intx _arg_stack; // bit set of stack-allocatable arguments intx _arg_returned; // bit set of returned arguments - int _creation_mileage; // method mileage at MDO creation - // How many invocations has this MDO seen? // These counters are used to determine the exact age of MDO. // We need those because in tiered a method can be concurrently @@ -2225,9 +2222,6 @@ public: int size_in_bytes() const { return _size; } int size() const { return align_metadata_size(align_up(_size, BytesPerWord)/BytesPerWord); } - int creation_mileage() const { return _creation_mileage; } - void set_creation_mileage(int x) { _creation_mileage = x; } - int invocation_count() { if (invocation_counter()->carry()) { return InvocationCounter::count_limit; @@ -2280,8 +2274,7 @@ public: int num_blocks() const { return _num_blocks; } void set_num_blocks(short n) { _num_blocks = n; } - bool is_mature() const; // consult mileage and ProfileMaturityPercentage - static int mileage_of(Method* m); + bool is_mature() const; // Support for interprocedural escape analysis, from Thomas Kotzmann. enum EscapeFlag { From b045e3fbd7920465b5b67d43e35db98b935241d5 Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Wed, 9 Apr 2025 05:34:01 +0000 Subject: [PATCH 072/843] 8352681: C2 compilation hits asserts "must set the initial type just once" Reviewed-by: chagedorn, dfenacci --- src/hotspot/share/opto/memnode.cpp | 15 +++-- .../TestReduceAllocationAndSetTypeTwice.java | 62 +++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationAndSetTypeTwice.java diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index a19dbd664eb..e596db8e0c7 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -289,10 +289,17 @@ static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const T toop->isa_instptr() && toop->is_instptr()->instance_klass()->is_java_lang_Object() && toop->offset() == Type::OffsetBot)) { - // compress paths and change unreachable cycles to TOP - // If not, we can update the input infinitely along a MergeMem cycle - // Equivalent code in PhiNode::Ideal - Node* m = phase->transform(mmem); + // IGVN _delay_transform may be set to true and if that is the case and mmem + // is already a registered node then the validation inside transform will + // complain. + Node* m = mmem; + PhaseIterGVN* igvn = phase->is_IterGVN(); + if (igvn == nullptr || !igvn->delay_transform()) { + // compress paths and change unreachable cycles to TOP + // If not, we can update the input infinitely along a MergeMem cycle + // Equivalent code in PhiNode::Ideal + m = phase->transform(mmem); + } // If transformed to a MergeMem, get the desired slice // Otherwise the returned node represents memory for every slice mem = (m->is_MergeMem())? m->as_MergeMem()->memory_at(alias_idx) : m; diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationAndSetTypeTwice.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationAndSetTypeTwice.java new file mode 100644 index 00000000000..b44e70f5362 --- /dev/null +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestReduceAllocationAndSetTypeTwice.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8352681 + * @summary Check that RAM does not crash when split load through phi + * tries to register an old node twice with IGVN. + * @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationAndSetTypeTwice*::* + * -XX:CompileCommand=dontinline,*TestReduceAllocationAndSetTypeTwice*::* + * -Xcomp compiler.escapeAnalysis.TestReduceAllocationAndSetTypeTwice + * @run main compiler.escapeAnalysis.TestReduceAllocationAndSetTypeTwice + */ + +package compiler.escapeAnalysis; + +public class TestReduceAllocationAndSetTypeTwice { + public static double dummy() { + return 3.1415; + } + + public static double test(double param) { + Double double_1 = -26.335025324149626D; + Double double_2 = 87.9546734116494D; + + for (int i = 0, j = 0; i < 256; i++) { + if (param != param) { + j--; + } else if (dummy() > 0) { + return (j < 1234 ? double_1 : double_2); + } + } + + return 10.0; + } + + public static void main(String[] args) { + for (int i = 0; i < 512; i++) { + test(-3.1415); + } + } +} From 3340e13fd0a8d25212003e8371a135471b2f44b3 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Wed, 9 Apr 2025 06:19:08 +0000 Subject: [PATCH 073/843] 8352994: ZGC: Fix regression introduced in JDK-8350572 Reviewed-by: aboldtch, tschatzl --- src/hotspot/share/gc/z/zVerify.cpp | 2 +- test/jdk/ProblemList-zgc.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index 439a3710185..117d27997ee 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -61,7 +61,7 @@ // with callers to this function. Typically used to verify that object oops // and headers are safe to access. void z_verify_safepoints_are_blocked() { - if (VMError::is_error_reported_in_current_thread()) { + if (VMError::is_error_reported() && VMError::is_error_reported_in_current_thread()) { // The current thread has crashed and is creating an error report. // This may occur from any thread state, skip the safepoint_are_blocked // verification. diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt index 2bd7691be10..ab44c5e47a9 100644 --- a/test/jdk/ProblemList-zgc.txt +++ b/test/jdk/ProblemList-zgc.txt @@ -38,4 +38,3 @@ sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java 8307393 generic-all sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java 8307393 generic-all com/sun/jdi/ThreadMemoryLeakTest.java 8307402 generic-all -com/sun/jdi/JdbStopInNotificationThreadTest.java 8351607 linux-all From 0f70aae1cc4fd48ef2de3b0fe4741a32660ed4f9 Mon Sep 17 00:00:00 2001 From: Evgeny Nikitin Date: Wed, 9 Apr 2025 07:03:24 +0000 Subject: [PATCH 074/843] 8353841: [jittester] Fix JITTester build after asm removal Reviewed-by: thartmann, chagedorn --- .../hotspot/jtreg/testlibrary/jittester/Makefile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary/jittester/Makefile b/test/hotspot/jtreg/testlibrary/jittester/Makefile index be06329a535..ec88f62e9ed 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/Makefile +++ b/test/hotspot/jtreg/testlibrary/jittester/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -83,6 +83,8 @@ TESTLIBRARY_SRC_FILES = $(TESTLIBRARY_SRC_DIR)/Asserts.java \ $(TESTLIBRARY_SRC_DIR)/util/FileUtils.java \ $(TESTLIBRARY_SRC_DIR)/util/Pair.java +ASM_SRC_DIR = ../asm/org/objectweb/asm/ + .PHONY: cleantmp all: $(DIST_JAR) @@ -95,11 +97,15 @@ manifest: @echo 'X-COMMENT: Main-Class will be added automatically by build' >> $(MANIFEST) @echo 'Main-Class: jdk.test.lib.jittester.Automatic' >> $(MANIFEST) -compile_testlib: INIT - $(JAVAC) -XDignore.symbol.file --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.base/org.objectweb.asm=ALL-UNNAMED -Xlint $(TESTLIBRARY_SRC_FILES) -d $(CLASSES_DIR) +compile_asm: INIT + $(shell find $(ASM_SRC_DIR) -name '*.java' > $(CLASSES_DIR)/filelist_asm) + ${JAVAC} -d $(CLASSES_DIR) @$(CLASSES_DIR)/filelist_asm -COMPILE: INIT filelist compile_testlib - $(JAVAC) -cp $(CLASSES_DIR) -XDignore.symbol.file --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.base/org.objectweb.asm=ALL-UNNAMED -Xlint -sourcepath $(SRC_DIR) -d $(CLASSES_DIR) @filelist +compile_testlib: INIT + $(JAVAC) -XDignore.symbol.file --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED -Xlint $(TESTLIBRARY_SRC_FILES) -d $(CLASSES_DIR) + +COMPILE: INIT filelist compile_asm compile_testlib + $(JAVAC) -cp $(CLASSES_DIR) -XDignore.symbol.file --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED -Xlint -sourcepath $(SRC_DIR) -d $(CLASSES_DIR) @filelist filelist: $(SRC_FILES) @rm -f $@ From 6df34c361e0d1b6fe90ca97c1aaa56e57a86d12c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 9 Apr 2025 07:28:47 +0000 Subject: [PATCH 075/843] 8353174: Clean up thread register handling after 32-bit x86 removal Reviewed-by: cslucas, kvn, vlivanov --- src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 4 +- src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 5 +- src/hotspot/cpu/x86/c1_Runtime1_x86.cpp | 21 +- src/hotspot/cpu/x86/downcallLinker_x86_64.cpp | 4 +- src/hotspot/cpu/x86/interp_masm_x86.cpp | 20 +- src/hotspot/cpu/x86/interp_masm_x86.hpp | 5 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 185 ++++++------------ src/hotspot/cpu/x86/macroAssembler_x86.hpp | 46 ++--- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 15 +- src/hotspot/cpu/x86/stubGenerator_x86_64.cpp | 10 +- .../x86/stubGenerator_x86_64_arraycopy.cpp | 2 +- .../x86/templateInterpreterGenerator_x86.cpp | 13 +- .../templateInterpreterGenerator_x86_64.cpp | 4 +- src/hotspot/cpu/x86/templateTable_x86.cpp | 14 +- src/hotspot/cpu/x86/x86_64.ad | 4 +- 15 files changed, 135 insertions(+), 217 deletions(-) diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index fa1bfaa71db..04e32e2b8be 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -326,7 +326,7 @@ void LIR_Assembler::clinit_barrier(ciMethod* method) { Register klass = rscratch1; __ mov_metadata(klass, method->holder()->constant_encoding()); - __ clinit_barrier(klass, r15_thread, &L_skip_barrier /*L_fast_path*/); + __ clinit_barrier(klass, &L_skip_barrier /*L_fast_path*/); __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); @@ -482,7 +482,7 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { code_stub->set_safepoint_offset(__ offset()); __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub->entry(), r15_thread, true /* at_return */, true /* in_nmethod */); + __ safepoint_poll(*code_stub->entry(), true /* at_return */, true /* in_nmethod */); __ ret(0); } diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index 7ffa6d9bdd4..dd8c075cb87 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -62,8 +62,7 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr } if (LockingMode == LM_LIGHTWEIGHT) { - const Register thread = r15_thread; - lightweight_lock(disp_hdr, obj, hdr, thread, tmp, slow_case); + lightweight_lock(disp_hdr, obj, hdr, tmp, slow_case); } else if (LockingMode == LM_LEGACY) { Label done; // Load object header @@ -128,7 +127,7 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_ verify_oop(obj); if (LockingMode == LM_LIGHTWEIGHT) { - lightweight_unlock(obj, disp_hdr, r15_thread, hdr, slow_case); + lightweight_unlock(obj, disp_hdr, hdr, slow_case); } else if (LockingMode == LM_LEGACY) { // test if object header is pointing to the displaced header, and if so, restore // the displaced header in the object - if the object header is not pointing to diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index bb5111fa652..f42032bb275 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -51,7 +51,7 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, int args_size) { // setup registers - const Register thread = r15_thread; // is callee-saved register (Visual C++ calling conventions) + const Register thread = r15_thread; assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different"); assert(oop_result1 != thread && metadata_result != thread, "registers must be different"); assert(args_size >= 0, "illegal args_size"); @@ -66,11 +66,11 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre int call_offset = -1; if (!align_stack) { - set_last_Java_frame(thread, noreg, rbp, nullptr, rscratch1); + set_last_Java_frame(noreg, rbp, nullptr, rscratch1); } else { address the_pc = pc(); call_offset = offset(); - set_last_Java_frame(thread, noreg, rbp, the_pc, rscratch1); + set_last_Java_frame(noreg, rbp, the_pc, rscratch1); andptr(rsp, -(StackAlignmentInBytes)); // Align stack } @@ -84,7 +84,7 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre guarantee(thread != rax, "change this code"); push(rax); { Label L; - get_thread(rax); + get_thread_slow(rax); cmpptr(thread, rax); jcc(Assembler::equal, L); int3(); @@ -93,7 +93,7 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre } pop(rax); #endif - reset_last_Java_frame(thread, true); + reset_last_Java_frame(true); // check for pending exceptions { Label L; @@ -120,10 +120,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre } // get oop results if there are any and reset the values in the thread if (oop_result1->is_valid()) { - get_vm_result(oop_result1, thread); + get_vm_result(oop_result1); } if (metadata_result->is_valid()) { - get_vm_result_2(metadata_result, thread); + get_vm_result_2(metadata_result); } assert(call_offset >= 0, "Should be set"); @@ -715,8 +715,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { const Register thread = r15_thread; // No need to worry about dummy __ mov(c_rarg0, thread); - - __ set_last_Java_frame(thread, noreg, rbp, nullptr, rscratch1); + __ set_last_Java_frame(noreg, rbp, nullptr, rscratch1); // do the call __ call(RuntimeAddress(target)); OopMapSet* oop_maps = new OopMapSet(); @@ -726,7 +725,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { guarantee(thread != rax, "change this code"); __ push(rax); { Label L; - __ get_thread(rax); + __ get_thread_slow(rax); __ cmpptr(thread, rax); __ jcc(Assembler::equal, L); __ stop("StubAssembler::call_RT: rdi/r15 not callee saved?"); @@ -734,7 +733,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { } __ pop(rax); #endif - __ reset_last_Java_frame(thread, true); + __ reset_last_Java_frame(true); // check for pending exceptions { Label L; diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp index 15c311ffd39..c48940198ea 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp @@ -291,7 +291,7 @@ void DowncallLinker::StubGenerator::generate() { Assembler::StoreLoad | Assembler::StoreStore)); } - __ safepoint_poll(L_safepoint_poll_slow_path, r15_thread, true /* at_return */, false /* in_nmethod */); + __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, false /* in_nmethod */); __ cmpl(Address(r15_thread, JavaThread::suspend_flags_offset()), 0); __ jcc(Assembler::notEqual, L_safepoint_poll_slow_path); @@ -305,7 +305,7 @@ void DowncallLinker::StubGenerator::generate() { __ jcc(Assembler::equal, L_reguard); __ bind(L_after_reguard); - __ reset_last_Java_frame(r15_thread, true); + __ reset_last_Java_frame(true); __ block_comment("} thread native2java"); } diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index 84a99060a3e..93117ff8b7d 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -296,7 +296,6 @@ void InterpreterMacroAssembler::call_VM_leaf_base(address entry_point, } void InterpreterMacroAssembler::call_VM_base(Register oop_result, - Register java_thread, Register last_java_sp, address entry_point, int number_of_arguments, @@ -319,7 +318,7 @@ void InterpreterMacroAssembler::call_VM_base(Register oop_result, } #endif /* ASSERT */ // super call - MacroAssembler::call_VM_base(oop_result, noreg, last_java_sp, + MacroAssembler::call_VM_base(oop_result, last_java_sp, entry_point, number_of_arguments, check_exceptions); // interpreter specific @@ -379,7 +378,7 @@ void InterpreterMacroAssembler::restore_after_resume(bool is_native) { } } -void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { +void InterpreterMacroAssembler::check_and_handle_popframe() { if (JvmtiExport::can_pop_frame()) { Label L; // Initiate popframe handling only if it is not already being @@ -389,7 +388,7 @@ void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) // This method is only called just after the call into the vm in // call_VM_base, so the arg registers are available. Register pop_cond = c_rarg0; - movl(pop_cond, Address(java_thread, JavaThread::popframe_condition_offset())); + movl(pop_cond, Address(r15_thread, JavaThread::popframe_condition_offset())); testl(pop_cond, JavaThread::popframe_pending_bit); jcc(Assembler::zero, L); testl(pop_cond, JavaThread::popframe_processing_bit); @@ -430,7 +429,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { } -void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { +void InterpreterMacroAssembler::check_and_handle_earlyret() { if (JvmtiExport::can_force_early_return()) { Label L; Register tmp = c_rarg0; @@ -810,13 +809,13 @@ void InterpreterMacroAssembler::remove_activation( // the stack, will call InterpreterRuntime::at_unwind. Label slow_path; Label fast_path; - safepoint_poll(slow_path, rthread, true /* at_return */, false /* in_nmethod */); + safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); jmp(fast_path); bind(slow_path); push(state); - set_last_Java_frame(rthread, noreg, rbp, (address)pc(), rscratch1); + set_last_Java_frame(noreg, rbp, (address)pc(), rscratch1); super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), rthread); - reset_last_Java_frame(rthread, true); + reset_last_Java_frame(true); pop(state); bind(fast_path); @@ -1031,8 +1030,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) { } if (LockingMode == LM_LIGHTWEIGHT) { - const Register thread = r15_thread; - lightweight_lock(lock_reg, obj_reg, swap_reg, thread, tmp_reg, slow_case); + lightweight_lock(lock_reg, obj_reg, swap_reg, tmp_reg, slow_case); } else if (LockingMode == LM_LEGACY) { // Load immediate 1 into swap_reg %rax movl(swap_reg, 1); @@ -1141,7 +1139,7 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) { movptr(Address(lock_reg, BasicObjectLock::obj_offset()), NULL_WORD); if (LockingMode == LM_LIGHTWEIGHT) { - lightweight_unlock(obj_reg, swap_reg, r15_thread, header_reg, slow_case); + lightweight_unlock(obj_reg, swap_reg, header_reg, slow_case); } else if (LockingMode == LM_LEGACY) { // Load the old header from BasicLock structure movptr(header_reg, Address(swap_reg, diff --git a/src/hotspot/cpu/x86/interp_masm_x86.hpp b/src/hotspot/cpu/x86/interp_masm_x86.hpp index e537e9efc96..308d700ff4f 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.hpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.hpp @@ -42,7 +42,6 @@ class InterpreterMacroAssembler: public MacroAssembler { protected: virtual void call_VM_base(Register oop_result, - Register java_thread, Register last_java_sp, address entry_point, int number_of_arguments, @@ -58,8 +57,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void jump_to_entry(address entry); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); + virtual void check_and_handle_popframe(); + virtual void check_and_handle_earlyret(); void load_earlyret_value(TosState state); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index c92ce2f283c..a2173be609b 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -724,17 +724,6 @@ void MacroAssembler::pushptr(AddressLiteral src, Register rscratch) { } } -void MacroAssembler::reset_last_Java_frame(bool clear_fp) { - reset_last_Java_frame(r15_thread, clear_fp); -} - -void MacroAssembler::set_last_Java_frame(Register last_java_sp, - Register last_java_fp, - address last_java_pc, - Register rscratch) { - set_last_Java_frame(r15_thread, last_java_sp, last_java_fp, last_java_pc, rscratch); -} - static void pass_arg0(MacroAssembler* masm, Register arg) { if (c_rarg0 != arg ) { masm->mov(c_rarg0, arg); @@ -1487,8 +1476,7 @@ void MacroAssembler::call_VM(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { - Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); - call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); + call_VM_base(oop_result, last_java_sp, entry_point, number_of_arguments, check_exceptions); } void MacroAssembler::call_VM(Register oop_result, @@ -1533,8 +1521,7 @@ void MacroAssembler::super_call_VM(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { - Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); - MacroAssembler::call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); + MacroAssembler::call_VM_base(oop_result, last_java_sp, entry_point, number_of_arguments, check_exceptions); } void MacroAssembler::super_call_VM(Register oop_result, @@ -1575,31 +1562,22 @@ void MacroAssembler::super_call_VM(Register oop_result, } void MacroAssembler::call_VM_base(Register oop_result, - Register java_thread, Register last_java_sp, address entry_point, int number_of_arguments, bool check_exceptions) { - // determine java_thread register - if (!java_thread->is_valid()) { -#ifdef _LP64 - java_thread = r15_thread; -#else - java_thread = rdi; - get_thread(java_thread); -#endif // LP64 - } + Register java_thread = r15_thread; + // determine last_java_sp register if (!last_java_sp->is_valid()) { last_java_sp = rsp; } // debugging support assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); - LP64_ONLY(assert(java_thread == r15_thread, "unexpected register")); #ifdef ASSERT // TraceBytecodes does not use r12 but saves it over the call, so don't verify // r12 is the heapbase. - LP64_ONLY(if (UseCompressedOops && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");) + if (UseCompressedOops && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?"); #endif // ASSERT assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); @@ -1607,53 +1585,42 @@ void MacroAssembler::call_VM_base(Register oop_result, // push java thread (becomes first argument of C function) - NOT_LP64(push(java_thread); number_of_arguments++); - LP64_ONLY(mov(c_rarg0, r15_thread)); + mov(c_rarg0, r15_thread); // set last Java frame before call assert(last_java_sp != rbp, "can't use ebp/rbp"); // Only interpreter should have to set fp - set_last_Java_frame(java_thread, last_java_sp, rbp, nullptr, rscratch1); + set_last_Java_frame(last_java_sp, rbp, nullptr, rscratch1); // do the call, remove parameters MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); - // restore the thread (cannot use the pushed argument since arguments - // may be overwritten by C code generated by an optimizing compiler); - // however can use the register value directly if it is callee saved. - if (LP64_ONLY(true ||) java_thread == rdi || java_thread == rsi) { - // rdi & rsi (also r15) are callee saved -> nothing to do #ifdef ASSERT - guarantee(java_thread != rax, "change this code"); - push(rax); - { Label L; - get_thread(rax); - cmpptr(java_thread, rax); - jcc(Assembler::equal, L); - STOP("MacroAssembler::call_VM_base: rdi not callee saved?"); - bind(L); - } - pop(rax); -#endif - } else { - get_thread(java_thread); + // Check that thread register is not clobbered. + guarantee(java_thread != rax, "change this code"); + push(rax); + { Label L; + get_thread_slow(rax); + cmpptr(java_thread, rax); + jcc(Assembler::equal, L); + STOP("MacroAssembler::call_VM_base: java_thread not callee saved?"); + bind(L); } + pop(rax); +#endif + // reset last Java frame // Only interpreter should have to clear fp - reset_last_Java_frame(java_thread, true); + reset_last_Java_frame(true); // C++ interp handles this in the interpreter - check_and_handle_popframe(java_thread); - check_and_handle_earlyret(java_thread); + check_and_handle_popframe(); + check_and_handle_earlyret(); if (check_exceptions) { // check for pending exceptions (java_thread is set upon return) - cmpptr(Address(java_thread, Thread::pending_exception_offset()), NULL_WORD); -#ifndef _LP64 - jump_cc(Assembler::notEqual, - RuntimeAddress(StubRoutines::forward_exception_entry())); -#else + cmpptr(Address(r15_thread, Thread::pending_exception_offset()), NULL_WORD); // This used to conditionally jump to forward_exception however it is // possible if we relocate that the branch will not reach. So we must jump // around so we can always reach @@ -1662,36 +1629,24 @@ void MacroAssembler::call_VM_base(Register oop_result, jcc(Assembler::equal, ok); jump(RuntimeAddress(StubRoutines::forward_exception_entry())); bind(ok); -#endif // LP64 } // get oop result if there is one and reset the value in the thread if (oop_result->is_valid()) { - get_vm_result(oop_result, java_thread); + get_vm_result(oop_result); } } void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { + // Calculate the value for last_Java_sp somewhat subtle. + // call_VM does an intermediate call which places a return address on + // the stack just under the stack pointer as the user finished with it. + // This allows use to retrieve last_Java_pc from last_Java_sp[-1]. - // Calculate the value for last_Java_sp - // somewhat subtle. call_VM does an intermediate call - // which places a return address on the stack just under the - // stack pointer as the user finished with it. This allows - // use to retrieve last_Java_pc from last_Java_sp[-1]. - // On 32bit we then have to push additional args on the stack to accomplish - // the actual requested call. On 64bit call_VM only can use register args - // so the only extra space is the return address that call_VM created. - // This hopefully explains the calculations here. - -#ifdef _LP64 // We've pushed one address, correct last_Java_sp lea(rax, Address(rsp, wordSize)); -#else - lea(rax, Address(rsp, (1 + number_of_arguments) * wordSize)); -#endif // LP64 - - call_VM_base(oop_result, noreg, rax, entry_point, number_of_arguments, check_exceptions); + call_VM_base(oop_result, rax, entry_point, number_of_arguments, check_exceptions); } // Use this method when MacroAssembler version of call_VM_leaf_base() should be called from Interpreter. @@ -1768,21 +1723,21 @@ void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Reg MacroAssembler::call_VM_leaf_base(entry_point, 4); } -void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) { - movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); - movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD); +void MacroAssembler::get_vm_result(Register oop_result) { + movptr(oop_result, Address(r15_thread, JavaThread::vm_result_offset())); + movptr(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); verify_oop_msg(oop_result, "broken oop in call_VM_base"); } -void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) { - movptr(metadata_result, Address(java_thread, JavaThread::vm_result_2_offset())); - movptr(Address(java_thread, JavaThread::vm_result_2_offset()), NULL_WORD); +void MacroAssembler::get_vm_result_2(Register metadata_result) { + movptr(metadata_result, Address(r15_thread, JavaThread::vm_result_2_offset())); + movptr(Address(r15_thread, JavaThread::vm_result_2_offset()), NULL_WORD); } -void MacroAssembler::check_and_handle_earlyret(Register java_thread) { +void MacroAssembler::check_and_handle_earlyret() { } -void MacroAssembler::check_and_handle_popframe(Register java_thread) { +void MacroAssembler::check_and_handle_popframe() { } void MacroAssembler::cmp32(AddressLiteral src1, int32_t imm, Register rscratch) { @@ -3170,20 +3125,16 @@ void MacroAssembler::stop_if_in_cont(Register cont, const char* name) { } #endif -void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp) { // determine java_thread register - if (!java_thread->is_valid()) { - java_thread = rdi; - get_thread(java_thread); - } +void MacroAssembler::reset_last_Java_frame(bool clear_fp) { // determine java_thread register // we must set sp to zero to clear frame - movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); // must clear fp, so that compiled frames are not confused; it is // possible that we need it only for debugging if (clear_fp) { - movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); } // Always clear the pc because it could have been set by make_walkable() - movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); vzeroupper(); } @@ -3202,15 +3153,15 @@ void MacroAssembler::save_rax(Register tmp) { else if (tmp != rax) mov(tmp, rax); } -void MacroAssembler::safepoint_poll(Label& slow_path, Register thread_reg, bool at_return, bool in_nmethod) { +void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod) { if (at_return) { // Note that when in_nmethod is set, the stack pointer is incremented before the poll. Therefore, // we may safely use rsp instead to perform the stack watermark check. - cmpptr(in_nmethod ? rsp : rbp, Address(thread_reg, JavaThread::polling_word_offset())); + cmpptr(in_nmethod ? rsp : rbp, Address(r15_thread, JavaThread::polling_word_offset())); jcc(Assembler::above, slow_path); return; } - testb(Address(thread_reg, JavaThread::polling_word_offset()), SafepointMechanism::poll_bit()); + testb(Address(r15_thread, JavaThread::polling_word_offset()), SafepointMechanism::poll_bit()); jcc(Assembler::notZero, slow_path); // handshake bit set implies poll } @@ -3219,44 +3170,36 @@ void MacroAssembler::safepoint_poll(Label& slow_path, Register thread_reg, bool // When entering C land, the rbp, & rsp of the last Java frame have to be recorded // in the (thread-local) JavaThread object. When leaving C land, the last Java fp // has to be reset to 0. This is required to allow proper stack traversal. -void MacroAssembler::set_last_Java_frame(Register java_thread, - Register last_java_sp, +void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_java_fp, address last_java_pc, Register rscratch) { vzeroupper(); - // determine java_thread register - if (!java_thread->is_valid()) { - java_thread = rdi; - get_thread(java_thread); - } // determine last_java_sp register if (!last_java_sp->is_valid()) { last_java_sp = rsp; } // last_java_fp is optional if (last_java_fp->is_valid()) { - movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), last_java_fp); + movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), last_java_fp); } // last_java_pc is optional if (last_java_pc != nullptr) { - Address java_pc(java_thread, + Address java_pc(r15_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); lea(java_pc, InternalAddress(last_java_pc), rscratch); } - movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), last_java_sp); + movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), last_java_sp); } -#ifdef _LP64 void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_java_fp, Label &L, Register scratch) { lea(scratch, L); movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), scratch); - set_last_Java_frame(r15_thread, last_java_sp, last_java_fp, nullptr, scratch); + set_last_Java_frame(last_java_sp, last_java_fp, nullptr, scratch); } -#endif void MacroAssembler::shlptr(Register dst, int imm8) { LP64_ONLY(shlq(dst, imm8)) NOT_LP64(shll(dst, imm8)); @@ -4111,8 +4054,8 @@ void MacroAssembler::clear_jobject_tag(Register possibly_non_local) { } void MacroAssembler::resolve_jobject(Register value, - Register thread, Register tmp) { + Register thread = r15_thread; assert_different_registers(value, thread, tmp); Label done, tagged, weak_tagged; testptr(value, value); @@ -4144,8 +4087,8 @@ void MacroAssembler::resolve_jobject(Register value, } void MacroAssembler::resolve_global_jobject(Register value, - Register thread, Register tmp) { + Register thread = r15_thread; assert_different_registers(value, thread, tmp); Label done; @@ -5476,7 +5419,7 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass, #endif // LP64 -void MacroAssembler::clinit_barrier(Register klass, Register thread, Label* L_fast_path, Label* L_slow_path) { +void MacroAssembler::clinit_barrier(Register klass, Label* L_fast_path, Label* L_slow_path) { assert(L_fast_path != nullptr || L_slow_path != nullptr, "at least one is required"); Label L_fallthrough; @@ -5492,7 +5435,7 @@ void MacroAssembler::clinit_barrier(Register klass, Register thread, Label* L_fa jcc(Assembler::equal, *L_fast_path); // Fast path check: current thread is initializer thread - cmpptr(thread, Address(klass, InstanceKlass::init_thread_offset())); + cmpptr(r15_thread, Address(klass, InstanceKlass::init_thread_offset())); if (L_slow_path == &L_fallthrough) { jcc(Assembler::equal, *L_fast_path); bind(*L_slow_path); @@ -10746,33 +10689,29 @@ Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) } // This is simply a call to Thread::current() -void MacroAssembler::get_thread(Register thread) { +void MacroAssembler::get_thread_slow(Register thread) { if (thread != rax) { push(rax); } - LP64_ONLY(push(rdi);) - LP64_ONLY(push(rsi);) + push(rdi); + push(rsi); push(rdx); push(rcx); -#ifdef _LP64 push(r8); push(r9); push(r10); push(r11); -#endif MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, Thread::current), 0); -#ifdef _LP64 pop(r11); pop(r10); pop(r9); pop(r8); -#endif pop(rcx); pop(rdx); - LP64_ONLY(pop(rsi);) - LP64_ONLY(pop(rdi);) + pop(rsi); + pop(rdi); if (thread != rax) { mov(thread, rax); pop(rax); @@ -10801,7 +10740,9 @@ void MacroAssembler::check_stack_alignment(Register sp, const char* msg, unsigne // reg_rax: rax // thread: the thread which attempts to lock obj // tmp: a temporary register -void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) { +void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Register reg_rax, Register tmp, Label& slow) { + Register thread = r15_thread; + assert(reg_rax == rax, ""); assert_different_registers(basic_lock, obj, reg_rax, thread, tmp); @@ -10855,7 +10796,9 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe // reg_rax: rax // thread: the thread // tmp: a temporary register -void MacroAssembler::lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) { +void MacroAssembler::lightweight_unlock(Register obj, Register reg_rax, Register tmp, Label& slow) { + Register thread = r15_thread; + assert(reg_rax == rax, ""); assert_different_registers(obj, reg_rax, thread, tmp); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 36ef3a69d49..79f99afded2 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -59,13 +59,10 @@ class MacroAssembler: public Assembler { // may customize this version by overriding it for its purposes (e.g., to save/restore // additional registers when doing a VM call). // - // If no java_thread register is specified (noreg) than rdi will be used instead. call_VM_base - // returns the register which contains the thread upon return. If a thread register has been - // specified, the return value will correspond to that register. If no last_java_sp is specified - // (noreg) than rsp will be used instead. + // call_VM_base returns the register which contains the thread upon return. + // If no last_java_sp is specified (noreg) than rsp will be used instead. virtual void call_VM_base( // returns the register containing the thread upon return Register oop_result, // where an oop-result ends up if any; use noreg otherwise - Register java_thread, // the thread if computed before ; use noreg otherwise Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise address entry_point, // the entry point int number_of_arguments, // the number of arguments (w/o thread) to pop after the call @@ -85,8 +82,8 @@ class MacroAssembler: public Assembler { // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. // The implementation is only non-empty for the InterpreterMacroAssembler, // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); + virtual void check_and_handle_popframe(); + virtual void check_and_handle_earlyret(); Address as_Address(AddressLiteral adr); Address as_Address(ArrayAddress adr, Register rscratch); @@ -224,9 +221,10 @@ class MacroAssembler: public Assembler { void enter(); void leave(); - // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information) - // The pointer will be loaded into the thread register. - void get_thread(Register thread); + // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information). + // The pointer will be loaded into the thread register. This is a slow version that does native call. + // Normally, JavaThread pointer is available in r15_thread, use that where possible. + void get_thread_slow(Register thread); #ifdef _LP64 // Support for argument shuffling @@ -291,8 +289,8 @@ class MacroAssembler: public Assembler { Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - void get_vm_result (Register oop_result, Register thread); - void get_vm_result_2(Register metadata_result, Register thread); + void get_vm_result (Register oop_result); + void get_vm_result_2(Register metadata_result); // These always tightly bind to MacroAssembler::call_VM_base // bypassing the virtual implementation @@ -323,35 +321,22 @@ class MacroAssembler: public Assembler { void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3); void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4); - // last Java Frame (fills frame anchor) - void set_last_Java_frame(Register thread, - Register last_java_sp, - Register last_java_fp, - address last_java_pc, - Register rscratch); - - // thread in the default location (r15_thread on 64bit) void set_last_Java_frame(Register last_java_sp, Register last_java_fp, address last_java_pc, Register rscratch); -#ifdef _LP64 void set_last_Java_frame(Register last_java_sp, Register last_java_fp, Label &last_java_pc, Register scratch); -#endif - void reset_last_Java_frame(Register thread, bool clear_fp); - - // thread in the default location (r15_thread on 64bit) void reset_last_Java_frame(bool clear_fp); // jobjects void clear_jobject_tag(Register possibly_non_local); - void resolve_jobject(Register value, Register thread, Register tmp); - void resolve_global_jobject(Register value, Register thread, Register tmp); + void resolve_jobject(Register value, Register tmp); + void resolve_global_jobject(Register value, Register tmp); // C 'boolean' to Java boolean: x == 0 ? 0 : 1 void c2bool(Register x); @@ -762,7 +747,6 @@ public: Label& L_success); void clinit_barrier(Register klass, - Register thread, Label* L_fast_path = nullptr, Label* L_slow_path = nullptr); @@ -837,7 +821,7 @@ public: // Check for reserved stack access in method being exited (for JIT) void reserved_stack_check(); - void safepoint_poll(Label& slow_path, Register thread_reg, bool at_return, bool in_nmethod); + void safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod); void verify_tlab(); @@ -2247,8 +2231,8 @@ public: void check_stack_alignment(Register sp, const char* msg, unsigned bias = 0, Register tmp = noreg); - void lightweight_lock(Register basic_lock, Register obj, Register reg_rax, Register thread, Register tmp, Label& slow); - void lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow); + void lightweight_lock(Register basic_lock, Register obj, Register reg_rax, Register tmp, Label& slow); + void lightweight_unlock(Register obj, Register reg_rax, Register tmp, Label& slow); #ifdef _LP64 void save_legacy_gprs(); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index d3e7e23678a..09c102aa5d1 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -1104,7 +1104,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm Register klass = rscratch1; __ load_method_holder(klass, method); - __ clinit_barrier(klass, r15_thread, &L_skip_barrier /*L_fast_path*/); + __ clinit_barrier(klass, &L_skip_barrier /*L_fast_path*/); __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); // slow path @@ -2003,7 +2003,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, Label L_skip_barrier; Register klass = r10; __ mov_metadata(klass, method->method_holder()); // InstanceKlass* - __ clinit_barrier(klass, r15_thread, &L_skip_barrier /*L_fast_path*/); + __ clinit_barrier(klass, &L_skip_barrier /*L_fast_path*/); __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); // slow path @@ -2280,7 +2280,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ inc_held_monitor_count(); } else { assert(LockingMode == LM_LIGHTWEIGHT, "must be"); - __ lightweight_lock(lock_reg, obj_reg, swap_reg, r15_thread, rscratch1, slow_path_lock); + __ lightweight_lock(lock_reg, obj_reg, swap_reg, rscratch1, slow_path_lock); } // Slow path will re-enter here @@ -2340,7 +2340,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, Label Continue; Label slow_path; - __ safepoint_poll(slow_path, r15_thread, true /* at_return */, false /* in_nmethod */); + __ safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); __ cmpl(Address(r15_thread, JavaThread::suspend_flags_offset()), 0); __ jcc(Assembler::equal, Continue); @@ -2431,7 +2431,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ dec_held_monitor_count(); } else { assert(LockingMode == LM_LIGHTWEIGHT, "must be"); - __ lightweight_unlock(obj_reg, swap_reg, r15_thread, lock_reg, slow_path_unlock); + __ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock); } // slow path re-enters here @@ -2456,7 +2456,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Unbox oop result, e.g. JNIHandles::resolve value. if (is_reference_type(ret_type)) { __ resolve_jobject(rax /* value */, - r15_thread /* thread */, rcx /* tmp */); } @@ -3234,7 +3233,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti __ jcc(Assembler::notEqual, pending); // get the returned Method* - __ get_vm_result_2(rbx, r15_thread); + __ get_vm_result_2(rbx); __ movptr(Address(rsp, RegisterSaver::rbx_offset_in_bytes()), rbx); __ movptr(Address(rsp, RegisterSaver::rax_offset_in_bytes()), rax); @@ -3661,7 +3660,7 @@ RuntimeStub* SharedRuntime::generate_jfr_write_checkpoint() { __ reset_last_Java_frame(true); // rax is jobject handle result, unpack and process it through a barrier. - __ resolve_global_jobject(rax, r15_thread, c_rarg0); + __ resolve_global_jobject(rax, c_rarg0); __ leave(); __ ret(0); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 7e63e6fb49b..9fcb044b09a 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -339,7 +339,7 @@ address StubGenerator::generate_call_stub(address& return_address) { __ jcc(Assembler::equal, L1); __ stop("StubRoutines::call_stub: r15_thread is corrupted"); __ bind(L1); - __ get_thread(rbx); + __ get_thread_slow(rbx); __ cmpptr(r15_thread, thread); __ jcc(Assembler::equal, L2); __ stop("StubRoutines::call_stub: r15_thread is modified by call"); @@ -426,7 +426,7 @@ address StubGenerator::generate_catch_exception() { __ jcc(Assembler::equal, L1); __ stop("StubRoutines::catch_exception: r15_thread is corrupted"); __ bind(L1); - __ get_thread(rbx); + __ get_thread_slow(rbx); __ cmpptr(r15_thread, thread); __ jcc(Assembler::equal, L2); __ stop("StubRoutines::catch_exception: r15_thread is modified by call"); @@ -1313,7 +1313,7 @@ void StubGenerator::setup_arg_regs_using_thread(int nargs) { __ mov(rax, r9); // r9 is also saved_r15 } __ mov(saved_r15, r15); // r15 is callee saved and needs to be restored - __ get_thread(r15_thread); + __ get_thread_slow(r15_thread); assert(c_rarg0 == rcx && c_rarg1 == rdx && c_rarg2 == r8 && c_rarg3 == r9, "unexpected argument registers"); __ movptr(Address(r15_thread, in_bytes(JavaThread::windows_saved_rdi_offset())), rdi); @@ -1337,7 +1337,7 @@ void StubGenerator::restore_arg_regs_using_thread() { assert(_regs_in_thread, "wrong call to restore_arg_regs"); const Register saved_r15 = r9; #ifdef _WIN64 - __ get_thread(r15_thread); + __ get_thread_slow(r15_thread); __ movptr(rsi, Address(r15_thread, in_bytes(JavaThread::windows_saved_rsi_offset()))); __ movptr(rdi, Address(r15_thread, in_bytes(JavaThread::windows_saved_rdi_offset()))); __ mov(r15, saved_r15); // r15 is callee saved and needs to be restored @@ -3974,7 +3974,7 @@ address StubGenerator::generate_upcall_stub_load_target() { StubCodeMark mark(this, stub_id); address start = __ pc(); - __ resolve_global_jobject(j_rarg0, r15_thread, rscratch1); + __ resolve_global_jobject(j_rarg0, rscratch1); // Load target method from receiver __ load_heap_oop(rbx, Address(j_rarg0, java_lang_invoke_MethodHandle::form_offset()), rscratch1); __ load_heap_oop(rbx, Address(rbx, java_lang_invoke_LambdaForm::vmentry_offset()), rscratch1); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp index ccc8e456d57..1e056f15213 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp @@ -2476,7 +2476,7 @@ address StubGenerator::generate_checkcast_copy(StubGenStubId stub_id, address *e #ifdef ASSERT Label L2; - __ get_thread(r14); + __ get_thread_slow(r14); __ cmpptr(r15_thread, r14); __ jcc(Assembler::equal, L2); __ stop("StubRoutines::call_stub: r15_thread is modified by call"); diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index efbdac8244d..fecc804a044 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -204,10 +204,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, } if (JvmtiExport::can_pop_frame()) { - __ check_and_handle_popframe(r15_thread); + __ check_and_handle_popframe(); } if (JvmtiExport::can_force_early_return()) { - __ check_and_handle_earlyret(r15_thread); + __ check_and_handle_earlyret(); } __ dispatch_next(state, step); @@ -991,7 +991,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { Label Continue; Label slow_path; - __ safepoint_poll(slow_path, thread, true /* at_return */, false /* in_nmethod */); + __ safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); __ cmpl(Address(thread, JavaThread::suspend_flags_offset()), 0); __ jcc(Assembler::equal, Continue); @@ -1034,7 +1034,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { } // reset_last_Java_frame - __ reset_last_Java_frame(thread, true); + __ reset_last_Java_frame(true); if (CheckJNICalls) { // clear_pending_jni_exception_check @@ -1057,7 +1057,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ pop(ltos); // Unbox oop result, e.g. JNIHandles::resolve value. __ resolve_jobject(rax /* value */, - thread /* thread */, t /* tmp */); __ movptr(Address(rbp, frame::interpreter_frame_oop_temp_offset*wordSize), rax); // keep stack depth as expected by pushing oop which will eventually be discarded @@ -1495,7 +1494,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // PC must point into interpreter here __ set_last_Java_frame(noreg, rbp, __ pc(), rscratch1); __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), r15_thread, c_rarg1, c_rarg2); - __ reset_last_Java_frame(thread, true); + __ reset_last_Java_frame(true); // Restore the last_sp and null it out __ movptr(rcx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); @@ -1548,7 +1547,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // remove the activation (without doing throws on illegalMonitorExceptions) __ remove_activation(vtos, rdx, false, true, false); // restore exception - __ get_vm_result(rax, thread); + __ get_vm_result(rax); // In between activations - previous activation type unknown yet // compute continuation point - the continuation point expects the diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp index f4ed1081c3b..6be702f2699 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp @@ -190,7 +190,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { // c_rarg1: scratch (rsi on non-Win64, rdx on Win64) Label slow_path; - __ safepoint_poll(slow_path, r15_thread, true /* at_return */, false /* in_nmethod */); + __ safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); // We don't generate local frame and don't align stack because // we call stub code and there is no safepoint on this path. @@ -234,7 +234,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // r13: senderSP must preserved for slow path, set SP to it on fast path Label slow_path; - __ safepoint_poll(slow_path, r15_thread, false /* at_return */, false /* in_nmethod */); + __ safepoint_poll(slow_path, false /* at_return */, false /* in_nmethod */); // We don't generate local frame and don't align stack because // we call stub code and there is no safepoint on this path. diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp index b378bc431fa..1641abac923 100644 --- a/src/hotspot/cpu/x86/templateTable_x86.cpp +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp @@ -478,7 +478,7 @@ void TemplateTable::condy_helper(Label& Done) { const Register rarg = c_rarg1; __ movl(rarg, (int)bytecode()); call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg); - __ get_vm_result_2(flags, r15_thread); + __ get_vm_result_2(flags); // VMr = obj = base address to find primitive value to push // VMr2 = flags = (tos, off) using format of CPCE::_flags __ movl(off, flags); @@ -2263,12 +2263,10 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no, if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) { const Register method = temp; const Register klass = temp; - const Register thread = r15_thread; - assert(thread != noreg, "x86_32 not supported"); __ movptr(method, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); __ load_method_holder(klass, method); - __ clinit_barrier(klass, thread, nullptr /*L_fast_path*/, &L_clinit_barrier_slow); + __ clinit_barrier(klass, nullptr /*L_fast_path*/, &L_clinit_barrier_slow); } } @@ -3572,7 +3570,7 @@ void TemplateTable::_new() { // make sure klass is initialized // init_state needs acquire, but x86 is TSO, and so we are already good. assert(VM_Version::supports_fast_class_init_checks(), "must support fast class initialization checks"); - __ clinit_barrier(rcx, r15_thread, nullptr /*L_fast_path*/, &slow_case); + __ clinit_barrier(rcx, nullptr /*L_fast_path*/, &slow_case); // get instance_size in InstanceKlass (scaled to a count of bytes) __ movl(rdx, Address(rcx, Klass::layout_helper_offset())); @@ -3712,7 +3710,7 @@ void TemplateTable::checkcast() { call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); // vm_result_2 has metadata result - __ get_vm_result_2(rax, r15_thread); + __ get_vm_result_2(rax); __ pop_ptr(rdx); // restore receiver __ jmpb(resolved); @@ -3767,9 +3765,9 @@ void TemplateTable::instanceof() { __ push(atos); // save receiver for result, and for GC call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(rax, r15_thread); + // vm_result_2 has metadata result + __ get_vm_result_2(rax); __ pop_ptr(rdx); // restore receiver __ verify_oop(rdx); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index b94ff7dbd9e..5781ffce4bd 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -845,7 +845,7 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { Register klass = rscratch1; __ mov_metadata(klass, C->method()->holder()->constant_encoding()); - __ clinit_barrier(klass, r15_thread, &L_skip_barrier /*L_fast_path*/); + __ clinit_barrier(klass, &L_skip_barrier /*L_fast_path*/); __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); // slow path @@ -943,7 +943,7 @@ void MachEpilogNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub, r15_thread, true /* at_return */, true /* in_nmethod */); + __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */); } } From 9ee5590328e7d5f5070efdbd7ffc44cb660005cc Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Wed, 9 Apr 2025 08:01:13 +0000 Subject: [PATCH 076/843] 8334046: Set different values for CompLevel_any and CompLevel_all Reviewed-by: shade, kvn --- src/hotspot/share/compiler/compilerDefinitions.hpp | 2 +- .../jtreg/compiler/whitebox/CompilerWhiteBoxTest.java | 8 +++++--- test/lib/jdk/test/whitebox/WhiteBox.java | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index bdaa6dffb8f..2c1ae85af8a 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -53,7 +53,7 @@ enum MethodCompilation { // Enumeration to distinguish tiers of compilation enum CompLevel : s1 { - CompLevel_any = -1, // Used for querying the state + CompLevel_any = -2, // Used for querying the state CompLevel_all = -1, // Used for changing the state CompLevel_none = 0, // Interpreter CompLevel_simple = 1, // C1 diff --git a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java index f87292be019..dde2b3cdfd0 100644 --- a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java +++ b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java @@ -41,8 +41,10 @@ import java.util.function.Function; public abstract class CompilerWhiteBoxTest { /** {@code CompLevel::CompLevel_none} -- Interpreter */ public static final int COMP_LEVEL_NONE = 0; - /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */ - public static final int COMP_LEVEL_ANY = -1; + /** {@code CompLevel::CompLevel_any} */ + public static final int COMP_LEVEL_ANY = -2; + /** {@code CompLevel::CompLevel_all} */ + public static final int COMP_LEVEL_ALL = -1; /** {@code CompLevel::CompLevel_simple} -- C1 */ public static final int COMP_LEVEL_SIMPLE = 1; /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation & backedge counters */ @@ -284,7 +286,7 @@ public abstract class CompilerWhiteBoxTest { } protected final void makeNotCompilable() { - WHITE_BOX.makeMethodNotCompilable(method, COMP_LEVEL_ANY, + WHITE_BOX.makeMethodNotCompilable(method, COMP_LEVEL_ALL, testCase.isOsr()); } diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index f0e164d94b5..2744978b8a9 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -345,7 +345,7 @@ public class WhiteBox { return isMethodCompiled0(method, isOsr); } public boolean isMethodCompilable(Executable method) { - return isMethodCompilable(method, -1 /*any*/); + return isMethodCompilable(method, -2 /*any*/); } public boolean isMethodCompilable(Executable method, int compLevel) { return isMethodCompilable(method, compLevel, false /*not osr*/); @@ -393,7 +393,7 @@ public class WhiteBox { return deoptimizeMethod0(method, isOsr); } public void makeMethodNotCompilable(Executable method) { - makeMethodNotCompilable(method, -1 /*any*/); + makeMethodNotCompilable(method, -1 /*all*/); } public void makeMethodNotCompilable(Executable method, int compLevel) { makeMethodNotCompilable(method, compLevel, false /*not osr*/); From 250eb743c112fbcc45bf2b3ded1c644b19893577 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 9 Apr 2025 08:22:48 +0000 Subject: [PATCH 077/843] 8353192: C2: Clean up x86 backend after 32-bit x86 removal Reviewed-by: kvn, epeter --- src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp | 14 - src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 119 +----- src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 21 +- src/hotspot/cpu/x86/matcher_x86.hpp | 31 -- src/hotspot/cpu/x86/x86.ad | 377 +++--------------- src/hotspot/share/adlc/archDesc.cpp | 3 +- 6 files changed, 73 insertions(+), 492 deletions(-) diff --git a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp index 83ecdee5219..b4f8e9d9514 100644 --- a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp +++ b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp @@ -43,22 +43,8 @@ void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { __ bind(entry()); InternalAddress safepoint_pc(masm.pc() - masm.offset() + _safepoint_offset); -#ifdef _LP64 __ lea(rscratch1, safepoint_pc); __ movptr(Address(r15_thread, JavaThread::saved_exception_pc_offset()), rscratch1); -#else - const Register tmp1 = rcx; - const Register tmp2 = rdx; - __ push(tmp1); - __ push(tmp2); - - __ lea(tmp1, safepoint_pc); - __ get_thread(tmp2); - __ movptr(Address(tmp2, JavaThread::saved_exception_pc_offset()), tmp1); - - __ pop(tmp2); - __ pop(tmp1); -#endif __ jump(callback_addr); } diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index b6d513f50f2..9ca46333668 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -107,16 +107,6 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool movptr(Address(rsp, framesize), (int32_t)0xbadb100d); } -#ifndef _LP64 - // If method sets FPU control word do it now - if (fp_mode_24b) { - fldcw(ExternalAddress(StubRoutines::x86::addr_fpu_cntrl_wrd_24())); - } - if (UseSSE >= 2 && VerifyFPU) { - verify_FPU(0, "FPU stack must be clean on entry"); - } -#endif - #ifdef ASSERT if (VerifyStackAtCalls) { Label L; @@ -133,7 +123,6 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool if (!is_stub) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - #ifdef _LP64 // We put the non-hot code of the nmethod entry barrier out-of-line in a stub. Label dummy_slow_path; Label dummy_continuation; @@ -147,10 +136,6 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool continuation = &stub->continuation(); } bs->nmethod_entry_barrier(this, slow_path, continuation); -#else - // Don't bother with out-of-line nmethod entry barrier stub for x86_32. - bs->nmethod_entry_barrier(this, nullptr /* slow_path */, nullptr /* continuation */); -#endif } } @@ -299,7 +284,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp // Locked by current thread if difference with current SP is less than one page. subptr(tmpReg, rsp); // Next instruction set ZFlag == 1 (Success) if difference is less then one page. - andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - (int)os::vm_page_size())) ); + andptr(tmpReg, (int32_t) (7 - (int)os::vm_page_size()) ); movptr(Address(boxReg, 0), tmpReg); } jmp(DONE_LABEL); @@ -307,10 +292,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp bind(IsInflated); // The object is inflated. tmpReg contains pointer to ObjectMonitor* + markWord::monitor_value -#ifndef _LP64 - // Just take slow path to avoid dealing with 64 bit atomic instructions here. - orl(boxReg, 1); // set ICC.ZF=0 to indicate failure -#else // Unconditionally set box->_displaced_header = markWord::unused_mark(). // Without cast to int32_t this style of movptr will destroy r10 which is typically obj. movptr(Address(boxReg, 0), checked_cast(markWord::unused_mark().value())); @@ -329,7 +310,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp jccb(Assembler::notEqual, NO_COUNT); // If not recursive, ZF = 0 at this point (fail) incq(Address(scrReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); xorq(rax, rax); // Set ZF = 1 (success) for recursive lock, denoting locking success -#endif // _LP64 bind(DONE_LABEL); // ZFlag == 1 count in fast path @@ -338,10 +318,8 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp bind(COUNT); if (LockingMode == LM_LEGACY) { -#ifdef _LP64 // Count monitors in fast path increment(Address(thread, JavaThread::held_monitor_count_offset())); -#endif } xorl(tmpReg, tmpReg); // Set ZF == 1 @@ -404,11 +382,6 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t // It's inflated. -#ifndef _LP64 - // Just take slow path to avoid dealing with 64 bit atomic instructions here. - orl(boxReg, 1); // set ICC.ZF=0 to indicate failure - jmpb(DONE_LABEL); -#else // Despite our balanced locking property we still check that m->_owner == Self // as java routines or native JNI code called by this thread might // have released the lock. @@ -462,7 +435,6 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t bind (LSuccess); testl (boxReg, 0); // set ICC.ZF=1 to indicate success jmpb (DONE_LABEL); -#endif // _LP64 if (LockingMode == LM_LEGACY) { bind (Stacked); @@ -482,9 +454,7 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t if (LockingMode == LM_LEGACY) { // Count monitors in fast path -#ifdef _LP64 decrementq(Address(r15_thread, JavaThread::held_monitor_count_offset())); -#endif } xorl(tmpReg, tmpReg); // Set ZF == 1 @@ -563,11 +533,6 @@ void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Regist { // Handle inflated monitor. bind(inflated); -#ifndef _LP64 - // Just take slow path to avoid dealing with 64 bit atomic instructions here. - orl(box, 1); // set ICC.ZF=0 to indicate failure - jmpb(slow_path); -#else const Register monitor = t; if (!UseObjectMonitorTable) { @@ -633,7 +598,6 @@ void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Regist increment(recursions_address); bind(monitor_locked); -#endif // _LP64 } bind(locked); @@ -746,11 +710,6 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, bind(inflated); -#ifndef _LP64 - // Just take slow path to avoid dealing with 64 bit atomic instructions here. - orl(t, 1); // set ICC.ZF=0 to indicate failure - jmpb(slow_path); -#else if (!UseObjectMonitorTable) { assert(mark == monitor, "should be the same here"); } else { @@ -800,7 +759,6 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, // Recursive unlock. bind(recursive); decrement(recursions_address); -#endif // _LP64 } bind(unlocked); @@ -1522,7 +1480,6 @@ void C2_MacroAssembler::vinsert(BasicType typ, XMMRegister dst, XMMRegister src, } } -#ifdef _LP64 void C2_MacroAssembler::vgather8b_masked_offset(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, @@ -1561,7 +1518,6 @@ void C2_MacroAssembler::vgather8b_masked_offset(BasicType elem_bt, } } } -#endif // _LP64 void C2_MacroAssembler::vgather8b_offset(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, @@ -1633,7 +1589,7 @@ void C2_MacroAssembler::vgather_subword(BasicType elem_ty, XMMRegister dst, if (mask == noreg) { vgather8b_offset(elem_ty, temp_dst, base, idx_base, offset, rtmp, vlen_enc); } else { - LP64_ONLY(vgather8b_masked_offset(elem_ty, temp_dst, base, idx_base, offset, mask, mask_idx, rtmp, vlen_enc)); + vgather8b_masked_offset(elem_ty, temp_dst, base, idx_base, offset, mask, mask_idx, rtmp, vlen_enc); } // TEMP_PERM_VEC(temp_dst) = PERMUTE TMP_VEC_64(temp_dst) PERM_INDEX(xtmp1) vpermd(temp_dst, xtmp1, temp_dst, vlen_enc == Assembler::AVX_512bit ? vlen_enc : Assembler::AVX_256bit); @@ -2037,7 +1993,6 @@ void C2_MacroAssembler::reduceI(int opcode, int vlen, } } -#ifdef _LP64 void C2_MacroAssembler::reduceL(int opcode, int vlen, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2) { @@ -2049,7 +2004,6 @@ void C2_MacroAssembler::reduceL(int opcode, int vlen, default: assert(false, "wrong vector length"); } } -#endif // _LP64 void C2_MacroAssembler::reduceF(int opcode, int vlen, XMMRegister dst, XMMRegister src, XMMRegister vtmp1, XMMRegister vtmp2) { switch (vlen) { @@ -2299,7 +2253,6 @@ void C2_MacroAssembler::reduce32S(int opcode, Register dst, Register src1, XMMRe reduce16S(opcode, dst, src1, vtmp1, vtmp1, vtmp2); } -#ifdef _LP64 void C2_MacroAssembler::reduce2L(int opcode, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2) { pshufd(vtmp2, src2, 0xE); reduce_operation_128(T_LONG, opcode, vtmp2, src2); @@ -2325,7 +2278,6 @@ void C2_MacroAssembler::genmask(KRegister dst, Register len, Register temp) { bzhiq(temp, temp, len); kmovql(dst, temp); } -#endif // _LP64 void C2_MacroAssembler::reduce2F(int opcode, XMMRegister dst, XMMRegister src, XMMRegister vtmp) { reduce_operation_128(T_FLOAT, opcode, dst, src); @@ -2741,7 +2693,6 @@ void C2_MacroAssembler::vpadd(BasicType elem_bt, XMMRegister dst, XMMRegister sr } } -#ifdef _LP64 void C2_MacroAssembler::vpbroadcast(BasicType elem_bt, XMMRegister dst, Register src, int vlen_enc) { assert(UseAVX >= 2, "required"); bool is_bw = ((elem_bt == T_BYTE) || (elem_bt == T_SHORT)); @@ -2770,7 +2721,6 @@ void C2_MacroAssembler::vpbroadcast(BasicType elem_bt, XMMRegister dst, Register } } } -#endif void C2_MacroAssembler::vconvert_b2x(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vlen_enc) { switch (to_elem_bt) { @@ -3698,7 +3648,7 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, XMMRegister vec1, int ae, KRegister mask) { ShortBranchVerifier sbv(this); Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; - Label COMPARE_WIDE_VECTORS_LOOP_FAILED; // used only _LP64 && AVX3 + Label COMPARE_WIDE_VECTORS_LOOP_FAILED; // used only AVX3 int stride, stride2, adr_stride, adr_stride1, adr_stride2; int stride2x2 = 0x40; Address::ScaleFactor scale = Address::no_scale; @@ -3768,7 +3718,7 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR; Label COMPARE_WIDE_VECTORS_LOOP_AVX2; Label COMPARE_TAIL_LONG; - Label COMPARE_WIDE_VECTORS_LOOP_AVX3; // used only _LP64 && AVX3 + Label COMPARE_WIDE_VECTORS_LOOP_AVX3; // used only AVX3 int pcmpmask = 0x19; if (ae == StrIntrinsicNode::LL) { @@ -3838,7 +3788,6 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, // In a loop, compare 16-chars (32-bytes) at once using (vpxor+vptest) bind(COMPARE_WIDE_VECTORS_LOOP); -#ifdef _LP64 if ((AVX3Threshold == 0) && VM_Version::supports_avx512vlbw()) { // trying 64 bytes fast loop cmpl(cnt2, stride2x2); jccb(Assembler::below, COMPARE_WIDE_VECTORS_LOOP_AVX2); @@ -3862,8 +3811,6 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, vpxor(vec1, vec1); jmpb(COMPARE_WIDE_TAIL); }//if (VM_Version::supports_avx512vlbw()) -#endif // _LP64 - bind(COMPARE_WIDE_VECTORS_LOOP_AVX2); if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) { @@ -4032,7 +3979,6 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, } jmpb(DONE_LABEL); -#ifdef _LP64 if (VM_Version::supports_avx512vlbw()) { bind(COMPARE_WIDE_VECTORS_LOOP_FAILED); @@ -4058,7 +4004,6 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, subl(result, cnt1); jmpb(POP_LABEL); }//if (VM_Version::supports_avx512vlbw()) -#endif // _LP64 // Discard the stored length difference bind(POP_LABEL); @@ -4133,7 +4078,6 @@ void C2_MacroAssembler::count_positives(Register ary1, Register len, // check the tail for absense of negatives // ~(~0 << len) applied up to two times (for 32-bit scenario) -#ifdef _LP64 { Register tmp3_aliased = len; mov64(tmp3_aliased, 0xFFFFFFFFFFFFFFFF); @@ -4141,33 +4085,7 @@ void C2_MacroAssembler::count_positives(Register ary1, Register len, notq(tmp3_aliased); kmovql(mask2, tmp3_aliased); } -#else - Label k_init; - jmp(k_init); - // We could not read 64-bits from a general purpose register thus we move - // data required to compose 64 1's to the instruction stream - // We emit 64 byte wide series of elements from 0..63 which later on would - // be used as a compare targets with tail count contained in tmp1 register. - // Result would be a k register having tmp1 consecutive number or 1 - // counting from least significant bit. - address tmp = pc(); - emit_int64(0x0706050403020100); - emit_int64(0x0F0E0D0C0B0A0908); - emit_int64(0x1716151413121110); - emit_int64(0x1F1E1D1C1B1A1918); - emit_int64(0x2726252423222120); - emit_int64(0x2F2E2D2C2B2A2928); - emit_int64(0x3736353433323130); - emit_int64(0x3F3E3D3C3B3A3938); - - bind(k_init); - lea(len, InternalAddress(tmp)); - // create mask to test for negative byte inside a vector - evpbroadcastb(vec1, tmp1, Assembler::AVX_512bit); - evpcmpgtb(mask2, vec1, Address(len, 0), Assembler::AVX_512bit); - -#endif evpcmpgtb(mask1, mask2, vec2, Address(ary1, 0), Assembler::AVX_512bit); ktestq(mask1, mask2); jcc(Assembler::zero, DONE); @@ -4414,7 +4332,6 @@ void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register lea(ary2, Address(ary2, limit, Address::times_1)); negptr(limit); -#ifdef _LP64 if ((AVX3Threshold == 0) && VM_Version::supports_avx512vlbw()) { // trying 64 bytes fast loop Label COMPARE_WIDE_VECTORS_LOOP_AVX2, COMPARE_WIDE_VECTORS_LOOP_AVX3; @@ -4451,7 +4368,7 @@ void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register bind(COMPARE_WIDE_VECTORS_LOOP_AVX2); }//if (VM_Version::supports_avx512vlbw()) -#endif //_LP64 + bind(COMPARE_WIDE_VECTORS); vmovdqu(vec1, Address(ary1, limit, scaleFactor)); if (expand_ary2) { @@ -4618,8 +4535,6 @@ void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register } } -#ifdef _LP64 - static void convertF2I_slowpath(C2_MacroAssembler& masm, C2GeneralStub& stub) { #define __ masm. Register dst = stub.data<0>(); @@ -4666,8 +4581,6 @@ void C2_MacroAssembler::convertF2I(BasicType dst_bt, BasicType src_bt, Register bind(stub->continuation()); } -#endif // _LP64 - void C2_MacroAssembler::evmasked_op(int ideal_opc, BasicType eType, KRegister mask, XMMRegister dst, XMMRegister src1, int imm8, bool merge, int vlen_enc) { switch(ideal_opc) { @@ -5327,7 +5240,6 @@ void C2_MacroAssembler::vector_castD2X_evex(BasicType to_elem_bt, XMMRegister ds } } -#ifdef _LP64 void C2_MacroAssembler::vector_round_double_evex(XMMRegister dst, XMMRegister src, AddressLiteral double_sign_flip, AddressLiteral new_mxcsr, int vec_enc, Register tmp, XMMRegister xtmp1, XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2) { @@ -5379,7 +5291,6 @@ void C2_MacroAssembler::vector_round_float_avx(XMMRegister dst, XMMRegister src, ldmxcsr(ExternalAddress(StubRoutines::x86::addr_mxcsr_std()), tmp /*rscratch*/); } -#endif // _LP64 void C2_MacroAssembler::vector_unsigned_cast(XMMRegister dst, XMMRegister src, int vlen_enc, BasicType from_elem_bt, BasicType to_elem_bt) { @@ -5510,7 +5421,6 @@ void C2_MacroAssembler::evpternlog(XMMRegister dst, int func, KRegister mask, XM } } -#ifdef _LP64 void C2_MacroAssembler::vector_long_to_maskvec(XMMRegister dst, Register src, Register rtmp1, Register rtmp2, XMMRegister xtmp, int mask_len, int vec_enc) { @@ -5768,7 +5678,6 @@ void C2_MacroAssembler::vector_compress_expand(int opcode, XMMRegister dst, XMMR } } } -#endif void C2_MacroAssembler::vector_signum_evex(int opcode, XMMRegister dst, XMMRegister src, XMMRegister zero, XMMRegister one, KRegister ktmp1, int vec_enc) { @@ -5833,10 +5742,8 @@ void C2_MacroAssembler::vector_maskall_operation(KRegister dst, Register src, in void C2_MacroAssembler::vbroadcast(BasicType bt, XMMRegister dst, int imm32, Register rtmp, int vec_enc) { int lane_size = type2aelembytes(bt); - bool is_LP64 = LP64_ONLY(true) NOT_LP64(false); - if ((is_LP64 || lane_size < 8) && - ((is_non_subword_integral_type(bt) && VM_Version::supports_avx512vl()) || - (is_subword_type(bt) && VM_Version::supports_avx512vlbw()))) { + if ((is_non_subword_integral_type(bt) && VM_Version::supports_avx512vl()) || + (is_subword_type(bt) && VM_Version::supports_avx512vlbw())) { movptr(rtmp, imm32); switch(lane_size) { case 1 : evpbroadcastb(dst, rtmp, vec_enc); break; @@ -5848,7 +5755,7 @@ void C2_MacroAssembler::vbroadcast(BasicType bt, XMMRegister dst, int imm32, Reg } } else { movptr(rtmp, imm32); - LP64_ONLY(movq(dst, rtmp)) NOT_LP64(movdl(dst, rtmp)); + movq(dst, rtmp); switch(lane_size) { case 1 : vpbroadcastb(dst, dst, vec_enc); break; case 2 : vpbroadcastw(dst, dst, vec_enc); break; @@ -5983,14 +5890,6 @@ void C2_MacroAssembler::vector_popcount_integral_evex(BasicType bt, XMMRegister } } -#ifndef _LP64 -void C2_MacroAssembler::vector_maskall_operation32(KRegister dst, Register src, KRegister tmp, int mask_len) { - assert(VM_Version::supports_avx512bw(), ""); - kmovdl(tmp, src); - kunpckdql(dst, tmp, tmp); -} -#endif - // Bit reversal algorithm first reverses the bits of each byte followed by // a byte level reversal for multi-byte primitive types (short/int/long). // Algorithm performs a lookup table access to get reverse bit sequence @@ -6450,7 +6349,6 @@ void C2_MacroAssembler::udivmodI(Register rax, Register divisor, Register rdx, R bind(done); } -#ifdef _LP64 void C2_MacroAssembler::reverseI(Register dst, Register src, XMMRegister xtmp1, XMMRegister xtmp2, Register rtmp) { if(VM_Version::supports_gfni()) { @@ -6614,7 +6512,6 @@ void C2_MacroAssembler::udivmodL(Register rax, Register divisor, Register rdx, R subq(rdx, tmp); // remainder bind(done); } -#endif void C2_MacroAssembler::rearrange_bytes(XMMRegister dst, XMMRegister shuffle, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, KRegister ktmp, diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 29380609b9a..2c5fb4b516a 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -130,9 +130,7 @@ public: // Covert B2X void vconvert_b2x(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vlen_enc); -#ifdef _LP64 void vpbroadcast(BasicType elem_bt, XMMRegister dst, Register src, int vlen_enc); -#endif // blend void evpcmp(BasicType typ, KRegister kdmask, KRegister ksmask, XMMRegister src1, XMMRegister src2, int comparison, int vector_len); @@ -152,10 +150,8 @@ public: // dst = src1 reduce(op, src2) using vtmp as temps void reduceI(int opcode, int vlen, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2); -#ifdef _LP64 void reduceL(int opcode, int vlen, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2); void genmask(KRegister dst, Register len, Register temp); -#endif // _LP64 // dst = reduce(op, src2) using vtmp as temps void reduce_fp(int opcode, int vlen, @@ -202,11 +198,9 @@ public: void reduce32S(int opcode, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2); // Long Reduction -#ifdef _LP64 void reduce2L(int opcode, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2); void reduce4L(int opcode, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2); void reduce8L(int opcode, Register dst, Register src1, XMMRegister src2, XMMRegister vtmp1, XMMRegister vtmp2); -#endif // _LP64 // Float Reduction void reduce2F (int opcode, XMMRegister dst, XMMRegister src, XMMRegister vtmp); @@ -237,7 +231,6 @@ public: void unordered_reduce_operation_256(BasicType typ, int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2); public: -#ifdef _LP64 void vector_mask_operation_helper(int opc, Register dst, Register tmp, int masklen); void vector_mask_operation(int opc, Register dst, KRegister mask, Register tmp, int masklen, int masksize, int vec_enc); @@ -246,14 +239,9 @@ public: Register tmp, int masklen, BasicType bt, int vec_enc); void vector_long_to_maskvec(XMMRegister dst, Register src, Register rtmp1, Register rtmp2, XMMRegister xtmp, int mask_len, int vec_enc); -#endif void vector_maskall_operation(KRegister dst, Register src, int mask_len); -#ifndef _LP64 - void vector_maskall_operation32(KRegister dst, Register src, KRegister ktmp, int mask_len); -#endif - void string_indexof_char(Register str1, Register cnt1, Register ch, Register result, XMMRegister vec1, XMMRegister vec2, XMMRegister vec3, Register tmp); @@ -313,9 +301,7 @@ public: void arrays_hashcode_elvload(XMMRegister dst, AddressLiteral src, BasicType eltype); void arrays_hashcode_elvcast(XMMRegister dst, BasicType eltype); -#ifdef _LP64 void convertF2I(BasicType dst_bt, BasicType src_bt, Register dst, XMMRegister src); -#endif void evmasked_op(int ideal_opc, BasicType eType, KRegister mask, XMMRegister dst, XMMRegister src1, XMMRegister src2, @@ -390,7 +376,6 @@ public: void vector_mask_cast(XMMRegister dst, XMMRegister src, BasicType dst_bt, BasicType src_bt, int vlen); -#ifdef _LP64 void vector_round_double_evex(XMMRegister dst, XMMRegister src, AddressLiteral double_sign_flip, AddressLiteral new_mxcsr, int vec_enc, Register tmp, XMMRegister xtmp1, XMMRegister xtmp2, KRegister ktmp1, KRegister ktmp2); @@ -403,13 +388,11 @@ public: void vector_compress_expand_avx2(int opcode, XMMRegister dst, XMMRegister src, XMMRegister mask, Register rtmp, Register rscratch, XMMRegister permv, XMMRegister xtmp, BasicType bt, int vec_enc); -#endif // _LP64 void udivI(Register rax, Register divisor, Register rdx); void umodI(Register rax, Register divisor, Register rdx); void udivmodI(Register rax, Register divisor, Register rdx, Register tmp); -#ifdef _LP64 void reverseI(Register dst, Register src, XMMRegister xtmp1, XMMRegister xtmp2, Register rtmp); void reverseL(Register dst, Register src, XMMRegister xtmp1, @@ -417,7 +400,6 @@ public: void udivL(Register rax, Register divisor, Register rdx); void umodL(Register rax, Register divisor, Register rdx); void udivmodL(Register rax, Register divisor, Register rdx, Register tmp); -#endif void evpternlog(XMMRegister dst, int func, KRegister mask, XMMRegister src2, XMMRegister src3, bool merge, BasicType bt, int vlen_enc); @@ -511,10 +493,9 @@ public: Register mask, XMMRegister xtmp1, XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, Register midx, Register length, int vector_len, int vlen_enc); -#ifdef _LP64 void vgather8b_masked_offset(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, Register offset, Register mask, Register midx, Register rtmp, int vlen_enc); -#endif + void vgather8b_offset(BasicType elem_bt, XMMRegister dst, Register base, Register idx_base, Register offset, Register rtmp, int vlen_enc); diff --git a/src/hotspot/cpu/x86/matcher_x86.hpp b/src/hotspot/cpu/x86/matcher_x86.hpp index 78591989b5b..41486c244b2 100644 --- a/src/hotspot/cpu/x86/matcher_x86.hpp +++ b/src/hotspot/cpu/x86/matcher_x86.hpp @@ -59,53 +59,34 @@ static constexpr bool isSimpleConstant64(jlong value) { // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. //return value == (int) value; // Cf. storeImmL and immL32. - // Probably always true, even if a temp register is required. -#ifdef _LP64 return true; -#else - return false; -#endif } -#ifdef _LP64 // No additional cost for CMOVL. static constexpr int long_cmove_cost() { return 0; } -#else - // Needs 2 CMOV's for longs. - static constexpr int long_cmove_cost() { return 1; } -#endif -#ifdef _LP64 // No CMOVF/CMOVD with SSE2 static int float_cmove_cost() { return ConditionalMoveLimit; } -#else - // No CMOVF/CMOVD with SSE/SSE2 - static int float_cmove_cost() { return (UseSSE>=1) ? ConditionalMoveLimit : 0; } -#endif static bool narrow_oop_use_complex_address() { - NOT_LP64(ShouldNotCallThis();) assert(UseCompressedOops, "only for compressed oops code"); return (LogMinObjAlignmentInBytes <= 3); } static bool narrow_klass_use_complex_address() { - NOT_LP64(ShouldNotCallThis();) assert(UseCompressedClassPointers, "only for compressed klass code"); return (CompressedKlassPointers::shift() <= 3); } // Prefer ConN+DecodeN over ConP. static bool const_oop_prefer_decode() { - NOT_LP64(ShouldNotCallThis();) // Prefer ConN+DecodeN over ConP. return true; } // Prefer ConP over ConNKlass+DecodeNKlass. static bool const_klass_prefer_decode() { - NOT_LP64(ShouldNotCallThis();) return false; } @@ -123,24 +104,12 @@ // Are floats converted to double when stored to stack during deoptimization? // On x64 it is stored without conversion so we can use normal access. - // On x32 it is stored with conversion only when FPU is used for floats. -#ifdef _LP64 static constexpr bool float_in_double() { return false; } -#else - static bool float_in_double() { - return (UseSSE == 0); - } -#endif // Do ints take an entire long register or just half? -#ifdef _LP64 static const bool int_in_long = true; -#else - static const bool int_in_long = false; -#endif - // Does the CPU supports vector variable shift instructions? static bool supports_vector_variable_shifts(void) { diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index afa1a92287d..2d7548c37a8 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -210,8 +210,6 @@ reg_def XMM7n( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(13)); reg_def XMM7o( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(14)); reg_def XMM7p( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(15)); -#ifdef _LP64 - reg_def XMM8 ( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()); reg_def XMM8b( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(1)); reg_def XMM8c( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(2)); @@ -620,13 +618,7 @@ reg_def XMM31n( SOC, SOC, Op_RegF, 31, xmm31->as_VMReg()->next(13)); reg_def XMM31o( SOC, SOC, Op_RegF, 31, xmm31->as_VMReg()->next(14)); reg_def XMM31p( SOC, SOC, Op_RegF, 31, xmm31->as_VMReg()->next(15)); -#endif // _LP64 - -#ifdef _LP64 reg_def RFLAGS(SOC, SOC, 0, 16, VMRegImpl::Bad()); -#else -reg_def RFLAGS(SOC, SOC, 0, 8, VMRegImpl::Bad()); -#endif // _LP64 // AVX3 Mask Registers. reg_def K1 (SOC, SOC, Op_RegI, 1, k1->as_VMReg()); @@ -658,17 +650,16 @@ alloc_class chunk1(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM0h, XMM4, XMM4b, XMM4c, XMM4d, XMM4e, XMM4f, XMM4g, XMM4h, XMM4i, XMM4j, XMM4k, XMM4l, XMM4m, XMM4n, XMM4o, XMM4p, XMM5, XMM5b, XMM5c, XMM5d, XMM5e, XMM5f, XMM5g, XMM5h, XMM5i, XMM5j, XMM5k, XMM5l, XMM5m, XMM5n, XMM5o, XMM5p, XMM6, XMM6b, XMM6c, XMM6d, XMM6e, XMM6f, XMM6g, XMM6h, XMM6i, XMM6j, XMM6k, XMM6l, XMM6m, XMM6n, XMM6o, XMM6p, - XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, XMM7i, XMM7j, XMM7k, XMM7l, XMM7m, XMM7n, XMM7o, XMM7p -#ifdef _LP64 - ,XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM8i, XMM8j, XMM8k, XMM8l, XMM8m, XMM8n, XMM8o, XMM8p, + XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, XMM7i, XMM7j, XMM7k, XMM7l, XMM7m, XMM7n, XMM7o, XMM7p, + XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM8i, XMM8j, XMM8k, XMM8l, XMM8m, XMM8n, XMM8o, XMM8p, XMM9, XMM9b, XMM9c, XMM9d, XMM9e, XMM9f, XMM9g, XMM9h, XMM9i, XMM9j, XMM9k, XMM9l, XMM9m, XMM9n, XMM9o, XMM9p, XMM10, XMM10b, XMM10c, XMM10d, XMM10e, XMM10f, XMM10g, XMM10h, XMM10i, XMM10j, XMM10k, XMM10l, XMM10m, XMM10n, XMM10o, XMM10p, XMM11, XMM11b, XMM11c, XMM11d, XMM11e, XMM11f, XMM11g, XMM11h, XMM11i, XMM11j, XMM11k, XMM11l, XMM11m, XMM11n, XMM11o, XMM11p, XMM12, XMM12b, XMM12c, XMM12d, XMM12e, XMM12f, XMM12g, XMM12h, XMM12i, XMM12j, XMM12k, XMM12l, XMM12m, XMM12n, XMM12o, XMM12p, XMM13, XMM13b, XMM13c, XMM13d, XMM13e, XMM13f, XMM13g, XMM13h, XMM13i, XMM13j, XMM13k, XMM13l, XMM13m, XMM13n, XMM13o, XMM13p, XMM14, XMM14b, XMM14c, XMM14d, XMM14e, XMM14f, XMM14g, XMM14h, XMM14i, XMM14j, XMM14k, XMM14l, XMM14m, XMM14n, XMM14o, XMM14p, - XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h, XMM15i, XMM15j, XMM15k, XMM15l, XMM15m, XMM15n, XMM15o, XMM15p - ,XMM16, XMM16b, XMM16c, XMM16d, XMM16e, XMM16f, XMM16g, XMM16h, XMM16i, XMM16j, XMM16k, XMM16l, XMM16m, XMM16n, XMM16o, XMM16p, + XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h, XMM15i, XMM15j, XMM15k, XMM15l, XMM15m, XMM15n, XMM15o, XMM15p, + XMM16, XMM16b, XMM16c, XMM16d, XMM16e, XMM16f, XMM16g, XMM16h, XMM16i, XMM16j, XMM16k, XMM16l, XMM16m, XMM16n, XMM16o, XMM16p, XMM17, XMM17b, XMM17c, XMM17d, XMM17e, XMM17f, XMM17g, XMM17h, XMM17i, XMM17j, XMM17k, XMM17l, XMM17m, XMM17n, XMM17o, XMM17p, XMM18, XMM18b, XMM18c, XMM18d, XMM18e, XMM18f, XMM18g, XMM18h, XMM18i, XMM18j, XMM18k, XMM18l, XMM18m, XMM18n, XMM18o, XMM18p, XMM19, XMM19b, XMM19c, XMM19d, XMM19e, XMM19f, XMM19g, XMM19h, XMM19i, XMM19j, XMM19k, XMM19l, XMM19m, XMM19n, XMM19o, XMM19p, @@ -683,9 +674,7 @@ alloc_class chunk1(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM0h, XMM28, XMM28b, XMM28c, XMM28d, XMM28e, XMM28f, XMM28g, XMM28h, XMM28i, XMM28j, XMM28k, XMM28l, XMM28m, XMM28n, XMM28o, XMM28p, XMM29, XMM29b, XMM29c, XMM29d, XMM29e, XMM29f, XMM29g, XMM29h, XMM29i, XMM29j, XMM29k, XMM29l, XMM29m, XMM29n, XMM29o, XMM29p, XMM30, XMM30b, XMM30c, XMM30d, XMM30e, XMM30f, XMM30g, XMM30h, XMM30i, XMM30j, XMM30k, XMM30l, XMM30m, XMM30n, XMM30o, XMM30p, - XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h, XMM31i, XMM31j, XMM31k, XMM31l, XMM31m, XMM31n, XMM31o, XMM31p -#endif - ); + XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h, XMM31i, XMM31j, XMM31k, XMM31l, XMM31m, XMM31n, XMM31o, XMM31p); alloc_class chunk2(K7, K7_H, K6, K6_H, @@ -726,18 +715,15 @@ reg_class float_reg_legacy(XMM0, XMM4, XMM5, XMM6, - XMM7 -#ifdef _LP64 - ,XMM8, + XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, - XMM15 -#endif - ); + XMM15); // Class for evex float registers reg_class float_reg_evex(XMM0, @@ -747,9 +733,8 @@ reg_class float_reg_evex(XMM0, XMM4, XMM5, XMM6, - XMM7 -#ifdef _LP64 - ,XMM8, + XMM7, + XMM8, XMM9, XMM10, XMM11, @@ -772,9 +757,7 @@ reg_class float_reg_evex(XMM0, XMM28, XMM29, XMM30, - XMM31 -#endif - ); + XMM31); reg_class_dynamic float_reg(float_reg_evex, float_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic float_reg_vl(float_reg_evex, float_reg_legacy, %{ VM_Version::supports_evex() && VM_Version::supports_avx512vl() %} ); @@ -787,18 +770,15 @@ reg_class double_reg_legacy(XMM0, XMM0b, XMM4, XMM4b, XMM5, XMM5b, XMM6, XMM6b, - XMM7, XMM7b -#ifdef _LP64 - ,XMM8, XMM8b, + XMM7, XMM7b, + XMM8, XMM8b, XMM9, XMM9b, XMM10, XMM10b, XMM11, XMM11b, XMM12, XMM12b, XMM13, XMM13b, XMM14, XMM14b, - XMM15, XMM15b -#endif - ); + XMM15, XMM15b); // Class for evex double registers reg_class double_reg_evex(XMM0, XMM0b, @@ -808,9 +788,8 @@ reg_class double_reg_evex(XMM0, XMM0b, XMM4, XMM4b, XMM5, XMM5b, XMM6, XMM6b, - XMM7, XMM7b -#ifdef _LP64 - ,XMM8, XMM8b, + XMM7, XMM7b, + XMM8, XMM8b, XMM9, XMM9b, XMM10, XMM10b, XMM11, XMM11b, @@ -833,9 +812,7 @@ reg_class double_reg_evex(XMM0, XMM0b, XMM28, XMM28b, XMM29, XMM29b, XMM30, XMM30b, - XMM31, XMM31b -#endif - ); + XMM31, XMM31b); reg_class_dynamic double_reg(double_reg_evex, double_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic double_reg_vl(double_reg_evex, double_reg_legacy, %{ VM_Version::supports_evex() && VM_Version::supports_avx512vl() %} ); @@ -848,18 +825,15 @@ reg_class vectors_reg_legacy(XMM0, XMM4, XMM5, XMM6, - XMM7 -#ifdef _LP64 - ,XMM8, + XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, - XMM15 -#endif - ); + XMM15); // Class for evex 32bit vector registers reg_class vectors_reg_evex(XMM0, @@ -869,9 +843,8 @@ reg_class vectors_reg_evex(XMM0, XMM4, XMM5, XMM6, - XMM7 -#ifdef _LP64 - ,XMM8, + XMM7, + XMM8, XMM9, XMM10, XMM11, @@ -894,9 +867,7 @@ reg_class vectors_reg_evex(XMM0, XMM28, XMM29, XMM30, - XMM31 -#endif - ); + XMM31); reg_class_dynamic vectors_reg(vectors_reg_evex, vectors_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic vectors_reg_vlbwdq(vectors_reg_evex, vectors_reg_legacy, %{ VM_Version::supports_avx512vlbwdq() %} ); @@ -909,18 +880,15 @@ reg_class vectord_reg_legacy(XMM0, XMM0b, XMM4, XMM4b, XMM5, XMM5b, XMM6, XMM6b, - XMM7, XMM7b -#ifdef _LP64 - ,XMM8, XMM8b, + XMM7, XMM7b, + XMM8, XMM8b, XMM9, XMM9b, XMM10, XMM10b, XMM11, XMM11b, XMM12, XMM12b, XMM13, XMM13b, XMM14, XMM14b, - XMM15, XMM15b -#endif - ); + XMM15, XMM15b); // Class for all 64bit vector registers reg_class vectord_reg_evex(XMM0, XMM0b, @@ -930,9 +898,8 @@ reg_class vectord_reg_evex(XMM0, XMM0b, XMM4, XMM4b, XMM5, XMM5b, XMM6, XMM6b, - XMM7, XMM7b -#ifdef _LP64 - ,XMM8, XMM8b, + XMM7, XMM7b, + XMM8, XMM8b, XMM9, XMM9b, XMM10, XMM10b, XMM11, XMM11b, @@ -955,9 +922,7 @@ reg_class vectord_reg_evex(XMM0, XMM0b, XMM28, XMM28b, XMM29, XMM29b, XMM30, XMM30b, - XMM31, XMM31b -#endif - ); + XMM31, XMM31b); reg_class_dynamic vectord_reg(vectord_reg_evex, vectord_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic vectord_reg_vlbwdq(vectord_reg_evex, vectord_reg_legacy, %{ VM_Version::supports_avx512vlbwdq() %} ); @@ -970,18 +935,15 @@ reg_class vectorx_reg_legacy(XMM0, XMM0b, XMM0c, XMM0d, XMM4, XMM4b, XMM4c, XMM4d, XMM5, XMM5b, XMM5c, XMM5d, XMM6, XMM6b, XMM6c, XMM6d, - XMM7, XMM7b, XMM7c, XMM7d -#ifdef _LP64 - ,XMM8, XMM8b, XMM8c, XMM8d, + XMM7, XMM7b, XMM7c, XMM7d, + XMM8, XMM8b, XMM8c, XMM8d, XMM9, XMM9b, XMM9c, XMM9d, XMM10, XMM10b, XMM10c, XMM10d, XMM11, XMM11b, XMM11c, XMM11d, XMM12, XMM12b, XMM12c, XMM12d, XMM13, XMM13b, XMM13c, XMM13d, XMM14, XMM14b, XMM14c, XMM14d, - XMM15, XMM15b, XMM15c, XMM15d -#endif - ); + XMM15, XMM15b, XMM15c, XMM15d); // Class for all 128bit vector registers reg_class vectorx_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, @@ -991,9 +953,8 @@ reg_class vectorx_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, XMM4, XMM4b, XMM4c, XMM4d, XMM5, XMM5b, XMM5c, XMM5d, XMM6, XMM6b, XMM6c, XMM6d, - XMM7, XMM7b, XMM7c, XMM7d -#ifdef _LP64 - ,XMM8, XMM8b, XMM8c, XMM8d, + XMM7, XMM7b, XMM7c, XMM7d, + XMM8, XMM8b, XMM8c, XMM8d, XMM9, XMM9b, XMM9c, XMM9d, XMM10, XMM10b, XMM10c, XMM10d, XMM11, XMM11b, XMM11c, XMM11d, @@ -1016,9 +977,7 @@ reg_class vectorx_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, XMM28, XMM28b, XMM28c, XMM28d, XMM29, XMM29b, XMM29c, XMM29d, XMM30, XMM30b, XMM30c, XMM30d, - XMM31, XMM31b, XMM31c, XMM31d -#endif - ); + XMM31, XMM31b, XMM31c, XMM31d); reg_class_dynamic vectorx_reg(vectorx_reg_evex, vectorx_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic vectorx_reg_vlbwdq(vectorx_reg_evex, vectorx_reg_legacy, %{ VM_Version::supports_avx512vlbwdq() %} ); @@ -1031,18 +990,15 @@ reg_class vectory_reg_legacy(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0 XMM4, XMM4b, XMM4c, XMM4d, XMM4e, XMM4f, XMM4g, XMM4h, XMM5, XMM5b, XMM5c, XMM5d, XMM5e, XMM5f, XMM5g, XMM5h, XMM6, XMM6b, XMM6c, XMM6d, XMM6e, XMM6f, XMM6g, XMM6h, - XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h -#ifdef _LP64 - ,XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, + XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, + XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM9, XMM9b, XMM9c, XMM9d, XMM9e, XMM9f, XMM9g, XMM9h, XMM10, XMM10b, XMM10c, XMM10d, XMM10e, XMM10f, XMM10g, XMM10h, XMM11, XMM11b, XMM11c, XMM11d, XMM11e, XMM11f, XMM11g, XMM11h, XMM12, XMM12b, XMM12c, XMM12d, XMM12e, XMM12f, XMM12g, XMM12h, XMM13, XMM13b, XMM13c, XMM13d, XMM13e, XMM13f, XMM13g, XMM13h, XMM14, XMM14b, XMM14c, XMM14d, XMM14e, XMM14f, XMM14g, XMM14h, - XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h -#endif - ); + XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h); // Class for all 256bit vector registers reg_class vectory_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM0h, @@ -1052,9 +1008,8 @@ reg_class vectory_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM4, XMM4b, XMM4c, XMM4d, XMM4e, XMM4f, XMM4g, XMM4h, XMM5, XMM5b, XMM5c, XMM5d, XMM5e, XMM5f, XMM5g, XMM5h, XMM6, XMM6b, XMM6c, XMM6d, XMM6e, XMM6f, XMM6g, XMM6h, - XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h -#ifdef _LP64 - ,XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, + XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, + XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM9, XMM9b, XMM9c, XMM9d, XMM9e, XMM9f, XMM9g, XMM9h, XMM10, XMM10b, XMM10c, XMM10d, XMM10e, XMM10f, XMM10g, XMM10h, XMM11, XMM11b, XMM11c, XMM11d, XMM11e, XMM11f, XMM11g, XMM11h, @@ -1077,9 +1032,7 @@ reg_class vectory_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM28, XMM28b, XMM28c, XMM28d, XMM28e, XMM28f, XMM28g, XMM28h, XMM29, XMM29b, XMM29c, XMM29d, XMM29e, XMM29f, XMM29g, XMM29h, XMM30, XMM30b, XMM30c, XMM30d, XMM30e, XMM30f, XMM30g, XMM30h, - XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h -#endif - ); + XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h); reg_class_dynamic vectory_reg(vectory_reg_evex, vectory_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic vectory_reg_vlbwdq(vectory_reg_evex, vectory_reg_legacy, %{ VM_Version::supports_avx512vlbwdq() %} ); @@ -1092,17 +1045,16 @@ reg_class vectorz_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM4, XMM4b, XMM4c, XMM4d, XMM4e, XMM4f, XMM4g, XMM4h, XMM4i, XMM4j, XMM4k, XMM4l, XMM4m, XMM4n, XMM4o, XMM4p, XMM5, XMM5b, XMM5c, XMM5d, XMM5e, XMM5f, XMM5g, XMM5h, XMM5i, XMM5j, XMM5k, XMM5l, XMM5m, XMM5n, XMM5o, XMM5p, XMM6, XMM6b, XMM6c, XMM6d, XMM6e, XMM6f, XMM6g, XMM6h, XMM6i, XMM6j, XMM6k, XMM6l, XMM6m, XMM6n, XMM6o, XMM6p, - XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, XMM7i, XMM7j, XMM7k, XMM7l, XMM7m, XMM7n, XMM7o, XMM7p -#ifdef _LP64 - ,XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM8i, XMM8j, XMM8k, XMM8l, XMM8m, XMM8n, XMM8o, XMM8p, + XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, XMM7i, XMM7j, XMM7k, XMM7l, XMM7m, XMM7n, XMM7o, XMM7p, + XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM8i, XMM8j, XMM8k, XMM8l, XMM8m, XMM8n, XMM8o, XMM8p, XMM9, XMM9b, XMM9c, XMM9d, XMM9e, XMM9f, XMM9g, XMM9h, XMM9i, XMM9j, XMM9k, XMM9l, XMM9m, XMM9n, XMM9o, XMM9p, XMM10, XMM10b, XMM10c, XMM10d, XMM10e, XMM10f, XMM10g, XMM10h, XMM10i, XMM10j, XMM10k, XMM10l, XMM10m, XMM10n, XMM10o, XMM10p, XMM11, XMM11b, XMM11c, XMM11d, XMM11e, XMM11f, XMM11g, XMM11h, XMM11i, XMM11j, XMM11k, XMM11l, XMM11m, XMM11n, XMM11o, XMM11p, XMM12, XMM12b, XMM12c, XMM12d, XMM12e, XMM12f, XMM12g, XMM12h, XMM12i, XMM12j, XMM12k, XMM12l, XMM12m, XMM12n, XMM12o, XMM12p, XMM13, XMM13b, XMM13c, XMM13d, XMM13e, XMM13f, XMM13g, XMM13h, XMM13i, XMM13j, XMM13k, XMM13l, XMM13m, XMM13n, XMM13o, XMM13p, XMM14, XMM14b, XMM14c, XMM14d, XMM14e, XMM14f, XMM14g, XMM14h, XMM14i, XMM14j, XMM14k, XMM14l, XMM14m, XMM14n, XMM14o, XMM14p, - XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h, XMM15i, XMM15j, XMM15k, XMM15l, XMM15m, XMM15n, XMM15o, XMM15p - ,XMM16, XMM16b, XMM16c, XMM16d, XMM16e, XMM16f, XMM16g, XMM16h, XMM16i, XMM16j, XMM16k, XMM16l, XMM16m, XMM16n, XMM16o, XMM16p, + XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h, XMM15i, XMM15j, XMM15k, XMM15l, XMM15m, XMM15n, XMM15o, XMM15p, + XMM16, XMM16b, XMM16c, XMM16d, XMM16e, XMM16f, XMM16g, XMM16h, XMM16i, XMM16j, XMM16k, XMM16l, XMM16m, XMM16n, XMM16o, XMM16p, XMM17, XMM17b, XMM17c, XMM17d, XMM17e, XMM17f, XMM17g, XMM17h, XMM17i, XMM17j, XMM17k, XMM17l, XMM17m, XMM17n, XMM17o, XMM17p, XMM18, XMM18b, XMM18c, XMM18d, XMM18e, XMM18f, XMM18g, XMM18h, XMM18i, XMM18j, XMM18k, XMM18l, XMM18m, XMM18n, XMM18o, XMM18p, XMM19, XMM19b, XMM19c, XMM19d, XMM19e, XMM19f, XMM19g, XMM19h, XMM19i, XMM19j, XMM19k, XMM19l, XMM19m, XMM19n, XMM19o, XMM19p, @@ -1117,9 +1069,7 @@ reg_class vectorz_reg_evex(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM28, XMM28b, XMM28c, XMM28d, XMM28e, XMM28f, XMM28g, XMM28h, XMM28i, XMM28j, XMM28k, XMM28l, XMM28m, XMM28n, XMM28o, XMM28p, XMM29, XMM29b, XMM29c, XMM29d, XMM29e, XMM29f, XMM29g, XMM29h, XMM29i, XMM29j, XMM29k, XMM29l, XMM29m, XMM29n, XMM29o, XMM29p, XMM30, XMM30b, XMM30c, XMM30d, XMM30e, XMM30f, XMM30g, XMM30h, XMM30i, XMM30j, XMM30k, XMM30l, XMM30m, XMM30n, XMM30o, XMM30p, - XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h, XMM31i, XMM31j, XMM31k, XMM31l, XMM31m, XMM31n, XMM31o, XMM31p -#endif - ); + XMM31, XMM31b, XMM31c, XMM31d, XMM31e, XMM31f, XMM31g, XMM31h, XMM31i, XMM31j, XMM31k, XMM31l, XMM31m, XMM31n, XMM31o, XMM31p); // Class for restricted 512bit vector registers reg_class vectorz_reg_legacy(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM0h, XMM0i, XMM0j, XMM0k, XMM0l, XMM0m, XMM0n, XMM0o, XMM0p, @@ -1129,18 +1079,15 @@ reg_class vectorz_reg_legacy(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0 XMM4, XMM4b, XMM4c, XMM4d, XMM4e, XMM4f, XMM4g, XMM4h, XMM4i, XMM4j, XMM4k, XMM4l, XMM4m, XMM4n, XMM4o, XMM4p, XMM5, XMM5b, XMM5c, XMM5d, XMM5e, XMM5f, XMM5g, XMM5h, XMM5i, XMM5j, XMM5k, XMM5l, XMM5m, XMM5n, XMM5o, XMM5p, XMM6, XMM6b, XMM6c, XMM6d, XMM6e, XMM6f, XMM6g, XMM6h, XMM6i, XMM6j, XMM6k, XMM6l, XMM6m, XMM6n, XMM6o, XMM6p, - XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, XMM7i, XMM7j, XMM7k, XMM7l, XMM7m, XMM7n, XMM7o, XMM7p -#ifdef _LP64 - ,XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM8i, XMM8j, XMM8k, XMM8l, XMM8m, XMM8n, XMM8o, XMM8p, + XMM7, XMM7b, XMM7c, XMM7d, XMM7e, XMM7f, XMM7g, XMM7h, XMM7i, XMM7j, XMM7k, XMM7l, XMM7m, XMM7n, XMM7o, XMM7p, + XMM8, XMM8b, XMM8c, XMM8d, XMM8e, XMM8f, XMM8g, XMM8h, XMM8i, XMM8j, XMM8k, XMM8l, XMM8m, XMM8n, XMM8o, XMM8p, XMM9, XMM9b, XMM9c, XMM9d, XMM9e, XMM9f, XMM9g, XMM9h, XMM9i, XMM9j, XMM9k, XMM9l, XMM9m, XMM9n, XMM9o, XMM9p, XMM10, XMM10b, XMM10c, XMM10d, XMM10e, XMM10f, XMM10g, XMM10h, XMM10i, XMM10j, XMM10k, XMM10l, XMM10m, XMM10n, XMM10o, XMM10p, XMM11, XMM11b, XMM11c, XMM11d, XMM11e, XMM11f, XMM11g, XMM11h, XMM11i, XMM11j, XMM11k, XMM11l, XMM11m, XMM11n, XMM11o, XMM11p, XMM12, XMM12b, XMM12c, XMM12d, XMM12e, XMM12f, XMM12g, XMM12h, XMM12i, XMM12j, XMM12k, XMM12l, XMM12m, XMM12n, XMM12o, XMM12p, XMM13, XMM13b, XMM13c, XMM13d, XMM13e, XMM13f, XMM13g, XMM13h, XMM13i, XMM13j, XMM13k, XMM13l, XMM13m, XMM13n, XMM13o, XMM13p, XMM14, XMM14b, XMM14c, XMM14d, XMM14e, XMM14f, XMM14g, XMM14h, XMM14i, XMM14j, XMM14k, XMM14l, XMM14m, XMM14n, XMM14o, XMM14p, - XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h, XMM15i, XMM15j, XMM15k, XMM15l, XMM15m, XMM15n, XMM15o, XMM15p -#endif - ); + XMM15, XMM15b, XMM15c, XMM15d, XMM15e, XMM15f, XMM15g, XMM15h, XMM15i, XMM15j, XMM15k, XMM15l, XMM15m, XMM15n, XMM15o, XMM15p); reg_class_dynamic vectorz_reg (vectorz_reg_evex, vectorz_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic vectorz_reg_vl(vectorz_reg_evex, vectorz_reg_legacy, %{ VM_Version::supports_evex() && VM_Version::supports_avx512vl() %} ); @@ -1199,21 +1146,10 @@ class HandlerImpl { return NativeJump::instruction_size; } -#ifdef _LP64 static uint size_deopt_handler() { // three 5 byte instructions plus one move for unreachable address. return 15+3; } -#else - static uint size_deopt_handler() { - // NativeCall instruction size is the same as NativeJump. - // exception handler starts out as jump and can be patched to - // a call be deoptimization. (4932387) - // Note that this value is also credited (in output.cpp) to - // the size of the code section. - return 5 + NativeJump::instruction_size; // pushl(); jmp; - } -#endif }; inline Assembler::AvxVectorLen vector_length_encoding(int bytes) { @@ -1334,7 +1270,6 @@ int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) { } int offset = __ offset(); -#ifdef _LP64 address the_pc = (address) __ pc(); Label next; // push a "the_pc" on the stack without destroying any registers @@ -1345,10 +1280,6 @@ int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) { __ bind(next); // adjust it so it matches "the_pc" __ subptr(Address(rsp, 0), __ offset() - offset); -#else - InternalAddress here(__ pc()); - __ pushptr(here.addr(), noreg); -#endif __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow %d", (__ offset() - offset)); @@ -1372,17 +1303,10 @@ static Assembler::Width widthForType(BasicType bt) { //============================================================================= // Float masks come from different places depending on platform. -#ifdef _LP64 static address float_signmask() { return StubRoutines::x86::float_sign_mask(); } static address float_signflip() { return StubRoutines::x86::float_sign_flip(); } static address double_signmask() { return StubRoutines::x86::double_sign_mask(); } static address double_signflip() { return StubRoutines::x86::double_sign_flip(); } -#else - static address float_signmask() { return (address)float_signmask_pool; } - static address float_signflip() { return (address)float_signflip_pool; } - static address double_signmask() { return (address)double_signmask_pool; } - static address double_signflip() { return (address)double_signflip_pool; } -#endif static address vector_short_to_byte_mask() { return StubRoutines::x86::vector_short_to_byte_mask(); } static address vector_int_to_byte_mask() { return StubRoutines::x86::vector_int_to_byte_mask(); } static address vector_byte_perm_mask() { return StubRoutines::x86::vector_byte_perm_mask(); } @@ -1404,7 +1328,6 @@ bool Matcher::match_rule_supported(int opcode) { if (!has_match_rule(opcode)) { return false; // no match rule present } - const bool is_LP64 = LP64_ONLY(true) NOT_LP64(false); switch (opcode) { case Op_AbsVL: case Op_StoreVectorScatter: @@ -1509,7 +1432,7 @@ bool Matcher::match_rule_supported(int opcode) { } break; case Op_PopulateIndex: - if (!is_LP64 || (UseAVX < 2)) { + if (UseAVX < 2) { return false; } break; @@ -1524,9 +1447,7 @@ bool Matcher::match_rule_supported(int opcode) { } break; case Op_CompareAndSwapL: -#ifdef _LP64 case Op_CompareAndSwapP: -#endif break; case Op_StrIndexOf: if (!UseSSE42Intrinsics) { @@ -1555,7 +1476,6 @@ bool Matcher::match_rule_supported(int opcode) { return false; } break; -#ifdef _LP64 case Op_MaxD: case Op_MaxF: case Op_MinD: @@ -1564,7 +1484,6 @@ bool Matcher::match_rule_supported(int opcode) { return false; } break; -#endif case Op_CacheWB: case Op_CacheWBPreSync: case Op_CacheWBPostSync: @@ -1607,7 +1526,7 @@ bool Matcher::match_rule_supported(int opcode) { case Op_VectorCmpMasked: case Op_VectorMaskGen: - if (!is_LP64 || UseAVX < 3 || !VM_Version::supports_bmi2()) { + if (UseAVX < 3 || !VM_Version::supports_bmi2()) { return false; } break; @@ -1615,50 +1534,25 @@ bool Matcher::match_rule_supported(int opcode) { case Op_VectorMaskLastTrue: case Op_VectorMaskTrueCount: case Op_VectorMaskToLong: - if (!is_LP64 || UseAVX < 1) { + if (UseAVX < 1) { return false; } break; case Op_RoundF: case Op_RoundD: - if (!is_LP64) { - return false; - } break; case Op_CopySignD: case Op_CopySignF: - if (UseAVX < 3 || !is_LP64) { + if (UseAVX < 3) { return false; } if (!VM_Version::supports_avx512vl()) { return false; } break; -#ifndef _LP64 - case Op_AddReductionVF: - case Op_AddReductionVD: - case Op_MulReductionVF: - case Op_MulReductionVD: - if (UseSSE < 1) { // requires at least SSE - return false; - } - break; - case Op_MulAddVS2VI: - case Op_RShiftVL: - case Op_AbsVD: - case Op_NegVD: - if (UseSSE < 2) { - return false; - } - break; -#endif // !LP64 case Op_CompressBits: - if (!VM_Version::supports_bmi2() || (!is_LP64 && UseSSE < 2)) { - return false; - } - break; case Op_ExpandBits: - if (!VM_Version::supports_bmi2() || (!is_LP64 && (UseSSE < 2 || !VM_Version::supports_bmi1()))) { + if (!VM_Version::supports_bmi2()) { return false; } break; @@ -1683,14 +1577,9 @@ bool Matcher::match_rule_supported(int opcode) { } break; case Op_SqrtD: -#ifdef _LP64 if (UseSSE < 2) { return false; } -#else - // x86_32.ad has a special match rule for SqrtD. - // Together with common x86 rules, this handles all UseSSE cases. -#endif break; case Op_ConvF2HF: case Op_ConvHF2F: @@ -1722,7 +1611,6 @@ bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, Basi // Identify extra cases that we might want to provide match rules for vector nodes and // other intrinsics guarded with vector length (vlen) and element type (bt). bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { - const bool is_LP64 = LP64_ONLY(true) NOT_LP64(false); if (!match_rule_supported(opcode)) { return false; } @@ -1769,7 +1657,7 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { case Op_ClearArray: case Op_VectorMaskGen: case Op_VectorCmpMasked: - if (!is_LP64 || !VM_Version::supports_avx512bw()) { + if (!VM_Version::supports_avx512bw()) { return false; } if ((size_in_bits != 512) && !VM_Version::supports_avx512vl()) { @@ -1819,19 +1707,7 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { if (is_subword_type(bt) && (UseSSE < 4)) { return false; } -#ifndef _LP64 - if (bt == T_BYTE || bt == T_LONG) { - return false; - } -#endif break; -#ifndef _LP64 - case Op_VectorInsert: - if (bt == T_LONG || bt == T_DOUBLE) { - return false; - } - break; -#endif case Op_MinReductionV: case Op_MaxReductionV: if ((bt == T_INT || is_subword_type(bt)) && UseSSE < 4) { @@ -1846,11 +1722,6 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { if (UseAVX > 2 && (!VM_Version::supports_avx512dq() && size_in_bits == 512)) { return false; } -#ifndef _LP64 - if (bt == T_BYTE || bt == T_LONG) { - return false; - } -#endif break; case Op_VectorTest: if (UseSSE < 4) { @@ -1935,10 +1806,9 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { return false; } if (is_subword_type(bt) && - (!is_LP64 || - (size_in_bits > 256 && !VM_Version::supports_avx512bw()) || - (size_in_bits < 64) || - (bt == T_SHORT && !VM_Version::supports_bmi2()))) { + ((size_in_bits > 256 && !VM_Version::supports_avx512bw()) || + (size_in_bits < 64) || + (bt == T_SHORT && !VM_Version::supports_bmi2()))) { return false; } break; @@ -2007,14 +1877,11 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { if (is_subword_type(bt) && !VM_Version::supports_avx512_vbmi2()) { return false; } - if (!is_LP64 && !VM_Version::supports_avx512vl() && size_in_bits < 512) { - return false; - } if (size_in_bits < 128 ) { return false; } case Op_VectorLongToMask: - if (UseAVX < 1 || !is_LP64) { + if (UseAVX < 1) { return false; } if (UseAVX < 3 && !VM_Version::supports_bmi2()) { @@ -2062,7 +1929,6 @@ bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType return false; } - const bool is_LP64 = LP64_ONLY(true) NOT_LP64(false); int size_in_bits = vlen * type2aelembytes(bt) * BitsPerByte; if (size_in_bits != 512 && !VM_Version::supports_avx512vl()) { return false; @@ -2398,7 +2264,6 @@ static bool clone_shift(Node* shift, Matcher* matcher, Matcher::MStack& mstack, address_visited.set(shift->_idx); // Flag as address_visited mstack.push(shift->in(2), Matcher::Visit); Node *conv = shift->in(1); -#ifdef _LP64 // Allow Matcher to match the rule which bypass // ConvI2L operation for an array index on LP64 // if the index value is positive. @@ -2408,9 +2273,9 @@ static bool clone_shift(Node* shift, Matcher* matcher, Matcher::MStack& mstack, !matcher->is_visited(conv)) { address_visited.set(conv->_idx); // Flag as address_visited mstack.push(conv->in(1), Matcher::Pre_Visit); - } else -#endif + } else { mstack.push(conv, Matcher::Pre_Visit); + } return true; } return false; @@ -2548,7 +2413,7 @@ bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, if (adr->is_AddP() && !adr->in(AddPNode::Base)->is_top() && !adr->in(AddPNode::Offset)->is_Con() && - LP64_ONLY( off->get_long() == (int) (off->get_long()) && ) // immL32 + off->get_long() == (int) (off->get_long()) && // immL32 // Are there other uses besides address expressions? !is_visited(adr)) { address_visited.set(adr->_idx); // Flag as address_visited @@ -2622,26 +2487,18 @@ static void vec_mov_helper(C2_MacroAssembler *masm, int src_lo, int dst_lo, case Op_VecS: // copy whole register case Op_VecD: case Op_VecX: -#ifndef _LP64 - __ movdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo])); -#else if ((UseAVX < 3) || VM_Version::supports_avx512vl()) { __ movdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo])); } else { __ vextractf32x4(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 0x0); } -#endif break; case Op_VecY: -#ifndef _LP64 - __ vmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo])); -#else if ((UseAVX < 3) || VM_Version::supports_avx512vl()) { __ vmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo])); } else { __ vextractf64x4(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 0x0); } -#endif break; case Op_VecZ: __ evmovdquq(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 2); @@ -2680,28 +2537,20 @@ void vec_spill_helper(C2_MacroAssembler *masm, bool is_load, __ movq(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset)); break; case Op_VecX: -#ifndef _LP64 - __ movdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset)); -#else if ((UseAVX < 3) || VM_Version::supports_avx512vl()) { __ movdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset)); } else { __ vpxor(as_XMMRegister(Matcher::_regEncode[reg]), as_XMMRegister(Matcher::_regEncode[reg]), as_XMMRegister(Matcher::_regEncode[reg]), 2); __ vinsertf32x4(as_XMMRegister(Matcher::_regEncode[reg]), as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset),0x0); } -#endif break; case Op_VecY: -#ifndef _LP64 - __ vmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset)); -#else if ((UseAVX < 3) || VM_Version::supports_avx512vl()) { __ vmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset)); } else { __ vpxor(as_XMMRegister(Matcher::_regEncode[reg]), as_XMMRegister(Matcher::_regEncode[reg]), as_XMMRegister(Matcher::_regEncode[reg]), 2); __ vinsertf64x4(as_XMMRegister(Matcher::_regEncode[reg]), as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset),0x0); } -#endif break; case Op_VecZ: __ evmovdquq(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset), 2); @@ -2718,28 +2567,20 @@ void vec_spill_helper(C2_MacroAssembler *masm, bool is_load, __ movq(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg])); break; case Op_VecX: -#ifndef _LP64 - __ movdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg])); -#else if ((UseAVX < 3) || VM_Version::supports_avx512vl()) { __ movdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg])); } else { __ vextractf32x4(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 0x0); } -#endif break; case Op_VecY: -#ifndef _LP64 - __ vmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg])); -#else if ((UseAVX < 3) || VM_Version::supports_avx512vl()) { __ vmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg])); } else { __ vextractf64x4(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 0x0); } -#endif break; case Op_VecZ: __ evmovdquq(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 2); @@ -3970,7 +3811,6 @@ instruct reinterpret_shrink(vec dst, legVec src) %{ // ---------------------------------------------------------------------------------------------------- -#ifdef _LP64 instruct roundD_reg(legRegD dst, legRegD src, immU8 rmode) %{ match(Set dst (RoundDoubleMode src rmode)); format %{ "roundsd $dst,$src" %} @@ -4041,7 +3881,6 @@ instruct vround8D_mem(vec dst, memory mem, immU8 rmode) %{ %} ins_pipe( pipe_slow ); %} -#endif // _LP64 instruct onspinwait() %{ match(OnSpinWait); @@ -4259,7 +4098,6 @@ instruct vgather_subwordGT8B_off(vec dst, memory mem, rRegP idx_base, rRegI offs %} -#ifdef _LP64 instruct vgather_masked_subwordLE8B_avx3(vec dst, memory mem, rRegP idx_base, immI_0 offset, kReg mask, rRegL mask_idx, rRegP tmp, rRegI rtmp, rRegL rtmp2, rFlagsReg cr) %{ predicate(VM_Version::supports_avx512bw() && is_subword_type(Matcher::vector_element_basic_type(n)) && Matcher::vector_length_in_bytes(n) <= 8); match(Set dst (LoadVectorGatherMasked mem (Binary idx_base (Binary mask offset)))); @@ -4422,7 +4260,6 @@ instruct vgather_masked_subwordGT8B_off_avx2(vec dst, memory mem, rRegP idx_base %} ins_pipe( pipe_slow ); %} -#endif // ====================Scatter======================================= @@ -4538,7 +4375,6 @@ instruct vReplS_reg(vec dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct ReplHF_imm(vec dst, immH con, rRegI rtmp) %{ match(Set dst (Replicate con)); effect(TEMP rtmp); @@ -4565,7 +4401,6 @@ instruct ReplHF_reg(vec dst, regF src, rRegI rtmp) %{ %} ins_pipe( pipe_slow ); %} -#endif instruct ReplS_mem(vec dst, memory mem) %{ predicate(UseAVX >= 2 && Matcher::vector_element_basic_type(n) == T_SHORT); @@ -4662,7 +4497,6 @@ instruct ReplI_M1(vec dst, immI_M1 con) %{ // ====================ReplicateL======================================= -#ifdef _LP64 // Replicate long (8 byte) scalar to be vector instruct ReplL_reg(vec dst, rRegL src) %{ predicate(Matcher::vector_element_basic_type(n) == T_LONG); @@ -4683,61 +4517,6 @@ instruct ReplL_reg(vec dst, rRegL src) %{ %} ins_pipe( pipe_slow ); %} -#else // _LP64 -// Replicate long (8 byte) scalar to be vector -instruct ReplL_reg(vec dst, eRegL src, vec tmp) %{ - predicate(Matcher::vector_length(n) <= 4 && Matcher::vector_element_basic_type(n) == T_LONG); - match(Set dst (Replicate src)); - effect(TEMP dst, USE src, TEMP tmp); - format %{ "replicateL $dst,$src" %} - ins_encode %{ - uint vlen = Matcher::vector_length(this); - if (vlen == 2) { - __ movdl($dst$$XMMRegister, $src$$Register); - __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); - __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - } else if (VM_Version::supports_avx512vl()) { // AVX512VL for <512bit operands - int vlen_enc = Assembler::AVX_256bit; - __ movdl($dst$$XMMRegister, $src$$Register); - __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); - __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); - __ vpbroadcastq($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } else { - __ movdl($dst$$XMMRegister, $src$$Register); - __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); - __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - } - %} - ins_pipe( pipe_slow ); -%} - -instruct ReplL_reg_leg(legVec dst, eRegL src, legVec tmp) %{ - predicate(Matcher::vector_length(n) == 8 && Matcher::vector_element_basic_type(n) == T_LONG); - match(Set dst (Replicate src)); - effect(TEMP dst, USE src, TEMP tmp); - format %{ "replicateL $dst,$src" %} - ins_encode %{ - if (VM_Version::supports_avx512vl()) { - __ movdl($dst$$XMMRegister, $src$$Register); - __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); - __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); - __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti64x4($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, 0x1); - } else { - int vlen_enc = Assembler::AVX_512bit; - __ movdl($dst$$XMMRegister, $src$$Register); - __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); - __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); - __ vpbroadcastq($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } - %} - ins_pipe( pipe_slow ); -%} -#endif // _LP64 instruct ReplL_mem(vec dst, memory mem) %{ predicate(Matcher::vector_element_basic_type(n) == T_LONG); @@ -5011,7 +4790,6 @@ instruct insert64(vec dst, vec src, rRegI val, immU8 idx, legVec vtmp) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct insert2L(vec dst, rRegL val, immU8 idx) %{ predicate(Matcher::vector_length(n) == 2); match(Set dst (VectorInsert (Binary dst val) idx)); @@ -5062,7 +4840,6 @@ instruct insert8L(vec dst, vec src, rRegL val, immU8 idx, legVec vtmp) %{ %} ins_pipe( pipe_slow ); %} -#endif instruct insertF(vec dst, regF val, immU8 idx) %{ predicate(Matcher::vector_length(n) < 8); @@ -5108,7 +4885,6 @@ instruct vinsertF(vec dst, vec src, regF val, immU8 idx, vec vtmp) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct insert2D(vec dst, regD val, immU8 idx, rRegL tmp) %{ predicate(Matcher::vector_length(n) == 2); match(Set dst (VectorInsert (Binary dst val) idx)); @@ -5163,7 +4939,6 @@ instruct insert8D(vec dst, vec src, regD val, immI idx, rRegL tmp, legVec vtmp) %} ins_pipe( pipe_slow ); %} -#endif // ====================REDUCTION ARITHMETIC======================================= @@ -5190,7 +4965,6 @@ instruct reductionI(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtm // =======================Long Reduction========================================== -#ifdef _LP64 instruct reductionL(rRegL dst, rRegL src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ predicate(Matcher::vector_element_basic_type(n->in(2)) == T_LONG && !VM_Version::supports_avx512dq()); match(Set dst (AddReductionVL src1 src2)); @@ -5228,7 +5002,6 @@ instruct reductionL_avx512dq(rRegL dst, rRegL src1, vec src2, vec vtmp1, vec vtm %} ins_pipe( pipe_slow ); %} -#endif // _LP64 // =======================Float Reduction========================================== @@ -5440,7 +5213,6 @@ instruct unordered_reduction8D(regD dst, regD src1, legVec src2, legVec vtmp1, l // =======================Byte Reduction========================================== -#ifdef _LP64 instruct reductionB(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtmp2) %{ predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE && !VM_Version::supports_avx512bw()); match(Set dst (AddReductionVI src1 src2)); @@ -5476,7 +5248,6 @@ instruct reductionB_avx512bw(rRegI dst, rRegI src1, vec src2, vec vtmp1, vec vtm %} ins_pipe( pipe_slow ); %} -#endif // =======================Short Reduction========================================== @@ -6777,7 +6548,6 @@ instruct signumV_reg_evex(vec dst, vec src, vec zero, vec one, kReg ktmp1) %{ // Result going from high bit to low bit is 0x11100100 = 0xe4 // --------------------------------------- -#ifdef _LP64 instruct copySignF_reg(regF dst, regF src, regF tmp1, rRegI tmp2) %{ match(Set dst (CopySignF dst src)); effect(TEMP tmp1, TEMP tmp2); @@ -6803,8 +6573,6 @@ instruct copySignD_imm(regD dst, regD src, regD tmp1, rRegL tmp2, immD zero) %{ ins_pipe( pipe_slow ); %} -#endif // _LP64 - //----------------------------- CompressBits/ExpandBits ------------------------ instruct compressBitsI_reg(rRegI dst, rRegI src, rRegI mask) %{ @@ -7977,7 +7745,6 @@ instruct vucast(vec dst, vec src) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct vround_float_avx(vec dst, vec src, rRegP tmp, vec xtmp1, vec xtmp2, vec xtmp3, vec xtmp4, rFlagsReg cr) %{ predicate(!VM_Version::supports_avx512vl() && Matcher::vector_length_in_bytes(n) < 64 && @@ -8027,8 +7794,6 @@ instruct vround_reg_evex(vec dst, vec src, rRegP tmp, vec xtmp1, vec xtmp2, kReg ins_pipe( pipe_slow ); %} -#endif // _LP64 - // --------------------------------- VectorMaskCmp -------------------------------------- instruct vcmpFD(legVec dst, legVec src1, legVec src2, immI8 cond) %{ @@ -8238,9 +8003,7 @@ instruct extractI(rRegI dst, legVec src, immU8 idx) %{ predicate(Matcher::vector_length_in_bytes(n->in(1)) <= 16); // src match(Set dst (ExtractI src idx)); match(Set dst (ExtractS src idx)); -#ifdef _LP64 match(Set dst (ExtractB src idx)); -#endif format %{ "extractI $dst,$src,$idx\t!" %} ins_encode %{ assert($idx$$constant < (int)Matcher::vector_length(this, $src), "out of bounds"); @@ -8256,9 +8019,7 @@ instruct vextractI(rRegI dst, legVec src, immI idx, legVec vtmp) %{ Matcher::vector_length_in_bytes(n->in(1)) == 64); // src match(Set dst (ExtractI src idx)); match(Set dst (ExtractS src idx)); -#ifdef _LP64 match(Set dst (ExtractB src idx)); -#endif effect(TEMP vtmp); format %{ "vextractI $dst,$src,$idx\t! using $vtmp as TEMP" %} ins_encode %{ @@ -8271,7 +8032,6 @@ instruct vextractI(rRegI dst, legVec src, immI idx, legVec vtmp) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct extractL(rRegL dst, legVec src, immU8 idx) %{ predicate(Matcher::vector_length(n->in(1)) <= 2); // src match(Set dst (ExtractL src idx)); @@ -8299,7 +8059,6 @@ instruct vextractL(rRegL dst, legVec src, immU8 idx, legVec vtmp) %{ %} ins_pipe( pipe_slow ); %} -#endif instruct extractF(legRegF dst, legVec src, immU8 idx, legVec vtmp) %{ predicate(Matcher::vector_length(n->in(1)) <= 4); @@ -8564,7 +8323,6 @@ instruct vabsnegD(vec dst, vec src) %{ //------------------------------------- VectorTest -------------------------------------------- -#ifdef _LP64 instruct vptest_lt16(rFlagsRegU cr, legVec src1, legVec src2, legVec vtmp) %{ predicate(Matcher::vector_length_in_bytes(n->in(1)) < 16); match(Set cr (VectorTest src1 src2)); @@ -8632,7 +8390,6 @@ instruct ktest_ge8(rFlagsRegU cr, kReg src1, kReg src2) %{ %} ins_pipe( pipe_slow ); %} -#endif //------------------------------------- LoadMask -------------------------------------------- @@ -8883,7 +8640,6 @@ instruct loadIotaIndices(vec dst, immI_0 src) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct VectorPopulateIndex(vec dst, rRegI src1, immI_1 src2, vec vtmp) %{ match(Set dst (PopulateIndex src1 src2)); effect(TEMP dst, TEMP vtmp); @@ -8915,7 +8671,7 @@ instruct VectorPopulateLIndex(vec dst, rRegL src1, immI_1 src2, vec vtmp) %{ %} ins_pipe( pipe_slow ); %} -#endif + //-------------------------------- Rearrange ---------------------------------- // LoadShuffle/Rearrange for Byte @@ -9496,7 +9252,6 @@ instruct vmasked_store_evex(memory mem, vec src, kReg mask) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct verify_vector_alignment(rRegP addr, immL32 mask, rFlagsReg cr) %{ match(Set addr (VerifyVectorAlignment addr mask)); effect(KILL cr); @@ -9710,7 +9465,6 @@ instruct vmask_first_or_last_true_avx(rRegI dst, vec mask, immI size, rRegL tmp, %} // --------------------------------- Compress/Expand Operations --------------------------- -#ifdef _LP64 instruct vcompress_reg_avx(vec dst, vec src, vec mask, rRegI rtmp, rRegL rscratch, vec perm, vec xtmp, rFlagsReg cr) %{ predicate(!VM_Version::supports_avx512vl() && Matcher::vector_length_in_bytes(n) <= 32); match(Set dst (CompressV src mask)); @@ -9726,7 +9480,6 @@ instruct vcompress_reg_avx(vec dst, vec src, vec mask, rRegI rtmp, rRegL rscratc %} ins_pipe( pipe_slow ); %} -#endif instruct vcompress_expand_reg_evex(vec dst, vec src, kReg mask) %{ predicate(VM_Version::supports_avx512vl() || Matcher::vector_length_in_bytes(n) == 64); @@ -9754,8 +9507,6 @@ instruct vcompress_mask_reg_evex(kReg dst, kReg mask, rRegL rtmp1, rRegL rtmp2, ins_pipe( pipe_slow ); %} -#endif // _LP64 - // -------------------------------- Bit and Byte Reversal Vector Operations ------------------------ instruct vreverse_reg(vec dst, vec src, vec xtmp1, vec xtmp2, rRegI rtmp) %{ @@ -10476,7 +10227,6 @@ instruct mask_all_evexI_LE32(kReg dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -#ifdef _LP64 instruct mask_not_immLT8(kReg dst, kReg src, rRegI rtmp, kReg ktmp, immI_M1 cnt) %{ predicate(Matcher::vector_length(n) < 8 && VM_Version::supports_avx512dq()); match(Set dst (XorVMask src (MaskAll cnt))); @@ -10541,7 +10291,6 @@ instruct long_to_mask_evex(kReg dst, rRegL src) %{ %} ins_pipe( pipe_slow ); %} -#endif instruct mask_opers_evex(kReg dst, kReg src1, kReg src2, kReg kscratch) %{ match(Set dst (AndVMask src1 src2)); diff --git a/src/hotspot/share/adlc/archDesc.cpp b/src/hotspot/share/adlc/archDesc.cpp index 8a7d0ee40c4..263752c521d 100644 --- a/src/hotspot/share/adlc/archDesc.cpp +++ b/src/hotspot/share/adlc/archDesc.cpp @@ -751,12 +751,11 @@ bool ArchDesc::check_usage() { callback.do_form_by_name("sRegL"); // special generic vector operands only used in Matcher::pd_specialize_generic_vector_operand - // x86_32 combine x86.ad and x86_32.ad, the vec*/legVec* can not be cleaned from IA32 #if defined(AARCH64) callback.do_form_by_name("vecA"); callback.do_form_by_name("vecD"); callback.do_form_by_name("vecX"); -#elif defined(IA32) || defined(AMD64) +#elif defined(AMD64) callback.do_form_by_name("vecS"); callback.do_form_by_name("vecD"); callback.do_form_by_name("vecX"); From f7fa05f577a28870202ccaa3544c34b58bd4adfe Mon Sep 17 00:00:00 2001 From: Daishi Tabata Date: Wed, 9 Apr 2025 09:11:24 +0000 Subject: [PATCH 078/843] 8353698: Output of Simple Web Server is garbled if the console's encoding is not UTF-8 Reviewed-by: djelinski, dfuchs --- .../httpserver/simpleserver/JWebServer.java | 6 ++--- .../sun/net/httpserver/simpleserver/Main.java | 5 ++-- .../simpleserver/CommandLineNegativeTest.java | 21 +++++++++-------- .../CommandLinePortNotSpecifiedTest.java | 5 ++-- .../simpleserver/CommandLinePositiveTest.java | 23 ++++++++++--------- .../jwebserver/CommandLineNegativeTest.java | 21 +++++++++-------- .../CommandLinePortNotSpecifiedTest.java | 5 ++-- .../jwebserver/CommandLinePositiveTest.java | 23 ++++++++++--------- .../jwebserver/IPv6BoundHost.java | 4 +++- .../jwebserver/MaxRequestTimeTest.java | 5 ++-- 10 files changed, 62 insertions(+), 56 deletions(-) diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java index a7daa46bdff..c97162ef9bd 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,6 @@ package sun.net.httpserver.simpleserver; import java.io.PrintWriter; -import static java.nio.charset.StandardCharsets.UTF_8; - /** * Programmatic entry point to start the jwebserver tool. */ @@ -65,7 +63,7 @@ public class JWebServer { setMaxReqTime(); setMaxConnectionsIfNotSet(); - int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "jwebserver", args); + int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true), "jwebserver", args); if (ec != 0) { System.exit(ec); } // otherwise, the server has either been started successfully and diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java index 9ccbbd3edac..81ff4e91cac 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package sun.net.httpserver.simpleserver; import java.io.PrintWriter; -import static java.nio.charset.StandardCharsets.UTF_8; /** * Programmatic entry point to start "java -m jdk.httpserver". @@ -61,7 +60,7 @@ public class Main { setMaxReqTime(); JWebServer.setMaxConnectionsIfNotSet(); - int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "java", args); + int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true), "java", args); if (ec != 0) { System.exit(ec); } // otherwise, the server has either been started successfully and diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java index 3a22d54f36d..717b92158b8 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ import static org.testng.Assert.assertFalse; public class CommandLineNegativeTest { static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String LOCALE_OPT = "-Duser.language=en -Duser.country=US"; static final String JAVA = getJava(JAVA_HOME); static final Path CWD = Path.of(".").toAbsolutePath().normalize(); static final Path TEST_DIR = CWD.resolve("CommandLineNegativeTest"); @@ -74,7 +75,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "unknownOption") public void testBadOption(String opt) throws Throwable { out.println("\n--- testUnknownOption, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt) .shouldNotHaveExitValue(0) .shouldContain("Error: unknown option: " + opt); } @@ -97,7 +98,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "tooManyOptionArgs") public void testTooManyOptionArgs(String opt, String arg) throws Throwable { out.println("\n--- testTooManyOptionArgs, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, arg, arg) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, arg, arg) .shouldNotHaveExitValue(0) .shouldContain("Error: unknown option: " + arg); } @@ -124,7 +125,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "noArg") public void testNoArg(String opt, String msg) throws Throwable { out.println("\n--- testNoArg, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt) .shouldNotHaveExitValue(0) .shouldContain("Error: no value given for " + opt) .shouldContain(msg); @@ -148,7 +149,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "invalidValue") public void testInvalidValue(String opt, String val) throws Throwable { out.println("\n--- testInvalidValue, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, val) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, val) .shouldNotHaveExitValue(0) .shouldContain("Error: invalid value given for " + opt + ": " + val); } @@ -159,7 +160,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "portOptions") public void testPortOutOfRange(String opt) throws Throwable { out.println("\n--- testPortOutOfRange, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, "65536") // range 0 to 65535 + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, "65536") // range 0 to 65535 .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "port out of range:65536"); } @@ -172,7 +173,7 @@ public class CommandLineNegativeTest { out.println("\n--- testRootNotAbsolute, opt=\"%s\" ".formatted(opt)); var root = Path.of("."); assertFalse(root.isAbsolute()); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, root.toString()) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, root.toString()) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path is not absolute:"); } @@ -182,7 +183,7 @@ public class CommandLineNegativeTest { out.println("\n--- testRootNotADirectory, opt=\"%s\" ".formatted(opt)); var file = TEST_FILE.toString(); assertFalse(Files.isDirectory(TEST_FILE)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, file) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, file) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path is not a directory: " + file); } @@ -192,7 +193,7 @@ public class CommandLineNegativeTest { out.println("\n--- testRootDoesNotExist, opt=\"%s\" ".formatted(opt)); Path root = TEST_DIR.resolve("not/existent/dir"); assertFalse(Files.exists(root)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, root.toString()) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, root.toString()) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path does not exist: " + root.toString()); } @@ -209,7 +210,7 @@ public class CommandLineNegativeTest { try { root.toFile().setReadable(false, false); assertFalse(Files.isReadable(root)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, root.toString()) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, root.toString()) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path is not readable: " + root.toString()); } finally { diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java index ba414a9d0c1..61a872a8655 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ import static java.lang.System.out; public class CommandLinePortNotSpecifiedTest { static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String LOCALE_OPT = "-Duser.language=en -Duser.country=US"; static final String JAVA = getJava(JAVA_HOME); static final Path CWD = Path.of(".").toAbsolutePath().normalize(); static final Path TEST_DIR = CWD.resolve("CommandLinePortNotSpecifiedTest"); @@ -84,7 +85,7 @@ public class CommandLinePortNotSpecifiedTest { @Test public void testPortNotSpecified() throws Throwable { out.println("\n--- testPortNotSpecified"); - simpleserver(JAVA, "-m", "jdk.httpserver") + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java index 8cf1f8daf94..de5d6b54334 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ public class CommandLinePositiveTest { static final String JAVA_VERSION = System.getProperty("java.version"); static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String LOCALE_OPT = "-Duser.language=en -Duser.country=US"; static final String JAVA = getJava(JAVA_HOME); static final Path CWD = Path.of(".").toAbsolutePath().normalize(); static final Path TEST_DIR = CWD.resolve("CommandLinePositiveTest"); @@ -84,7 +85,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "directoryOptions") public void testDirectory(String opt) throws Throwable { out.println("\n--- testDirectory, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", "-p", "0", opt, TEST_DIR_STR) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", "-p", "0", opt, TEST_DIR_STR) .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -97,7 +98,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "portOptions") public void testPort(String opt) throws Throwable { out.println("\n--- testPort, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, "0") + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, "0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -128,7 +129,7 @@ public class CommandLinePositiveTest { out.println("\n--- testHelp, opt=\"%s\" ".formatted(opt)); simpleserver(WaitForLine.HELP_STARTUP_LINE, false, // do not explicitly destroy the process - JAVA, "-m", "jdk.httpserver", opt) + JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt) .shouldHaveExitValue(0) .shouldContain(USAGE_TEXT) .shouldContain(OPTIONS_TEXT); @@ -142,7 +143,7 @@ public class CommandLinePositiveTest { out.println("\n--- testVersion, opt=\"%s\" ".formatted(opt)); simpleserver(WaitForLine.VERSION_STARTUP_LINE, false, // do not explicitly destroy the process - JAVA, "-m", "jdk.httpserver", opt) + JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt) .shouldHaveExitValue(0); } @@ -152,12 +153,12 @@ public class CommandLinePositiveTest { @Test(dataProvider = "bindOptions") public void testBindAllInterfaces(String opt) throws Throwable { out.println("\n--- testBindAllInterfaces, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", "-p", "0", opt, "0.0.0.0") + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", "-p", "0", opt, "0.0.0.0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on 0.0.0.0 (all interfaces) port") .shouldContain("URL http://" + InetAddress.getLocalHost().getHostAddress()); if (IPSupport.hasIPv6()) { - simpleserver(JAVA, "-m", "jdk.httpserver", opt, "::0") + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, "::0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on 0.0.0.0 (all interfaces) port") .shouldContain("URL http://" + InetAddress.getLocalHost().getHostAddress()); @@ -167,7 +168,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "bindOptions") public void testLastOneWinsBindAddress(String opt) throws Throwable { out.println("\n--- testLastOneWinsBindAddress, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", "-p", "0", opt, "123.4.5.6", opt, LOOPBACK_ADDR) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", "-p", "0", opt, "123.4.5.6", opt, LOOPBACK_ADDR) .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") .shouldContain("URL http://" + LOOPBACK_ADDR); @@ -177,7 +178,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "directoryOptions") public void testLastOneWinsDirectory(String opt) throws Throwable { out.println("\n--- testLastOneWinsDirectory, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", "-p", "0", opt, TEST_DIR_STR, opt, TEST_DIR_STR) + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", "-p", "0", opt, TEST_DIR_STR, opt, TEST_DIR_STR) .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -190,7 +191,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "outputOptions") public void testLastOneWinsOutput(String opt) throws Throwable { out.println("\n--- testLastOneWinsOutput, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", "-p", "0", opt, "none", opt, "verbose") + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", "-p", "0", opt, "none", opt, "verbose") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -200,7 +201,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "portOptions") public void testLastOneWinsPort(String opt) throws Throwable { out.println("\n--- testLastOneWinsPort, opt=\"%s\" ".formatted(opt)); - simpleserver(JAVA, "-m", "jdk.httpserver", opt, "-999", opt, "0") + simpleserver(JAVA, LOCALE_OPT, "-m", "jdk.httpserver", opt, "-999", opt, "0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java index 77671d1e82d..9c7a89696e2 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,7 @@ public class CommandLineNegativeTest { static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); static final String JWEBSERVER = getJwebserver(JAVA_HOME); + static final String LOCALE_OPT = "-J-Duser.language=en -J-Duser.country=US"; static final Path CWD = Path.of(".").toAbsolutePath().normalize(); static final Path TEST_DIR = CWD.resolve("CommandLineNegativeTest"); static final Path TEST_FILE = TEST_DIR.resolve("file.txt"); @@ -74,7 +75,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "unknownOption") public void testBadOption(String opt) throws Throwable { out.println("\n--- testUnknownOption, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, opt) + simpleserver(JWEBSERVER, LOCALE_OPT, opt) .shouldNotHaveExitValue(0) .shouldContain("Error: unknown option: " + opt); } @@ -97,7 +98,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "tooManyOptionArgs") public void testTooManyOptionArgs(String opt, String arg) throws Throwable { out.println("\n--- testTooManyOptionArgs, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, opt, arg, arg) + simpleserver(JWEBSERVER, LOCALE_OPT, opt, arg, arg) .shouldNotHaveExitValue(0) .shouldContain("Error: unknown option: " + arg); } @@ -124,7 +125,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "noArg") public void testNoArg(String opt, String msg) throws Throwable { out.println("\n--- testNoArg, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, opt) + simpleserver(JWEBSERVER, LOCALE_OPT, opt) .shouldNotHaveExitValue(0) .shouldContain("Error: no value given for " + opt) .shouldContain(msg); @@ -148,7 +149,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "invalidValue") public void testInvalidValue(String opt, String val) throws Throwable { out.println("\n--- testInvalidValue, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, opt, val) + simpleserver(JWEBSERVER, LOCALE_OPT, opt, val) .shouldNotHaveExitValue(0) .shouldContain("Error: invalid value given for " + opt + ": " + val); } @@ -159,7 +160,7 @@ public class CommandLineNegativeTest { @Test(dataProvider = "portOptions") public void testPortOutOfRange(String opt) throws Throwable { out.println("\n--- testPortOutOfRange, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, opt, "65536") // range 0 to 65535 + simpleserver(JWEBSERVER, LOCALE_OPT, opt, "65536") // range 0 to 65535 .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "port out of range:65536"); } @@ -172,7 +173,7 @@ public class CommandLineNegativeTest { out.println("\n--- testRootNotAbsolute, opt=\"%s\" ".formatted(opt)); var root = Path.of("."); assertFalse(root.isAbsolute()); - simpleserver(JWEBSERVER, opt, root.toString()) + simpleserver(JWEBSERVER, LOCALE_OPT, opt, root.toString()) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path is not absolute:"); } @@ -182,7 +183,7 @@ public class CommandLineNegativeTest { out.println("\n--- testRootNotADirectory, opt=\"%s\" ".formatted(opt)); var file = TEST_FILE.toString(); assertFalse(Files.isDirectory(TEST_FILE)); - simpleserver(JWEBSERVER, opt, file) + simpleserver(JWEBSERVER, LOCALE_OPT, opt, file) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path is not a directory: " + file); } @@ -192,7 +193,7 @@ public class CommandLineNegativeTest { out.println("\n--- testRootDoesNotExist, opt=\"%s\" ".formatted(opt)); Path root = TEST_DIR.resolve("not/existent/dir"); assertFalse(Files.exists(root)); - simpleserver(JWEBSERVER, opt, root.toString()) + simpleserver(JWEBSERVER, LOCALE_OPT, opt, root.toString()) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path does not exist: " + root.toString()); } @@ -209,7 +210,7 @@ public class CommandLineNegativeTest { try { root.toFile().setReadable(false, false); assertFalse(Files.isReadable(root)); - simpleserver(JWEBSERVER, opt, root.toString()) + simpleserver(JWEBSERVER, LOCALE_OPT, opt, root.toString()) .shouldNotHaveExitValue(0) .shouldContain("Error: server config failed: " + "Path is not readable: " + root.toString()); } finally { diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java index 4d850442b25..cd2ccbeded4 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ import static java.lang.System.out; public class CommandLinePortNotSpecifiedTest { static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String LOCALE_OPT = "-J-Duser.language=en -J-Duser.country=US"; static final String JWEBSERVER = getJwebserver(JAVA_HOME); static final Path CWD = Path.of(".").toAbsolutePath().normalize(); static final Path TEST_DIR = CWD.resolve("CommandLinePortNotSpecifiedTest"); @@ -84,7 +85,7 @@ public class CommandLinePortNotSpecifiedTest { @Test public void testPortNotSpecified() throws Throwable { out.println("\n--- testPortNotSpecified"); - simpleserver(JWEBSERVER) + simpleserver(JWEBSERVER, LOCALE_OPT) .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java index 88a843bc4ac..fc05c44377c 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ public class CommandLinePositiveTest { static final String JAVA_VERSION = System.getProperty("java.version"); static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String LOCALE_OPT = "-J-Duser.language=en -J-Duser.country=US"; static final String JWEBSERVER = getJwebserver(JAVA_HOME); static final Path CWD = Path.of(".").toAbsolutePath().normalize(); static final Path TEST_DIR = CWD.resolve("CommandLinePositiveTest"); @@ -84,7 +85,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "directoryOptions") public void testDirectory(String opt) throws Throwable { out.println("\n--- testDirectory, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, "-p", "0", opt, TEST_DIR_STR) + simpleserver(JWEBSERVER, LOCALE_OPT, "-p", "0", opt, TEST_DIR_STR) .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -97,7 +98,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "portOptions") public void testPort(String opt) throws Throwable { out.println("\n--- testPort, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, opt, "0") + simpleserver(JWEBSERVER, LOCALE_OPT, opt, "0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -128,7 +129,7 @@ public class CommandLinePositiveTest { out.println("\n--- testHelp, opt=\"%s\" ".formatted(opt)); simpleserver(WaitForLine.HELP_STARTUP_LINE, false, // do not explicitly destroy the process - JWEBSERVER, opt) + JWEBSERVER, LOCALE_OPT, opt) .shouldHaveExitValue(0) .shouldContain(USAGE_TEXT) .shouldContain(OPTIONS_TEXT); @@ -142,7 +143,7 @@ public class CommandLinePositiveTest { out.println("\n--- testVersion, opt=\"%s\" ".formatted(opt)); simpleserver(WaitForLine.VERSION_STARTUP_LINE, false, // do not explicitly destroy the process - JWEBSERVER, opt) + JWEBSERVER, LOCALE_OPT, opt) .shouldHaveExitValue(0); } @@ -152,12 +153,12 @@ public class CommandLinePositiveTest { @Test(dataProvider = "bindOptions") public void testBindAllInterfaces(String opt) throws Throwable { out.println("\n--- testBindAllInterfaces, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, "-p", "0", opt, "0.0.0.0") + simpleserver(JWEBSERVER, LOCALE_OPT, "-p", "0", opt, "0.0.0.0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on 0.0.0.0 (all interfaces) port") .shouldContain("URL http://" + InetAddress.getLocalHost().getHostAddress()); if (IPSupport.hasIPv6()) { - simpleserver(JWEBSERVER, opt, "::0") + simpleserver(JWEBSERVER, LOCALE_OPT, opt, "::0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on 0.0.0.0 (all interfaces) port") .shouldContain("URL http://" + InetAddress.getLocalHost().getHostAddress()); @@ -167,7 +168,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "bindOptions") public void testLastOneWinsBindAddress(String opt) throws Throwable { out.println("\n--- testLastOneWinsBindAddress, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, "-p", "0", opt, "123.4.5.6", opt, LOOPBACK_ADDR) + simpleserver(JWEBSERVER, LOCALE_OPT, "-p", "0", opt, "123.4.5.6", opt, LOOPBACK_ADDR) .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") .shouldContain("URL http://" + LOOPBACK_ADDR); @@ -177,7 +178,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "directoryOptions") public void testLastOneWinsDirectory(String opt) throws Throwable { out.println("\n--- testLastOneWinsDirectory, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, "-p", "0", opt, TEST_DIR_STR, opt, TEST_DIR_STR) + simpleserver(JWEBSERVER, LOCALE_OPT, "-p", "0", opt, TEST_DIR_STR, opt, TEST_DIR_STR) .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -190,7 +191,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "outputOptions") public void testLastOneWinsOutput(String opt) throws Throwable { out.println("\n--- testLastOneWinsOutput, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, "-p", "0", opt, "none", opt, "verbose") + simpleserver(JWEBSERVER, LOCALE_OPT, "-p", "0", opt, "none", opt, "verbose") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") @@ -200,7 +201,7 @@ public class CommandLinePositiveTest { @Test(dataProvider = "portOptions") public void testLastOneWinsPort(String opt) throws Throwable { out.println("\n--- testLastOneWinsPort, opt=\"%s\" ".formatted(opt)); - simpleserver(JWEBSERVER, opt, "-999", opt, "0") + simpleserver(JWEBSERVER, LOCALE_OPT, opt, "-999", opt, "0") .shouldHaveExitValue(NORMAL_EXIT_CODE) .shouldContain("Binding to loopback by default. For all interfaces use \"-b 0.0.0.0\" or \"-b ::\".") .shouldContain("Serving " + TEST_DIR_STR + " and subdirectories on " + LOOPBACK_ADDR + " port") diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/IPv6BoundHost.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/IPv6BoundHost.java index 04c9c3c6fc6..1aa32505ae4 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/IPv6BoundHost.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/IPv6BoundHost.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ public class IPv6BoundHost { private static final Path JDK_BIN_DIR = Path.of(System.getProperty("java.home")).resolve("bin"); private static final Path JWEBSERVER_BINARY = OperatingSystem.isWindows() ? JDK_BIN_DIR.resolve("jwebserver.exe") : JDK_BIN_DIR.resolve("jwebserver"); + private static final String LOCALE_OPT = "-J-Duser.language=en -J-Duser.country=US"; public static void main(final String[] args) throws Exception { IPSupport.printPlatformSupport(System.err); // for debug purposes @@ -68,6 +69,7 @@ public class IPv6BoundHost { final StringBuilder sb = new StringBuilder(); // stdout & stderr final List cmd = new ArrayList<>(); cmd.add(JWEBSERVER_BINARY.toString()); + cmd.add(LOCALE_OPT); cmd.addAll(args); // start the process and await the waitForLine before returning final Process p = ProcessTools.startProcess("8332020-test", new ProcessBuilder(cmd), diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java index e530c980565..c972f87dc18 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java +++ b/test/jdk/com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,7 @@ import static org.testng.Assert.*; */ public class MaxRequestTimeTest { static final Path JAVA_HOME = Path.of(System.getProperty("java.home")); + static final String LOCALE_OPT = "-J-Duser.language=en -J-Duser.country=US"; static final String JWEBSERVER = getJwebserver(JAVA_HOME); static final Path CWD = Path.of(".").toAbsolutePath().normalize(); static final Path TEST_DIR = CWD.resolve("MaxRequestTimeTest"); @@ -174,7 +175,7 @@ public class MaxRequestTimeTest { static Process startProcess(String name, StringBuffer sb) throws Throwable { // starts the process, parses the port and awaits startup line before sending requests return ProcessTools.startProcess(name, - new ProcessBuilder(JWEBSERVER, "-p", "0").directory(TEST_DIR.toFile()), + new ProcessBuilder(JWEBSERVER, LOCALE_OPT, "-p", "0").directory(TEST_DIR.toFile()), line -> { if (line.startsWith(REGULAR_STARTUP_LINE_STRING_2)) { parseAndSetPort(line); } sb.append(line + "\n"); From a1d566ce4b0315591ece489347c5d1c253f06be9 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Wed, 9 Apr 2025 09:28:36 +0000 Subject: [PATCH 079/843] 8348853: Fold layout helper check for objects implementing non-array interfaces Reviewed-by: thartmann, roland --- src/hotspot/share/ci/ciMetadata.hpp | 2 +- src/hotspot/share/opto/library_call.cpp | 7 +------ src/hotspot/share/opto/memnode.cpp | 6 ++---- src/hotspot/share/opto/type.cpp | 19 +++++++++++++++++++ src/hotspot/share/opto/type.hpp | 4 ++++ 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/ci/ciMetadata.hpp b/src/hotspot/share/ci/ciMetadata.hpp index 62b67d65483..2e232c59188 100644 --- a/src/hotspot/share/ci/ciMetadata.hpp +++ b/src/hotspot/share/ci/ciMetadata.hpp @@ -103,7 +103,7 @@ class ciMetadata: public ciBaseObject { Metadata* constant_encoding() { return _metadata; } - bool equals(ciMetadata* obj) const { return (this == obj); } + bool equals(const ciMetadata* obj) const { return (this == obj); } uint hash() { return ident() * 31; } // ??? diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 708225ba3aa..783631bf08d 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -4305,12 +4305,7 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) { // Keep track of the fact that 'obj' is an array to prevent // array specific accesses from floating above the guard. - Node* cast = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM)); - // Check for top because in rare cases, the type system can determine that - // the object can't be an array but the layout helper check is not folded. - if (!cast->is_top()) { - *obj = cast; - } + *obj = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM)); } return ctrl; } diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index e596db8e0c7..9cd3dcfee41 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2218,10 +2218,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const { // This will help short-circuit some reflective code. if (tkls->offset() == in_bytes(Klass::layout_helper_offset()) && tkls->isa_instklassptr() && // not directly typed as an array - !tkls->is_instklassptr()->instance_klass()->is_java_lang_Object() // not the supertype of all T[] and specifically not Serializable & Cloneable - ) { - // Note: When interfaces are reliable, we can narrow the interface - // test to (klass != Serializable && klass != Cloneable). + !tkls->is_instklassptr()->might_be_an_array() // not the supertype of all T[] (java.lang.Object) or has an interface that is not Serializable or Cloneable + ) { assert(Opcode() == Op_LoadI, "must load an int from _layout_helper"); jint min_size = Klass::instance_layout_helper(oopDesc::header_size(), false); // The key property of this type is that it folds up tests diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 474145f2d06..4556555acea 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -3685,6 +3685,12 @@ bool TypeInterfaces::singleton(void) const { return Type::singleton(); } +bool TypeInterfaces::has_non_array_interface() const { + assert(TypeAryPtr::_array_interfaces != nullptr, "How come Type::Initialize_shared wasn't called yet?"); + + return !TypeAryPtr::_array_interfaces->contains(this); +} + //------------------------------TypeOopPtr------------------------------------- TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, bool xk, ciObject* o, int offset, int instance_id, const TypePtr* speculative, int inline_depth) @@ -6197,6 +6203,19 @@ template bool TypePtr::is_java_subtype_of_helper_for_instan return this_one->klass()->is_subtype_of(other->klass()) && this_one->_interfaces->contains(other->_interfaces); } +bool TypeInstKlassPtr::might_be_an_array() const { + if (!instance_klass()->is_java_lang_Object()) { + // TypeInstKlassPtr can be an array only if it is java.lang.Object: the only supertype of array types. + return false; + } + if (interfaces()->has_non_array_interface()) { + // Arrays only implement Cloneable and Serializable. If we see any other interface, [this] cannot be an array. + return false; + } + // Cannot prove it's not an array. + return true; +} + bool TypeInstKlassPtr::is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const { return TypePtr::is_java_subtype_of_helper_for_instance(this, other, this_exact, other_exact); } diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index fe460cfb1d4..9c40e1ab3cd 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -943,6 +943,7 @@ public: const Type* xmeet(const Type* t) const; bool singleton(void) const; + bool has_non_array_interface() const; }; //------------------------------TypePtr---------------------------------------- @@ -1420,6 +1421,7 @@ private: class TypeAryPtr : public TypeOopPtr { friend class Type; friend class TypePtr; + friend class TypeInterfaces; TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, bool is_autobox_cache, @@ -1692,6 +1694,8 @@ public: return klass()->as_instance_klass(); } + bool might_be_an_array() const; + bool is_same_java_type_as_helper(const TypeKlassPtr* other) const; bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const; bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const; From cd9fa3f7aa0324c575943deebb41f4f7ff4f73d3 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Wed, 9 Apr 2025 09:47:03 +0000 Subject: [PATCH 080/843] 8353439: Shell grouping of -XX:OnError= commands is surprising Reviewed-by: dholmes, stuefe --- src/hotspot/share/utilities/vmError.cpp | 10 ++++--- .../runtime/ErrorHandling/TestOnError.java | 29 ++++++++++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index ef04d69ee99..8131df80c0e 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -136,7 +136,9 @@ static const char* env_list[] = { nullptr // End marker. }; -// A simple parser for -XX:OnError, usage: +// A simple parser for lists of commands such as -XX:OnError and -XX:OnOutOfMemoryError +// Command list (ptr) is expected to be a sequence of commands delineated by semicolons and/or newlines. +// Usage: // ptr = OnError; // while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr) != nullptr) // ... ... @@ -145,13 +147,13 @@ static char* next_OnError_command(char* buf, int buflen, const char** ptr) { const char* cmd = *ptr; - // skip leading blanks or ';' - while (*cmd == ' ' || *cmd == ';') cmd++; + // skip leading blanks, ';' or newlines + while (*cmd == ' ' || *cmd == ';' || *cmd == '\n') cmd++; if (*cmd == '\0') return nullptr; const char * cmdend = cmd; - while (*cmdend != '\0' && *cmdend != ';') cmdend++; + while (*cmdend != '\0' && *cmdend != ';' && *cmdend != '\n') cmdend++; Arguments::copy_expand_pid(cmd, cmdend - cmd, buf, buflen); diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/TestOnError.java b/test/hotspot/jtreg/runtime/ErrorHandling/TestOnError.java index 53410c5379c..41f2c5eeb42 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/TestOnError.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/TestOnError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,10 @@ public class TestOnError { public static void main(String[] args) throws Exception { String msg = "Test Succeeded"; + String msg1 = "OnError Test Message1"; + String msg2 = "OnError Test Message2"; + // Basic OnError test: ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-XX:-CreateCoredumpOnCrash", "-XX:ErrorHandlerTest=14", // trigger potential SEGV @@ -59,6 +62,30 @@ public class TestOnError { both get written to stdout. */ output.stdoutShouldMatch("^" + msg); // match start of line only + + // Test multiple OnError arguments: + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:-CreateCoredumpOnCrash", + "-XX:ErrorHandlerTest=14", + "-XX:OnError=echo " + msg1, + "-XX:OnError=echo " + msg2, + TestOnError.class.getName()); + + output = new OutputAnalyzer(pb.start()); + output.stdoutShouldMatch("^" + msg1); + output.stdoutShouldMatch("^" + msg2); + + // Test one argument with multiple commands using ; separator: + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:-CreateCoredumpOnCrash", + "-XX:ErrorHandlerTest=14", + "-XX:OnError=echo " + msg1 + ";echo " + msg2, + TestOnError.class.getName()); + + output = new OutputAnalyzer(pb.start()); + output.stdoutShouldMatch("^" + msg1); + output.stdoutShouldMatch("^" + msg2); + System.out.println("PASSED"); } } From 7aeaa3c21c1420191fe8ff59e4cf99eae830754d Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Wed, 9 Apr 2025 10:40:03 +0000 Subject: [PATCH 081/843] 8187520: Add --disable-java-warnings-as-errors configure option Reviewed-by: shade, erikj --- make/Docs.gmk | 8 +++----- make/autoconf/configure.ac | 1 + make/autoconf/jdk-options.m4 | 12 ++++++++++++ make/autoconf/spec.gmk.template | 1 + make/common/JavaCompilation.gmk | 9 +++++---- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/make/Docs.gmk b/make/Docs.gmk index 0948f8ff76c..5f10d623211 100644 --- a/make/Docs.gmk +++ b/make/Docs.gmk @@ -92,10 +92,6 @@ REFERENCE_TAGS := $(JAVADOC_TAGS) JAVADOC_DISABLED_DOCLINT_WARNINGS := missing JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio -# Allow overriding on the command line -# (intentionally sharing name with the javac option) -JAVA_WARNINGS_ARE_ERRORS ?= -Werror - # The initial set of options for javadoc JAVADOC_OPTIONS := -use -keywords -notimestamp \ -serialwarn -encoding ISO-8859-1 -docencoding UTF-8 -breakiterator \ @@ -322,7 +318,9 @@ define SetupApiDocsGenerationBody # Ignore the doclint warnings in certain packages $1_OPTIONS += -Xdoclint/package:$$(call CommaList, $$(addprefix -, \ $$(JAVADOC_DISABLED_DOCLINT_PACKAGES))) - $1_OPTIONS += $$(JAVA_WARNINGS_ARE_ERRORS) + ifeq ($$(JAVA_WARNINGS_AS_ERRORS), true) + $1_OPTIONS += -Werror + endif $1_DOC_TITLE := $$($1_LONG_NAME)
Version $$(VERSION_SPECIFICATION) API \ Specification diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index fffe17daad8..e05b5ae3b90 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -261,6 +261,7 @@ JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT JDKOPT_SETUP_MACOSX_SIGNING JDKOPT_SETUP_SIGNING_HOOK +JDKOPT_SETUP_JAVA_WARNINGS ################################################################################ # diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 72e731e7ffc..79e44dd4ad1 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -988,6 +988,18 @@ AC_DEFUN([JDKOPT_SETUP_SIGNING_HOOK], AC_SUBST(SIGNING_HOOK) ]) +################################################################################ +# +# Setup how javac should handle warnings. +# +AC_DEFUN([JDKOPT_SETUP_JAVA_WARNINGS], +[ + UTIL_ARG_ENABLE(NAME: java-warnings-as-errors, DEFAULT: true, + RESULT: JAVA_WARNINGS_AS_ERRORS, + DESC: [consider java warnings to be an error]) + AC_SUBST(JAVA_WARNINGS_AS_ERRORS) +]) + ################################################################################ # # fallback linker diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template index 17a913a2d90..907a60290ec 100644 --- a/make/autoconf/spec.gmk.template +++ b/make/autoconf/spec.gmk.template @@ -517,6 +517,7 @@ DISABLED_WARNINGS_CXX := @DISABLED_WARNINGS_CXX@ # A global flag (true or false) determining if native warnings are considered errors. WARNINGS_AS_ERRORS := @WARNINGS_AS_ERRORS@ +JAVA_WARNINGS_AS_ERRORS := @JAVA_WARNINGS_AS_ERRORS@ CFLAGS_CCACHE := @CFLAGS_CCACHE@ ADLC_LANGSTD_CXXFLAGS := @ADLC_LANGSTD_CXXFLAGS@ diff --git a/make/common/JavaCompilation.gmk b/make/common/JavaCompilation.gmk index f48aefcd517..70b3557baea 100644 --- a/make/common/JavaCompilation.gmk +++ b/make/common/JavaCompilation.gmk @@ -264,15 +264,16 @@ define SetupJavaCompilationBody $$(error Invalid value for COMPILER in SetupJavaCompilation for $1: '$$($1_COMPILER)') endif - # Allow overriding on the command line - JAVA_WARNINGS_ARE_ERRORS ?= -Werror - # Tell javac to do exactly as told and no more PARANOIA_FLAGS := -implicit:none -Xprefer:source -XDignore.symbol.file=true -encoding ascii - $1_FLAGS += -g -Xlint:all $$($1_TARGET_RELEASE) $$(PARANOIA_FLAGS) $$(JAVA_WARNINGS_ARE_ERRORS) + $1_FLAGS += -g -Xlint:all $$($1_TARGET_RELEASE) $$(PARANOIA_FLAGS) $1_FLAGS += $$($1_JAVAC_FLAGS) + ifeq ($$(JAVA_WARNINGS_AS_ERRORS), true) + $1_FLAGS += -Werror + endif + ifneq ($$($1_DISABLED_WARNINGS), ) $1_FLAGS += -Xlint:$$(call CommaList, $$(addprefix -, $$($1_DISABLED_WARNINGS))) endif From 6c93ad42f38b49ea96155340c4b6bbedfcef2a90 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 9 Apr 2025 12:36:35 +0000 Subject: [PATCH 082/843] 8351927: Change VirtualThread implementation to use use FJP delayed task handling Reviewed-by: vklang --- .../share/classes/java/lang/System.java | 4 - .../classes/java/lang/VirtualThread.java | 104 ++++++++------ .../jdk/internal/access/JavaLangAccess.java | 8 +- .../jdk/internal/vm/JcmdVThreadCommands.java | 15 +- .../dcmd/thread/VThreadCommandsTest.java | 8 +- .../bench/java/lang/VirtualThreadParking.java | 98 +++++++++++++ .../bench/java/lang/VirtualThreadSleep.java | 70 ++++++++++ .../java/util/concurrent/DelayedTasks.java | 130 ++++++++++++++++++ 8 files changed, 364 insertions(+), 73 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/lang/VirtualThreadParking.java create mode 100644 test/micro/org/openjdk/bench/java/lang/VirtualThreadSleep.java create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/DelayedTasks.java diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 241e479458d..903f6e34e2e 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -2290,10 +2290,6 @@ public final class System { return VirtualThread.defaultScheduler(); } - public Stream virtualThreadDelayedTaskSchedulers() { - return VirtualThread.delayedTaskSchedulers(); - } - public StackWalker newStackWalkerInstance(Set options, ContinuationScope contScope, Continuation continuation) { diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index dc8c6a852d0..964a5360ad6 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ package java.lang; -import java.util.Arrays; import java.util.Locale; import java.util.Objects; import java.util.concurrent.CountDownLatch; @@ -38,7 +37,6 @@ import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; import jdk.internal.event.VirtualThreadEndEvent; import jdk.internal.event.VirtualThreadStartEvent; import jdk.internal.event.VirtualThreadSubmitFailedEvent; @@ -66,7 +64,6 @@ final class VirtualThread extends BaseVirtualThread { private static final Unsafe U = Unsafe.getUnsafe(); private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads"); private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler(); - private static final ScheduledExecutorService[] DELAYED_TASK_SCHEDULERS = createDelayedTaskSchedulers(); private static final long STATE = U.objectFieldOffset(VirtualThread.class, "state"); private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit"); @@ -193,13 +190,6 @@ final class VirtualThread extends BaseVirtualThread { return DEFAULT_SCHEDULER; } - /** - * Returns a stream of the delayed task schedulers used to support timed operations. - */ - static Stream delayedTaskSchedulers() { - return Arrays.stream(DELAYED_TASK_SCHEDULERS); - } - /** * Returns the continuation scope used for virtual threads. */ @@ -567,8 +557,9 @@ final class VirtualThread extends BaseVirtualThread { setState(newState = PARKED); } else { // schedule unpark + long timeout = this.timeout; assert timeout > 0; - timeoutTask = schedule(this::unpark, timeout, NANOSECONDS); + timeoutTask = schedule(this::parkTimeoutExpired, timeout, NANOSECONDS); setState(newState = TIMED_PARKED); } @@ -618,6 +609,7 @@ final class VirtualThread extends BaseVirtualThread { // the timeout task to coordinate access to the sequence number and to // ensure the timeout task doesn't execute until the thread has got to // the TIMED_WAIT state. + long timeout = this.timeout; assert timeout > 0; synchronized (timedWaitLock()) { byte seqNo = ++timedWaitSeqNo; @@ -890,7 +882,19 @@ final class VirtualThread extends BaseVirtualThread { } /** - * Invoked by timer thread when wait timeout for virtual thread has expired. + * Invoked by FJP worker thread or STPE thread when park timeout expires. + */ + private void parkTimeoutExpired() { + assert !VirtualThread.currentThread().isVirtual(); + if (!getAndSetParkPermit(true) + && (state() == TIMED_PARKED) + && compareAndSetState(TIMED_PARKED, UNPARKED)) { + lazySubmitRunContinuation(); + } + } + + /** + * Invoked by FJP worker thread or STPE thread when wait timeout expires. * If the virtual thread is in timed-wait then this method will unblock the thread * and submit its task so that it continues and attempts to reenter the monitor. * This method does nothing if the thread has been woken by notify or interrupt. @@ -913,7 +917,7 @@ final class VirtualThread extends BaseVirtualThread { } } if (unblocked) { - submitRunContinuation(); + lazySubmitRunContinuation(); return; } // need to retry when thread is suspended in time-wait @@ -1444,40 +1448,54 @@ final class VirtualThread extends BaseVirtualThread { /** * Schedule a runnable task to run after a delay. */ - private static Future schedule(Runnable command, long delay, TimeUnit unit) { - long tid = Thread.currentThread().threadId(); - int index = (int) tid & (DELAYED_TASK_SCHEDULERS.length - 1); - return DELAYED_TASK_SCHEDULERS[index].schedule(command, delay, unit); + private Future schedule(Runnable command, long delay, TimeUnit unit) { + if (scheduler instanceof ForkJoinPool pool) { + return pool.schedule(command, delay, unit); + } else { + return DelayedTaskSchedulers.schedule(command, delay, unit); + } } /** - * Creates the ScheduledThreadPoolExecutors used to execute delayed tasks. + * Supports scheduling a runnable task to run after a delay. It uses a number + * of ScheduledThreadPoolExecutor instances to reduce contention on the delayed + * work queue used. This class is used when using a custom scheduler. */ - private static ScheduledExecutorService[] createDelayedTaskSchedulers() { - String propName = "jdk.virtualThreadScheduler.timerQueues"; - String propValue = System.getProperty(propName); - int queueCount; - if (propValue != null) { - queueCount = Integer.parseInt(propValue); - if (queueCount != Integer.highestOneBit(queueCount)) { - throw new RuntimeException("Value of " + propName + " must be power of 2"); + private static class DelayedTaskSchedulers { + private static final ScheduledExecutorService[] INSTANCE = createDelayedTaskSchedulers(); + + static Future schedule(Runnable command, long delay, TimeUnit unit) { + long tid = Thread.currentThread().threadId(); + int index = (int) tid & (INSTANCE.length - 1); + return INSTANCE[index].schedule(command, delay, unit); + } + + private static ScheduledExecutorService[] createDelayedTaskSchedulers() { + String propName = "jdk.virtualThreadScheduler.timerQueues"; + String propValue = System.getProperty(propName); + int queueCount; + if (propValue != null) { + queueCount = Integer.parseInt(propValue); + if (queueCount != Integer.highestOneBit(queueCount)) { + throw new RuntimeException("Value of " + propName + " must be power of 2"); + } + } else { + int ncpus = Runtime.getRuntime().availableProcessors(); + queueCount = Math.max(Integer.highestOneBit(ncpus / 4), 1); } - } else { - int ncpus = Runtime.getRuntime().availableProcessors(); - queueCount = Math.max(Integer.highestOneBit(ncpus / 4), 1); + var schedulers = new ScheduledExecutorService[queueCount]; + for (int i = 0; i < queueCount; i++) { + ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor) + Executors.newScheduledThreadPool(1, task -> { + Thread t = InnocuousThread.newThread("VirtualThread-unparker", task); + t.setDaemon(true); + return t; + }); + stpe.setRemoveOnCancelPolicy(true); + schedulers[i] = stpe; + } + return schedulers; } - var schedulers = new ScheduledExecutorService[queueCount]; - for (int i = 0; i < queueCount; i++) { - ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor) - Executors.newScheduledThreadPool(1, task -> { - Thread t = InnocuousThread.newThread("VirtualThread-unparker", task); - t.setDaemon(true); - return t; - }); - stpe.setRemoveOnCancelPolicy(true); - schedulers[i] = stpe; - } - return schedulers; } /** @@ -1514,4 +1532,4 @@ final class VirtualThread extends BaseVirtualThread { unblocker.setDaemon(true); unblocker.start(); } -} +} \ No newline at end of file diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index 077683a3bf2..8edeb731cee 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Stream; import jdk.internal.loader.NativeLibraries; @@ -586,11 +585,6 @@ public interface JavaLangAccess { */ Executor virtualThreadDefaultScheduler(); - /** - * Returns a stream of the delayed task schedulers used for virtual threads. - */ - Stream virtualThreadDelayedTaskSchedulers(); - /** * Creates a new StackWalker */ diff --git a/src/java.base/share/classes/jdk/internal/vm/JcmdVThreadCommands.java b/src/java.base/share/classes/jdk/internal/vm/JcmdVThreadCommands.java index 66ac6c2aca9..b97deb942bc 100644 --- a/src/java.base/share/classes/jdk/internal/vm/JcmdVThreadCommands.java +++ b/src/java.base/share/classes/jdk/internal/vm/JcmdVThreadCommands.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,19 +50,6 @@ public class JcmdVThreadCommands { sb.append(JLA.virtualThreadDefaultScheduler()) .append(System.lineSeparator()); - // break - sb.append(System.lineSeparator()); - - // delayed task schedulers - sb.append("Delayed task schedulers:").append(System.lineSeparator()); - var delayedTaskSchedulers = JLA.virtualThreadDelayedTaskSchedulers().toList(); - IntStream.range(0, delayedTaskSchedulers.size()) - .forEach(i -> sb.append('[') - .append(i) - .append("] ") - .append(delayedTaskSchedulers.get(i)) - .append(System.lineSeparator())); - return sb.toString().getBytes(StandardCharsets.UTF_8); } diff --git a/test/hotspot/jtreg/serviceability/dcmd/thread/VThreadCommandsTest.java b/test/hotspot/jtreg/serviceability/dcmd/thread/VThreadCommandsTest.java index de2b7249612..3d3ca813540 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/thread/VThreadCommandsTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/thread/VThreadCommandsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,13 +59,11 @@ class VThreadCommandsTest { */ @Test void testVThreadScheduler() { - // ensure default scheduler and timeout schedulers are initialized + // ensure default scheduler is initialized Thread.startVirtualThread(() -> { }); jcmd("Thread.vthread_scheduler") - .shouldContain(Objects.toIdentityString(defaultScheduler())) - .shouldContain("Delayed task schedulers:") - .shouldContain("[0] " + ScheduledThreadPoolExecutor.class.getName()); + .shouldContain(Objects.toIdentityString(defaultScheduler())); } /** diff --git a/test/micro/org/openjdk/bench/java/lang/VirtualThreadParking.java b/test/micro/org/openjdk/bench/java/lang/VirtualThreadParking.java new file mode 100644 index 00000000000..ad6233fd4bd --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/VirtualThreadParking.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.LockSupport; +import org.openjdk.jmh.annotations.*; + +@BenchmarkMode(Mode.Throughput) +@State(Scope.Benchmark) +@Warmup(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3) +@OutputTimeUnit(TimeUnit.SECONDS) +public class VirtualThreadParking { + + @Param({"100", "1000", "10000"}) + int threadCount; + + /** + * Starts N threads that time-park, main thread unparks. + */ + @Benchmark + public void timedParkAndUnpark1() throws Exception { + var threads = new Thread[threadCount]; + var unparked = new boolean[threadCount]; + for (int i = 0; i < threadCount; i++) { + threads[i] = Thread.ofVirtual().start(() -> { + LockSupport.parkNanos(Long.MAX_VALUE); + }); + } + int remaining = threadCount; + while (remaining > 0) { + for (int i = 0; i < threadCount; i++) { + if (!unparked[i]) { + Thread t = threads[i]; + if (t.getState() == Thread.State.TIMED_WAITING) { + LockSupport.unpark(t); + unparked[i] = true; + remaining--; + } + } + } + if (remaining > 0) { + Thread.yield(); + } + } + for (Thread t : threads) { + t.join(); + } + } + + /** + * Starts N threads that time-park, start another N threads to unpark. + */ + @Benchmark + public void timedParkAndUnpark2() throws Exception { + var threads = new Thread[threadCount * 2]; + for (int i = 0; i < threadCount; i++) { + threads[i] = Thread.ofVirtual().start(() -> { + LockSupport.parkNanos(Long.MAX_VALUE); + }); + } + for (int i = 0; i < threadCount; i++) { + Thread thread1 = threads[i]; + Thread thread2 = Thread.ofVirtual().start(() -> { + while (thread1.getState() != Thread.State.TIMED_WAITING) { + Thread.yield(); + } + LockSupport.unpark(thread1); + }); + threads[threadCount + i] = thread2; + } + for (Thread t : threads) { + t.join(); + } + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/java/lang/VirtualThreadSleep.java b/test/micro/org/openjdk/bench/java/lang/VirtualThreadSleep.java new file mode 100644 index 00000000000..7b7e47f5b59 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/VirtualThreadSleep.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; + +@BenchmarkMode(Mode.Throughput) +@State(Scope.Benchmark) +@Warmup(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3) +//@OutputTimeUnit(TimeUnit.SECONDS) +public class VirtualThreadSleep { + + @Param({"1000", "10000", "100000"}) + int threadCount; + + @Benchmark + public void sleep10() throws Exception { + var threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; i++) { + threads[i] = Thread.ofVirtual().start(() -> { + try { + Thread.sleep(10); + } catch (InterruptedException e) { } + }); + } + for (Thread t : threads) { + t.join(); + } + } + + @Benchmark + public void sleep10x10() throws Exception { + var threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; i++) { + threads[i] = Thread.ofVirtual().start(() -> { + try { + for (int k = 0; k < 10; k++) { + Thread.sleep(10); + } + } catch (InterruptedException e) { } + }); + } + for (Thread t : threads) { + t.join(); + } + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/java/util/concurrent/DelayedTasks.java b/test/micro/org/openjdk/bench/java/util/concurrent/DelayedTasks.java new file mode 100644 index 00000000000..1798459d6e8 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/DelayedTasks.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import java.util.*; +import java.util.concurrent.*; +import java.util.function.Supplier; +import org.openjdk.jmh.annotations.*; + +/** + * Benchmark to compare delayed task scheduling with ScheduledThreadPoolExcutor and ForkJoinPool. + */ + +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Fork(value = 3) +@Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) +@State(Scope.Thread) +public class DelayedTasks { + + private Supplier stpeSupplier; + private Supplier fjpSupplier; + + @Setup + public void setup() { + stpeSupplier = () -> { + ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + ((ScheduledThreadPoolExecutor) executor).setRemoveOnCancelPolicy(true); + return executor; + }; + int nprocs = Runtime.getRuntime().availableProcessors(); + fjpSupplier = () -> new ForkJoinPool(nprocs); + } + + @Param({"100", "1000", "10000"}) + int delayedTasks; + + // delayed tasks cancelled by main thread + private void mainThreadCancels(Supplier supplier) { + try (ScheduledExecutorService ses = supplier.get()) { + var futures = new ScheduledFuture[delayedTasks]; + for (int i = 0; i < delayedTasks; i++) { + futures[i] = ses.schedule(() -> { }, 30L, TimeUnit.MINUTES); + } + for (ScheduledFuture f : futures) { + f.cancel(false); + } + } + } + + // delayed tasks cancelled by virtual threads + private void virtualThreadCancels(Supplier supplier) throws Exception { + try (ScheduledExecutorService ses = supplier.get()) { + var futures = new ScheduledFuture[delayedTasks]; + var threads = new Thread[delayedTasks]; + for (int i = 0; i < delayedTasks; i++) { + ScheduledFuture future = ses.schedule(() -> { }, 30L, TimeUnit.MINUTES); + futures[i] = future; + threads[i] = Thread.ofVirtual().start(() -> future.cancel(false)); + } + for (Thread t : threads) { + t.join(); + } + } + } + + // delayed task executes + private void delayedTaskExecutes(Supplier supplier) throws Exception { + try (ScheduledExecutorService ses = supplier.get()) { + var futures = new ScheduledFuture[delayedTasks]; + for (int i = 0; i < delayedTasks; i++) { + futures[i] = ses.schedule(() -> { }, 10L, TimeUnit.MILLISECONDS); + } + for (ScheduledFuture f : futures) { + f.get(); + } + } + } + + @Benchmark + public void spteMainThreadCancels() { + mainThreadCancels(stpeSupplier); + } + + @Benchmark + public void spteVirtualThreadCancels() throws Exception { + virtualThreadCancels(stpeSupplier); + } + + @Benchmark + public void spteDelayedTaskExecutes() throws Exception { + delayedTaskExecutes(stpeSupplier); + } + + @Benchmark + public void fjpMainThreadCancels() { + mainThreadCancels(fjpSupplier); + } + + @Benchmark + public void fjpVirtualThreadCancels() throws Exception { + virtualThreadCancels(fjpSupplier); + } + + @Benchmark + public void fjpDelayedTaskExecutes() throws Exception { + delayedTaskExecutes(fjpSupplier); + } +} \ No newline at end of file From f9d705b17e5d90f7bc5f9759f692182bb4da3445 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Wed, 9 Apr 2025 12:44:47 +0000 Subject: [PATCH 083/843] 8351757: Test java/foreign/TestDeadlock.java#FileChannel_map timed out after passing Reviewed-by: djelinski, rriggs --- test/jdk/java/foreign/TestDeadlock.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/foreign/TestDeadlock.java b/test/jdk/java/foreign/TestDeadlock.java index 9144fad3830..8511a01d2f5 100644 --- a/test/jdk/java/foreign/TestDeadlock.java +++ b/test/jdk/java/foreign/TestDeadlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,12 @@ /* * @test id=Arena_allocateFrom - * @run main/othervm/timeout=5 --enable-native-access=ALL-UNNAMED -Xlog:class+init TestDeadlock Arena + * @run main/othervm/timeout=10 --enable-native-access=ALL-UNNAMED -Xlog:class+init TestDeadlock Arena */ /* * @test id=FileChannel_map - * @run main/othervm/timeout=5 --enable-native-access=ALL-UNNAMED -Xlog:class+init TestDeadlock FileChannel + * @run main/othervm/timeout=60 --enable-native-access=ALL-UNNAMED -Xlog:class+init TestDeadlock FileChannel */ import java.lang.foreign.*; From da462cf2255f55c1059f9d9bf479231408a72b55 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Wed, 9 Apr 2025 12:58:00 +0000 Subject: [PATCH 084/843] 8353692: Relax memory constraint on updating ObjectMonitorTable's item count Reviewed-by: rkennke, dholmes --- src/hotspot/share/runtime/lightweightSynchronizer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/runtime/lightweightSynchronizer.cpp b/src/hotspot/share/runtime/lightweightSynchronizer.cpp index 471a5c00e20..c2a4e73f034 100644 --- a/src/hotspot/share/runtime/lightweightSynchronizer.cpp +++ b/src/hotspot/share/runtime/lightweightSynchronizer.cpp @@ -115,15 +115,16 @@ class ObjectMonitorTable : AllStatic { }; static void inc_items_count() { - Atomic::inc(&_items_count); + Atomic::inc(&_items_count, memory_order_relaxed); } static void dec_items_count() { - Atomic::dec(&_items_count); + Atomic::dec(&_items_count, memory_order_relaxed); } static double get_load_factor() { - return (double)_items_count / (double)_table_size; + size_t count = Atomic::load(&_items_count); + return (double)count / (double)_table_size; } static size_t table_size(Thread* current = Thread::current()) { From 9d8b93b6e2fa7a6c81d96f82ae8f5de222027879 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Wed, 9 Apr 2025 13:08:21 +0000 Subject: [PATCH 085/843] 8354181: [Backout] 8334046: Set different values for CompLevel_any and CompLevel_all Reviewed-by: thartmann, chagedorn --- src/hotspot/share/compiler/compilerDefinitions.hpp | 2 +- .../jtreg/compiler/whitebox/CompilerWhiteBoxTest.java | 8 +++----- test/lib/jdk/test/whitebox/WhiteBox.java | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index 2c1ae85af8a..bdaa6dffb8f 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -53,7 +53,7 @@ enum MethodCompilation { // Enumeration to distinguish tiers of compilation enum CompLevel : s1 { - CompLevel_any = -2, // Used for querying the state + CompLevel_any = -1, // Used for querying the state CompLevel_all = -1, // Used for changing the state CompLevel_none = 0, // Interpreter CompLevel_simple = 1, // C1 diff --git a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java index dde2b3cdfd0..f87292be019 100644 --- a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java +++ b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java @@ -41,10 +41,8 @@ import java.util.function.Function; public abstract class CompilerWhiteBoxTest { /** {@code CompLevel::CompLevel_none} -- Interpreter */ public static final int COMP_LEVEL_NONE = 0; - /** {@code CompLevel::CompLevel_any} */ - public static final int COMP_LEVEL_ANY = -2; - /** {@code CompLevel::CompLevel_all} */ - public static final int COMP_LEVEL_ALL = -1; + /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */ + public static final int COMP_LEVEL_ANY = -1; /** {@code CompLevel::CompLevel_simple} -- C1 */ public static final int COMP_LEVEL_SIMPLE = 1; /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation & backedge counters */ @@ -286,7 +284,7 @@ public abstract class CompilerWhiteBoxTest { } protected final void makeNotCompilable() { - WHITE_BOX.makeMethodNotCompilable(method, COMP_LEVEL_ALL, + WHITE_BOX.makeMethodNotCompilable(method, COMP_LEVEL_ANY, testCase.isOsr()); } diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 2744978b8a9..f0e164d94b5 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -345,7 +345,7 @@ public class WhiteBox { return isMethodCompiled0(method, isOsr); } public boolean isMethodCompilable(Executable method) { - return isMethodCompilable(method, -2 /*any*/); + return isMethodCompilable(method, -1 /*any*/); } public boolean isMethodCompilable(Executable method, int compLevel) { return isMethodCompilable(method, compLevel, false /*not osr*/); @@ -393,7 +393,7 @@ public class WhiteBox { return deoptimizeMethod0(method, isOsr); } public void makeMethodNotCompilable(Executable method) { - makeMethodNotCompilable(method, -1 /*all*/); + makeMethodNotCompilable(method, -1 /*any*/); } public void makeMethodNotCompilable(Executable method, int compLevel) { makeMethodNotCompilable(method, compLevel, false /*not osr*/); From c3e043956e72996a56a7ae9822782ba4dfdc0607 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Wed, 9 Apr 2025 13:47:24 +0000 Subject: [PATCH 086/843] 8354121: Use a record class rather than a lambda in AbstractMemorySegmentImpl::cleanupAction Reviewed-by: liach --- .../foreign/AbstractMemorySegmentImpl.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 83fb6881a41..d7636032c28 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -162,9 +162,19 @@ public abstract sealed class AbstractMemorySegmentImpl // Using a static helper method ensures there is no unintended lambda capturing of `this` private static Runnable cleanupAction(long address, long newSize, Consumer cleanup) { - return cleanup != null ? - () -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address, newSize)) : - null; + + record CleanupAction(long address, long newSize, Consumer cleanup) implements Runnable { + @Override + public void run() { + cleanup().accept(SegmentFactories.makeNativeSegmentUnchecked(address(), newSize())); + } + } + + return cleanup != null + // Use a record (which is always static) instead of a lambda to avoid + // capturing and to enable early use in the init sequence. + ? new CleanupAction(address, newSize, cleanup) + : null; } private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) { From 7a7b9ed7fe4a10bca155b0877c3e731f9d343b92 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Wed, 9 Apr 2025 14:49:04 +0000 Subject: [PATCH 087/843] 8353727: HeapDumpPath doesn't expand %p Reviewed-by: stuefe, lmesnik --- src/hotspot/share/services/heapDumper.cpp | 76 ++++++------------- .../TestHeapDumpOnOutOfMemoryError.java | 19 +++-- 2 files changed, 34 insertions(+), 61 deletions(-) diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp index b30b0428648..7a2c8d52969 100644 --- a/src/hotspot/share/services/heapDumper.cpp +++ b/src/hotspot/share/services/heapDumper.cpp @@ -43,6 +43,7 @@ #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "runtime/arguments.hpp" #include "runtime/continuationWrapper.inline.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" @@ -2747,71 +2748,45 @@ void HeapDumper::dump_heap() { void HeapDumper::dump_heap(bool oome) { static char base_path[JVM_MAXPATHLEN] = {'\0'}; static uint dump_file_seq = 0; - char* my_path; + char my_path[JVM_MAXPATHLEN]; const int max_digit_chars = 20; - - const char* dump_file_name = "java_pid"; - const char* dump_file_ext = HeapDumpGzipLevel > 0 ? ".hprof.gz" : ".hprof"; + const char* dump_file_name = HeapDumpGzipLevel > 0 ? "java_pid%p.hprof.gz" : "java_pid%p.hprof"; // The dump file defaults to java_pid.hprof in the current working // directory. HeapDumpPath= can be used to specify an alternative // dump file name or a directory where dump file is created. if (dump_file_seq == 0) { // first time in, we initialize base_path - // Calculate potentially longest base path and check if we have enough - // allocated statically. - const size_t total_length = - (HeapDumpPath == nullptr ? 0 : strlen(HeapDumpPath)) + - strlen(os::file_separator()) + max_digit_chars + - strlen(dump_file_name) + strlen(dump_file_ext) + 1; - if (total_length > sizeof(base_path)) { + // Set base path (name or directory, default or custom, without seq no), doing %p substitution. + const char *path_src = (HeapDumpPath != nullptr && HeapDumpPath[0] != '\0') ? HeapDumpPath : dump_file_name; + if (!Arguments::copy_expand_pid(path_src, strlen(path_src), base_path, JVM_MAXPATHLEN - max_digit_chars)) { warning("Cannot create heap dump file. HeapDumpPath is too long."); return; } - - bool use_default_filename = true; - if (HeapDumpPath == nullptr || HeapDumpPath[0] == '\0') { - // HeapDumpPath= not specified - } else { - strcpy(base_path, HeapDumpPath); - // check if the path is a directory (must exist) - DIR* dir = os::opendir(base_path); - if (dir == nullptr) { - use_default_filename = false; - } else { - // HeapDumpPath specified a directory. We append a file separator - // (if needed). - os::closedir(dir); - size_t fs_len = strlen(os::file_separator()); - if (strlen(base_path) >= fs_len) { - char* end = base_path; - end += (strlen(base_path) - fs_len); - if (strcmp(end, os::file_separator()) != 0) { - strcat(base_path, os::file_separator()); - } + // Check if the path is an existing directory + DIR* dir = os::opendir(base_path); + if (dir != nullptr) { + os::closedir(dir); + // Path is a directory. Append a file separator (if needed). + size_t fs_len = strlen(os::file_separator()); + if (strlen(base_path) >= fs_len) { + char* end = base_path; + end += (strlen(base_path) - fs_len); + if (strcmp(end, os::file_separator()) != 0) { + strcat(base_path, os::file_separator()); } } + // Then add the default name, with %p substitution. Use my_path temporarily. + if (!Arguments::copy_expand_pid(dump_file_name, strlen(dump_file_name), my_path, JVM_MAXPATHLEN - max_digit_chars)) { + warning("Cannot create heap dump file. HeapDumpPath is too long."); + return; + } + const size_t dlen = strlen(base_path); + jio_snprintf(&base_path[dlen], sizeof(base_path) - dlen, "%s", my_path); } - // If HeapDumpPath wasn't a file name then we append the default name - if (use_default_filename) { - const size_t dlen = strlen(base_path); // if heap dump dir specified - jio_snprintf(&base_path[dlen], sizeof(base_path)-dlen, "%s%d%s", - dump_file_name, os::current_process_id(), dump_file_ext); - } - const size_t len = strlen(base_path) + 1; - my_path = (char*)os::malloc(len, mtInternal); - if (my_path == nullptr) { - warning("Cannot create heap dump file. Out of system memory."); - return; - } - strncpy(my_path, base_path, len); + strncpy(my_path, base_path, JVM_MAXPATHLEN); } else { // Append a sequence number id for dumps following the first const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0 - my_path = (char*)os::malloc(len, mtInternal); - if (my_path == nullptr) { - warning("Cannot create heap dump file. Out of system memory."); - return; - } jio_snprintf(my_path, len, "%s.%d", base_path, dump_file_seq); } dump_file_seq++; // increment seq number for next time we dump @@ -2819,5 +2794,4 @@ void HeapDumper::dump_heap(bool oome) { HeapDumper dumper(false /* no GC before heap dump */, oome /* pass along out-of-memory-error flag */); dumper.dump(my_path, tty, HeapDumpGzipLevel); - os::free(my_path); } diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/TestHeapDumpOnOutOfMemoryError.java b/test/hotspot/jtreg/runtime/ErrorHandling/TestHeapDumpOnOutOfMemoryError.java index fb098bd27fe..66df532983a 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/TestHeapDumpOnOutOfMemoryError.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/TestHeapDumpOnOutOfMemoryError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,10 +71,12 @@ public class TestHeapDumpOnOutOfMemoryError { } } test(args[1]); + System.out.println("PASSED"); } static void test(String type) throws Exception { - String heapdumpFilename = type + ".hprof"; + // Test using %p pid substitution in HeapDumpPath: + String heapdumpFilename = type + ".%p.hprof"; ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=" + heapdumpFilename, // Note: When trying to provoke a metaspace OOM we may generate a lot of classes. In debug VMs this @@ -94,13 +96,10 @@ public class TestHeapDumpOnOutOfMemoryError { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.stdoutShouldNotBeEmpty(); - output.shouldContain("Dumping heap to " + type + ".hprof"); - File dump = new File(heapdumpFilename); - Asserts.assertTrue(dump.exists() && dump.isFile(), - "Could not find dump file " + dump.getAbsolutePath()); - - HprofParser.parse(new File(heapdumpFilename)); - System.out.println("PASSED"); + String expectedHeapdumpFilename = type + "." + output.pid() + ".hprof"; + output.shouldContain("Dumping heap to " + expectedHeapdumpFilename); + File dump = new File(expectedHeapdumpFilename); + Asserts.assertTrue(dump.exists() && dump.isFile(), "Expected heap dump file " + dump.getAbsolutePath()); + HprofParser.parse(new File(expectedHeapdumpFilename)); } - } From 4dc9e58906772bf8ee444cb1618aa43f66593d79 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Wed, 9 Apr 2025 14:51:15 +0000 Subject: [PATCH 088/843] 8310310: Migrate CreateSymbols tool in make/langtools to Classfile API Reviewed-by: ihse, jlahoda --- .../tools/symbolgenerator/CreateSymbols.java | 1355 +++++------------ make/modules/jdk.compiler/Gendata.gmk | 1 - make/scripts/generate-symbol-data.sh | 3 +- .../platform/CanHandleClassFilesTest.java | 9 +- .../createsymbols/CreateSymbolsTest.java | 6 +- 5 files changed, 360 insertions(+), 1014 deletions(-) diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 6faefecd424..db8924c79fb 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, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,18 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.StringWriter; import java.io.Writer; +import java.lang.classfile.*; +import java.lang.classfile.attribute.*; +import java.lang.classfile.constantpool.ClassEntry; +import java.lang.classfile.constantpool.ConstantPoolBuilder; +import java.lang.classfile.constantpool.ConstantValueEntry; +import java.lang.classfile.constantpool.IntegerEntry; +import java.lang.classfile.constantpool.Utf8Entry; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.constant.ModuleDesc; +import java.lang.constant.PackageDesc; +import java.lang.reflect.AccessFlag; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.FileVisitResult; @@ -88,63 +100,6 @@ import javax.tools.JavaFileObject.Kind; import javax.tools.StandardLocation; import com.sun.source.util.JavacTask; -import com.sun.tools.classfile.AccessFlags; -import com.sun.tools.classfile.Annotation; -import com.sun.tools.classfile.Annotation.Annotation_element_value; -import com.sun.tools.classfile.Annotation.Array_element_value; -import com.sun.tools.classfile.Annotation.Class_element_value; -import com.sun.tools.classfile.Annotation.Enum_element_value; -import com.sun.tools.classfile.Annotation.Primitive_element_value; -import com.sun.tools.classfile.Annotation.element_value; -import com.sun.tools.classfile.Annotation.element_value_pair; -import com.sun.tools.classfile.AnnotationDefault_attribute; -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.CONSTANT_Class_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Integer_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Long_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Module_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Package_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; -import com.sun.tools.classfile.ConstantPool.CPInfo; -import com.sun.tools.classfile.ConstantPool.InvalidIndex; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.ConstantValue_attribute; -import com.sun.tools.classfile.Deprecated_attribute; -import com.sun.tools.classfile.Descriptor; -import com.sun.tools.classfile.Exceptions_attribute; -import com.sun.tools.classfile.Field; -import com.sun.tools.classfile.InnerClasses_attribute; -import com.sun.tools.classfile.InnerClasses_attribute.Info; -import com.sun.tools.classfile.Method; -import com.sun.tools.classfile.ModulePackages_attribute; -import com.sun.tools.classfile.MethodParameters_attribute; -import com.sun.tools.classfile.ModuleMainClass_attribute; -import com.sun.tools.classfile.ModuleResolution_attribute; -import com.sun.tools.classfile.ModuleTarget_attribute; -import com.sun.tools.classfile.Module_attribute; -import com.sun.tools.classfile.Module_attribute.ExportsEntry; -import com.sun.tools.classfile.Module_attribute.OpensEntry; -import com.sun.tools.classfile.Module_attribute.ProvidesEntry; -import com.sun.tools.classfile.Module_attribute.RequiresEntry; -import com.sun.tools.classfile.NestHost_attribute; -import com.sun.tools.classfile.NestMembers_attribute; -import com.sun.tools.classfile.PermittedSubclasses_attribute; -import com.sun.tools.classfile.Record_attribute; -import com.sun.tools.classfile.Record_attribute.ComponentInfo; -import com.sun.tools.classfile.RuntimeAnnotations_attribute; -import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; -import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.Signature_attribute; import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.util.Assert; @@ -154,13 +109,15 @@ import java.nio.file.DirectoryStream; import java.util.Optional; import java.util.function.Consumer; +import static java.lang.classfile.ClassFile.ACC_PROTECTED; +import static java.lang.classfile.ClassFile.ACC_PUBLIC; + /** * A tool for processing the .sym.txt files. * * To add historical data for JDK N, N >= 11, do the following: * * cd /src/jdk.compiler/share/data/symbols - * * /bin/java --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \ - * --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ + * * /bin/java --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ * --add-exports jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \ * --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ * --add-modules jdk.jdeps \ @@ -409,7 +366,7 @@ public class CreateSymbols { reader.moveNext(); break; default: - throw new IllegalStateException("Unknown key: " + reader.lineKey); + throw new IllegalArgumentException("Unknown key: " + reader.lineKey); } } } @@ -432,7 +389,7 @@ public class CreateSymbols { reader.moveNext(); break; default: - throw new IllegalStateException("Unknown key: " + reader.lineKey); + throw new IllegalArgumentException("Unknown key: " + reader.lineKey); } } } @@ -830,31 +787,12 @@ public class CreateSymbols { ModuleHeaderDescription header, char version, Function version2ModuleVersion) throws IOException { - List constantPool = new ArrayList<>(); - constantPool.add(null); - int currentClass = addClass(constantPool, "module-info"); - int superclass = 0; - int[] interfaces = new int[0]; - AccessFlags flags = new AccessFlags(header.flags); - Map attributesMap = new HashMap<>(); - String versionString = Character.toString(version); - addAttributes(moduleDescription, header, constantPool, attributesMap, - version2ModuleVersion.apply(version)); - Attributes attributes = new Attributes(attributesMap); - CPInfo[] cpData = constantPool.toArray(new CPInfo[constantPool.size()]); - ConstantPool cp = new ConstantPool(cpData); - ClassFile classFile = new ClassFile(0xCAFEBABE, - Target.DEFAULT.minorVersion, - Target.DEFAULT.majorVersion, - cp, - flags, - currentClass, - superclass, - interfaces, - new Field[0], - new Method[0], - attributes); + var classFile = ClassFile.of().build(ClassDesc.of("module-info"), clb -> { + clb.withFlags(header.flags); + addAttributes(moduleDescription, header, clb, version2ModuleVersion.apply(version)); + }); + String versionString = Character.toString(version); doWrite(directory2FileData, versionString, moduleDescription.name, "module-info" + EXTENSION, classFile); } @@ -863,57 +801,26 @@ public class CreateSymbols { ClassHeaderDescription header, String module, String version) throws IOException { - List constantPool = new ArrayList<>(); - constantPool.add(null); - List methods = new ArrayList<>(); - for (MethodDescription methDesc : classDescription.methods) { - if (disjoint(methDesc.versions, version)) - continue; - Descriptor descriptor = new Descriptor(addString(constantPool, methDesc.descriptor)); - //TODO: LinkedHashMap to avoid param annotations vs. Signature problem in javac's ClassReader: - Map attributesMap = new LinkedHashMap<>(); - addAttributes(methDesc, constantPool, attributesMap); - Attributes attributes = new Attributes(attributesMap); - AccessFlags flags = new AccessFlags(methDesc.flags); - int nameString = addString(constantPool, methDesc.name); - methods.add(new Method(flags, nameString, descriptor, attributes)); - } - List fields = new ArrayList<>(); - for (FieldDescription fieldDesc : classDescription.fields) { - if (disjoint(fieldDesc.versions, version)) - continue; - Descriptor descriptor = new Descriptor(addString(constantPool, fieldDesc.descriptor)); - Map attributesMap = new HashMap<>(); - addAttributes(fieldDesc, constantPool, attributesMap); - Attributes attributes = new Attributes(attributesMap); - AccessFlags flags = new AccessFlags(fieldDesc.flags); - int nameString = addString(constantPool, fieldDesc.name); - fields.add(new Field(flags, nameString, descriptor, attributes)); - } - int currentClass = addClass(constantPool, classDescription.name); - int superclass = header.extendsAttr != null ? addClass(constantPool, header.extendsAttr) : 0; - int[] interfaces = new int[header.implementsAttr.size()]; - int i = 0; - for (String intf : header.implementsAttr) { - interfaces[i++] = addClass(constantPool, intf); - } - AccessFlags flags = new AccessFlags(header.flags); - Map attributesMap = new HashMap<>(); - addAttributes(header, constantPool, attributesMap); - Attributes attributes = new Attributes(attributesMap); - ConstantPool cp = new ConstantPool(constantPool.toArray(new CPInfo[constantPool.size()])); - ClassFile classFile = new ClassFile(0xCAFEBABE, - Target.DEFAULT.minorVersion, - Target.DEFAULT.majorVersion, - cp, - flags, - currentClass, - superclass, - interfaces, - fields.toArray(new Field[0]), - methods.toArray(new Method[0]), - attributes); - + var classFile = ClassFile.of().build(ClassDesc.ofInternalName(classDescription.name), clb -> { + if (header.extendsAttr != null) + clb.withSuperclass(ClassDesc.ofInternalName(header.extendsAttr)); + clb.withInterfaceSymbols(header.implementsAttr.stream().map(ClassDesc::ofInternalName).collect(Collectors.toList())) + .withFlags(header.flags); + for (FieldDescription fieldDesc : classDescription.fields) { + if (disjoint(fieldDesc.versions, version)) + continue; + clb.withField(fieldDesc.name, ClassDesc.ofDescriptor(fieldDesc.descriptor), fb -> { + addAttributes(fieldDesc, fb); + fb.withFlags(fieldDesc.flags); + }); + } + for (MethodDescription methDesc : classDescription.methods) { + if (disjoint(methDesc.versions, version)) + continue; + clb.withMethod(methDesc.name, MethodTypeDesc.ofDescriptor(methDesc.descriptor), methDesc.flags, mb -> addAttributes(methDesc, mb)); + } + addAttributes(header, clb); + }); doWrite(directory2FileData, version, module, classDescription.name + EXTENSION, classFile); } @@ -921,19 +828,13 @@ public class CreateSymbols { String version, String moduleName, String fileName, - ClassFile classFile) throws IOException { + byte[] classFile) throws IOException { int lastSlash = fileName.lastIndexOf('/'); String pack = lastSlash != (-1) ? fileName.substring(0, lastSlash + 1) : "/"; String directory = version + "/" + moduleName + "/" + pack; String fullFileName = version + "/" + moduleName + "/" + fileName; - try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - ClassWriter w = new ClassWriter(); - - w.write(classFile, out); - - openDirectory(directory2FileData, directory) - .add(new FileData(fullFileName, out.toByteArray())); - } + openDirectory(directory2FileData, directory) + .add(new FileData(fullFileName, classFile)); } private Set openDirectory(Map> directory2FileData, @@ -955,278 +856,147 @@ public class CreateSymbols { private void addAttributes(ModuleDescription md, ModuleHeaderDescription header, - List cp, - Map attributes, + ClassBuilder builder, String moduleVersion) { - addGenericAttributes(header, cp, attributes); + addGenericAttributes(header, builder); if (header.moduleResolution != null) { - int attrIdx = addString(cp, Attribute.ModuleResolution); - final ModuleResolution_attribute resIdx = - new ModuleResolution_attribute(attrIdx, - header.moduleResolution); - attributes.put(Attribute.ModuleResolution, resIdx); + builder.with(ModuleResolutionAttribute.of(header.moduleResolution)); } if (header.moduleTarget != null) { - int attrIdx = addString(cp, Attribute.ModuleTarget); - int targetIdx = addString(cp, header.moduleTarget); - attributes.put(Attribute.ModuleTarget, - new ModuleTarget_attribute(attrIdx, targetIdx)); + builder.with(ModuleTargetAttribute.of(header.moduleTarget)); } if (header.moduleMainClass != null) { - int attrIdx = addString(cp, Attribute.ModuleMainClass); - int targetIdx = addClassName(cp, header.moduleMainClass); - attributes.put(Attribute.ModuleMainClass, - new ModuleMainClass_attribute(attrIdx, targetIdx)); + builder.with(ModuleMainClassAttribute.of(ClassDesc.ofInternalName(header.moduleMainClass))); } - int versionIdx = addString(cp, moduleVersion); - int attrIdx = addString(cp, Attribute.Module); - attributes.put(Attribute.Module, - new Module_attribute(attrIdx, - addModuleName(cp, md.name), - 0, - versionIdx, - header.requires - .stream() - .map(r -> createRequiresEntry(cp, r)) - .collect(Collectors.toList()) - .toArray(new RequiresEntry[0]), - header.exports - .stream() - .map(e -> createExportsEntry(cp, e)) - .collect(Collectors.toList()) - .toArray(new ExportsEntry[0]), - header.opens - .stream() - .map(e -> createOpensEntry(cp, e)) - .collect(Collectors.toList()) - .toArray(new OpensEntry[0]), - header.uses - .stream() - .mapToInt(u -> addClassName(cp, u)) - .toArray(), - header.provides - .stream() - .map(p -> createProvidesEntry(cp, p)) - .collect(Collectors.toList()) - .toArray(new ProvidesEntry[0]))); - addInnerClassesAttribute(header, cp, attributes); + builder.with(ModuleAttribute.of(ModuleDesc.of(md.name), mb -> { + mb.moduleVersion(moduleVersion); + for (var req : header.requires) { + mb.requires(ModuleDesc.of(req.moduleName), req.flags, req.version); // nullable version + } + for (var exp : header.exports) { + if (exp.isQualified()) { + mb.exports(PackageDesc.ofInternalName(exp.packageName()), 0, exp.to.stream().map(ModuleDesc::of).toArray(ModuleDesc[]::new)); + } else { + mb.exports(PackageDesc.ofInternalName(exp.packageName()), 0); + } + } + for (var open : header.opens) { + mb.opens(PackageDesc.ofInternalName(open), 0); + } + for (var use : header.uses) { + mb.uses(ClassDesc.ofInternalName(use)); + } + for (var provide : header.provides) { + mb.provides(ClassDesc.ofInternalName(provide.interfaceName), + provide.implNames.stream().map(ClassDesc::ofInternalName).toArray(ClassDesc[]::new)); + } + })); + addInnerClassesAttribute(header, builder); } - private static RequiresEntry createRequiresEntry(List cp, - RequiresDescription r) { - final int idx = addModuleName(cp, r.moduleName); - return new RequiresEntry(idx, - r.flags, - r.version != null - ? addString(cp, r.version) - : 0); - } - - private static ExportsEntry createExportsEntry(List cp, - ExportsDescription export) { - int[] to; - if (export.isQualified()) { - to = export.to.stream() - .mapToInt(module -> addModuleName(cp, module)) - .toArray(); - } else { - to = new int[0]; - } - return new ExportsEntry(addPackageName(cp, export.packageName()), 0, to); - } - - private static OpensEntry createOpensEntry(List cp, String e) { - return new OpensEntry(addPackageName(cp, e), 0, new int[0]); - } - - private static ProvidesEntry createProvidesEntry(List cp, - ModuleHeaderDescription.ProvidesDescription p) { - final int idx = addClassName(cp, p.interfaceName); - return new ProvidesEntry(idx, p.implNames - .stream() - .mapToInt(i -> addClassName(cp, i)) - .toArray()); - } - - private void addAttributes(ClassHeaderDescription header, - List constantPool, Map attributes) { - addGenericAttributes(header, constantPool, attributes); + private void addAttributes(ClassHeaderDescription header, ClassBuilder builder) { + addGenericAttributes(header, builder); if (header.nestHost != null) { - int attributeString = addString(constantPool, Attribute.NestHost); - int nestHost = addClass(constantPool, header.nestHost); - attributes.put(Attribute.NestHost, - new NestHost_attribute(attributeString, nestHost)); + builder.with(NestHostAttribute.of(ClassDesc.ofInternalName(header.nestHost))); } if (header.nestMembers != null && !header.nestMembers.isEmpty()) { - int attributeString = addString(constantPool, Attribute.NestMembers); - int[] nestMembers = new int[header.nestMembers.size()]; - int i = 0; - for (String intf : header.nestMembers) { - nestMembers[i++] = addClass(constantPool, intf); - } - attributes.put(Attribute.NestMembers, - new NestMembers_attribute(attributeString, nestMembers)); + builder.with(NestMembersAttribute.ofSymbols(header.nestMembers.stream().map(ClassDesc::ofInternalName).collect(Collectors.toList()))); } if (header.isRecord) { - assert header.recordComponents != null; - int attributeString = addString(constantPool, Attribute.Record); - ComponentInfo[] recordComponents = new ComponentInfo[header.recordComponents.size()]; - int i = 0; - for (RecordComponentDescription rcd : header.recordComponents) { - int name = addString(constantPool, rcd.name); - Descriptor desc = new Descriptor(addString(constantPool, rcd.descriptor)); - Map nestedAttrs = new HashMap<>(); - addGenericAttributes(rcd, constantPool, nestedAttrs); - Attributes attrs = new Attributes(nestedAttrs); - recordComponents[i++] = new ComponentInfo(name, desc, attrs); - } - attributes.put(Attribute.Record, - new Record_attribute(attributeString, recordComponents)); + builder.with(RecordAttribute.of(header.recordComponents.stream().map(desc -> { + List> attributes = new ArrayList<>(); + addGenericAttributes(desc, attributes::add, builder.constantPool()); + return RecordComponentInfo.of(desc.name, ClassDesc.ofDescriptor(desc.descriptor), attributes); + }).collect(Collectors.toList()))); } if (header.isSealed) { - int attributeString = addString(constantPool, Attribute.PermittedSubclasses); - int[] subclasses = new int[header.permittedSubclasses.size()]; - int i = 0; - for (String intf : header.permittedSubclasses) { - subclasses[i++] = addClass(constantPool, intf); - } - attributes.put(Attribute.PermittedSubclasses, - new PermittedSubclasses_attribute(attributeString, subclasses)); + builder.with(PermittedSubclassesAttribute.ofSymbols(header.permittedSubclasses.stream().map(ClassDesc::ofInternalName).collect(Collectors.toList()))); } - addInnerClassesAttribute(header, constantPool, attributes); + addInnerClassesAttribute(header, builder); } - private void addInnerClassesAttribute(HeaderDescription header, - List constantPool, Map attributes) { + private void addInnerClassesAttribute(HeaderDescription header, ClassBuilder builder) { if (header.innerClasses != null && !header.innerClasses.isEmpty()) { - Info[] innerClasses = new Info[header.innerClasses.size()]; - int i = 0; - for (InnerClassInfo info : header.innerClasses) { - innerClasses[i++] = - new Info(info.innerClass == null ? 0 : addClass(constantPool, info.innerClass), - info.outerClass == null ? 0 : addClass(constantPool, info.outerClass), - info.innerClassName == null ? 0 : addString(constantPool, info.innerClassName), - new AccessFlags(info.innerClassFlags)); - } - int attributeString = addString(constantPool, Attribute.InnerClasses); - attributes.put(Attribute.InnerClasses, - new InnerClasses_attribute(attributeString, innerClasses)); + builder.with(InnerClassesAttribute.of(header.innerClasses.stream() + .map(info -> java.lang.classfile.attribute.InnerClassInfo.of( + ClassDesc.ofInternalName(info.innerClass), + Optional.ofNullable(info.outerClass).map(ClassDesc::ofInternalName), + Optional.ofNullable(info.innerClassName), + info.innerClassFlags + )).collect(Collectors.toList()))); } } - private void addAttributes(MethodDescription desc, List constantPool, Map attributes) { - addGenericAttributes(desc, constantPool, attributes); + private void addAttributes(MethodDescription desc, MethodBuilder builder) { + addGenericAttributes(desc, builder); if (desc.thrownTypes != null) { - int[] exceptions = new int[desc.thrownTypes.size()]; - int i = 0; - for (String exc : desc.thrownTypes) { - exceptions[i++] = addClass(constantPool, exc); - } - int attributeString = addString(constantPool, Attribute.Exceptions); - attributes.put(Attribute.Exceptions, - new Exceptions_attribute(attributeString, exceptions)); + builder.with(ExceptionsAttribute.ofSymbols(desc.thrownTypes.stream() + .map(ClassDesc::ofInternalName).collect(Collectors.toList()))); } if (desc.annotationDefaultValue != null) { - int attributeString = addString(constantPool, Attribute.AnnotationDefault); - element_value attributeValue = createAttributeValue(constantPool, - desc.annotationDefaultValue); - attributes.put(Attribute.AnnotationDefault, - new AnnotationDefault_attribute(attributeString, attributeValue)); + builder.with(AnnotationDefaultAttribute.of(createAttributeValue(desc.annotationDefaultValue))); } if (desc.classParameterAnnotations != null && !desc.classParameterAnnotations.isEmpty()) { - int attributeString = - addString(constantPool, Attribute.RuntimeInvisibleParameterAnnotations); - Annotation[][] annotations = - createParameterAnnotations(constantPool, desc.classParameterAnnotations); - attributes.put(Attribute.RuntimeInvisibleParameterAnnotations, - new RuntimeInvisibleParameterAnnotations_attribute(attributeString, - annotations)); + builder.with(RuntimeInvisibleParameterAnnotationsAttribute.of(createParameterAnnotations(desc.classParameterAnnotations))); } if (desc.runtimeParameterAnnotations != null && !desc.runtimeParameterAnnotations.isEmpty()) { - int attributeString = - addString(constantPool, Attribute.RuntimeVisibleParameterAnnotations); - Annotation[][] annotations = - createParameterAnnotations(constantPool, desc.runtimeParameterAnnotations); - attributes.put(Attribute.RuntimeVisibleParameterAnnotations, - new RuntimeVisibleParameterAnnotations_attribute(attributeString, - annotations)); + builder.with(RuntimeVisibleParameterAnnotationsAttribute.of(createParameterAnnotations(desc.runtimeParameterAnnotations))); } if (desc.methodParameters != null && !desc.methodParameters.isEmpty()) { - int attributeString = - addString(constantPool, Attribute.MethodParameters); - MethodParameters_attribute.Entry[] entries = - desc.methodParameters - .stream() - .map(p -> new MethodParameters_attribute.Entry(p.name == null || p.name.isEmpty() ? 0 - : addString(constantPool, p.name), - p.flags)) - .toArray(s -> new MethodParameters_attribute.Entry[s]); - attributes.put(Attribute.MethodParameters, - new MethodParameters_attribute(attributeString, entries)); + builder.with(MethodParametersAttribute.of(desc.methodParameters.stream() + .map(mp -> MethodParameterInfo.ofParameter(Optional.ofNullable(mp.name), mp.flags)).collect(Collectors.toList()))); } } - private void addAttributes(FieldDescription desc, List constantPool, Map attributes) { - addGenericAttributes(desc, constantPool, attributes); + private void addAttributes(FieldDescription desc, FieldBuilder builder) { + addGenericAttributes(desc, builder); if (desc.constantValue != null) { - Pair constantPoolEntry = - addConstant(constantPool, desc.constantValue, false); - Assert.checkNonNull(constantPoolEntry); - int constantValueString = addString(constantPool, Attribute.ConstantValue); - attributes.put(Attribute.ConstantValue, - new ConstantValue_attribute(constantValueString, constantPoolEntry.fst)); + var cp = builder.constantPool(); + ConstantValueEntry entry = switch (desc.constantValue) { + case Boolean v -> cp.intEntry(v ? 1 : 0); + case Character v -> cp.intEntry(v); + case Integer v -> cp.intEntry(v); + case Long v -> cp.longEntry(v); + case Float v -> cp.floatEntry(v); + case Double v -> cp.doubleEntry(v); + case String v -> cp.stringEntry(v); + default -> throw new IllegalArgumentException(desc.constantValue.getClass().toString()); + }; + builder.with(ConstantValueAttribute.of(entry)); } } - private void addGenericAttributes(FeatureDescription desc, List constantPool, Map attributes) { + @SuppressWarnings("unchecked") + private void addGenericAttributes(FeatureDescription desc, ClassFileBuilder builder) { + addGenericAttributes(desc, (Consumer>) builder, builder.constantPool()); + } + + private void addGenericAttributes(FeatureDescription desc, Consumer> sink, ConstantPoolBuilder cpb) { + @SuppressWarnings("unchecked") + var builder = (Consumer>) sink; if (desc.deprecated) { - int attributeString = addString(constantPool, Attribute.Deprecated); - attributes.put(Attribute.Deprecated, - new Deprecated_attribute(attributeString)); + builder.accept(DeprecatedAttribute.of()); } if (desc.signature != null) { - int attributeString = addString(constantPool, Attribute.Signature); - int signatureString = addString(constantPool, desc.signature); - attributes.put(Attribute.Signature, - new Signature_attribute(attributeString, signatureString)); + builder.accept(SignatureAttribute.of(cpb.utf8Entry(desc.signature))); } if (desc.classAnnotations != null && !desc.classAnnotations.isEmpty()) { - int attributeString = addString(constantPool, Attribute.RuntimeInvisibleAnnotations); - Annotation[] annotations = createAnnotations(constantPool, desc.classAnnotations); - attributes.put(Attribute.RuntimeInvisibleAnnotations, - new RuntimeInvisibleAnnotations_attribute(attributeString, annotations)); + builder.accept(RuntimeInvisibleAnnotationsAttribute.of(createAnnotations(desc.classAnnotations))); } if (desc.runtimeAnnotations != null && !desc.runtimeAnnotations.isEmpty()) { - int attributeString = addString(constantPool, Attribute.RuntimeVisibleAnnotations); - Annotation[] annotations = createAnnotations(constantPool, desc.runtimeAnnotations); - attributes.put(Attribute.RuntimeVisibleAnnotations, - new RuntimeVisibleAnnotations_attribute(attributeString, annotations)); + builder.accept(RuntimeVisibleAnnotationsAttribute.of(createAnnotations(desc.runtimeAnnotations))); } } - private Annotation[] createAnnotations(List constantPool, List desc) { - Annotation[] result = new Annotation[desc.size()]; - int i = 0; - - for (AnnotationDescription ad : desc) { - result[i++] = createAnnotation(constantPool, ad); - } - - return result; + private List createAnnotations(List desc) { + return desc.stream().map(this::createAnnotation).collect(Collectors.toList()); } - private Annotation[][] createParameterAnnotations(List constantPool, List> desc) { - Annotation[][] result = new Annotation[desc.size()][]; - int i = 0; - - for (List paramAnnos : desc) { - result[i++] = createAnnotations(constantPool, paramAnnos); - } - - return result; + private List> createParameterAnnotations(List> desc) { + return desc.stream().map(this::createAnnotations).collect(Collectors.toList()); } - private Annotation createAnnotation(List constantPool, AnnotationDescription desc) { + private Annotation createAnnotation(AnnotationDescription desc) { String annotationType = desc.annotationType; Map values = desc.values; @@ -1257,184 +1027,33 @@ public class CreateSymbols { annotationType = RESTRICTED_ANNOTATION_INTERNAL; } - return new Annotation(null, - addString(constantPool, annotationType), - createElementPairs(constantPool, values)); + return Annotation.of(ClassDesc.ofDescriptor(annotationType), + createElementPairs(values)); } - private element_value_pair[] createElementPairs(List constantPool, Map annotationAttributes) { - element_value_pair[] pairs = new element_value_pair[annotationAttributes.size()]; - int i = 0; - - for (Entry e : annotationAttributes.entrySet()) { - int elementNameString = addString(constantPool, e.getKey()); - element_value value = createAttributeValue(constantPool, e.getValue()); - pairs[i++] = new element_value_pair(elementNameString, value); - } - - return pairs; + private List createElementPairs(Map annotationAttributes) { + return annotationAttributes.entrySet().stream() + .map(e -> AnnotationElement.of(e.getKey(), createAttributeValue(e.getValue()))) + .collect(Collectors.toList()); } - private element_value createAttributeValue(List constantPool, Object value) { - Pair constantPoolEntry = addConstant(constantPool, value, true); - if (constantPoolEntry != null) { - return new Primitive_element_value(constantPoolEntry.fst, constantPoolEntry.snd); - } else if (value instanceof EnumConstant) { - EnumConstant ec = (EnumConstant) value; - return new Enum_element_value(addString(constantPool, ec.type), - addString(constantPool, ec.constant), - 'e'); - } else if (value instanceof ClassConstant) { - ClassConstant cc = (ClassConstant) value; - return new Class_element_value(addString(constantPool, cc.type), 'c'); - } else if (value instanceof AnnotationDescription) { - Annotation annotation = createAnnotation(constantPool, ((AnnotationDescription) value)); - return new Annotation_element_value(annotation, '@'); - } else if (value instanceof Collection) { - @SuppressWarnings("unchecked") - Collection array = (Collection) value; - element_value[] values = new element_value[array.size()]; - int i = 0; - - for (Object elem : array) { - values[i++] = createAttributeValue(constantPool, elem); - } - - return new Array_element_value(values, '['); - } - throw new IllegalStateException(value.getClass().getName()); - } - - private static Pair addConstant(List constantPool, Object value, boolean annotation) { - if (value instanceof Boolean) { - return Pair.of(addToCP(constantPool, new CONSTANT_Integer_info(((Boolean) value) ? 1 : 0)), 'Z'); - } else if (value instanceof Byte) { - return Pair.of(addToCP(constantPool, new CONSTANT_Integer_info((byte) value)), 'B'); - } else if (value instanceof Character) { - return Pair.of(addToCP(constantPool, new CONSTANT_Integer_info((char) value)), 'C'); - } else if (value instanceof Short) { - return Pair.of(addToCP(constantPool, new CONSTANT_Integer_info((short) value)), 'S'); - } else if (value instanceof Integer) { - return Pair.of(addToCP(constantPool, new CONSTANT_Integer_info((int) value)), 'I'); - } else if (value instanceof Long) { - return Pair.of(addToCP(constantPool, new CONSTANT_Long_info((long) value)), 'J'); - } else if (value instanceof Float) { - return Pair.of(addToCP(constantPool, new CONSTANT_Float_info((float) value)), 'F'); - } else if (value instanceof Double) { - return Pair.of(addToCP(constantPool, new CONSTANT_Double_info((double) value)), 'D'); - } else if (value instanceof String) { - int stringIndex = addString(constantPool, (String) value); - if (annotation) { - return Pair.of(stringIndex, 's'); - } else { - return Pair.of(addToCP(constantPool, new CONSTANT_String_info(null, stringIndex)), 's'); - } - } - - return null; - } - - private static int addString(List constantPool, String string) { - Assert.checkNonNull(string); - - int i = 0; - for (CPInfo info : constantPool) { - if (info instanceof CONSTANT_Utf8_info) { - if (((CONSTANT_Utf8_info) info).value.equals(string)) { - return i; - } - } - i++; - } - - return addToCP(constantPool, new CONSTANT_Utf8_info(string)); - } - - private static int addInt(List constantPool, int value) { - int i = 0; - for (CPInfo info : constantPool) { - if (info instanceof CONSTANT_Integer_info) { - if (((CONSTANT_Integer_info) info).value == value) { - return i; - } - } - i++; - } - - return addToCP(constantPool, new CONSTANT_Integer_info(value)); - } - - private static int addModuleName(List constantPool, String moduleName) { - int nameIdx = addString(constantPool, moduleName); - int i = 0; - for (CPInfo info : constantPool) { - if (info instanceof CONSTANT_Module_info) { - if (((CONSTANT_Module_info) info).name_index == nameIdx) { - return i; - } - } - i++; - } - - return addToCP(constantPool, new CONSTANT_Module_info(null, nameIdx)); - } - - private static int addPackageName(List constantPool, String packageName) { - int nameIdx = addString(constantPool, packageName); - int i = 0; - for (CPInfo info : constantPool) { - if (info instanceof CONSTANT_Package_info) { - if (((CONSTANT_Package_info) info).name_index == nameIdx) { - return i; - } - } - i++; - } - - return addToCP(constantPool, new CONSTANT_Package_info(null, nameIdx)); - } - - private static int addClassName(List constantPool, String className) { - int nameIdx = addString(constantPool, className); - int i = 0; - for (CPInfo info : constantPool) { - if (info instanceof CONSTANT_Class_info) { - if (((CONSTANT_Class_info) info).name_index == nameIdx) { - return i; - } - } - i++; - } - - return addToCP(constantPool, new CONSTANT_Class_info(null, nameIdx)); - } - - private static int addToCP(List constantPool, CPInfo entry) { - int result = constantPool.size(); - - constantPool.add(entry); - - if (entry.size() > 1) { - constantPool.add(null); - } - - return result; - } - - private static int addClass(List constantPool, String className) { - int classNameIndex = addString(constantPool, className); - - int i = 0; - for (CPInfo info : constantPool) { - if (info instanceof CONSTANT_Class_info) { - if (((CONSTANT_Class_info) info).name_index == classNameIndex) { - return i; - } - } - i++; - } - - return addToCP(constantPool, new CONSTANT_Class_info(null, classNameIndex)); + private AnnotationValue createAttributeValue(Object value) { + return switch (value) { + case Boolean v -> AnnotationValue.ofBoolean(v); + case Byte v -> AnnotationValue.ofByte(v); + case Character v -> AnnotationValue.ofChar(v); + case Short v -> AnnotationValue.ofShort(v); + case Integer v -> AnnotationValue.ofInt(v); + case Long v -> AnnotationValue.ofLong(v); + case Float v -> AnnotationValue.ofFloat(v); + case Double v -> AnnotationValue.ofDouble(v); + case String v -> AnnotationValue.ofString(v); + case EnumConstant v -> AnnotationValue.ofEnum(ClassDesc.ofDescriptor(v.type), v.constant); + case ClassConstant v -> AnnotationValue.ofClass(ClassDesc.ofDescriptor(v.type)); + case AnnotationDescription v -> AnnotationValue.ofAnnotation(createAnnotation(v)); + case Collection v -> AnnotationValue.ofArray(v.stream().map(this::createAttributeValue).collect(Collectors.toList())); + default -> throw new IllegalArgumentException(value.getClass().getName()); + }; } // // @@ -1509,7 +1128,7 @@ public class CreateSymbols { classFileData.add(data.toByteArray()); } } catch (IOException ex) { - throw new IllegalStateException(ex); + throw new IllegalArgumentException(ex); } return classFileData; @@ -1525,12 +1144,8 @@ public class CreateSymbols { new HashMap<>(); for (byte[] classFileData : classData) { - try (InputStream in = new ByteArrayInputStream(classFileData)) { - inspectModuleInfoClassFile(in, - currentVersionModules, version); - } catch (IOException | ConstantPoolException ex) { - throw new IllegalStateException(ex); - } + inspectModuleInfoClassFile(classFileData, + currentVersionModules, version); } ExcludeIncludeList currentEIList; @@ -1561,28 +1176,25 @@ public class CreateSymbols { try (InputStream in = new ByteArrayInputStream(classFileData)) { inspectClassFile(in, currentVersionClasses, currentEIList, version, - cf -> { - PermittedSubclasses_attribute permitted = (PermittedSubclasses_attribute) cf.getAttribute(Attribute.PermittedSubclasses); + cm -> { + var permitted = cm.findAttribute(Attributes.permittedSubclasses()).orElse(null); if (permitted != null) { - try { - String currentPack = cf.getName().substring(0, cf.getName().lastIndexOf('/')); + var name = cm.thisClass().asInternalName(); + String currentPack = name.substring(0, name.lastIndexOf('/')); - for (int i = 0; i < permitted.subtypes.length; i++) { - String permittedClassName = cf.constant_pool.getClassInfo(permitted.subtypes[i]).getName(); - if (!currentEIList.accepts(permittedClassName, false)) { - String permittedPack = permittedClassName.substring(0, permittedClassName.lastIndexOf('/')); + for (var sub : permitted.permittedSubclasses()) { + String permittedClassName = sub.asInternalName(); + if (!currentEIList.accepts(permittedClassName, false)) { + String permittedPack = permittedClassName.substring(0, permittedClassName.lastIndexOf('/')); - extraModulesPackagesToDerive.computeIfAbsent(permittedPack, x -> new HashSet<>()) - .add(currentPack); - } + extraModulesPackagesToDerive.computeIfAbsent(permittedPack, x -> new HashSet<>()) + .add(currentPack); } - } catch (ConstantPoolException ex) { - throw new IllegalStateException(ex); } } }); - } catch (IOException | ConstantPoolException ex) { - throw new IllegalStateException(ex); + } catch (IOException ex) { + throw new IllegalArgumentException(ex); } } @@ -1648,12 +1260,8 @@ public class CreateSymbols { Path moduleInfo = p.resolve("module-info.class"); if (Files.isReadable(moduleInfo)) { - ModuleDescription md; - - try (InputStream in = Files.newInputStream(moduleInfo)) { - md = inspectModuleInfoClassFile(in, + ModuleDescription md = inspectModuleInfoClassFile(Files.readAllBytes(moduleInfo), currentVersionModules, version); - } if (md == null) { continue; } @@ -1715,8 +1323,8 @@ public class CreateSymbols { } } } - } catch (IOException | ConstantPoolException ex) { - throw new IllegalStateException(ex); + } catch (IOException ex) { + throw new IllegalArgumentException(ex); } finishClassLoading(classes, modules, currentVersionModules, currentVersionClasses, currentEIList, version, baseline); @@ -1724,7 +1332,7 @@ public class CreateSymbols { private void loadFromDirectoryHandleClassFile(Path path, ClassList currentVersionClasses, ExcludeIncludeList currentEIList, String version, - List todo) throws IOException, ConstantPoolException { + List todo) throws IOException { try (InputStream in = Files.newInputStream(path)) { inspectClassFile(in, currentVersionClasses, currentEIList, version, @@ -2244,45 +1852,41 @@ public class CreateSymbols { public static String PROFILE_ANNOTATION = "Ljdk/Profile+Annotation;"; public static boolean ALLOW_NON_EXISTING_CLASSES = false; - private void inspectClassFile(InputStream in, ClassList classes, ExcludeIncludeList excludesIncludes, String version) throws IOException, ConstantPoolException { + private void inspectClassFile(InputStream in, ClassList classes, ExcludeIncludeList excludesIncludes, String version) throws IOException { inspectClassFile(in, classes, excludesIncludes, version, cf -> {}); } private void inspectClassFile(InputStream in, ClassList classes, ExcludeIncludeList excludesIncludes, String version, - Consumer extraTask) throws IOException, ConstantPoolException { - ClassFile cf = ClassFile.read(in); + Consumer extraTask) throws IOException { + ClassModel cm = ClassFile.of().parse(in.readAllBytes()); - if (cf.access_flags.is(AccessFlags.ACC_MODULE)) { + if (cm.isModuleInfo()) { return ; } - if (!excludesIncludes.accepts(cf.getName(), true)) { + if (!excludesIncludes.accepts(cm.thisClass().asInternalName(), true)) { return ; } - extraTask.accept(cf); + extraTask.accept(cm); ClassHeaderDescription headerDesc = new ClassHeaderDescription(); - headerDesc.flags = cf.access_flags.flags; + headerDesc.flags = cm.flags().flagsMask(); - if (cf.super_class != 0) { - headerDesc.extendsAttr = cf.getSuperclassName(); + if (cm.superclass().isPresent()) { + headerDesc.extendsAttr = cm.superclass().get().asInternalName(); } - List interfaces = new ArrayList<>(); - for (int i = 0; i < cf.interfaces.length; i++) { - interfaces.add(cf.getInterfaceName(i)); - } - headerDesc.implementsAttr = interfaces; - for (Attribute attr : cf.attributes) { - if (!readAttribute(cf, headerDesc, attr)) + headerDesc.implementsAttr = cm.interfaces().stream().map(ClassEntry::asInternalName).collect(Collectors.toList()); + for (var attr : cm.attributes()) { + if (!readAttribute(headerDesc, attr)) return ; } ClassDescription clazzDesc = null; for (ClassDescription cd : classes) { - if (cd.name.equals(cf.getName())) { + if (cd.name.equals(cm.thisClass().asInternalName())) { clazzDesc = cd; break; } @@ -2290,54 +1894,54 @@ public class CreateSymbols { if (clazzDesc == null) { clazzDesc = new ClassDescription(); - clazzDesc.name = cf.getName(); + clazzDesc.name = cm.thisClass().asInternalName(); classes.add(clazzDesc); } addClassHeader(clazzDesc, headerDesc, version, null); - for (Method m : cf.methods) { - if (!include(m.access_flags.flags)) + for (var m : cm.methods()) { + if (!include(m.flags().flagsMask())) continue; MethodDescription methDesc = new MethodDescription(); - methDesc.flags = m.access_flags.flags; - methDesc.name = m.getName(cf.constant_pool); - methDesc.descriptor = m.descriptor.getValue(cf.constant_pool); - for (Attribute attr : m.attributes) { - readAttribute(cf, methDesc, attr); + methDesc.flags = m.flags().flagsMask(); + methDesc.name = m.methodName().stringValue(); + methDesc.descriptor = m.methodType().stringValue(); + for (var attr : m.attributes()) { + readAttribute(methDesc, attr); } addMethod(clazzDesc, methDesc, version, null); } - for (Field f : cf.fields) { - if (!include(f.access_flags.flags)) + for (var f : cm.fields()) { + if (!include(f.flags().flagsMask())) continue; FieldDescription fieldDesc = new FieldDescription(); - fieldDesc.flags = f.access_flags.flags; - fieldDesc.name = f.getName(cf.constant_pool); - fieldDesc.descriptor = f.descriptor.getValue(cf.constant_pool); - for (Attribute attr : f.attributes) { - readAttribute(cf, fieldDesc, attr); + fieldDesc.flags = f.flags().flagsMask(); + fieldDesc.name = f.fieldName().stringValue(); + fieldDesc.descriptor = f.fieldType().stringValue(); + for (var attr : f.attributes()) { + readAttribute(fieldDesc, attr); } addField(clazzDesc, fieldDesc, version, null); } } - private ModuleDescription inspectModuleInfoClassFile(InputStream in, + private ModuleDescription inspectModuleInfoClassFile(byte[] data, Map modules, - String version) throws IOException, ConstantPoolException { - ClassFile cf = ClassFile.read(in); + String version) { + ClassModel cm = ClassFile.of().parse(data); - if (!cf.access_flags.is(AccessFlags.ACC_MODULE)) { + if (!cm.flags().has(AccessFlag.MODULE)) { return null; } ModuleHeaderDescription headerDesc = new ModuleHeaderDescription(); headerDesc.versions = version; - headerDesc.flags = cf.access_flags.flags; + headerDesc.flags = cm.flags().flagsMask(); - for (Attribute attr : cf.attributes) { - if (!readAttribute(cf, headerDesc, attr)) + for (var attr : cm.attributes()) { + if (!readAttribute(headerDesc, attr)) return null; } @@ -2361,56 +1965,46 @@ public class CreateSymbols { Set additionalIncludes = new HashSet<>(); for (byte[] classFileData : classData) { - try (InputStream in = new ByteArrayInputStream(classFileData)) { - ClassFile cf = ClassFile.read(in); - - additionalIncludes.addAll(otherRelevantTypesWithOwners(cf)); - } catch (IOException | ConstantPoolException ex) { - throw new IllegalStateException(ex); - } + additionalIncludes.addAll(otherRelevantTypesWithOwners(ClassFile.of().parse(classFileData))); } return additionalIncludes; } - private Set otherRelevantTypesWithOwners(ClassFile cf) { + private Set otherRelevantTypesWithOwners(ClassModel cm) { Set supertypes = new HashSet<>(); - try { - if (cf.access_flags.is(AccessFlags.ACC_MODULE)) { - return supertypes; - } - - Set additionalClasses = new HashSet<>(); - - if (cf.super_class != 0) { - additionalClasses.add(cf.getSuperclassName()); - } - for (int i = 0; i < cf.interfaces.length; i++) { - additionalClasses.add(cf.getInterfaceName(i)); - } - PermittedSubclasses_attribute permitted = (PermittedSubclasses_attribute) cf.getAttribute(Attribute.PermittedSubclasses); - if (permitted != null) { - for (int i = 0; i < permitted.subtypes.length; i++) { - additionalClasses.add(cf.constant_pool.getClassInfo(permitted.subtypes[i]).getName()); - } - } - - for (String additional : additionalClasses) { - int dollar; - - supertypes.add(additional); - - while ((dollar = additional.lastIndexOf('$')) != (-1)) { - additional = additional.substring(0, dollar); - supertypes.add(additional); - } - } - + if (cm.flags().has(AccessFlag.MODULE)) { return supertypes; - } catch (ConstantPoolException ex) { - throw new IllegalStateException(ex); } + + Set additionalClasses = new HashSet<>(); + + if (cm.superclass().isPresent()) { + additionalClasses.add(cm.superclass().get().asInternalName()); + } + for (var iface : cm.interfaces()) { + additionalClasses.add(iface.asInternalName()); + } + var permitted = cm.findAttribute(Attributes.permittedSubclasses()).orElse(null); + if (permitted != null) { + for (var sub : permitted.permittedSubclasses()) { + additionalClasses.add(sub.asInternalName()); + } + } + + for (String additional : additionalClasses) { + int dollar; + + supertypes.add(additional); + + while ((dollar = additional.lastIndexOf('$')) != (-1)) { + additional = additional.substring(0, dollar); + supertypes.add(additional); + } + } + + return supertypes; } private void addModuleHeader(ModuleDescription moduleDesc, @@ -2435,7 +2029,7 @@ public class CreateSymbols { } private boolean include(int accessFlags) { - return (accessFlags & (AccessFlags.ACC_PUBLIC | AccessFlags.ACC_PROTECTED)) != 0; + return (accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) != 0; } private void addClassHeader(ClassDescription clazzDesc, ClassHeaderDescription headerDesc, String version, String baseline) { @@ -2531,367 +2125,135 @@ public class CreateSymbols { } } - private boolean readAttribute(ClassFile cf, FeatureDescription feature, Attribute attr) throws ConstantPoolException { - String attrName = attr.getName(cf.constant_pool); - switch (attrName) { - case Attribute.AnnotationDefault: - assert feature instanceof MethodDescription; - element_value defaultValue = ((AnnotationDefault_attribute) attr).default_value; - ((MethodDescription) feature).annotationDefaultValue = - convertElementValue(cf.constant_pool, defaultValue); - break; - case "Deprecated": - feature.deprecated = true; - break; - case "Exceptions": - assert feature instanceof MethodDescription; - List thrownTypes = new ArrayList<>(); - Exceptions_attribute exceptionAttr = (Exceptions_attribute) attr; - for (int i = 0; i < exceptionAttr.exception_index_table.length; i++) { - thrownTypes.add(exceptionAttr.getException(i, cf.constant_pool)); - } - ((MethodDescription) feature).thrownTypes = thrownTypes; - break; - case Attribute.InnerClasses: + private boolean readAttribute(FeatureDescription feature, Attribute attr) { + switch (attr) { + case AnnotationDefaultAttribute a -> + ((MethodDescription) feature).annotationDefaultValue = convertElementValue(a.defaultValue()); + case DeprecatedAttribute _ -> feature.deprecated = true; + case ExceptionsAttribute a -> ((MethodDescription) feature).thrownTypes = a.exceptions().stream().map(ClassEntry::asInternalName).collect(Collectors.toList()); + case InnerClassesAttribute a -> { if (feature instanceof ModuleHeaderDescription) break; //XXX - assert feature instanceof ClassHeaderDescription; - List innerClasses = new ArrayList<>(); - InnerClasses_attribute innerClassesAttr = (InnerClasses_attribute) attr; - for (int i = 0; i < innerClassesAttr.number_of_classes; i++) { - CONSTANT_Class_info outerClassInfo = - innerClassesAttr.classes[i].getOuterClassInfo(cf.constant_pool); - InnerClassInfo info = new InnerClassInfo(); - CONSTANT_Class_info innerClassInfo = - innerClassesAttr.classes[i].getInnerClassInfo(cf.constant_pool); - info.innerClass = innerClassInfo != null ? innerClassInfo.getName() : null; - info.outerClass = outerClassInfo != null ? outerClassInfo.getName() : null; - info.innerClassName = innerClassesAttr.classes[i].getInnerName(cf.constant_pool); - info.innerClassFlags = innerClassesAttr.classes[i].inner_class_access_flags.flags; - innerClasses.add(info); - } - ((ClassHeaderDescription) feature).innerClasses = innerClasses; - break; - case "RuntimeInvisibleAnnotations": - feature.classAnnotations = annotations2Description(cf.constant_pool, attr); - break; - case "RuntimeVisibleAnnotations": - feature.runtimeAnnotations = annotations2Description(cf.constant_pool, attr); - break; - case "Signature": - feature.signature = ((Signature_attribute) attr).getSignature(cf.constant_pool); - break; - case "ConstantValue": - assert feature instanceof FieldDescription; - Object value = convertConstantValue(cf.constant_pool.get(((ConstantValue_attribute) attr).constantvalue_index), ((FieldDescription) feature).descriptor); - if (((FieldDescription) feature).descriptor.equals("C")) { - value = (char) (int) value; - } - ((FieldDescription) feature).constantValue = value; - break; - case "SourceFile": - //ignore, not needed - break; - case "BootstrapMethods": - //ignore, not needed - break; - case "Code": - //ignore, not needed - break; - case "EnclosingMethod": + ((ClassHeaderDescription) feature).innerClasses = a.classes().stream().map(cfi -> { + var info = new InnerClassInfo(); + info.innerClass = cfi.innerClass().asInternalName(); + info.outerClass = cfi.outerClass().map(ClassEntry::asInternalName).orElse(null); + info.innerClassName = cfi.innerName().map(Utf8Entry::stringValue).orElse(null); + info.innerClassFlags = cfi.flagsMask(); + return info; + }).collect(Collectors.toList()); + } + case RuntimeInvisibleAnnotationsAttribute a -> feature.classAnnotations = annotations2Description(a.annotations()); + case RuntimeVisibleAnnotationsAttribute a -> feature.runtimeAnnotations = annotations2Description(a.annotations()); + case SignatureAttribute a -> feature.signature = a.signature().stringValue(); + case ConstantValueAttribute a -> { + var f = (FieldDescription) feature; + f.constantValue = convertConstantValue(a.constant(), f.descriptor); + } + case SourceFileAttribute _, BootstrapMethodsAttribute _, CodeAttribute _, SyntheticAttribute _ -> {} + case EnclosingMethodAttribute _ -> { return false; - case "Synthetic": - break; - case "RuntimeVisibleParameterAnnotations": - assert feature instanceof MethodDescription; - ((MethodDescription) feature).runtimeParameterAnnotations = - parameterAnnotations2Description(cf.constant_pool, attr); - break; - case "RuntimeInvisibleParameterAnnotations": - assert feature instanceof MethodDescription; - ((MethodDescription) feature).classParameterAnnotations = - parameterAnnotations2Description(cf.constant_pool, attr); - break; - case Attribute.Module: { - assert feature instanceof ModuleHeaderDescription; - ModuleHeaderDescription header = - (ModuleHeaderDescription) feature; - Module_attribute mod = (Module_attribute) attr; - - header.name = cf.constant_pool - .getModuleInfo(mod.module_name) - .getName(); - - header.exports = - Arrays.stream(mod.exports) - .map(ee -> ExportsDescription.create(cf, ee)) - .collect(Collectors.toList()); + } + case RuntimeVisibleParameterAnnotationsAttribute a -> ((MethodDescription) feature).runtimeParameterAnnotations = parameterAnnotations2Description(a.parameterAnnotations()); + case RuntimeInvisibleParameterAnnotationsAttribute a -> ((MethodDescription) feature).classParameterAnnotations = parameterAnnotations2Description(a.parameterAnnotations()); + case ModuleAttribute a -> { + ModuleHeaderDescription header = (ModuleHeaderDescription) feature; + header.name = a.moduleName().name().stringValue(); + header.exports = a.exports().stream().map(ExportsDescription::create).collect(Collectors.toList()); if (header.extraModulePackages != null) { header.exports.forEach(ed -> header.extraModulePackages.remove(ed.packageName())); } - header.requires = - Arrays.stream(mod.requires) - .map(r -> RequiresDescription.create(cf, r)) - .collect(Collectors.toList()); - header.uses = Arrays.stream(mod.uses_index) - .mapToObj(use -> getClassName(cf, use)) - .collect(Collectors.toList()); - header.provides = - Arrays.stream(mod.provides) - .map(p -> ProvidesDescription.create(cf, p)) - .collect(Collectors.toList()); - break; + header.requires = a.requires().stream().map(RequiresDescription::create).collect(Collectors.toList()); + header.uses = a.uses().stream().map(ClassEntry::asInternalName).collect(Collectors.toList()); + header.provides = a.provides().stream().map(ProvidesDescription::create).collect(Collectors.toList()); } - case Attribute.ModuleTarget: { - assert feature instanceof ModuleHeaderDescription; - ModuleHeaderDescription header = - (ModuleHeaderDescription) feature; - ModuleTarget_attribute mod = (ModuleTarget_attribute) attr; - if (mod.target_platform_index != 0) { - header.moduleTarget = - cf.constant_pool - .getUTF8Value(mod.target_platform_index); - } - break; - } - case Attribute.ModuleResolution: { - assert feature instanceof ModuleHeaderDescription; - ModuleHeaderDescription header = - (ModuleHeaderDescription) feature; - ModuleResolution_attribute mod = - (ModuleResolution_attribute) attr; - header.moduleResolution = mod.resolution_flags; - break; - } - case Attribute.ModulePackages: - assert feature instanceof ModuleHeaderDescription; - ModuleHeaderDescription header = - (ModuleHeaderDescription) feature; - ModulePackages_attribute mod = - (ModulePackages_attribute) attr; - header.extraModulePackages = new ArrayList<>(); - for (int i = 0; i < mod.packages_count; i++) { - String packageName = getPackageName(cf, mod.packages_index[i]); + case ModuleTargetAttribute a -> ((ModuleHeaderDescription) feature).moduleTarget = a.targetPlatform().stringValue(); + case ModuleResolutionAttribute a -> ((ModuleHeaderDescription) feature).moduleResolution = a.resolutionFlags(); + case ModulePackagesAttribute a -> { + var header = (ModuleHeaderDescription) feature; + header.extraModulePackages = a.packages().stream().mapMulti((packageItem, sink) -> { + var packageName = packageItem.name().stringValue(); if (header.exports == null || - header.exports.stream().noneMatch(ed -> ed.packageName().equals(packageName))) { - header.extraModulePackages.add(packageName); + header.exports.stream().noneMatch(ed -> ed.packageName().equals(packageName))) { + sink.accept(packageName); } - } - break; - case Attribute.ModuleHashes: - break; - case Attribute.NestHost: { - assert feature instanceof ClassHeaderDescription; - NestHost_attribute nestHost = (NestHost_attribute) attr; - ClassHeaderDescription chd = (ClassHeaderDescription) feature; - chd.nestHost = nestHost.getNestTop(cf.constant_pool).getName(); - break; + }).collect(Collectors.toList()); } - case Attribute.NestMembers: { - assert feature instanceof ClassHeaderDescription; - NestMembers_attribute nestMembers = (NestMembers_attribute) attr; - ClassHeaderDescription chd = (ClassHeaderDescription) feature; - chd.nestMembers = Arrays.stream(nestMembers.members_indexes) - .mapToObj(i -> getClassName(cf, i)) - .collect(Collectors.toList()); - break; - } - case Attribute.Record: { - assert feature instanceof ClassHeaderDescription; - Record_attribute record = (Record_attribute) attr; - List components = new ArrayList<>(); - for (ComponentInfo info : record.component_info_arr) { - RecordComponentDescription rcd = new RecordComponentDescription(); - rcd.name = info.getName(cf.constant_pool); - rcd.descriptor = info.descriptor.getValue(cf.constant_pool); - for (Attribute nestedAttr : info.attributes) { - readAttribute(cf, rcd, nestedAttr); - } - components.add(rcd); - } - ClassHeaderDescription chd = (ClassHeaderDescription) feature; + case ModuleHashesAttribute _ -> {} + case NestHostAttribute a -> ((ClassHeaderDescription) feature).nestHost = a.nestHost().asInternalName(); + case NestMembersAttribute a -> ((ClassHeaderDescription) feature).nestMembers = a.nestMembers().stream().map(ClassEntry::asInternalName).collect(Collectors.toList()); + case RecordAttribute a -> { + var chd = (ClassHeaderDescription) feature; chd.isRecord = true; - chd.recordComponents = components; - break; + chd.recordComponents = a.components().stream().map(rci -> { + var rcd = new RecordComponentDescription(); + rcd.name = rci.name().stringValue(); + rcd.descriptor = rci.descriptor().stringValue(); + rci.attributes().forEach(child -> readAttribute(rcd, child)); + return rcd; + }).collect(Collectors.toList()); } - case Attribute.MethodParameters: { - assert feature instanceof MethodDescription; - MethodParameters_attribute params = (MethodParameters_attribute) attr; - MethodDescription method = (MethodDescription) feature; - method.methodParameters = new ArrayList<>(); - for (MethodParameters_attribute.Entry e : params.method_parameter_table) { - String name = e.name_index == 0 ? null - : cf.constant_pool.getUTF8Value(e.name_index); - MethodDescription.MethodParam param = - new MethodDescription.MethodParam(e.flags, name); - method.methodParameters.add(param); - } - break; - } - case Attribute.PermittedSubclasses: { - assert feature instanceof ClassHeaderDescription; - PermittedSubclasses_attribute permittedSubclasses = (PermittedSubclasses_attribute) attr; - ClassHeaderDescription chd = (ClassHeaderDescription) feature; - chd.permittedSubclasses = Arrays.stream(permittedSubclasses.subtypes) - .mapToObj(i -> getClassName(cf, i)) - .collect(Collectors.toList()); + case MethodParametersAttribute a -> ((MethodDescription) feature).methodParameters = a.parameters().stream() + .map(mpi -> new MethodDescription.MethodParam(mpi.flagsMask(), mpi.name().map(Utf8Entry::stringValue).orElse(null))) + .collect(Collectors.toList()); + case PermittedSubclassesAttribute a -> { + var chd = (ClassHeaderDescription) feature; chd.isSealed = true; - break; + chd.permittedSubclasses = a.permittedSubclasses().stream().map(ClassEntry::asInternalName).collect(Collectors.toList()); } - case Attribute.ModuleMainClass: { - ModuleMainClass_attribute moduleMainClass = (ModuleMainClass_attribute) attr; - assert feature instanceof ModuleHeaderDescription; - ModuleHeaderDescription mhd = (ModuleHeaderDescription) feature; - mhd.moduleMainClass = moduleMainClass.getMainClassName(cf.constant_pool); - break; - } - default: - throw new IllegalStateException("Unhandled attribute: " + - attrName); + case ModuleMainClassAttribute a -> ((ModuleHeaderDescription) feature).moduleMainClass = a.mainClass().asInternalName(); + default -> throw new IllegalArgumentException("Unhandled attribute: " + attr.attributeName()); // Do nothing } return true; } - private static String getClassName(ClassFile cf, int idx) { - try { - return cf.constant_pool.getClassInfo(idx).getName(); - } catch (InvalidIndex ex) { - throw new IllegalStateException(ex); - } catch (ConstantPool.UnexpectedEntry ex) { - throw new IllegalStateException(ex); - } catch (ConstantPoolException ex) { - throw new IllegalStateException(ex); - } - } - - private static String getPackageName(ClassFile cf, int idx) { - try { - return cf.constant_pool.getPackageInfo(idx).getName(); - } catch (InvalidIndex ex) { - throw new IllegalStateException(ex); - } catch (ConstantPool.UnexpectedEntry ex) { - throw new IllegalStateException(ex); - } catch (ConstantPoolException ex) { - throw new IllegalStateException(ex); - } - } - - private static String getModuleName(ClassFile cf, int idx) { - try { - return cf.constant_pool.getModuleInfo(idx).getName(); - } catch (InvalidIndex ex) { - throw new IllegalStateException(ex); - } catch (ConstantPool.UnexpectedEntry ex) { - throw new IllegalStateException(ex); - } catch (ConstantPoolException ex) { - throw new IllegalStateException(ex); - } - } - public static String INJECTED_VERSION = null; - private static String getVersion(ClassFile cf, int idx) { + private static String getVersion(Optional version) { if (INJECTED_VERSION != null) { return INJECTED_VERSION; } - if (idx == 0) - return null; - try { - return ((CONSTANT_Utf8_info) cf.constant_pool.get(idx)).value; - } catch (InvalidIndex ex) { - throw new IllegalStateException(ex); - } + return version.map(Utf8Entry::stringValue).orElse(null); } - Object convertConstantValue(CPInfo info, String descriptor) throws ConstantPoolException { - if (info instanceof CONSTANT_Integer_info) { - if ("Z".equals(descriptor)) - return ((CONSTANT_Integer_info) info).value == 1; - else - return ((CONSTANT_Integer_info) info).value; - } else if (info instanceof CONSTANT_Long_info) { - return ((CONSTANT_Long_info) info).value; - } else if (info instanceof CONSTANT_Float_info) { - return ((CONSTANT_Float_info) info).value; - } else if (info instanceof CONSTANT_Double_info) { - return ((CONSTANT_Double_info) info).value; - } else if (info instanceof CONSTANT_String_info) { - return ((CONSTANT_String_info) info).getString(); + Object convertConstantValue(ConstantValueEntry info, String descriptor) { + if (descriptor.length() == 1 && info instanceof IntegerEntry ie) { + var i = ie.intValue(); + return switch (descriptor.charAt(0)) { + case 'I', 'B', 'S' -> i; + case 'C' -> (char) i; + case 'Z' -> i == 1; + default -> throw new IllegalArgumentException(descriptor); + }; } - throw new IllegalStateException(info.getClass().getName()); + return info.constantValue(); } - Object convertElementValue(ConstantPool cp, element_value val) throws InvalidIndex, ConstantPoolException { - switch (val.tag) { - case 'Z': - return ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value != 0; - case 'B': - return (byte) ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - case 'C': - return (char) ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - case 'S': - return (short) ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - case 'I': - return ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - case 'J': - return ((CONSTANT_Long_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - case 'F': - return ((CONSTANT_Float_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - case 'D': - return ((CONSTANT_Double_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - case 's': - return ((CONSTANT_Utf8_info) cp.get(((Primitive_element_value) val).const_value_index)).value; - - case 'e': - return new EnumConstant(cp.getUTF8Value(((Enum_element_value) val).type_name_index), - cp.getUTF8Value(((Enum_element_value) val).const_name_index)); - case 'c': - return new ClassConstant(cp.getUTF8Value(((Class_element_value) val).class_info_index)); - - case '@': - return annotation2Description(cp, ((Annotation_element_value) val).annotation_value); - - case '[': - List values = new ArrayList<>(); - for (element_value elem : ((Array_element_value) val).values) { - values.add(convertElementValue(cp, elem)); - } - return values; - default: - throw new IllegalStateException("Currently unhandled tag: " + val.tag); - } + Object convertElementValue(AnnotationValue val) { + return switch (val) { + case AnnotationValue.OfConstant oc -> oc.resolvedValue(); + case AnnotationValue.OfEnum oe -> new EnumConstant(oe.className().stringValue(), oe.constantName().stringValue()); + case AnnotationValue.OfClass oc -> new ClassConstant(oc.className().stringValue()); + case AnnotationValue.OfArray oa -> oa.values().stream().map(this::convertElementValue).collect(Collectors.toList()); + case AnnotationValue.OfAnnotation oa -> annotation2Description(oa.annotation()); + }; } - private List annotations2Description(ConstantPool cp, Attribute attr) throws ConstantPoolException { - RuntimeAnnotations_attribute annotationsAttr = (RuntimeAnnotations_attribute) attr; - List descs = new ArrayList<>(); - for (Annotation a : annotationsAttr.annotations) { - descs.add(annotation2Description(cp, a)); - } - return descs; + private List annotations2Description(List annos) { + return annos.stream().map(this::annotation2Description).collect(Collectors.toList()); } - private List> parameterAnnotations2Description(ConstantPool cp, Attribute attr) throws ConstantPoolException { - RuntimeParameterAnnotations_attribute annotationsAttr = - (RuntimeParameterAnnotations_attribute) attr; - List> descs = new ArrayList<>(); - for (Annotation[] attrAnnos : annotationsAttr.parameter_annotations) { - List paramDescs = new ArrayList<>(); - for (Annotation ann : attrAnnos) { - paramDescs.add(annotation2Description(cp, ann)); - } - descs.add(paramDescs); - } - return descs; + private List> parameterAnnotations2Description(List> annos) { + return annos.stream().map(this::annotations2Description).collect(Collectors.toList()); } - private AnnotationDescription annotation2Description(ConstantPool cp, Annotation a) throws ConstantPoolException { - String annotationType = cp.getUTF8Value(a.type_index); + private AnnotationDescription annotation2Description(java.lang.classfile.Annotation a) { + String annotationType = a.className().stringValue(); Map values = new HashMap<>(); - for (element_value_pair e : a.element_value_pairs) { - values.put(cp.getUTF8Value(e.element_name_index), convertElementValue(cp, e.value)); + for (var e : a.elements()) { + values.put(e.name().stringValue(), convertElementValue(e.value())); } return new AnnotationDescription(annotationType, values); @@ -3181,7 +2543,7 @@ public class CreateSymbols { case "-module": break OUTER; default: - throw new IllegalStateException(reader.lineKey); + throw new IllegalArgumentException(reader.lineKey); } } } @@ -3396,15 +2758,11 @@ public class CreateSymbols { return new ExportsDescription(packageName, to); } - public static ExportsDescription create(ClassFile cf, - ExportsEntry ee) { - String packageName = getPackageName(cf, ee.exports_index); + public static ExportsDescription create(ModuleExportInfo ee) { + String packageName = ee.exportedPackage().name().stringValue(); List to = null; - if (ee.exports_to_count > 0) { - to = new ArrayList<>(); - for (int moduleIndex : ee.exports_to_index) { - to.add(getModuleName(cf, moduleIndex)); - } + if (!ee.exportsTo().isEmpty()) { + to = ee.exportsTo().stream().map(m -> m.name().stringValue()).collect(Collectors.toList()); } return new ExportsDescription(packageName, to); } @@ -3447,12 +2805,11 @@ public class CreateSymbols { ver); } - public static RequiresDescription create(ClassFile cf, - RequiresEntry req) { - String mod = getModuleName(cf, req.requires_index); - String ver = getVersion(cf, req.requires_version_index); + public static RequiresDescription create(ModuleRequireInfo req) { + String mod = req.requires().name().stringValue(); + String ver = getVersion(req.requiresVersion()); return new RequiresDescription(mod, - req.requires_flags, + req.requiresFlagsMask(), ver); } @@ -3515,13 +2872,9 @@ public class CreateSymbols { implsList); } - public static ProvidesDescription create(ClassFile cf, - ProvidesEntry prov) { - String api = getClassName(cf, prov.provides_index); - List impls = - Arrays.stream(prov.with_index) - .mapToObj(wi -> getClassName(cf, wi)) - .collect(Collectors.toList()); + public static ProvidesDescription create(ModuleProvideInfo prov) { + String api = prov.provides().asInternalName(); + List impls = prov.providesWith().stream().map(ClassEntry::asInternalName).collect(Collectors.toList()); return new ProvidesDescription(api, impls); } @@ -3676,7 +3029,7 @@ public class CreateSymbols { case "-module": break OUTER; default: - throw new IllegalStateException(reader.lineKey); + throw new IllegalArgumentException(reader.lineKey); } } } @@ -4073,7 +3426,7 @@ public class CreateSymbols { static class FieldDescription extends FeatureDescription { String name; String descriptor; - Object constantValue; + Object constantValue; // Uses (unsigned) Integer for byte/short String keyName = "field"; @Override @@ -4149,7 +3502,7 @@ public class CreateSymbols { case "D": constantValue = Double.parseDouble(inConstantValue); break; case "Ljava/lang/String;": constantValue = inConstantValue; break; default: - throw new IllegalStateException("Unrecognized field type: " + descriptor); + throw new IllegalArgumentException("Unrecognized field type: " + descriptor); } } @@ -4416,7 +3769,7 @@ public class CreateSymbols { if (desc != null || allowNull) return desc; - throw new IllegalStateException("Cannot find: " + name); + throw new IllegalArgumentException("Cannot find: " + name); } private static final ClassDescription NONE = new ClassDescription(); @@ -4565,7 +3918,7 @@ public class CreateSymbols { valuePointer[0] += 5; return false; } else { - throw new IllegalStateException("Unrecognized boolean structure: " + value); + throw new IllegalArgumentException("Unrecognized boolean structure: " + value); } case 'B': return Byte.parseByte(readDigits(value, valuePointer)); case 'C': return value.charAt(valuePointer[0]++); @@ -4593,7 +3946,7 @@ public class CreateSymbols { case '@': return parseAnnotation(value, valuePointer); default: - throw new IllegalStateException("Unrecognized signature type: " + value.charAt(valuePointer[0] - 1) + "; value=" + value); + throw new IllegalArgumentException("Unrecognized signature type: " + value.charAt(valuePointer[0] - 1) + "; value=" + value); } } diff --git a/make/modules/jdk.compiler/Gendata.gmk b/make/modules/jdk.compiler/Gendata.gmk index 739625a5732..5bbd28b8037 100644 --- a/make/modules/jdk.compiler/Gendata.gmk +++ b/make/modules/jdk.compiler/Gendata.gmk @@ -53,7 +53,6 @@ COMPILECREATESYMBOLS_ADD_EXPORTS := \ --add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \ - --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \ # # TODO: Unify with jdk.javadoc-gendata. Should only compile this once and share. diff --git a/make/scripts/generate-symbol-data.sh b/make/scripts/generate-symbol-data.sh index 015beb582fd..6f38d873009 100644 --- a/make/scripts/generate-symbol-data.sh +++ b/make/scripts/generate-symbol-data.sh @@ -68,8 +68,7 @@ if [ "`git status --porcelain=v1 .`x" != "x" ] ; then exit 1 fi; -$1/bin/java --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \ - --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ +$1/bin/java --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ --add-modules jdk.jdeps \ diff --git a/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java b/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java index a8d4747babb..f91d9ea02b1 100644 --- a/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java +++ b/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.jvm:+open * jdk.compiler/com.sun.tools.javac.util:+open - * jdk.jdeps/com.sun.tools.classfile:+open * @build toolbox.ToolBox toolbox.JavacTask toolbox.Task * @run main CanHandleClassFilesTest */ @@ -76,8 +75,7 @@ public class CanHandleClassFilesTest { try (ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager()) { ToolBox tb = new ToolBox(); new JavacTask(tb) - .options("--add-exports", "jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + .options("--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", "--add-modules", "jdk.jdeps") @@ -102,8 +100,7 @@ public class CanHandleClassFilesTest { Module targetModule = cl.getUnnamedModule(); Stream.of("jdk.compiler/com.sun.tools.javac.api", "jdk.compiler/com.sun.tools.javac.jvm", - "jdk.compiler/com.sun.tools.javac.util", - "jdk.jdeps/com.sun.tools.classfile") + "jdk.compiler/com.sun.tools.javac.util") .forEach(p -> open(p, targetModule)); var createSymbolsClass = Class.forName("build.tools.symbolgenerator.CreateSymbols", false, cl); diff --git a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java index 97def1b1480..76c13582b73 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, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ * jdk.compiler/com.sun.tools.javac.jvm * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.util - * jdk.jdeps/com.sun.tools.classfile * @clean * * @run main/othervm CreateSymbolsTest */ @@ -107,8 +106,7 @@ public class CreateSymbolsTest { "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", - "--add-exports", "jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED"), + "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"), null, fm.getJavaFileObjectsFromPaths(files) ).call(); From 567c6885a377e5641deef9cd3498f79c5346cd6a Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 9 Apr 2025 15:03:38 +0000 Subject: [PATCH 089/843] 8353597: Refactor handling VM options for AOT cache input and output Reviewed-by: kvn, asmehra --- src/hotspot/share/cds/cdsConfig.cpp | 195 ++++++++++++------ src/hotspot/share/cds/cdsConfig.hpp | 44 ++-- src/hotspot/share/cds/dynamicArchive.cpp | 28 +-- src/hotspot/share/cds/dynamicArchive.hpp | 3 +- src/hotspot/share/cds/filemap.cpp | 19 +- src/hotspot/share/cds/filemap.hpp | 8 +- src/hotspot/share/cds/metaspaceShared.cpp | 26 +-- src/hotspot/share/cds/metaspaceShared.hpp | 1 - src/hotspot/share/memory/universe.cpp | 3 +- src/hotspot/share/runtime/arguments.cpp | 2 +- src/hotspot/share/runtime/java.cpp | 3 +- .../share/native/libsaproc/ps_core_common.c | 6 +- .../jtreg/runtime/cds/appcds/AOTFlags.java | 56 +++++ .../TestAutoCreateSharedArchive.java | 2 +- ...toCreateSharedArchiveNoDefaultArchive.java | 6 +- 15 files changed, 254 insertions(+), 148 deletions(-) diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 47613e09008..64ad07b0cf8 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -51,9 +51,10 @@ bool CDSConfig::_old_cds_flags_used = false; bool CDSConfig::_new_aot_flags_used = false; bool CDSConfig::_disable_heap_dumping = false; -char* CDSConfig::_default_archive_path = nullptr; -char* CDSConfig::_static_archive_path = nullptr; -char* CDSConfig::_dynamic_archive_path = nullptr; +const char* CDSConfig::_default_archive_path = nullptr; +const char* CDSConfig::_input_static_archive_path = nullptr; +const char* CDSConfig::_input_dynamic_archive_path = nullptr; +const char* CDSConfig::_output_archive_path = nullptr; JavaThread* CDSConfig::_dumper_thread = nullptr; @@ -66,7 +67,11 @@ int CDSConfig::get_status() { (is_using_archive() ? IS_USING_ARCHIVE : 0); } -void CDSConfig::initialize() { +DEBUG_ONLY(static bool _cds_ergo_initialize_started = false); + +void CDSConfig::ergo_initialize() { + DEBUG_ONLY(_cds_ergo_initialize_started = true); + if (is_dumping_static_archive() && !is_dumping_final_static_archive()) { // Note: -Xshare and -XX:AOTMode flags are mutually exclusive. // - Classic workflow: -Xshare:on and -Xshare:dump cannot take effect at the same time. @@ -83,10 +88,12 @@ void CDSConfig::initialize() { // Initialize shared archive paths which could include both base and dynamic archive paths // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly. - // - // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid. if (is_dumping_static_archive() || is_using_archive()) { - init_shared_archive_paths(); + if (new_aot_flags_used()) { + ergo_init_aot_paths(); + } else { + ergo_init_classic_archive_paths(); + } } if (!is_dumping_heap()) { @@ -94,7 +101,10 @@ void CDSConfig::initialize() { } } -char* CDSConfig::default_archive_path() { +const char* CDSConfig::default_archive_path() { + // The path depends on UseCompressedOops, etc, which are set by GC ergonomics just + // before CDSConfig::ergo_initialize() is called. + assert(_cds_ergo_initialize_started, "sanity"); if (_default_archive_path == nullptr) { stringStream tmp; const char* subdir = WINDOWS_ONLY("bin") NOT_WINDOWS("lib"); @@ -116,12 +126,12 @@ char* CDSConfig::default_archive_path() { return _default_archive_path; } -int CDSConfig::num_archives(const char* archive_path) { - if (archive_path == nullptr) { +int CDSConfig::num_archive_paths(const char* path_spec) { + if (path_spec == nullptr) { return 0; } int npaths = 1; - char* p = (char*)archive_path; + char* p = (char*)path_spec; while (*p != '\0') { if (*p == os::path_separator()[0]) { npaths++; @@ -131,9 +141,9 @@ int CDSConfig::num_archives(const char* archive_path) { return npaths; } -void CDSConfig::extract_shared_archive_paths(const char* archive_path, - char** base_archive_path, - char** top_archive_path) { +void CDSConfig::extract_archive_paths(const char* archive_path, + const char** base_archive_path, + const char** top_archive_path) { char* begin_ptr = (char*)archive_path; char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]); if (end_ptr == nullptr || end_ptr == begin_ptr) { @@ -157,7 +167,8 @@ void CDSConfig::extract_shared_archive_paths(const char* archive_path, *top_archive_path = cur_path; } -void CDSConfig::init_shared_archive_paths() { +void CDSConfig::ergo_init_classic_archive_paths() { + assert(_cds_ergo_initialize_started, "sanity"); if (ArchiveClassesAtExit != nullptr) { assert(!RecordDynamicDumpInfo, "already checked"); if (is_dumping_static_archive()) { @@ -172,21 +183,24 @@ void CDSConfig::init_shared_archive_paths() { } if (SharedArchiveFile == nullptr) { - _static_archive_path = default_archive_path(); + _input_static_archive_path = default_archive_path(); + if (is_dumping_static_archive()) { + _output_archive_path = _input_static_archive_path; + } } else { - int archives = num_archives(SharedArchiveFile); - assert(archives > 0, "must be"); + int num_archives = num_archive_paths(SharedArchiveFile); + assert(num_archives > 0, "must be"); - if (is_dumping_archive() && archives > 1) { + if (is_dumping_archive() && num_archives > 1) { vm_exit_during_initialization( "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping"); } if (is_dumping_static_archive()) { - assert(archives == 1, "must be"); + assert(num_archives == 1, "just checked above"); // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file - // will be overwritten no matter regardless of its contents - _static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); + // will be overwritten regardless of its contents + _output_archive_path = SharedArchiveFile; } else { // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa // is read from top.jsa @@ -197,48 +211,49 @@ void CDSConfig::init_shared_archive_paths() { // However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not // allow cases (b) and (c). Case (b) is already checked above. - if (archives > 2) { + if (num_archives > 2) { vm_exit_during_initialization( "Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option"); } - if (archives == 1) { - char* base_archive_path = nullptr; + + if (num_archives == 1) { + const char* base_archive_path = nullptr; bool success = FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path); if (!success) { // If +AutoCreateSharedArchive and the specified shared archive does not exist, // regenerate the dynamic archive base on default archive. if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) { - enable_dumping_dynamic_archive(); - ArchiveClassesAtExit = const_cast(SharedArchiveFile); - _static_archive_path = default_archive_path(); - SharedArchiveFile = nullptr; - } else { + enable_dumping_dynamic_archive(SharedArchiveFile); + FLAG_SET_ERGO(ArchiveClassesAtExit, SharedArchiveFile); + _input_static_archive_path = default_archive_path(); + FLAG_SET_ERGO(SharedArchiveFile, nullptr); + } else { if (AutoCreateSharedArchive) { warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."); AutoCreateSharedArchive = false; } - log_error(cds)("Not a valid %s (%s)", new_aot_flags_used() ? "AOT cache" : "archive", SharedArchiveFile); + log_error(cds)("Not a valid archive (%s)", SharedArchiveFile); Arguments::no_shared_spaces("invalid archive"); } } else if (base_archive_path == nullptr) { // User has specified a single archive, which is a static archive. - _static_archive_path = const_cast(SharedArchiveFile); + _input_static_archive_path = SharedArchiveFile; } else { // User has specified a single archive, which is a dynamic archive. - _dynamic_archive_path = const_cast(SharedArchiveFile); - _static_archive_path = base_archive_path; // has been c-heap allocated. + _input_dynamic_archive_path = SharedArchiveFile; + _input_static_archive_path = base_archive_path; // has been c-heap allocated. } } else { - extract_shared_archive_paths((const char*)SharedArchiveFile, - &_static_archive_path, &_dynamic_archive_path); - if (_static_archive_path == nullptr) { - assert(_dynamic_archive_path == nullptr, "must be"); + extract_archive_paths(SharedArchiveFile, + &_input_static_archive_path, &_input_dynamic_archive_path); + if (_input_static_archive_path == nullptr) { + assert(_input_dynamic_archive_path == nullptr, "must be"); Arguments::no_shared_spaces("invalid archive"); } } - if (_dynamic_archive_path != nullptr) { + if (_input_dynamic_archive_path != nullptr) { // Check for case (c) if (RecordDynamicDumpInfo) { vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", @@ -353,14 +368,22 @@ bool CDSConfig::has_unsupported_runtime_module_options() { return false; } -#define CHECK_ALIAS(f) check_flag_alias(FLAG_IS_DEFAULT(f), #f) +#define CHECK_NEW_FLAG(f) check_new_flag(FLAG_IS_DEFAULT(f), #f) -void CDSConfig::check_flag_alias(bool alias_is_default, const char* alias_name) { - if (old_cds_flags_used() && !alias_is_default) { +void CDSConfig::check_new_flag(bool new_flag_is_default, const char* new_flag_name) { + if (old_cds_flags_used() && !new_flag_is_default) { vm_exit_during_initialization(err_msg("Option %s cannot be used at the same time with " "-Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, " "DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile", - alias_name)); + new_flag_name)); + } +} + +#define CHECK_SINGLE_PATH(f) check_flag_single_path(#f, f) + +void CDSConfig::check_flag_single_path(const char* flag_name, const char* value) { + if (value != nullptr && num_archive_paths(value) != 1) { + vm_exit_during_initialization(err_msg("Option %s must specify a single file name", flag_name)); } } @@ -371,9 +394,13 @@ void CDSConfig::check_aot_flags() { _old_cds_flags_used = true; } - CHECK_ALIAS(AOTCache); - CHECK_ALIAS(AOTConfiguration); - CHECK_ALIAS(AOTMode); + // "New" AOT flags must not be mixed with "classic" flags such as -Xshare:dump + CHECK_NEW_FLAG(AOTCache); + CHECK_NEW_FLAG(AOTConfiguration); + CHECK_NEW_FLAG(AOTMode); + + CHECK_SINGLE_PATH(AOTCache); + CHECK_SINGLE_PATH(AOTConfiguration); if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) { // AOTCache/AOTConfiguration/AOTMode not used. @@ -411,11 +438,6 @@ void CDSConfig::check_aotmode_auto_or_on() { vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create"); } - if (!FLAG_IS_DEFAULT(AOTCache)) { - assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); - FLAG_SET_ERGO(SharedArchiveFile, AOTCache); - } - UseSharedSpaces = true; if (FLAG_IS_DEFAULT(AOTMode) || (strcmp(AOTMode, "auto") == 0)) { RequireSharedSpaces = false; @@ -430,10 +452,6 @@ void CDSConfig::check_aotmode_record() { vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record"); } - assert(FLAG_IS_DEFAULT(DumpLoadedClassList), "already checked"); - assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); - FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration); - FLAG_SET_ERGO(DumpLoadedClassList, nullptr); UseSharedSpaces = false; RequireSharedSpaces = false; _is_dumping_static_archive = true; @@ -449,10 +467,7 @@ void CDSConfig::check_aotmode_create() { vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create"); } - assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); - _is_dumping_final_static_archive = true; - FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration); UseSharedSpaces = true; RequireSharedSpaces = true; @@ -463,7 +478,29 @@ void CDSConfig::check_aotmode_create() { CDSConfig::enable_dumping_static_archive(); } +void CDSConfig::ergo_init_aot_paths() { + assert(_cds_ergo_initialize_started, "sanity"); + if (is_dumping_static_archive()) { + if (is_dumping_preimage_static_archive()) { + _output_archive_path = AOTConfiguration; + } else { + assert(is_dumping_final_static_archive(), "must be"); + _input_static_archive_path = AOTConfiguration; + _output_archive_path = AOTCache; + } + } else if (is_using_archive()) { + if (FLAG_IS_DEFAULT(AOTCache)) { + // Only -XX:AOTMode={auto,on} is specified + _input_static_archive_path = default_archive_path(); + } else { + _input_static_archive_path = AOTCache; + } + } +} + bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) { + assert(!_cds_ergo_initialize_started, "This is called earlier than CDSConfig::ergo_initialize()"); + check_aot_flags(); if (!FLAG_IS_DEFAULT(AOTMode)) { @@ -514,7 +551,7 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) { disable_dumping_dynamic_archive(); } else { - enable_dumping_dynamic_archive(); + enable_dumping_dynamic_archive(ArchiveClassesAtExit); } if (AutoCreateSharedArchive) { @@ -546,6 +583,34 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla return true; } +void CDSConfig::prepare_for_dumping() { + assert(CDSConfig::is_dumping_archive(), "sanity"); + + if (is_dumping_dynamic_archive() && !is_using_archive()) { + assert(!is_dumping_static_archive(), "cannot be dumping both static and dynamic archives"); + + // This could happen if SharedArchiveFile has failed to load: + // - -Xshare:off was specified + // - SharedArchiveFile points to an non-existent file. + // - SharedArchiveFile points to an archive that has failed CRC check + // - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive + +#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info." + if (RecordDynamicDumpInfo) { + log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG); + MetaspaceShared::unrecoverable_loading_error(); + } else { + assert(ArchiveClassesAtExit != nullptr, "sanity"); + log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG); + } +#undef __THEMSG + disable_dumping_dynamic_archive(); + return; + } + + check_unsupported_dumping_module_options(); +} + bool CDSConfig::is_dumping_classic_static_archive() { return _is_dumping_static_archive && !is_dumping_preimage_static_archive() && @@ -560,6 +625,18 @@ bool CDSConfig::is_dumping_final_static_archive() { return _is_dumping_final_static_archive; } +void CDSConfig::enable_dumping_dynamic_archive(const char* output_path) { + _is_dumping_dynamic_archive = true; + if (output_path == nullptr) { + // output_path can be null when the VM is started with -XX:+RecordDynamicDumpInfo + // in anticipation of "jcmd VM.cds dynamic_dump", which will provide the actual + // output path. + _output_archive_path = nullptr; + } else { + _output_archive_path = os::strdup_check_oom(output_path, mtArguments); + } +} + bool CDSConfig::allow_only_single_java_thread() { // See comments in JVM_StartThread() return is_dumping_classic_static_archive() || is_dumping_final_static_archive(); diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index f02258eb6fe..e96291f6534 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -42,9 +42,10 @@ class CDSConfig : public AllStatic { static bool _is_using_full_module_graph; static bool _has_aot_linked_classes; - static char* _default_archive_path; - static char* _static_archive_path; - static char* _dynamic_archive_path; + const static char* _default_archive_path; + const static char* _input_static_archive_path; + const static char* _input_dynamic_archive_path; + const static char* _output_archive_path; static bool _old_cds_flags_used; static bool _new_aot_flags_used; @@ -53,17 +54,24 @@ class CDSConfig : public AllStatic { static JavaThread* _dumper_thread; #endif - static void extract_shared_archive_paths(const char* archive_path, - char** base_archive_path, - char** top_archive_path); - static void init_shared_archive_paths(); + static void extract_archive_paths(const char* archive_path, + const char** base_archive_path, + const char** top_archive_path); + static int num_archive_paths(const char* path_spec); + static void check_flag_single_path(const char* flag_name, const char* value); - static void check_flag_alias(bool alias_is_default, const char* alias_name); + // Checks before Arguments::apply_ergo() + static void check_new_flag(bool new_flag_is_default, const char* new_flag_name); static void check_aot_flags(); static void check_aotmode_off(); static void check_aotmode_auto_or_on(); static void check_aotmode_record(); static void check_aotmode_create(); + static void check_unsupported_dumping_module_options(); + + // Called after Arguments::apply_ergo() has started + static void ergo_init_classic_archive_paths(); + static void ergo_init_aot_paths(); public: // Used by jdk.internal.misc.CDS.getCDSConfigStatus(); @@ -76,24 +84,25 @@ public: static int get_status() NOT_CDS_RETURN_(0); // Initialization and command-line checking - static void initialize() NOT_CDS_RETURN; + static void ergo_initialize() NOT_CDS_RETURN; static void set_old_cds_flags_used() { CDS_ONLY(_old_cds_flags_used = true); } static bool old_cds_flags_used() { return CDS_ONLY(_old_cds_flags_used) NOT_CDS(false); } static bool new_aot_flags_used() { return CDS_ONLY(_new_aot_flags_used) NOT_CDS(false); } static void check_internal_module_property(const char* key, const char* value) NOT_CDS_RETURN; static void check_incompatible_property(const char* key, const char* value) NOT_CDS_RETURN; - static void check_unsupported_dumping_module_options() NOT_CDS_RETURN; static bool has_unsupported_runtime_module_options() NOT_CDS_RETURN_(false); static bool check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) NOT_CDS_RETURN_(true); static const char* type_of_archive_being_loaded(); static const char* type_of_archive_being_written(); + static void prepare_for_dumping(); // --- Basic CDS features // archive(s) in general static bool is_dumping_archive() { return is_dumping_static_archive() || is_dumping_dynamic_archive(); } + + // input archive(s) static bool is_using_archive() NOT_CDS_RETURN_(false); - static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0); // static_archive static bool is_dumping_static_archive() { return CDS_ONLY(_is_dumping_static_archive) NOT_CDS(false); } @@ -125,7 +134,7 @@ public: // dynamic_archive static bool is_dumping_dynamic_archive() { return CDS_ONLY(_is_dumping_dynamic_archive) NOT_CDS(false); } - static void enable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = true); } + static void enable_dumping_dynamic_archive(const char* output_path) NOT_CDS_RETURN; static void disable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = false); } // Misc CDS features @@ -147,12 +156,11 @@ public: // archive_path - // Points to the classes.jsa in $JAVA_HOME - static char* default_archive_path() NOT_CDS_RETURN_(nullptr); - // The actual static archive (if any) selected at runtime - static const char* static_archive_path() { return CDS_ONLY(_static_archive_path) NOT_CDS(nullptr); } - // The actual dynamic archive (if any) selected at runtime - static const char* dynamic_archive_path() { return CDS_ONLY(_dynamic_archive_path) NOT_CDS(nullptr); } + // Points to the classes.jsa in $JAVA_HOME (could be input or output) + static const char* default_archive_path() NOT_CDS_RETURN_(nullptr); + static const char* input_static_archive_path() { return CDS_ONLY(_input_static_archive_path) NOT_CDS(nullptr); } + static const char* input_dynamic_archive_path() { return CDS_ONLY(_input_dynamic_archive_path) NOT_CDS(nullptr); } + static const char* output_archive_path() { return CDS_ONLY(_output_archive_path) NOT_CDS(nullptr); } // --- Archived java objects diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index c3a6db9e9b9..bf4257253e8 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -97,8 +97,6 @@ public: void gather_array_klasses(); public: - DynamicArchiveBuilder() : ArchiveBuilder() { } - // Do this before and after the archive dump to see if any corruption // is caused by dynamic dumping. void verify_universe(const char* info) { @@ -348,7 +346,7 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data, AOTClassLocatio FileMapInfo* dynamic_info = FileMapInfo::dynamic_info(); assert(dynamic_info != nullptr, "Sanity"); - dynamic_info->open_for_write(); + dynamic_info->open_as_output(); ArchiveHeapInfo no_heap_for_dynamic_dump; ArchiveBuilder::write_archive(dynamic_info, &no_heap_for_dynamic_dump); @@ -476,27 +474,6 @@ int DynamicArchive::num_array_klasses() { return _array_klasses != nullptr ? _array_klasses->length() : 0; } -void DynamicArchive::check_for_dynamic_dump() { - if (CDSConfig::is_dumping_dynamic_archive() && !CDSConfig::is_using_archive()) { - // This could happen if SharedArchiveFile has failed to load: - // - -Xshare:off was specified - // - SharedArchiveFile points to an non-existent file. - // - SharedArchiveFile points to an archive that has failed CRC check - // - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive - -#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info." - if (RecordDynamicDumpInfo) { - log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG); - MetaspaceShared::unrecoverable_loading_error(); - } else { - assert(ArchiveClassesAtExit != nullptr, "sanity"); - log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG); - } -#undef __THEMSG - CDSConfig::disable_dumping_dynamic_archive(); - } -} - void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAPS) { MetaspaceShared::link_shared_classes(CHECK); if (!jcmd_request && CDSConfig::is_dumping_regenerated_lambdaform_invokers()) { @@ -507,11 +484,12 @@ void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAP VMThread::execute(&op); } -void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) { +void DynamicArchive::dump_at_exit(JavaThread* current) { ExceptionMark em(current); ResourceMark rm(current); CDSConfig::DumperThreadMark dumper_thread_mark(current); + const char* archive_name = CDSConfig::output_archive_path(); if (!CDSConfig::is_dumping_dynamic_archive() || archive_name == nullptr) { return; } diff --git a/src/hotspot/share/cds/dynamicArchive.hpp b/src/hotspot/share/cds/dynamicArchive.hpp index 905c511c4e0..8c23750734c 100644 --- a/src/hotspot/share/cds/dynamicArchive.hpp +++ b/src/hotspot/share/cds/dynamicArchive.hpp @@ -63,9 +63,8 @@ private: static GrowableArray* _array_klasses; static Array* _dynamic_archive_array_klasses; public: - static void check_for_dynamic_dump(); static void dump_for_jcmd(const char* archive_name, TRAPS); - static void dump_at_exit(JavaThread* current, const char* archive_name); + static void dump_at_exit(JavaThread* current); static void dump_impl(bool jcmd_request, const char* archive_name, TRAPS); static bool is_mapped() { return FileMapInfo::dynamic_info() != nullptr; } static bool validate(FileMapInfo* dynamic_info); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index ebcd33f8bd5..580699b60b5 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -173,7 +173,7 @@ void FileMapInfo::populate_header(size_t core_region_alignment) { header_size = c_header_size; const char* default_base_archive_name = CDSConfig::default_archive_path(); - const char* current_base_archive_name = CDSConfig::static_archive_path(); + const char* current_base_archive_name = CDSConfig::input_static_archive_path(); if (!os::same_files(current_base_archive_name, default_base_archive_name)) { base_archive_name_size = strlen(current_base_archive_name) + 1; header_size += base_archive_name_size; @@ -209,7 +209,7 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, if (!info->is_static() && base_archive_name_size != 0) { // copy base archive name - copy_base_archive_name(CDSConfig::static_archive_path()); + copy_base_archive_name(CDSConfig::input_static_archive_path()); } _core_region_alignment = core_region_alignment; _obj_alignment = ObjectAlignmentInBytes; @@ -563,7 +563,7 @@ public: // true && (*base_archive_name) != nullptr: // is a valid dynamic archive. bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, - char** base_archive_name) { + const char** base_archive_name) { FileHeaderHelper file_helper(archive_name, false); *base_archive_name = nullptr; @@ -619,7 +619,7 @@ bool FileMapInfo::init_from_file(int fd) { // Good } else { if (CDSConfig::new_aot_flags_used()) { - log_warning(cds)("Not a valid %s %s", file_type, _full_path); + log_warning(cds)("Not a valid %s (%s)", file_type, _full_path); } else { log_warning(cds)("Not a base shared archive: %s", _full_path); } @@ -729,7 +729,7 @@ bool FileMapInfo::open_for_read() { // Write the FileMapInfo information to the file. -void FileMapInfo::open_for_write() { +void FileMapInfo::open_as_output() { LogMessage(cds) msg; if (msg.is_info()) { if (CDSConfig::is_dumping_preimage_static_archive()) { @@ -1759,7 +1759,7 @@ bool FileMapInfo::_memory_mapping_failed = false; // [1] validate_header() - done here. // [2] validate_shared_path_table - this is done later, because the table is in the RO // region of the archive, which is not mapped yet. -bool FileMapInfo::initialize() { +bool FileMapInfo::open_as_input() { assert(CDSConfig::is_using_archive(), "UseSharedSpaces expected."); assert(Arguments::has_jimage(), "The shared archive file cannot be used with an exploded module build."); @@ -1774,13 +1774,12 @@ bool FileMapInfo::initialize() { if (!open_for_read() || !init_from_file(_fd) || !validate_header()) { if (_is_static) { - log_info(cds)("Initialize static archive failed."); + log_info(cds)("Loading static archive failed."); return false; } else { - log_info(cds)("Initialize dynamic archive failed."); + log_info(cds)("Loading dynamic archive failed."); if (AutoCreateSharedArchive) { - CDSConfig::enable_dumping_dynamic_archive(); - ArchiveClassesAtExit = CDSConfig::dynamic_archive_path(); + CDSConfig::enable_dumping_dynamic_archive(_full_path); } return false; } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 50af87a5da7..8793e110948 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -268,7 +268,7 @@ private: public: FileMapHeader *header() const { return _header; } static bool get_base_archive_name_from_header(const char* archive_name, - char** base_archive_name); + const char** base_archive_name); static bool is_preimage_static_archive(const char* file); bool init_from_file(int fd); @@ -346,9 +346,8 @@ public: static void assert_mark(bool check); // File manipulation. - bool initialize() NOT_CDS_RETURN_(false); - bool open_for_read(); - void open_for_write(); + bool open_as_input() NOT_CDS_RETURN_(false); + void open_as_output(); void write_header(); void write_region(int region, char* base, size_t size, bool read_only, bool allow_exec); @@ -425,6 +424,7 @@ public: } private: + bool open_for_read(); void seek_to_position(size_t pos); bool map_heap_region_impl() NOT_CDS_JAVA_HEAP_RETURN_(false); void dealloc_heap_region() NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 85916ced3cf..ef2a6dcb8e6 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -678,14 +678,11 @@ void VM_PopulateDumpSharedSpace::doit() { CppVtables::zero_archived_vtables(); // Write the archive file - const char* static_archive; if (CDSConfig::is_dumping_final_static_archive()) { - static_archive = AOTCache; - FileMapInfo::free_current_info(); - } else { - static_archive = CDSConfig::static_archive_path(); + FileMapInfo::free_current_info(); // FIXME: should not free current info } - assert(static_archive != nullptr, "SharedArchiveFile not set?"); + const char* static_archive = CDSConfig::output_archive_path(); + assert(static_archive != nullptr, "sanity"); _map_info = new FileMapInfo(static_archive, true); _map_info->populate_header(MetaspaceShared::core_region_alignment()); _map_info->set_early_serialized_data(early_serialized_data); @@ -789,11 +786,6 @@ void MetaspaceShared::link_shared_classes(TRAPS) { } } -void MetaspaceShared::prepare_for_dumping() { - assert(CDSConfig::is_dumping_archive(), "sanity"); - CDSConfig::check_unsupported_dumping_module_options(); -} - // Preload classes from a list, populate the shared spaces and dump to a // file. void MetaspaceShared::preload_and_dump(TRAPS) { @@ -1023,7 +1015,7 @@ bool MetaspaceShared::write_static_archive(ArchiveBuilder* builder, FileMapInfo* // without runtime relocation. builder->relocate_to_requested(); - map_info->open_for_write(); + map_info->open_as_output(); if (!map_info->is_open()) { return false; } @@ -1214,10 +1206,10 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { } FileMapInfo* MetaspaceShared::open_static_archive() { - const char* static_archive = CDSConfig::static_archive_path(); + const char* static_archive = CDSConfig::input_static_archive_path(); assert(static_archive != nullptr, "sanity"); FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); - if (!mapinfo->initialize()) { + if (!mapinfo->open_as_input()) { delete(mapinfo); return nullptr; } @@ -1228,13 +1220,13 @@ FileMapInfo* MetaspaceShared::open_dynamic_archive() { if (CDSConfig::is_dumping_dynamic_archive()) { return nullptr; } - const char* dynamic_archive = CDSConfig::dynamic_archive_path(); + const char* dynamic_archive = CDSConfig::input_dynamic_archive_path(); if (dynamic_archive == nullptr) { return nullptr; } FileMapInfo* mapinfo = new FileMapInfo(dynamic_archive, false); - if (!mapinfo->initialize()) { + if (!mapinfo->open_as_input()) { delete(mapinfo); if (RequireSharedSpaces) { MetaspaceShared::unrecoverable_loading_error("Failed to initialize dynamic archive"); @@ -1817,7 +1809,7 @@ void MetaspaceShared::initialize_shared_spaces() { if (PrintSharedArchiveAndExit) { // Print archive names if (dynamic_mapinfo != nullptr) { - tty->print_cr("\n\nBase archive name: %s", CDSConfig::static_archive_path()); + tty->print_cr("\n\nBase archive name: %s", CDSConfig::input_static_archive_path()); tty->print_cr("Base archive version %d", static_mapinfo->version()); } else { tty->print_cr("Static archive name: %s", static_mapinfo->full_path()); diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index 8881dc6d6fd..e03994be1b9 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -71,7 +71,6 @@ class MetaspaceShared : AllStatic { n_regions = 4 // total number of regions }; - static void prepare_for_dumping() NOT_CDS_RETURN; static void preload_and_dump(TRAPS) NOT_CDS_RETURN; #ifdef _LP64 static void adjust_heap_sizes_for_dumping() NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index fe9c960b7f2..6f415ab93a4 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -897,14 +897,13 @@ jint universe_init() { ClassLoaderData::init_null_class_loader_data(); #if INCLUDE_CDS - DynamicArchive::check_for_dynamic_dump(); if (CDSConfig::is_using_archive()) { // Read the data structures supporting the shared spaces (shared // system dictionary, symbol table, etc.) MetaspaceShared::initialize_shared_spaces(); } if (CDSConfig::is_dumping_archive()) { - MetaspaceShared::prepare_for_dumping(); + CDSConfig::prepare_for_dumping(); } #endif diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 0927e87c748..d2e3df71dc4 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3708,7 +3708,7 @@ jint Arguments::apply_ergo() { CompressedKlassPointers::pre_initialize(); } - CDSConfig::initialize(); + CDSConfig::ergo_initialize(); // Initialize Metaspace flags and alignments Metaspace::ergo_initialize(); diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index bcf99c84ba4..b3ad15ae3ff 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -426,11 +426,10 @@ void before_exit(JavaThread* thread, bool halt) { #if INCLUDE_CDS // Dynamic CDS dumping must happen whilst we can still reliably // run Java code. - DynamicArchive::dump_at_exit(thread, ArchiveClassesAtExit); + DynamicArchive::dump_at_exit(thread); assert(!thread->has_pending_exception(), "must be"); #endif - // Actual shutdown logic begins here. #if INCLUDE_JVMCI diff --git a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c index bcce23f1221..3c244aab0f3 100644 --- a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c +++ b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -265,7 +265,7 @@ bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t siz #ifdef LINUX // mangled name of CDSConfig::_static_archive_path -#define SHARED_ARCHIVE_PATH_SYM "_ZN9CDSConfig20_static_archive_pathE" +#define SHARED_ARCHIVE_PATH_SYM "_ZN9CDSConfig26_input_static_archive_pathE" #define USE_SHARED_SPACES_SYM "UseSharedSpaces" #define SHARED_BASE_ADDRESS_SYM "SharedBaseAddress" #define LIBJVM_NAME "/libjvm.so" @@ -273,7 +273,7 @@ bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t siz #ifdef __APPLE__ // mangled name of CDSConfig::_static_archive_path -#define SHARED_ARCHIVE_PATH_SYM "__ZN9CDSConfig20_static_archive_pathE" +#define SHARED_ARCHIVE_PATH_SYM "__ZN9CDSConfig26_input_static_archive_pathE" #define USE_SHARED_SPACES_SYM "_UseSharedSpaces" #define SHARED_BASE_ADDRESS_SYM "_SharedBaseAddress" #define LIBJVM_NAME "/libjvm.dylib" diff --git a/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java index aeb0476346d..46f76fab368 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java @@ -26,12 +26,14 @@ * @test * @summary "AOT" aliases for traditional CDS command-line options * @requires vm.cds + * @requires vm.flagless * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build Hello * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello * @run driver AOTFlags */ +import java.io.File; import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.helpers.ClassFileInstaller; import jdk.test.lib.process.OutputAnalyzer; @@ -298,6 +300,60 @@ public class AOTFlags { "specified when the AOTConfiguration file was recorded"); out.shouldContain("Unable to use create AOT cache"); out.shouldHaveExitValue(1); + + //---------------------------------------------------------------------- + printTestCase("Cannot use multiple paths in AOTConfiguration"); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=record", + "-XX:AOTConfiguration=" + aotConfigFile + File.pathSeparator + "dummy", + "-cp", "noSuchJar.jar"); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Option AOTConfiguration must specify a single file name"); + out.shouldHaveExitValue(1); + + //---------------------------------------------------------------------- + printTestCase("Cannot use multiple paths in AOTCache"); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=create", + "-XX:AOTConfiguration=" + aotConfigFile, + "-XX:AOTCache=" + aotCacheFile + File.pathSeparator + "dummy", + "-cp", "noSuchJar.jar"); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Option AOTCache must specify a single file name"); + out.shouldHaveExitValue(1); + + //---------------------------------------------------------------------- + printTestCase("Cannot use a dynamic CDS archive for -XX:AOTCache"); + String staticArchive = "static.jsa"; + String dynamicArchive = "dynamic.jsa"; + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xshare:dump", + "-XX:SharedArchiveFile=" + staticArchive); + out = CDSTestUtils.executeAndLog(pb, "static"); + out.shouldHaveExitValue(0); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:SharedArchiveFile=" + staticArchive, + "-XX:ArchiveClassesAtExit=" + dynamicArchive, + "--version"); + out = CDSTestUtils.executeAndLog(pb, "dynamic"); + out.shouldHaveExitValue(0); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xlog:cds", + "-XX:AOTMode=on", + "-XX:AOTCache=" + dynamicArchive, + "--version"); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Unable to use AOT cache."); + out.shouldContain("Not a valid AOT cache (dynamic.jsa)"); + out.shouldHaveExitValue(1); } static int testNum = 0; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java index c8a04027a3d..3bc1e395b17 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java @@ -337,7 +337,7 @@ public class TestAutoCreateSharedArchive extends DynamicArchiveTestBase { .shouldContain(HELLO_WORLD) .shouldContain("The shared archive file version " + hex(version2) + " does not match the required version " + hex(currentCDSVersion)) .shouldContain("The shared archive file has the wrong version") - .shouldContain("Initialize dynamic archive failed") + .shouldContain("Loading dynamic archive failed") .shouldContain("Dumping shared data to file"); }); ft2 = Files.getLastModifiedTime(Paths.get(modVersion)); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java index 133f44521d5..4806f571dc6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,7 +112,7 @@ public class TestAutoCreateSharedArchiveNoDefaultArchive { "-version"); TestCommon.executeAndLog(pb, "show-version") .shouldHaveExitValue(0) - .shouldContain("Initialize static archive failed") + .shouldContain("Loading static archive failed") .shouldContain("Unable to map shared spaces") .shouldNotContain("sharing"); } @@ -132,7 +132,7 @@ public class TestAutoCreateSharedArchiveNoDefaultArchive { mainClass); TestCommon.executeAndLog(pb, "no-default-archive") .shouldHaveExitValue(0) - .shouldContain("Initialize static archive failed") + .shouldContain("Loading static archive failed") .shouldContain("Unable to map shared spaces") .shouldNotContain("Dumping shared data to file"); if (jsaFile.exists()) { From 1f21da75eb5d5eb7460b2953517514a0aa26b5de Mon Sep 17 00:00:00 2001 From: Raffaello Giulietti Date: Wed, 9 Apr 2025 15:16:02 +0000 Subject: [PATCH 090/843] 8351462: Improve robustness of String concatenation Reviewed-by: liach, pminborg, rriggs --- .../share/classes/java/lang/StringConcatHelper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/StringConcatHelper.java b/src/java.base/share/classes/java/lang/StringConcatHelper.java index 13ada0637ba..3b057ecb028 100644 --- a/src/java.base/share/classes/java/lang/StringConcatHelper.java +++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -52,6 +52,9 @@ final class StringConcatHelper { byte coder = String.LATIN1; for (String c : constants) { length += c.length(); + if (length < 0) { + throw new OutOfMemoryError("Total length of constants is out of range"); + } coder |= c.coder(); } this.constants = constants; From 5f2a604b633c0cd24f897f828a7c928c3d2b651c Mon Sep 17 00:00:00 2001 From: Danish Nawab Date: Wed, 9 Apr 2025 15:25:24 +0000 Subject: [PATCH 091/843] 8353840: JNativeScan should not abort for missing classes Reviewed-by: jvernee, liach --- .../tools/jnativescan/JNativeScanTask.java | 21 +++++++-- .../com/sun/tools/jnativescan/Main.java | 2 +- .../tools/jnativescan/NativeMethodFinder.java | 43 ++++++++++--------- .../jnativescan/TestMissingSystemClass.java | 14 ++++-- .../cases/classpath/missingsystem/App.java | 1 + 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/JNativeScanTask.java b/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/JNativeScanTask.java index 2ff172e9c1b..c57e033427e 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/JNativeScanTask.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/JNativeScanTask.java @@ -42,15 +42,17 @@ import java.util.zip.ZipFile; class JNativeScanTask { private final PrintWriter out; + private final PrintWriter err; private final List classPaths; private final List modulePaths; private final List cmdRootModules; private final Runtime.Version version; private final Action action; - public JNativeScanTask(PrintWriter out, List classPaths, List modulePaths, + public JNativeScanTask(PrintWriter out, PrintWriter err, List classPaths, List modulePaths, List cmdRootModules, Runtime.Version version, Action action) { this.out = out; + this.err = err; this.classPaths = classPaths; this.modulePaths = modulePaths; this.version = version; @@ -71,10 +73,13 @@ class JNativeScanTask { toScan.add(new ClassFileSource.Module(m.reference())); } + Set errors = new LinkedHashSet<>(); + Diagnostics diagnostics = (context, error) -> + errors.add("Error while processing method: " + context + ": " + error.getMessage()); SortedMap>> allRestrictedMethods; try(ClassResolver classesToScan = ClassResolver.forClassFileSources(toScan, version); ClassResolver systemClassResolver = ClassResolver.forSystemModules(version)) { - NativeMethodFinder finder = NativeMethodFinder.create(classesToScan, systemClassResolver); + NativeMethodFinder finder = NativeMethodFinder.create(diagnostics, classesToScan, systemClassResolver); allRestrictedMethods = finder.findAll(); } catch (IOException e) { throw new RuntimeException(e); @@ -82,7 +87,7 @@ class JNativeScanTask { switch (action) { case PRINT -> printNativeAccess(allRestrictedMethods); - case DUMP_ALL -> dumpAll(allRestrictedMethods); + case DUMP_ALL -> dumpAll(allRestrictedMethods, errors); } } @@ -156,7 +161,7 @@ class JNativeScanTask { out.println(nativeAccess); } - private void dumpAll(SortedMap>> allRestrictedMethods) { + private void dumpAll(SortedMap>> allRestrictedMethods, Set errors) { if (allRestrictedMethods.isEmpty()) { out.println(" "); } else { @@ -177,6 +182,10 @@ class JNativeScanTask { }); }); } + if (!errors.isEmpty()) { + err.println("Error(s) while processing classes:"); + errors.forEach(error -> err.println(" " + error)); + } } private static boolean isJarFile(Path path) throws JNativeScanFatalError { @@ -192,4 +201,8 @@ class JNativeScanTask { String packagePrefix = desc.packageName().isEmpty() ? "" : desc.packageName() + "."; return packagePrefix + desc.displayName(); } + + interface Diagnostics { + void error(MethodRef context, JNativeScanFatalError error); + } } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/Main.java b/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/Main.java index 425a106d599..9aa77a947a9 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/Main.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/Main.java @@ -165,7 +165,7 @@ public class Main { action = JNativeScanTask.Action.PRINT; } - new JNativeScanTask(out, classPathJars, modulePaths, rootModules, version, action).run(); + new JNativeScanTask(out, err, classPathJars, modulePaths, rootModules, version, action).run(); } private static String[] expandArgFiles(String[] args) throws JNativeScanFatalError { diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/NativeMethodFinder.java b/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/NativeMethodFinder.java index 681b954d4cd..b89c9db2858 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/NativeMethodFinder.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jnativescan/NativeMethodFinder.java @@ -24,6 +24,7 @@ */ package com.sun.tools.jnativescan; +import com.sun.tools.jnativescan.JNativeScanTask.Diagnostics; import com.sun.tools.jnativescan.RestrictedUse.NativeMethodDecl; import com.sun.tools.jnativescan.RestrictedUse.RestrictedMethodRefs; @@ -44,16 +45,19 @@ class NativeMethodFinder { private static final String RESTRICTED_NAME = "Ljdk/internal/javac/Restricted+Annotation;"; private final Map cache = new HashMap<>(); + private final Diagnostics diagnostics; private final ClassResolver classesToScan; private final ClassResolver systemClassResolver; - private NativeMethodFinder(ClassResolver classesToScan, ClassResolver systemClassResolver) { + private NativeMethodFinder(Diagnostics diagnostics, ClassResolver classesToScan, ClassResolver systemClassResolver) { + this.diagnostics = diagnostics; this.classesToScan = classesToScan; this.systemClassResolver = systemClassResolver; } - public static NativeMethodFinder create(ClassResolver classesToScan, ClassResolver systemClassResolver) throws JNativeScanFatalError, IOException { - return new NativeMethodFinder(classesToScan, systemClassResolver); + public static NativeMethodFinder create(Diagnostics diagnostics, ClassResolver classesToScan, + ClassResolver systemClassResolver) throws JNativeScanFatalError, IOException { + return new NativeMethodFinder(diagnostics, classesToScan, systemClassResolver); } public SortedMap>> findAll() throws JNativeScanFatalError { @@ -68,23 +72,22 @@ class NativeMethodFinder { } else { SortedSet perMethod = new TreeSet<>(Comparator.comparing(MethodRef::toString)); methodModel.code().ifPresent(code -> { - try { - code.forEach(e -> { - switch (e) { - case InvokeInstruction invoke -> { - MethodRef ref = MethodRef.ofInvokeInstruction(invoke); - if (isRestrictedMethod(ref)) { - perMethod.add(ref); - } - } - default -> { - } - } - }); - } catch (JNativeScanFatalError e) { - throw new JNativeScanFatalError("Error while processing method: " + - MethodRef.ofModel(methodModel), e); - } + code.forEach(e -> { + switch (e) { + case InvokeInstruction invoke -> { + MethodRef ref = MethodRef.ofInvokeInstruction(invoke); + try { + if (isRestrictedMethod(ref)) { + perMethod.add(ref); + } + } catch (JNativeScanFatalError ex) { + diagnostics.error(MethodRef.ofModel(methodModel), ex); + } + } + default -> { + } + } + }); }); if (!perMethod.isEmpty()) { perClass.add(new RestrictedMethodRefs(MethodRef.ofModel(methodModel), perMethod)); diff --git a/test/langtools/tools/jnativescan/TestMissingSystemClass.java b/test/langtools/tools/jnativescan/TestMissingSystemClass.java index 5806590d0e0..8b6266aa5d7 100644 --- a/test/langtools/tools/jnativescan/TestMissingSystemClass.java +++ b/test/langtools/tools/jnativescan/TestMissingSystemClass.java @@ -35,6 +35,9 @@ import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; public class TestMissingSystemClass extends JNativeScanTestBase { @@ -49,12 +52,15 @@ public class TestMissingSystemClass extends JNativeScanTestBase { @Test public void testSingleJarClassPath() { - assertFailure(jnativescan("--class-path", MISSING_SYSTEM.toString(), "--release", "21")) - .stdoutShouldBeEmpty() + List stderr = assertSuccess(jnativescan("--class-path", MISSING_SYSTEM.toString(), "--release", "21")) + .stdoutShouldContain("") + .stderrShouldContain("Error(s) while processing classes") .stderrShouldContain("Error while processing method") .stderrShouldContain("missingsystem.App::main(String[])void") - .stderrShouldContain("CAUSED BY:") .stderrShouldContain("System class can not be found") - .stderrShouldContain("java.lang.Compiler"); + .stderrShouldContain("java.lang.Compiler") + .stderrAsLines(); + + assertEquals(2, stderr.size(), "Unexpected number of lines in stderr"); } } diff --git a/test/langtools/tools/jnativescan/cases/classpath/missingsystem/App.java b/test/langtools/tools/jnativescan/cases/classpath/missingsystem/App.java index 0e20fe81eec..05812be45ce 100644 --- a/test/langtools/tools/jnativescan/cases/classpath/missingsystem/App.java +++ b/test/langtools/tools/jnativescan/cases/classpath/missingsystem/App.java @@ -28,5 +28,6 @@ public class App { // if we compile with --release 20, but run jnativescan // with --release 21, we should get an error java.lang.Compiler.enable(); + java.lang.Compiler.enable(); // should be de-duplicated in the error logs } } From 6352ee1a6e55e428db0eca97ecf8125770dc4a08 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 9 Apr 2025 17:43:11 +0000 Subject: [PATCH 092/843] 8349007: The jtreg test ResolvedMethodTableHash takes excessive time Reviewed-by: lmesnik, matsaave --- .../share/prims/resolvedMethodTable.cpp | 8 +- .../MemberName/ResolvedMethodTableHash.java | 125 ++++++++++-------- 2 files changed, 80 insertions(+), 53 deletions(-) diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp index 5b9b07c5842..cdd41730dea 100644 --- a/src/hotspot/share/prims/resolvedMethodTable.cpp +++ b/src/hotspot/share/prims/resolvedMethodTable.cpp @@ -175,7 +175,13 @@ oop ResolvedMethodTable::find_method(const Method* method) { ResolvedMethodTableLookup lookup(thread, method_hash(method), method); ResolvedMethodGet rmg(thread, method); - _local_table->get(thread, lookup, rmg); + bool rehash_warning = false; + _local_table->get(thread, lookup, rmg, &rehash_warning); + if (rehash_warning) { + // if load factor is low but we need to rehash that's a problem with the hash function. + log_info(membername, table)("Rehash warning, load factor %g", get_load_factor()); + trigger_concurrent_work(); + } return rmg.get_res_oop(); } diff --git a/test/hotspot/jtreg/runtime/MemberName/ResolvedMethodTableHash.java b/test/hotspot/jtreg/runtime/MemberName/ResolvedMethodTableHash.java index 8abc4d41b16..9ee6a808e24 100644 --- a/test/hotspot/jtreg/runtime/MemberName/ResolvedMethodTableHash.java +++ b/test/hotspot/jtreg/runtime/MemberName/ResolvedMethodTableHash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,11 @@ * @test * @bug 8249719 * @summary ResolvedMethodTable hash function should take method class into account - * @run main/othervm/manual -Xmx256m -XX:MaxMetaspaceSize=256m ResolvedMethodTableHash 200000 + * @requires vm.flagless + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run driver ResolvedMethodTableHash */ import java.lang.invoke.MethodHandle; @@ -35,34 +39,38 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -// The test generates thousands MethodHandles to the methods of the same name -// and the same signature. This should not take too long, unless Method hash +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +// The test generates a thousand MethodHandles to the methods of the same name +// and the same signature. The rehash warning shouldn't be returned, unless Method hash // function takes only the name and the signature as an input. -public class ResolvedMethodTableHash extends ClassLoader { +public class ResolvedMethodTableHash { - // Generate a MethodHandle for ClassName.m() - private MethodHandle generate(String className) throws ReflectiveOperationException { - byte[] buf = new byte[100]; - int size = writeClass(buf, className); - Class cls = defineClass(null, buf, 0, size); - return MethodHandles.publicLookup().findStatic(cls, "m", MethodType.methodType(void.class)); - } + public static class ResolvedMethodTableHashTest extends ClassLoader { + // Generate a MethodHandle for ClassName.m() + private MethodHandle generate(String className) throws ReflectiveOperationException { + byte[] buf = new byte[100]; + int size = writeClass(buf, className); + Class cls = defineClass(null, buf, 0, size); + return MethodHandles.publicLookup().findStatic(cls, "m", MethodType.methodType(void.class)); + } - private MethodHandle generateWithSameName() throws ReflectiveOperationException { - byte[] buf = new byte[100]; - int size = writeClass(buf, "MH$$"); - // use different classloader instances to load the classes with the same name - Class cls = new ResolvedMethodTableHash().defineClass(null, buf, 0, size); - return MethodHandles.publicLookup().findStatic(cls, "m", MethodType.methodType(void.class)); - } + private MethodHandle generateWithSameName() throws ReflectiveOperationException { + byte[] buf = new byte[100]; + int size = writeClass(buf, "MH$$"); + // use different classloader instances to load the classes with the same name + Class cls = new ResolvedMethodTableHashTest().defineClass(null, buf, 0, size); + return MethodHandles.publicLookup().findStatic(cls, "m", MethodType.methodType(void.class)); + } - // Produce a class file with the given name and a single method: - // public static native void m(); - private int writeClass(byte[] buf, String className) { - return ByteBuffer.wrap(buf) - .putInt(0xCAFEBABE) // magic - .putInt(50) // version: 50 - .putShort((short) 7) // constant_pool_count: 7 + // Produce a class file with the given name and a single method: + // public static native void m(); + private int writeClass(byte[] buf, String className) { + return ByteBuffer.wrap(buf) + .putInt(0xCAFEBABE) // magic + .putInt(50) // version: 50 + .putShort((short) 7) // constant_pool_count: 7 .put((byte) 7).putShort((short) 2) .put((byte) 1).putShort((short) className.length()).put(className.getBytes()) .put((byte) 7).putShort((short) 4) @@ -70,37 +78,50 @@ public class ResolvedMethodTableHash extends ClassLoader { .put((byte) 1).putShort((short) 1).put("m".getBytes()) .put((byte) 1).putShort((short) 3).put("()V".getBytes()) .putShort((short) 0x21) // access_flags: public super - .putShort((short) 1) // this_class: #1 - .putShort((short) 3) // super_class: #3 - .putShort((short) 0) // interfaces_count: 0 - .putShort((short) 0) // fields_count: 0 - .putShort((short) 1) // methods_count: 1 + .putShort((short) 1) // this_class: #1 + .putShort((short) 3) // super_class: #3 + .putShort((short) 0) // interfaces_count: 0 + .putShort((short) 0) // fields_count: 0 + .putShort((short) 1) // methods_count: 1 .putShort((short) 0x109) // access_flags: public static native - .putShort((short) 5) // name_index: #5 - .putShort((short) 6) // descriptor_index: #6 - .putShort((short) 0) // attributes_count: 0 - .putShort((short) 0) // attributes_count: 0 + .putShort((short) 5) // name_index: #5 + .putShort((short) 6) // descriptor_index: #6 + .putShort((short) 0) // attributes_count: 0 + .putShort((short) 0) // attributes_count: 0 .position(); + } + + public static void main(String[] args) throws Exception { + + ResolvedMethodTableHashTest generator = new ResolvedMethodTableHashTest(); + List handles = new ArrayList<>(); + + int count = 1001; + + for (int i = 0; i < count; i++) { + // prevents metaspace oom + if (i % 20 != 0) { + handles.add(generator.generate("MH$" + i)); + } else { + handles.add(generator.generateWithSameName()); + } + if (i % 1000 == 0) { + System.out.println("Generated " + i + " handles"); + } + } + + System.out.println("Test passed"); + } } public static void main(String[] args) throws Exception { - ResolvedMethodTableHash generator = new ResolvedMethodTableHash(); - List handles = new ArrayList<>(); - int count = args.length > 0 ? Integer.parseInt(args[0]) : 200000; - - for (int i = 0; i < count; i++) { - // prevents metaspace oom - if (i % 20 != 0) { - handles.add(generator.generate("MH$" + i)); - } else { - handles.add(generator.generateWithSameName()); - } - if (i % 1000 == 0) { - System.out.println("Generated " + i + " handles"); - } - } - - System.out.println("Test passed"); + // Running the table with only 1000 entries should not provoke a needs rehash warning, unless the hash code is bad. + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:membername+table", + ResolvedMethodTableHashTest.class.getName()); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[membername,table] Rehash warning, load factor"); + output.shouldContain("Generated 1000 handles"); + output.shouldHaveExitValue(0); } } From faacbd96a3dc1116f3af590439585844ff8048a1 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Wed, 9 Apr 2025 17:47:47 +0000 Subject: [PATCH 093/843] 8353938: hotspot/jtreg/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java fails on static JDK Reviewed-by: alanb --- .../jtreg/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java b/test/hotspot/jtreg/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java index 725bf086b3b..39068a47e95 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ import org.testng.annotations.Test; * * @test * @bug 8147388 + * @requires !jdk.static * @library /test/lib * @modules java.base/jdk.internal.misc * java.compiler From cc546e7a283faad40b75183887f6a1f433a2407f Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Wed, 9 Apr 2025 17:49:18 +0000 Subject: [PATCH 094/843] 8353549: Open source events tests batch2 Reviewed-by: honkar, kizune --- .../event/MouseEvent/DragMouseEventTest.java | 438 ++++++++++++++++++ .../MouseEvent/MouseEventsDuringDrag.java | 307 ++++++++++++ .../event/MouseEvent/MouseModifierTest.java | 181 ++++++++ .../awt/event/MouseEvent/MouseRButTest.java | 97 ++++ .../MouseEvent/TitleBarGetsMousePressed.java | 78 ++++ 5 files changed, 1101 insertions(+) create mode 100644 test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java create mode 100644 test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java create mode 100644 test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java create mode 100644 test/jdk/java/awt/event/MouseEvent/MouseRButTest.java create mode 100644 test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java diff --git a/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java b/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java new file mode 100644 index 00000000000..3f8d10651ff --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/DragMouseEventTest.java @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4327618 4327623 4327639 4327654 4327664 4327666 4327676 4327679 4507822 + * @summary Tests that MouseDragged and MouseReleased are triggered by Button, + * Checkbox, Choice, Label, List, Scrollbar, TextArea, TextField + * for Left, Middle and Right mouse buttons + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main/othervm -Dsun.java2d.uiScale=1 DragMouseEventTest +*/ + +import java.awt.BorderLayout; +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.Point; +import java.awt.Rectangle; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Arrays; + +import test.java.awt.regtesthelpers.Util; + +public class DragMouseEventTest { + private static ExtendedRobot robot; + private static DragMouseEventFrame dmef; + private static final int DELAY = 200; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(DragMouseEventTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (dmef != null) { + dmef.dispose(); + } + }); + } + } + + private static void createAndShowGUI() { + dmef = new DragMouseEventFrame(); + dmef.setVisible(true); + } + + private static void test() throws Exception { + robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + testComponent(dmef.scrollbar); + testComponent(dmef.choice); + testComponent(dmef.textarea); + testComponent(dmef.textfield); + testComponent(dmef.checkbox); + testComponent(dmef.label); + testComponent(dmef.list); + testComponent(dmef.button); + } + + private static void testComponent(Component component) throws Exception { + Rectangle componentBounds = Util.invokeOnEDT(() -> { + Point locationOnScreen = component.getLocationOnScreen(); + Dimension size = component.getSize(); + return new Rectangle(locationOnScreen, size); + }); + + Rectangle frameBounds = Util.invokeOnEDT(() -> dmef.getBounds()); + + Point start = new Point(componentBounds.x + 10, componentBounds.y + 10); + + Adapter adapter = getAdapterFromComponent(component); + + testItemStateChanged(component, adapter, start, componentBounds); + testActionListener(component, adapter, start); + + Point mid = getEndPoint(start, frameBounds, 3); + Point end = getEndPoint(start, frameBounds, 15); + + testButtonDrag(component, adapter, MouseEvent.BUTTON1_DOWN_MASK, start, mid, end); + testButtonDrag(component, adapter, MouseEvent.BUTTON2_DOWN_MASK, start, mid, end); + testButtonDrag(component, adapter, MouseEvent.BUTTON3_DOWN_MASK, start, mid, end); + } + + private static Adapter getAdapterFromComponent(Component component) { + return (Adapter) Arrays + .stream(component.getMouseListeners()) + .filter((m) -> m instanceof Adapter) + .findFirst() + .orElseThrow(); + } + + private static void testItemStateChanged(Component component, + Adapter adapter, + Point start, + Rectangle componentBounds) { + if (!(component instanceof Choice + || component instanceof Checkbox + || component instanceof List)) { + return; + } + + System.out.println("\ntestItemStateChanged " + component); + + adapter.reset(); + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + robot.click(); + + if (component instanceof Choice) { + robot.mouseMove(start.x, componentBounds.y + componentBounds.height + 25); + robot.waitForIdle(); + robot.click(); + } + + robot.waitForIdle(); + + if (!adapter.itemStateChangedReceived) { + throw new RuntimeException("itemStateChanged was not received for " + component); + } + } + + private static void testActionListener(Component component, + Adapter adapter, + Point start) { + if (!(component instanceof Button || component instanceof List)) { + // skip for not applicable components + return; + } + + System.out.println("\ntestActionListener " + component); + adapter.reset(); + + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + + if (component instanceof List) { + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(DELAY); + } else { + robot.click(); + } + + robot.waitForIdle(); + robot.delay(DELAY); + + if (!adapter.actionPerformedReceived) { + throw new RuntimeException("actionPerformed was not received for " + component); + } + } + + private static String getButtonName(int button) { + return switch (button) { + case MouseEvent.BUTTON1_DOWN_MASK -> "BUTTON1"; + case MouseEvent.BUTTON2_DOWN_MASK -> "BUTTON2"; + case MouseEvent.BUTTON3_DOWN_MASK -> "BUTTON3"; + default -> throw new IllegalStateException("Unexpected value: " + button); + }; + } + + private static void testButtonDrag(Component component, + Adapter adapter, + int button, + Point start, Point mid, Point end) { + String buttonName = getButtonName(button); + System.out.printf("\n> testButtonDrag: %s on %s\n", + buttonName, component); + + robot.mouseMove(start.x, start.y); + robot.waitForIdle(); + + robot.mousePress(button); + robot.waitForIdle(); + + System.out.printf("> gliding from (%d,%d) to (%d,%d)\n", + start.x, start.y, mid.x, mid.y); + robot.glide(start, mid); + robot.waitForIdle(); + robot.delay(DELAY); + + + // Catch events only after we leave the frame boundaries + adapter.reset(); + + System.out.printf("> gliding after crossing the border (%d,%d) to (%d,%d)\n", + mid.x, mid.y, end.x, end.y); + robot.glide(mid, end); + + robot.mouseRelease(button); + robot.waitForIdle(); + robot.delay(DELAY); + System.out.printf("> %s released\n", buttonName); + + boolean mouseDraggedReceived = adapter.mouseDraggedReceived; + boolean mouseReleasedReceived = adapter.mouseReleasedReceived; + + if (component instanceof Choice) { + // Close the popup if it is still open + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.delay(25); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.waitForIdle(); + robot.delay(DELAY); + } + + + if (!mouseDraggedReceived || !mouseReleasedReceived) { + throw new RuntimeException(("%d: Mouse drag or release was not received\n" + + "mouseDraggedReceived %b mouseReleasedReceived %b") + .formatted(button, mouseDraggedReceived, mouseReleasedReceived)); + } + } + + /* + * returns the closest border point with a specified offset + */ + private static Point getEndPoint(Point start, Rectangle bounds, int offset) { + int left = bounds.x; + int right = bounds.x + bounds.width; + int top = bounds.y; + int bottom = bounds.y + bounds.height; + + int distanceLeft = start.x - left; + int distanceRight = right - start.x; + int distanceTop = start.y - top; + int distanceBottom = bottom - start.y; + + int minDistance = Math.min( + Math.min(distanceLeft, distanceRight), + Math.min(distanceTop, distanceBottom) + ); + + if (minDistance == distanceLeft) { + return new Point(left - offset, start.y); + } else if (minDistance == distanceRight) { + return new Point(right + offset, start.y); + } else if (minDistance == distanceTop) { + return new Point(start.x, top - offset); + } else { + return new Point(start.x, bottom + offset); + } + } + + private static class DragMouseEventFrame extends Frame { + TextArea textarea = new TextArea("TextArea", 20, 30); + Label label = new Label("Label"); + Panel panel = new Panel(); + List list = new List(); + Choice choice = new Choice(); + Button button = new Button("Button"); + TextField textfield = new TextField("TextField"); + Checkbox checkbox = new Checkbox("CheckBox"); + Scrollbar scrollbar = new Scrollbar(); + Panel centerPanel = new Panel(); + + public DragMouseEventFrame() { + setTitle("DragMouseEventTest"); + + add(centerPanel, BorderLayout.CENTER); + centerPanel.setLayout(new FlowLayout()); + + add(panel, BorderLayout.NORTH); + panel.setLayout(new FlowLayout()); + + choice.add("choice item 1"); + choice.add("choice item 2"); + choice.add("choice item 3"); + panel.add(choice); + + Adapter adapter = new Adapter(); + choice.addMouseMotionListener(adapter); + choice.addMouseListener(adapter); + choice.addItemListener(adapter); + + adapter = new Adapter(); + panel.add(label); + label.addMouseMotionListener(adapter); + label.addMouseListener(adapter); + + adapter = new Adapter(); + panel.add(button); + button.addMouseMotionListener(adapter); + button.addMouseListener(adapter); + button.addActionListener(adapter); + + adapter = new Adapter(); + panel.add(checkbox); + checkbox.addMouseMotionListener(adapter); + checkbox.addMouseListener(adapter); + checkbox.addItemListener(adapter); + + adapter = new Adapter(); + panel.add(textfield, BorderLayout.EAST); + textfield.addMouseMotionListener(adapter); + textfield.addMouseListener(adapter); + textfield.addActionListener(adapter); + + adapter = new Adapter(); + add(textarea, BorderLayout.EAST); + textarea.addMouseMotionListener(adapter); + textarea.addMouseListener(adapter); + + adapter = new Adapter(); + list.add("list item 1"); + list.add("list item 2"); + add(list, BorderLayout.SOUTH); + list.addMouseMotionListener(adapter); + list.addMouseListener(adapter); + list.addActionListener(adapter); + list.addItemListener(adapter); + + adapter = new Adapter(); + add(scrollbar, BorderLayout.WEST); + scrollbar.addMouseMotionListener(adapter); + scrollbar.addMouseListener(adapter); + + setSize(500, 400); + setLocationRelativeTo(null); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + DragMouseEventFrame.this.dispose(); + } + }); + } + } + + private static class Adapter extends MouseAdapter + implements ActionListener, ItemListener { + + public volatile boolean mouseDraggedReceived = false; + public volatile boolean mouseReleasedReceived = false; + public volatile boolean itemStateChangedReceived = false; + public volatile boolean actionPerformedReceived = false; + + + public void mouseDragged(MouseEvent me) { + mouseDraggedReceived = true; + System.out.println(me.paramString()); + } + + private void consumeIfNeeded(MouseEvent me) { + Component c = me.getComponent(); + // do not show popup menu for the following components, + // as it may interfere with the testing. + if (c instanceof TextArea + || c instanceof TextField + || c instanceof Scrollbar) { + if (me.isPopupTrigger()) { + System.out.println("CONSUMED: " + me); + me.consume(); + } + } + } + + public void mouseReleased(MouseEvent me) { + consumeIfNeeded(me); + mouseReleasedReceived = true; + System.out.println(me.paramString()); + } + + public void mousePressed(MouseEvent me) { + consumeIfNeeded(me); + System.out.println(me.paramString()); + } + + public void mouseClicked(MouseEvent me) { + System.out.println(me.paramString()); + } + + public void actionPerformed(ActionEvent e) { + actionPerformedReceived = true; + System.out.println(e.paramString()); + } + + public void itemStateChanged(ItemEvent e) { + itemStateChangedReceived = true; + System.out.println(e.paramString()); + } + + public void reset() { + mouseDraggedReceived = false; + mouseReleasedReceived = false; + itemStateChangedReceived = false; + actionPerformedReceived = false; + } + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java b/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java new file mode 100644 index 00000000000..4a4c9d36af1 --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/MouseEventsDuringDrag.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4017222 + * @summary Checks whether mouse events are reported correctly during drag. + * @author Stuart Lawrence, Brent Christian: area=event + * @key headful + * @library /lib/client /java/awt/regtesthelpers + * @build ExtendedRobot Util + * @run main MouseEventsDuringDrag + */ + + +/* + * MouseEventsDuringDrag.java + * + * summary: + * On Solaris drag enter/exit events are only reported for the + * component where drag started, they're not reported on other + * components. On Win32 enter/exit events are reported correctly. + */ + +import test.java.awt.regtesthelpers.Util; + +import java.awt.Canvas; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class MouseEventsDuringDrag { + + private static ExtendedRobot robot; + private static Frame frame; + + private static final MouseHandler mouseHandler = new MouseHandler(); + + static Label lab; + static Canvas c1, c2; + static Choice choice; + + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(MouseEventsDuringDrag::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + robot = new ExtendedRobot(); + robot.waitForIdle(); + robot.delay(500); + + // Part 1: Press and hold down the mouse button inside the red box. + // Drag the mouse over to the blue box (whilst still holding down + // the mouse button). + // Whilst dragging the mouse from the red box, enter and exit + // events should be reported for the blue box. + testcase(c2, "c1 to c2"); + + // Part 2: Again, press and hold down the mouse button inside the red box. + // This time drag the mouse over to the Choice menu. + // Enter and exit events should be reported for the Choice menu. + testcase(choice, "c1 to choice"); + } + + private static void testcase(Component moveTo, String message) throws Exception { + System.out.println("\ntestcase: " + message); + Rectangle c1bounds = getBounds(c1); + Rectangle moveToBound = getBounds(moveTo); + + Point startDragLocation = + new Point(c1bounds.x + c1bounds.width - 10, + c1bounds.y + c1bounds.height / 2); + + Point endDragLocation = + new Point(moveToBound.x + 10, moveToBound.y + moveToBound.height / 2); + + robot.mouseMove(startDragLocation); + robot.waitForIdle(); + robot.delay(200); + mouseHandler.reset(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + robot.glide(startDragLocation, endDragLocation); + robot.waitForIdle(); + + robot.glide(endDragLocation.x, endDragLocation.y, endDragLocation.x - 20, endDragLocation.y); + + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + robot.delay(200); + + List actual = mouseHandler.getRecordedEvents(); + + List expected = List.of( + new EventRecord(MouseEvent.MOUSE_PRESSED, c1), + new EventRecord(MouseEvent.MOUSE_EXITED, c1), + new EventRecord(MouseEvent.MOUSE_ENTERED, moveTo), + new EventRecord(MouseEvent.MOUSE_EXITED, moveTo), + new EventRecord(MouseEvent.MOUSE_RELEASED, c1) + ); + + System.out.println("Expected:\n" + expected); + System.out.println("Actual:\n" + actual); + if (!actual.equals(expected)) { + throw new RuntimeException("Mismatch between expected and actual events\n%s\n%s" + .formatted(expected, actual)); + } + } + + private static Rectangle getBounds(Component c) throws Exception { + return Util.invokeOnEDT(() -> { + Point locationOnScreen = c.getLocationOnScreen(); + Dimension size = c.getSize(); + return new Rectangle(locationOnScreen.x, locationOnScreen.y, size.width, size.height); + }); + } + + private static void createAndShowGUI() { + frame = new Frame(); + MouseHandler mouseHandler = new MouseHandler(); + frame.setLayout(new GridBagLayout()); + + int canvasSize = 100; + c1 = new Canvas(); + c1.setPreferredSize(new Dimension(canvasSize, canvasSize)); + c1.setBackground(Color.red); + c1.addMouseListener(mouseHandler); + + c2 = new Canvas(); + c2.setPreferredSize(new Dimension(canvasSize, canvasSize)); + c2.setBackground(Color.blue); + c2.addMouseListener(mouseHandler); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.insets = new Insets(5, 5, 5, 5); + + gbc.gridx = 0; + gbc.gridy = 0; + frame.add(c1, gbc); + + gbc.gridx = 2; + frame.add(c2, gbc); + + Panel p1 = new Panel(); + p1.setLayout(new FlowLayout()); + choice = new Choice(); + choice.addItem("Choice"); + choice.addItem("One"); + choice.addItem("Two"); + choice.addMouseListener(mouseHandler); + p1.add(choice); + + gbc.gridx = 1; + gbc.gridy = 1; + frame.add(p1, gbc); + + lab = new Label(); + + gbc.gridx = 0; + gbc.gridy = 2; + gbc.gridwidth = 3; + frame.add(lab, gbc); + + frame.pack(); + frame.setLocationRelativeTo(null); + + frame.setVisible(true); + } + + record EventRecord(int eventId, Component component) { + + @Override + public String toString() { + StringBuilder str = new StringBuilder(80); + switch(eventId) { + case MouseEvent.MOUSE_PRESSED: + str.append("MOUSE_PRESSED"); + break; + case MouseEvent.MOUSE_RELEASED: + str.append("MOUSE_RELEASED"); + break; + case MouseEvent.MOUSE_CLICKED: + str.append("MOUSE_CLICKED"); + break; + case MouseEvent.MOUSE_ENTERED: + str.append("MOUSE_ENTERED"); + break; + case MouseEvent.MOUSE_EXITED: + str.append("MOUSE_EXITED"); + break; + case MouseEvent.MOUSE_MOVED: + str.append("MOUSE_MOVED"); + break; + case MouseEvent.MOUSE_DRAGGED: + str.append("MOUSE_DRAGGED"); + break; + case MouseEvent.MOUSE_WHEEL: + str.append("MOUSE_WHEEL"); + break; + default: + str.append("unknown type"); + } + return str.append(" ").append(component).toString(); + } + } + + static class MouseHandler extends MouseAdapter { + static final List list = new CopyOnWriteArrayList<>(); + + public void mousePressed(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse pressed in red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse pressed in blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse pressed in choice"); + } + } + + public void mouseReleased(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + lab.setText("Mouse released"); + } + + public void mouseEntered(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse entered red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse entered blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse entered choice"); + } + } + + public void mouseExited(MouseEvent e) { + list.add(new EventRecord(e.getID(), e.getComponent())); + if (e.getSource() == c1) { + lab.setText("Mouse exited red box"); + } else if (e.getSource() == c2) { + lab.setText("Mouse exited blue box"); + } else if (e.getSource() == choice) { + lab.setText("Mouse exited choice"); + } + } + + public void reset() { + list.clear(); + } + + public List getRecordedEvents() { + return new ArrayList<>(list); + } + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java b/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java new file mode 100644 index 00000000000..5b8f0f62f7b --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/MouseModifierTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4117523 + * @summary Solaris: MousePressed event has modifier=0 when left button is pressed + * @key headful + * @library /javax/swing/regtesthelpers /test/lib + * @build Util jdk.test.lib.Platform + * @run main MouseModifierTest +*/ + + +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import jdk.test.lib.Platform; + +public class MouseModifierTest { + private static Frame frame; + private static volatile MouseEvent lastMousePressedEvent = null; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(MouseModifierTest::createAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + Point centerPoint = Util.getCenterPoint(frame); + + System.out.println("MOUSE1 press case"); + + robot.mouseMove(centerPoint.x, centerPoint.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(300); + + if (lastMousePressedEvent == null + || lastMousePressedEvent.getModifiers() != InputEvent.BUTTON1_MASK) { + throw new RuntimeException("Test failed"); + } + + if (Platform.isWindows()) { + System.out.println("Windows: Testing ALT + MOUSE1 press case"); + lastMousePressedEvent = null; + robot.waitForIdle(); + robot.delay(300); + + robot.keyPress(KeyEvent.VK_ALT); + robot.delay(25); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(25); + robot.keyRelease(KeyEvent.VK_ALT); + robot.delay(25); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(300); + + int expectedModifiers = InputEvent.BUTTON1_MASK + | InputEvent.BUTTON2_MASK + | InputEvent.ALT_MASK; + if (lastMousePressedEvent == null + || lastMousePressedEvent.getModifiers() != expectedModifiers) { + throw new RuntimeException("Test failed"); + } + } + } + + private static void createAndShowGUI() { + frame = new Frame("MouseModifierTest"); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.addMouseListener(new MouseHandler()); + frame.setVisible(true); + } + + private static class MouseHandler extends MouseAdapter { + public void mouseClicked(MouseEvent e) { + System.out.println("\nmouseClicked:"); + printMouseEventDetail(e); + } + + public void mousePressed(MouseEvent e) { + lastMousePressedEvent = e; + System.out.println("\nmousePressed:"); + printMouseEventDetail(e); + } + + public void mouseReleased(MouseEvent e) { + System.out.println("\nmouseReleased:"); + printMouseEventDetail(e); + } + + public void mouseEntered(MouseEvent e) { + System.out.println("\nmouseEntered:"); + printMouseEventDetail(e); + } + + public void mouseExited(MouseEvent e) { + System.out.println("\nmouseExited:"); + printMouseEventDetail(e); + } + + private void printMouseEventDetail(MouseEvent e) { + System.out.println(e.toString()); + System.out.println("Modifiers: "); + printModifiers(e); + } + + private void printModifiers(MouseEvent e) { + if (e == null) { + return; + } + + int mod = e.getModifiers(); + + if ((mod & InputEvent.ALT_MASK) != 0) { + System.out.println("\tALT_MASK"); + } + if ((mod & InputEvent.BUTTON1_MASK) != 0) { + System.out.println("\tBUTTON1_MASK"); + } + if ((mod & InputEvent.BUTTON2_MASK) != 0) { + System.out.println("\tBUTTON2_MASK"); + } + if ((mod & InputEvent.BUTTON3_MASK) != 0) { + System.out.println("\tBUTTON3_MASK"); + } + if ((mod & InputEvent.CTRL_MASK) != 0) { + System.out.println("\tCTRL_MASK"); + } + if ((mod & InputEvent.META_MASK) != 0) { + System.out.println("\tMETA_MASK"); + } + if ((mod & InputEvent.SHIFT_MASK) != 0) { + System.out.println("\tSHIFT_MASK"); + } + } + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java b/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java new file mode 100644 index 00000000000..e5cb1195bae --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/MouseRButTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4037521 + * @summary Mouse Right button does not send mouseClick action + * @key headful + * @library /javax/swing/regtesthelpers + * @build Util + * @run main MouseRButTest + */ + +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class MouseRButTest { + private static Frame frame; + private static Button button; + private static final CountDownLatch latch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(MouseRButTest::createAndShowGUI); + + robot.waitForIdle(); + robot.delay(500); + + Point point = Util.getCenterPoint(button); + robot.mouseMove(point.x, point.y); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + + if (!latch.await(2, TimeUnit.SECONDS)) { + throw new RuntimeException("mouse click action was not sent"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowGUI() { + button = new Button("Click Me"); + button.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + System.out.println(e); + if (e.getModifiers() == e.BUTTON3_MASK) { + System.out.println("right mouse button clicked"); + latch.countDown(); + } + } + }); + + frame = new Frame(); + frame.setLayout(new FlowLayout()); + frame.add(button); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java b/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java new file mode 100644 index 00000000000..35f071a9e6d --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/TitleBarGetsMousePressed.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Frame; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 4074498 + * @summary Test: MOUSE_PRESSED events in the title bar of a frame + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TitleBarGetsMousePressed + */ +public class TitleBarGetsMousePressed { + private static final String INSTRUCTIONS = """ + 1. You will see a Frame window next to this window with instructions + 2. Clicking in the title bar of the Frame and even moving around the Frame + should not generate MOUSE_PRESSED / MOUSE_RELEASED / MOUSE_CLICKED events. + (printed below in the log area). + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("TitleBarGetsMousePressed Instructions") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TitleBarGetsMousePressed::createTestUI) + .logArea(5) + .build() + .awaitAndCheck(); + } + + private static Window createTestUI() { + Frame frame = new Frame("TitleBarGetsMousePressed"); + frame.setSize(300, 200); + frame.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent ev) { + PassFailJFrame.log("mouseClicked at x:" + ev.getX() + + " y:" + ev.getY()); + } + + public void mousePressed(MouseEvent ev) { + PassFailJFrame.log("mousePressed at x:" + ev.getX() + + " y:" + ev.getY()); + } + + public void mouseReleased(MouseEvent ev) { + PassFailJFrame.log("mouseReleased at x:" + ev.getX() + + " y:" + ev.getY()); + } + }); + + return frame; + } +} From 776e1cf1dfefd7cb1a0190ab71f71ad5ff25d0e4 Mon Sep 17 00:00:00 2001 From: Dean Long Date: Wed, 9 Apr 2025 20:06:49 +0000 Subject: [PATCH 095/843] 8353041: NeverBranchNode causes incorrect block frequency calculation Reviewed-by: thartmann, rcastanedalo --- src/hotspot/share/opto/domgraph.cpp | 14 +++++++++++++- src/hotspot/share/opto/gcm.cpp | 7 ++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/domgraph.cpp b/src/hotspot/share/opto/domgraph.cpp index a80358e1d0f..b52f4232c4e 100644 --- a/src/hotspot/share/opto/domgraph.cpp +++ b/src/hotspot/share/opto/domgraph.cpp @@ -233,9 +233,21 @@ uint Block_Stack::most_frequent_successor( Block *b ) { case Op_Jump: case Op_Root: case Op_Goto: - case Op_NeverBranch: freq_idx = 0; // fall thru break; + case Op_NeverBranch: { + Node* succ = n->as_NeverBranch()->proj_out(0)->unique_ctrl_out(); + int succ_idx = 0; // normal case + if (succ == b->_succs[1]->head()) { + // Edges swapped, rare case. May happen due to an unusual matcher + // traversal order for peeled infinite loops. + succ_idx = 1; + } else { + assert(succ == b->_succs[0]->head(), "succ not found"); + } + freq_idx = succ_idx; + break; + } case Op_TailCall: case Op_TailJump: case Op_ForwardException: diff --git a/src/hotspot/share/opto/gcm.cpp b/src/hotspot/share/opto/gcm.cpp index eeab96de3fa..a8080d5adb9 100644 --- a/src/hotspot/share/opto/gcm.cpp +++ b/src/hotspot/share/opto/gcm.cpp @@ -2160,8 +2160,13 @@ float Block::succ_prob(uint i) { // Pass frequency straight thru to target return 1.0f; - case Op_NeverBranch: + case Op_NeverBranch: { + Node* succ = n->as_NeverBranch()->proj_out(0)->unique_ctrl_out(); + if (_succs[i]->head() == succ) { + return 1.0f; + } return 0.0f; + } case Op_TailCall: case Op_TailJump: From 4a242e3a65f13c41c699d42b100ba2b252d7faaa Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Wed, 9 Apr 2025 20:14:10 +0000 Subject: [PATCH 096/843] 8354213: Restore pointless unicode characters to ASCII Reviewed-by: naoto, erikj, iris --- CONTRIBUTING.md | 2 +- doc/hotspot-unit-tests.md | 14 +++++++------- src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp | 2 +- .../gc/shared/barrierSetAssembler_riscv.cpp | 2 +- src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 6 +++--- src/hotspot/cpu/s390/disassembler_s390.cpp | 4 ++-- src/hotspot/cpu/s390/s390.ad | 2 +- src/hotspot/os/aix/libperfstat_aix.hpp | 2 +- .../linux_aarch64/atomic_linux_aarch64.S | 2 +- .../os_cpu/linux_aarch64/copy_linux_aarch64.S | 2 +- .../linux_aarch64/safefetch_linux_aarch64.S | 2 +- .../linux_aarch64/threadLS_linux_aarch64.S | 2 +- .../linux_riscv/orderAccess_linux_riscv.hpp | 4 ++-- src/hotspot/share/cds/archiveUtils.hpp | 2 +- src/hotspot/share/oops/method.cpp | 2 +- test/hotspot/gtest/gc/g1/test_g1CardSet.cpp | 2 +- test/hotspot/gtest/runtime/test_os_windows.cpp | 4 ++-- .../gcbarriers/TestZGCBarrierElision.java | 18 +++++++++--------- .../compiler/lib/generators/Generators.java | 2 +- .../JniArmHFTestGenerator.java.txt | 8 ++++---- .../java/awt/image/DrawImage/TiledImage.java | 2 +- test/jdk/jdk/jfr/tool/jfr.xsd | 4 ++-- 22 files changed, 45 insertions(+), 45 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a338235c1d..98ede25b88d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ # Contributing to the JDK -Please see the [OpenJDK Developers’ Guide](https://openjdk.org/guide/). +Please see the [OpenJDK Developers' Guide](https://openjdk.org/guide/). diff --git a/doc/hotspot-unit-tests.md b/doc/hotspot-unit-tests.md index e1222baa2e3..69a95307109 100644 --- a/doc/hotspot-unit-tests.md +++ b/doc/hotspot-unit-tests.md @@ -106,7 +106,7 @@ Prefer having checks inside test code. Not only does having test logic outside, e.g. verification method, depending on asserts in product code contradict with several items -above but also decreases test’s readability and stability. It is much +above but also decreases test's readability and stability. It is much easier to understand that a test is testing when all testing logic is located inside a test or nearby in shared test libraries. As a rule of thumb, the closer a check to a test, the better. @@ -119,7 +119,7 @@ Prefer `EXPECT` over `ASSERT` if possible. This is related to the [informativeness](#informativeness) property of tests, information for other checks can help to better localize a -defect’s root-cause. One should use `ASSERT` if it is impossible to +defect's root-cause. One should use `ASSERT` if it is impossible to continue test execution or if it does not make much sense. Later in the text, `EXPECT` forms will be used to refer to both `ASSERT/EXPECT`. @@ -160,7 +160,7 @@ value of the difference between `v1` and `v2` is not greater than `eps`. Use string special macros for C strings comparisons. -`EXPECT_EQ` just compares pointers’ values, which is hardly what one +`EXPECT_EQ` just compares pointers' values, which is hardly what one wants comparing C strings. GoogleTest provides `EXPECT_STREQ` and `EXPECT_STRNE` macros to compare C string contents. There are also case-insensitive versions `EXPECT_STRCASEEQ`, `EXPECT_STRCASENE`. @@ -226,7 +226,7 @@ subsystem, etc. This naming scheme helps to find tests, filter them and simplifies test failure analysis. For example, class `Foo` - test group `Foo`, -compiler logging subsystem - test group `CompilerLogging`, G1 GC — test +compiler logging subsystem - test group `CompilerLogging`, G1 GC - test group `G1GC`, and so forth. ### Filename @@ -287,7 +287,7 @@ Fixture classes should be named after tested classes, subsystems, etc All test purpose friends should have either `Test` or `Testable` suffix. -It greatly simplifies understanding of friendship’s purpose and allows +It greatly simplifies understanding of friendship's purpose and allows statically check that private members are not exposed unexpectedly. Having `FooTest` as a friend of `Foo` without any comments will be understood as a necessary evil to get testability. @@ -397,7 +397,7 @@ and filter out inapplicable tests. Restore changed flags. It is quite common for tests to configure JVM in a certain way -changing flags’ values. GoogleTest provides two ways to set up +changing flags' values. GoogleTest provides two ways to set up environment before a test and restore it afterward: using either constructor and destructor or `SetUp` and `TearDown` functions. Both ways require to use a test fixture class, which sometimes is too wordy. The @@ -406,7 +406,7 @@ be used in such cases to restore/set values. Caveats: -* Changing a flag’s value could break the invariants between flags' values and hence could lead to unexpected/unsupported JVM state. +* Changing a flag's value could break the invariants between flags' values and hence could lead to unexpected/unsupported JVM state. * `FLAG_SET_*` macros can change more than one flag (in order to maintain invariants) so it is hard to predict what flags will be diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp index b9bd7b356fa..d55521823ec 100644 --- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp @@ -87,7 +87,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { __ mv(t1, _array->as_pointer_register()); stub_id = C1StubId::throw_range_check_failed_id; } - // t0 and t1 are used as args in generate_exception_throw, + // t0 and t1 are used as args in generate_exception_throw, // so use x1/ra as the tmp register for rt_call. __ rt_call(Runtime1::entry_for(stub_id), ra); ce->add_call_info_here(_info); diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp index d66a86c750a..5b3c926cfa9 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp @@ -275,7 +275,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo // order, while allowing other independent instructions to be reordered. // Note: This may be slower than using a membar(load|load) (fence r,r). // Because processors will not start the second load until the first comes back. - // This means you can’t overlap the two loads, + // This means you can't overlap the two loads, // which is stronger than needed for ordering (stronger than TSO). __ srli(ra, t0, 32); __ orr(t1, t1, ra); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 153b6d77f99..e145639bbe7 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -670,9 +670,9 @@ class MacroAssembler: public Assembler { // JALR, return address stack updates: // | rd is x1/x5 | rs1 is x1/x5 | rd=rs1 | RAS action // | ----------- | ------------ | ------ |------------- - // | No | No | — | None - // | No | Yes | — | Pop - // | Yes | No | — | Push + // | No | No | - | None + // | No | Yes | - | Pop + // | Yes | No | - | Push // | Yes | Yes | No | Pop, then push // | Yes | Yes | Yes | Push // diff --git a/src/hotspot/cpu/s390/disassembler_s390.cpp b/src/hotspot/cpu/s390/disassembler_s390.cpp index 98cff15f2ae..a69851cfdba 100644 --- a/src/hotspot/cpu/s390/disassembler_s390.cpp +++ b/src/hotspot/cpu/s390/disassembler_s390.cpp @@ -62,7 +62,7 @@ address Disassembler::decode_instruction0(address here, outputStream * st, addre if (Assembler::is_z_nop((long)instruction_2bytes)) { #if 1 - st->print("nop "); // fill up to operand column, leads to better code comment alignment + st->print("nop "); // fill up to operand column, leads to better code comment alignment next = here + 2; #else // Compact disassembler output. Does not work the easy way. @@ -76,7 +76,7 @@ address Disassembler::decode_instruction0(address here, outputStream * st, addre instruction_2bytes = *(uint16_t*)(here+2*n_nops); } if (n_nops <= 4) { // do not group few subsequent nops - st->print("nop "); // fill up to operand column, leads to better code comment alignment + st->print("nop "); // fill up to operand column, leads to better code comment alignment next = here + 2; } else { st->print("nop count=%d", n_nops); diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index fc7de7e70e9..ea1bdb9e231 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -6581,7 +6581,7 @@ instruct mulHiL_reg_reg(revenRegL Rdst, roddRegL Rsrc1, iRegL Rsrc2, iRegL Rtmp1 Register tmp1 = $Rtmp1$$Register; Register tmp2 = $Rdst$$Register; // z/Architecture has only unsigned multiply (64 * 64 -> 128). - // implementing mulhs(a,b) = mulhu(a,b) – (a & (b>>63)) – (b & (a>>63)) + // implementing mulhs(a,b) = mulhu(a,b) - (a & (b>>63)) - (b & (a>>63)) __ z_srag(tmp2, src1, 63); // a>>63 __ z_srag(tmp1, src2, 63); // b>>63 __ z_ngr(tmp2, src2); // b & (a>>63) diff --git a/src/hotspot/os/aix/libperfstat_aix.hpp b/src/hotspot/os/aix/libperfstat_aix.hpp index f35f517b489..a984440e579 100644 --- a/src/hotspot/os/aix/libperfstat_aix.hpp +++ b/src/hotspot/os/aix/libperfstat_aix.hpp @@ -332,7 +332,7 @@ typedef struct { /* component perfstat_cpu_t from AIX 7.2 documentation */ u_longlong_t busy_stolen_purr; /* Number of busy cycles stolen by the hypervisor from a dedicated partition. */ u_longlong_t busy_stolen_spurr; /* Number of busy spurr cycles stolen by the hypervisor from a dedicated partition.*/ u_longlong_t shcpus_in_sys; /* Number of physical processors allocated for shared processor use, across all shared processors pools. */ - u_longlong_t entitled_pool_capacity; /* Entitled processor capacity of partition’s pool. */ + u_longlong_t entitled_pool_capacity; /* Entitled processor capacity of partition's pool. */ u_longlong_t pool_max_time; /* Summation of maximum time that can be consumed by the pool (nanoseconds). */ u_longlong_t pool_busy_time; /* Summation of busy (nonidle) time accumulated across all partitions in the pool (nanoseconds). */ u_longlong_t pool_scaled_busy_time; /* Scaled summation of busy (nonidle) time accumulated across all partitions in the pool (nanoseconds). */ diff --git a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S index b3e7f643979..9ae19fa0cd9 100644 --- a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S +++ b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S @@ -295,7 +295,7 @@ DECLARE_FUNC(aarch64_atomic_cmpxchg_8_relaxed_default_impl): ret /* Emit .note.gnu.property section in case of PAC or BTI being enabled. - * For more details see "ELF for the Arm® 64-bit Architecture (AArch64)". + * For more details see "ELF for the Arm(R) 64-bit Architecture (AArch64)". * https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst */ #ifdef __ARM_FEATURE_BTI_DEFAULT diff --git a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S index 33fe81d9206..8abf9f49057 100644 --- a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S +++ b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.S @@ -269,7 +269,7 @@ bwd_copy_drain: ret /* Emit .note.gnu.property section in case of PAC or BTI being enabled. - * For more details see "ELF for the Arm® 64-bit Architecture (AArch64)". + * For more details see "ELF for the Arm(R) 64-bit Architecture (AArch64)". * https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst */ #ifdef __ARM_FEATURE_BTI_DEFAULT diff --git a/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S index a26aab44ac4..ffffb7550bf 100644 --- a/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S +++ b/src/hotspot/os_cpu/linux_aarch64/safefetch_linux_aarch64.S @@ -50,7 +50,7 @@ DECLARE_FUNC(_SafeFetchN_continuation): ret /* Emit .note.gnu.property section in case of PAC or BTI being enabled. - * For more details see "ELF for the Arm® 64-bit Architecture (AArch64)". + * For more details see "ELF for the Arm(R) 64-bit Architecture (AArch64)". * https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst */ #ifdef __ARM_FEATURE_BTI_DEFAULT diff --git a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S index 55a252301d7..451c13773be 100644 --- a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S +++ b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S @@ -46,7 +46,7 @@ DECLARE_FUNC(_ZN10JavaThread25aarch64_get_thread_helperEv): .size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv /* Emit .note.gnu.property section in case of PAC or BTI being enabled. - * For more details see "ELF for the Arm® 64-bit Architecture (AArch64)". + * For more details see "ELF for the Arm(R) 64-bit Architecture (AArch64)". * https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst */ #ifdef __ARM_FEATURE_BTI_DEFAULT diff --git a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp index f46380aaac6..828a603577d 100644 --- a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp +++ b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp @@ -54,13 +54,13 @@ inline void OrderAccess::fence() { } inline void OrderAccess::cross_modify_fence_impl() { - // From 3 “Zifencei” Instruction-Fetch Fence, Version 2.0 + // From 3 "Zifencei" Instruction-Fetch Fence, Version 2.0 // "RISC-V does not guarantee that stores to instruction memory will be made // visible to instruction fetches on a RISC-V hart until that hart executes a // FENCE.I instruction. A FENCE.I instruction ensures that a subsequent // instruction fetch on a RISC-V hart will see any previous data stores // already visible to the same RISC-V hart. FENCE.I does not ensure that other - // RISC-V harts’ instruction fetches will observe the local hart’s stores in a + // RISC-V harts' instruction fetches will observe the local hart's stores in a // multiprocessor system." // // Hence to be able to use fence.i directly we need a kernel that supports diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 59146547aca..56d28ec910c 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -106,7 +106,7 @@ public: // within the archive (e.g., InstanceKlass::_name points to a Symbol in the archive). During dumping, we // built a bitmap that marks the locations of all these pointers (using ArchivePtrMarker, see comments above). // -// The contents of the archive assumes that it’s mapped at the default SharedBaseAddress (e.g. 0x800000000). +// The contents of the archive assumes that it's mapped at the default SharedBaseAddress (e.g. 0x800000000). // If the archive ends up being mapped at a different address (e.g. 0x810000000), SharedDataRelocator // is used to shift each marked pointer by a delta (0x10000000 in this example), so that it points to // the actually mapped location of the target object. diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 012420aaf50..0c4430b44c3 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -433,7 +433,7 @@ void Method::set_itable_index(int index) { // itable index should be the same as the runtime index. assert(_vtable_index == itable_index_max - index, "archived itable index is different from runtime index"); - return; // don’t write into the shared class + return; // don't write into the shared class } else { _vtable_index = itable_index_max - index; } diff --git a/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp b/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp index 1e4e478db79..958561dc15e 100644 --- a/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1CardSet.cpp @@ -70,7 +70,7 @@ public: ~G1CardSetTest() { } static uint next_random(uint& seed, uint i) { - // Park–Miller random number generator + // Park-Miller random number generator seed = (seed * 279470273u) % 0xfffffffb; return (seed % i); } diff --git a/test/hotspot/gtest/runtime/test_os_windows.cpp b/test/hotspot/gtest/runtime/test_os_windows.cpp index d539f20cbeb..83771368b57 100644 --- a/test/hotspot/gtest/runtime/test_os_windows.cpp +++ b/test/hotspot/gtest/runtime/test_os_windows.cpp @@ -82,7 +82,7 @@ void TestReserveMemorySpecial_test() { // 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); - EXPECT_TRUE(actual_location != nullptr) << "Unexpected reservation failure, can’t verify correct location"; + 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() { 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); - EXPECT_TRUE(aligned_request != nullptr) << "Unexpected reservation failure, can’t verify correct alignment"; + 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/jtreg/compiler/gcbarriers/TestZGCBarrierElision.java b/test/hotspot/jtreg/compiler/gcbarriers/TestZGCBarrierElision.java index d8bec5e4368..4c94cd62c42 100644 --- a/test/hotspot/jtreg/compiler/gcbarriers/TestZGCBarrierElision.java +++ b/test/hotspot/jtreg/compiler/gcbarriers/TestZGCBarrierElision.java @@ -191,7 +191,7 @@ class TestZGCCorrectBarrierElision { static void testAllocateThenAtomic(Inner i) { Outer o = new Outer(); Common.blackhole(o); - Common.field1VarHandle.getAndSet​(o, i); + Common.field1VarHandle.getAndSet(o, i); } @Test @@ -199,14 +199,14 @@ class TestZGCCorrectBarrierElision { @IR(counts = { IRNode.Z_GET_AND_SET_P_WITH_BARRIER_FLAG, Common.REMAINING, "1" }, phase = CompilePhase.FINAL_CODE) static void testLoadThenAtomic(Outer o, Inner i) { Common.blackhole(o.field1); - Common.field1VarHandle.getAndSet​(o, i); + Common.field1VarHandle.getAndSet(o, i); } @Test @IR(counts = { IRNode.Z_GET_AND_SET_P_WITH_BARRIER_FLAG, Common.REMAINING, "2" }, phase = CompilePhase.FINAL_CODE) static void testAtomicThenAtomicAnotherField(Outer o, Inner i) { - Common.field1VarHandle.getAndSet​(o, i); - Common.field2VarHandle.getAndSet​(o, i); + Common.field1VarHandle.getAndSet(o, i); + Common.field2VarHandle.getAndSet(o, i); } @Test @@ -390,14 +390,14 @@ class TestZGCEffectiveBarrierElision { @IR(counts = { IRNode.Z_GET_AND_SET_P_WITH_BARRIER_FLAG, Common.ELIDED, "1" }, phase = CompilePhase.FINAL_CODE) static void testStoreThenAtomic(Outer o, Inner i) { o.field1 = i; - Common.field1VarHandle.getAndSet​(o, i); + Common.field1VarHandle.getAndSet(o, i); } @Test @IR(counts = { IRNode.Z_GET_AND_SET_P_WITH_BARRIER_FLAG, Common.REMAINING, "1" }, phase = CompilePhase.FINAL_CODE) @IR(counts = { IRNode.Z_LOAD_P_WITH_BARRIER_FLAG, Common.ELIDED, "1" }, phase = CompilePhase.FINAL_CODE) static void testAtomicThenLoad(Outer o, Inner i) { - Common.field1VarHandle.getAndSet​(o, i); + Common.field1VarHandle.getAndSet(o, i); Common.blackhole(o.field1); } @@ -405,7 +405,7 @@ class TestZGCEffectiveBarrierElision { @IR(counts = { IRNode.Z_GET_AND_SET_P_WITH_BARRIER_FLAG, Common.REMAINING, "1" }, phase = CompilePhase.FINAL_CODE) @IR(counts = { IRNode.Z_STORE_P_WITH_BARRIER_FLAG, Common.ELIDED, "1" }, phase = CompilePhase.FINAL_CODE) static void testAtomicThenStore(Outer o, Inner i) { - Common.field1VarHandle.getAndSet​(o, i); + Common.field1VarHandle.getAndSet(o, i); o.field1 = i; } @@ -413,8 +413,8 @@ class TestZGCEffectiveBarrierElision { @IR(counts = { IRNode.Z_GET_AND_SET_P_WITH_BARRIER_FLAG, Common.REMAINING, "1" }, phase = CompilePhase.FINAL_CODE) @IR(counts = { IRNode.Z_GET_AND_SET_P_WITH_BARRIER_FLAG, Common.ELIDED, "1" }, phase = CompilePhase.FINAL_CODE) static void testAtomicThenAtomic(Outer o, Inner i) { - Common.field1VarHandle.getAndSet​(o, i); - Common.field1VarHandle.getAndSet​(o, i); + Common.field1VarHandle.getAndSet(o, i); + Common.field1VarHandle.getAndSet(o, i); } @Test diff --git a/test/hotspot/jtreg/compiler/lib/generators/Generators.java b/test/hotspot/jtreg/compiler/lib/generators/Generators.java index 16f1b6be9b1..231b9822990 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/Generators.java +++ b/test/hotspot/jtreg/compiler/lib/generators/Generators.java @@ -100,7 +100,7 @@ import jdk.test.lib.Utils; *

* Unless you have reasons to pick a specific distribution, you are encouraged to rely on {@link #ints()}, * {@link #longs()}, {@link #doubles()} and {@link #floats()}, which will randomly pick an interesting distribution. - * This is best practice, because that allows the test to be run under different conditions – maybe only a single + * This is best practice, because that allows the test to be run under different conditions - maybe only a single * distribution can trigger a bug. */ public final class Generators { diff --git a/test/hotspot/jtreg/vmTestbase/vm/jit/LongTransitions/JniArmHFTestGenerator.java.txt b/test/hotspot/jtreg/vmTestbase/vm/jit/LongTransitions/JniArmHFTestGenerator.java.txt index 9bd6f0b9308..91d5129f1eb 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/jit/LongTransitions/JniArmHFTestGenerator.java.txt +++ b/test/hotspot/jtreg/vmTestbase/vm/jit/LongTransitions/JniArmHFTestGenerator.java.txt @@ -435,7 +435,7 @@ enum NumberType { this.rndFnc = rndFnc; } - public String getСType() { + public String getCType() { return cType; } @@ -443,7 +443,7 @@ enum NumberType { return jType; } - public String getСConv() { + public String getCConv() { return cConv; } @@ -792,9 +792,9 @@ class ParameterListGenerator { String randomVal = list.get(type).getFnc(); - String ctype = list.get(type).getСType(); + String ctype = list.get(type).getCType(); String jtype = list.get(type).getJType(); - String cconv = list.get(type).getСConv(); + String cconv = list.get(type).getCConv(); String jconv = list.get(type).getJConv(); String varName = "p" + cnt; diff --git a/test/jdk/java/awt/image/DrawImage/TiledImage.java b/test/jdk/java/awt/image/DrawImage/TiledImage.java index 8faca3aec6a..bd64edc37fd 100644 --- a/test/jdk/java/awt/image/DrawImage/TiledImage.java +++ b/test/jdk/java/awt/image/DrawImage/TiledImage.java @@ -91,7 +91,7 @@ import java.util.Vector; * This bug is largely unnoticed because most {@code Raster.create} * methods actually create {@link WritableRaster} instances, even * when the user did not asked for writable raster. To make this - * bug apparent, we need to invoke {@code Raster.createRaster(…)} + * bug apparent, we need to invoke {@code Raster.createRaster(...)} * with a sample model for which no optimization is provided. */ public class TiledImage implements RenderedImage { diff --git a/test/jdk/jdk/jfr/tool/jfr.xsd b/test/jdk/jdk/jfr/tool/jfr.xsd index adf44493f86..8a8382a540a 100644 --- a/test/jdk/jdk/jfr/tool/jfr.xsd +++ b/test/jdk/jdk/jfr/tool/jfr.xsd @@ -1,4 +1,4 @@ - + @@ -78,4 +78,4 @@ - \ No newline at end of file + From 4954a336f88865a4c9b269ed2c152658275e9221 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Wed, 9 Apr 2025 20:20:15 +0000 Subject: [PATCH 097/843] 8350563: C2 compilation fails because PhaseCCP does not reach a fixpoint Co-authored-by: Matthias Ernst Reviewed-by: chagedorn, epeter --- src/hotspot/share/opto/mulnode.cpp | 7 ++- src/hotspot/share/opto/phaseX.cpp | 17 ++++-- .../jtreg/compiler/ccp/TestAndConZeroCCP.java | 59 +++++++++++++++++++ 3 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/ccp/TestAndConZeroCCP.java diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 3dbff5ca7bc..1d046583ee0 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -2201,12 +2201,17 @@ const Type* RotateRightNode::Value(PhaseGVN* phase) const { // Returns a lower bound on the number of trailing zeros in expr. static jint AndIL_min_trailing_zeros(const PhaseGVN* phase, const Node* expr, BasicType bt) { - expr = expr->uncast(); const TypeInteger* type = phase->type(expr)->isa_integer(bt); if (type == nullptr) { return 0; } + expr = expr->uncast(); + type = phase->type(expr)->isa_integer(bt); + if (type == nullptr) { + return 0; + } + if (type->is_con()) { jlong con = type->get_con_as_long(bt); return con == 0L ? (type2aelembytes(bt) * BitsPerByte) : count_trailing_zeros(con); diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index ad6d8b4112f..ae6e49e2c4e 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1993,14 +1993,19 @@ void PhaseCCP::push_load_barrier(Unique_Node_List& worklist, const BarrierSetC2* } } -// AndI/L::Value() optimizes patterns similar to (v << 2) & 3 to zero if they are bitwise disjoint. -// Add the AndI/L nodes back to the worklist to re-apply Value() in case the shift value changed. -// Pattern: parent -> LShift (use) -> (ConstraintCast | ConvI2L)* -> And +// AndI/L::Value() optimizes patterns similar to (v << 2) & 3, or CON & 3 to zero if they are bitwise disjoint. +// Add the AndI/L nodes back to the worklist to re-apply Value() in case the value is now a constant or shift +// value changed. void PhaseCCP::push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const { + const TypeInteger* parent_type = type(parent)->isa_integer(type(parent)->basic_type()); uint use_op = use->Opcode(); - if ((use_op == Op_LShiftI || use_op == Op_LShiftL) - && use->in(2) == parent) { // is shift value (right-hand side of LShift) - auto push_and_uses_to_worklist = [&](Node* n){ + if ( + // Pattern: parent (now constant) -> (ConstraintCast | ConvI2L)* -> And + (parent_type != nullptr && parent_type->is_con()) || + // Pattern: parent -> LShift (use) -> (ConstraintCast | ConvI2L)* -> And + ((use_op == Op_LShiftI || use_op == Op_LShiftL) && use->in(2) == parent)) { + + auto push_and_uses_to_worklist = [&](Node* n) { uint opc = n->Opcode(); if (opc == Op_AndI || opc == Op_AndL) { push_if_not_bottom_type(worklist, n); diff --git a/test/hotspot/jtreg/compiler/ccp/TestAndConZeroCCP.java b/test/hotspot/jtreg/compiler/ccp/TestAndConZeroCCP.java new file mode 100644 index 00000000000..4304db5489c --- /dev/null +++ b/test/hotspot/jtreg/compiler/ccp/TestAndConZeroCCP.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025, Google LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8350563 + * @summary Test that And nodes are monotonic and added to the CCP worklist if they have a constant as input. + * @run main/othervm -Xbatch -XX:-TieredCompilation compiler.ccp.TestAndConZeroCCP + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:RepeatCompilation=300 -XX:+StressIGVN -XX:+StressCCP -Xcomp + * -XX:CompileOnly=java.lang.Integer::parseInt compiler.ccp.TestAndConZeroCCP compileonly + * @run main compiler.ccp.TestAndConZeroCCP + */ +package compiler.ccp; + +import java.util.Arrays; + +public class TestAndConZeroCCP { + + public static void main(String[] args) { + Integer.parseInt("1"); + if (args.length != 0) { + return; + } + + for (int i = 0; i < 10000; ++i) { + run(); + } + } + + private static void run() { + for (int cp = 0; cp <= 1 << 16; cp++) { + Arrays.binarySearch(array, cp); + Character.getType(cp); + Character.isAlphabetic(cp); + } + } + + private static final int[] array = new int[3]; +} From e3f26b056e6b8403e6744b8a4cf59ccf4d217d89 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 9 Apr 2025 20:57:15 +0000 Subject: [PATCH 098/843] 8351319: AOT cache support for custom class loaders broken since JDK-8348426 Reviewed-by: ccheung, matsaave, jrose --- src/hotspot/share/cds/aotArtifactFinder.cpp | 11 ++- .../share/cds/dumpTimeClassInfo.inline.hpp | 8 ++- src/hotspot/share/cds/finalImageRecipes.cpp | 6 +- .../classfile/systemDictionaryShared.cpp | 17 ++++- .../classfile/systemDictionaryShared.hpp | 1 + src/hotspot/share/oops/constantPool.cpp | 16 ++++- src/hotspot/share/oops/klass.cpp | 12 +++- .../aotClassLinking/BulkLoaderTest.java | 71 ++++++++++++++++--- .../dynamicArchive/LambdaCustomLoader.java | 4 +- .../LambdaProxyCallerIsHidden.java | 6 +- .../dynamicArchive/RegularHiddenClass.java | 4 +- .../cds/appcds/test-classes/SimpleCusty.java | 30 ++++++++ test/lib/jdk/test/lib/cds/CDSAppTester.java | 33 +++++++-- 13 files changed, 185 insertions(+), 34 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/test-classes/SimpleCusty.java diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp index 6a7faee5133..95d242c2089 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.cpp +++ b/src/hotspot/share/cds/aotArtifactFinder.cpp @@ -152,10 +152,11 @@ void AOTArtifactFinder::find_artifacts() { SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* k, DumpTimeClassInfo& info) { if (!info.is_excluded() && _seen_classes->get(k) == nullptr) { info.set_excluded(); - if (log_is_enabled(Info, cds)) { + info.set_has_checked_exclusion(); + if (log_is_enabled(Debug, cds)) { ResourceMark rm; - log_info(cds)("Skipping %s: %s class", k->name()->as_C_string(), - k->is_hidden() ? "Hidden" : "AOT tooling"); + log_debug(cds)("Skipping %s: %s class", k->name()->as_C_string(), + k->is_hidden() ? "Unreferenced hidden" : "AOT tooling"); } } }); @@ -211,6 +212,10 @@ void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { _seen_classes->put_if_absent(ik, &created); if (created) { _all_cached_classes->append(ik); + if (CDSConfig::is_dumping_final_static_archive() && ik->is_shared_unregistered_class()) { + // The following are not appliable to unregistered classes + return; + } scan_oops_in_instance_class(ik); if (ik->is_hidden() && CDSConfig::is_initing_classes_at_dump_time()) { bool succeed = AOTClassLinker::try_add_candidate(ik); diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp index 042a0dadb20..6f5ca6d7915 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "cds/dumpTimeClassInfo.hpp" +#include "cds/cdsConfig.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/classLoaderData.inline.hpp" #include "oops/instanceKlass.hpp" @@ -44,7 +45,10 @@ void DumpTimeSharedClassTable::iterate_all_live_classes(Function function) const auto wrapper = [&] (InstanceKlass* k, DumpTimeClassInfo& info) { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); assert_lock_strong(DumpTimeTable_lock); - if (k->is_loader_alive()) { + if (CDSConfig::is_dumping_final_static_archive() && !k->is_loaded()) { + assert(k->is_shared_unregistered_class(), "must be"); + function(k, info); + } else if (k->is_loader_alive()) { function(k, info); assert(k->is_loader_alive(), "must not change"); } else { diff --git a/src/hotspot/share/cds/finalImageRecipes.cpp b/src/hotspot/share/cds/finalImageRecipes.cpp index 55855679a1c..bdfd261355b 100644 --- a/src/hotspot/share/cds/finalImageRecipes.cpp +++ b/src/hotspot/share/cds/finalImageRecipes.cpp @@ -102,7 +102,11 @@ void FinalImageRecipes::load_all_classes(TRAPS) { Klass* k = _all_klasses->at(i); if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); - if (!ik->is_shared_unregistered_class() && !ik->is_hidden()) { + if (ik->is_shared_unregistered_class()) { + SystemDictionaryShared::init_dumptime_info(ik); + SystemDictionaryShared::add_unregistered_class(THREAD, ik); + SystemDictionaryShared::copy_unregistered_class_size_and_crc32(ik); + } else if (!ik->is_hidden()) { Klass* actual = SystemDictionary::resolve_or_fail(ik->name(), class_loader, true, CHECK); if (actual != ik) { ResourceMark rm(THREAD); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 2fbee502b93..5c4ee3f9452 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -465,6 +465,21 @@ bool SystemDictionaryShared::add_unregistered_class(Thread* current, InstanceKla return (klass == *v); } +void SystemDictionaryShared::copy_unregistered_class_size_and_crc32(InstanceKlass* klass) { + precond(CDSConfig::is_dumping_final_static_archive()); + precond(klass->is_shared()); + + // A shared class must have a RunTimeClassInfo record + const RunTimeClassInfo* record = find_record(&_static_archive._unregistered_dictionary, + nullptr, klass->name()); + precond(record != nullptr); + precond(record->klass() == klass); + + DumpTimeClassInfo* info = get_info(klass); + info->_clsfile_size = record->crc()->_clsfile_size; + info->_clsfile_crc32 = record->crc()->_clsfile_crc32; +} + void SystemDictionaryShared::set_shared_class_misc_info(InstanceKlass* k, ClassFileStream* cfs) { assert(CDSConfig::is_dumping_archive(), "sanity"); assert(!is_builtin(k), "must be unregistered class"); @@ -667,7 +682,7 @@ bool SystemDictionaryShared::should_be_excluded(Klass* k) { } void SystemDictionaryShared::finish_exclusion_checks() { - if (CDSConfig::is_dumping_dynamic_archive()) { + if (CDSConfig::is_dumping_dynamic_archive() || CDSConfig::is_dumping_preimage_static_archive()) { // Do this first -- if a base class is excluded due to duplication, // all of its subclasses will also be excluded. ResourceMark rm; diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index e910bfb5d47..22fc3fd825d 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -248,6 +248,7 @@ public: return (k->shared_classpath_index() != UNREGISTERED_INDEX); } static bool add_unregistered_class(Thread* current, InstanceKlass* k); + static void copy_unregistered_class_size_and_crc32(InstanceKlass* klass); static void finish_exclusion_checks(); static DumpTimeSharedClassTable* dumptime_table() { return _dumptime_table; } diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 0b6f3543b7a..f6a94a984ce 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -476,9 +476,23 @@ void ConstantPool::remove_unshareable_info() { return; } + bool update_resolved_reference = true; + if (CDSConfig::is_dumping_final_static_archive()) { + ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(this); + InstanceKlass* src_holder = src_cp->pool_holder(); + if (src_holder->is_shared_unregistered_class()) { + // Unregistered classes are not loaded in the AOT assembly phase. The resolved reference length + // is already saved during the training run. + precond(!src_holder->is_loaded()); + precond(resolved_reference_length() >= 0); + precond(resolved_references() == nullptr); + update_resolved_reference = false; + } + } + // resolved_references(): remember its length. If it cannot be restored // from the archived heap objects at run time, we need to dynamically allocate it. - if (cache() != nullptr) { + if (update_resolved_reference && cache() != nullptr) { set_resolved_reference_length( resolved_references() != nullptr ? resolved_references()->length() : 0); set_resolved_references(OopHandle()); diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 9f166e13751..71da5e1da09 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -828,9 +828,15 @@ void Klass::remove_java_mirror() { if (CDSConfig::is_dumping_heap()) { Klass* src_k = ArchiveBuilder::current()->get_source_addr(this); oop orig_mirror = src_k->java_mirror(); - oop scratch_mirror = HeapShared::scratch_java_mirror(orig_mirror); - if (scratch_mirror != nullptr) { - _archived_mirror_index = HeapShared::append_root(scratch_mirror); + if (orig_mirror == nullptr) { + assert(CDSConfig::is_dumping_final_static_archive(), "sanity"); + assert(is_instance_klass(), "sanity"); + assert(InstanceKlass::cast(this)->is_shared_unregistered_class(), "sanity"); + } else { + oop scratch_mirror = HeapShared::scratch_java_mirror(orig_mirror); + if (scratch_mirror != nullptr) { + _archived_mirror_index = HeapShared::append_root(scratch_mirror); + } } } #endif diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java index 9db886e20a5..cbc4644d5ca 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java @@ -31,11 +31,14 @@ * @requires vm.cds.supports.aot.class.linking * @comment work around JDK-8345635 * @requires !vm.jvmci.enabled - * @library /test/jdk/lib/testlibrary /test/lib + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build InitiatingLoaderTester BadOldClassA BadOldClassB - * @build BulkLoaderTest + * @build jdk.test.whitebox.WhiteBox BulkLoaderTest SimpleCusty * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar BulkLoaderTestApp.jar BulkLoaderTestApp MyUtil InitiatingLoaderTester * BadOldClassA BadOldClassB + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar + * SimpleCusty + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar jdk.test.whitebox.WhiteBox * @run driver BulkLoaderTest STATIC */ @@ -44,13 +47,15 @@ * @requires vm.cds.supports.aot.class.linking * @comment work around JDK-8345635 * @requires !vm.jvmci.enabled - * @library /test/jdk/lib/testlibrary /test/lib + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build InitiatingLoaderTester BadOldClassA BadOldClassB - * @build jdk.test.whitebox.WhiteBox BulkLoaderTest + * @build jdk.test.whitebox.WhiteBox BulkLoaderTest SimpleCusty * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar BulkLoaderTestApp.jar BulkLoaderTestApp MyUtil InitiatingLoaderTester * BadOldClassA BadOldClassB - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. BulkLoaderTest DYNAMIC + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar + * SimpleCusty + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar jdk.test.whitebox.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:WhiteBox.jar BulkLoaderTest DYNAMIC */ /* @@ -58,16 +63,21 @@ * @requires vm.cds.supports.aot.class.linking * @comment work around JDK-8345635 * @requires !vm.jvmci.enabled - * @library /test/jdk/lib/testlibrary /test/lib - * @build InitiatingLoaderTester BadOldClassA BadOldClassB - * @build BulkLoaderTest + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @build jdk.test.whitebox.WhiteBox InitiatingLoaderTester BadOldClassA BadOldClassB + * @build BulkLoaderTest SimpleCusty * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar BulkLoaderTestApp.jar BulkLoaderTestApp MyUtil InitiatingLoaderTester * BadOldClassA BadOldClassB + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar + * SimpleCusty * @run driver BulkLoaderTest AOT */ import java.io.File; import java.lang.StackWalker.StackFrame; +import java.net.URL; +import java.net.URLClassLoader; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -76,6 +86,7 @@ import java.util.Set; import jdk.test.lib.cds.CDSAppTester; import jdk.test.lib.helpers.ClassFileInstaller; import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.whitebox.WhiteBox; public class BulkLoaderTest { static final String appJar = ClassFileInstaller.getJarPath("BulkLoaderTestApp.jar"); @@ -114,6 +125,7 @@ public class BulkLoaderTest { static class Tester extends CDSAppTester { public Tester() { super(mainClass); + useWhiteBox(ClassFileInstaller.getJarPath("WhiteBox.jar")); } @Override @@ -124,7 +136,7 @@ public class BulkLoaderTest { @Override public String[] vmArgs(RunMode runMode) { return new String[] { - "-Xlog:cds,cds+aot+load", + "-Xlog:cds,cds+aot+load,cds+class=debug", "-XX:+AOTClassLinking", }; } @@ -140,6 +152,12 @@ public class BulkLoaderTest { public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception { if (isAOTWorkflow() && runMode == RunMode.TRAINING) { out.shouldContain("Skipping BadOldClassA: Unlinked class not supported by AOTConfiguration"); + out.shouldContain("Skipping SimpleCusty: Duplicated unregistered class"); + } + + if (isDumping(runMode)) { + // Check that we are archiving classes for custom class loaders. + out.shouldMatch("cds,class.* SimpleCusty"); } } } @@ -152,6 +170,7 @@ class BulkLoaderTestApp { checkClasses(); checkInitiatingLoader(); checkOldClasses(); + checkCustomLoader(); } // Check the ClassLoader/Module/Package/ProtectionDomain/CodeSource of classes that are aot-linked @@ -275,6 +294,38 @@ class BulkLoaderTestApp { System.out.println("Caught VerifyError for BadOldClassB: " + e); } } + + + static void checkCustomLoader() throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + for (int i = 0; i < 2; i++) { + Object o = initFromCustomLoader(); + System.out.println(o); + Class c = o.getClass(); + if (wb.isSharedClass(BulkLoaderTestApp.class)) { + // We are running with BulkLoaderTestApp from the AOT cache (or CDS achive) + if (i == 0) { + if (!wb.isSharedClass(c)) { + throw new RuntimeException("The first loader should load SimpleCusty from AOT cache (or CDS achive)"); + } + } else { + if (wb.isSharedClass(c)) { + throw new RuntimeException("The second loader should not load SimpleCusty from AOT cache (or CDS achive)"); + } + } + } + } + } + + static Object initFromCustomLoader() throws Exception { + String path = "cust.jar"; + URL url = new File(path).toURI().toURL(); + URL[] urls = new URL[] {url}; + URLClassLoader urlClassLoader = + new URLClassLoader("MyLoader", urls, null); + Class c = Class.forName("SimpleCusty", true, urlClassLoader); + return c.newInstance(); + } } class MyUtil { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java index 205901e3769..4563aa60c89 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ public class LambdaCustomLoader extends DynamicArchiveTestBase { "-Xlog:class+load,cds=debug,cds+dynamic", "-cp", appJar, mainClass, appJar, "init", "keep-alive") .assertNormalExit(output -> { - output.shouldMatch("Skipping.LambHello[$][$]Lambda.*0x.*:.Hidden.class") + output.shouldMatch("Skipping.LambHello[$][$]Lambda.*0x.*:.Unreferenced.hidden.class") .shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaProxyCallerIsHidden.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaProxyCallerIsHidden.java index 0c8cad0b3a6..4ec7e817378 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaProxyCallerIsHidden.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaProxyCallerIsHidden.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,8 +59,8 @@ public class LambdaProxyCallerIsHidden extends DynamicArchiveTestBase { "-Xlog:class+load,cds+dynamic,cds=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldMatch("Skipping.LambdaHello_0x.*[$][$]Lambda.*:.Hidden.class") - .shouldMatch("Skipping.LambdaHello.0x.*:.Hidden.class") + output.shouldMatch("Skipping.LambdaHello_0x.*[$][$]Lambda.*:.Unreferenced.hidden.class") + .shouldMatch("Skipping.LambdaHello.0x.*:.Unreferenced.hidden.class") .shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java index 957e4cb6479..7793fd07bc3 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ public class RegularHiddenClass extends DynamicArchiveTestBase { "-Xlog:class+load=debug,cds+dynamic,cds=debug", "-cp", appJar, mainClass, "keep-alive") .assertNormalExit(output -> { - output.shouldMatch("cds.*Skipping.TestClass.0x.*Hidden.class") + output.shouldMatch("cds.*Skipping.TestClass.0x.*Unreferenced.hidden.class") .shouldNotMatch("cds.dynamic.*Archiving.hidden.TestClass.*") .shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/SimpleCusty.java b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/SimpleCusty.java new file mode 100644 index 00000000000..9c82e0eb15d --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/SimpleCusty.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// This class is to be loaded by a custom class loader. +public class SimpleCusty { + public String toString() { + return "Instance of SimpleCusty"; + } +} diff --git a/test/lib/jdk/test/lib/cds/CDSAppTester.java b/test/lib/jdk/test/lib/cds/CDSAppTester.java index 4de6778e4c2..f08cbf0e7e2 100644 --- a/test/lib/jdk/test/lib/cds/CDSAppTester.java +++ b/test/lib/jdk/test/lib/cds/CDSAppTester.java @@ -50,6 +50,7 @@ abstract public class CDSAppTester { private final String dynamicArchiveFileLog; private final String tempBaseArchiveFile; private int numProductionRuns = 0; + private String whiteBoxJar = null; public CDSAppTester(String name) { if (CDSTestUtils.DYNAMIC_DUMP) { @@ -150,6 +151,10 @@ abstract public class CDSAppTester { checkExitValue = b; } + public final void useWhiteBox(String whiteBoxJar) { + this.whiteBoxJar = whiteBoxJar; + } + public final boolean isStaticWorkflow() { return workflow == Workflow.STATIC; } @@ -199,6 +204,12 @@ abstract public class CDSAppTester { return output; } + private String[] addCommonVMArgs(RunMode runMode, String[] cmdLine) { + cmdLine = addClassOrModulePath(runMode, cmdLine); + cmdLine = addWhiteBox(cmdLine); + return cmdLine; + } + private String[] addClassOrModulePath(RunMode runMode, String[] cmdLine) { String cp = classpath(runMode); if (cp == null) { @@ -214,6 +225,16 @@ abstract public class CDSAppTester { return cmdLine; } + private String[] addWhiteBox(String[] cmdLine) { + if (whiteBoxJar != null) { + cmdLine = StringArrayUtils.concat(cmdLine, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xbootclasspath/a:" + whiteBoxJar); + } + return cmdLine; + } + private OutputAnalyzer recordAOTConfiguration() throws Exception { RunMode runMode = RunMode.TRAINING; String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode), @@ -223,7 +244,7 @@ abstract public class CDSAppTester { "class+load=debug", "cds=debug", "cds+class=debug")); - cmdLine = addClassOrModulePath(runMode, cmdLine); + cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); return executeAndCheck(cmdLine, runMode, aotConfigurationFile, aotConfigurationFileLog); } @@ -235,7 +256,7 @@ abstract public class CDSAppTester { "-XX:DumpLoadedClassList=" + classListFile, logToFile(classListFileLog, "class+load=debug")); - cmdLine = addClassOrModulePath(runMode, cmdLine); + cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); return executeAndCheck(cmdLine, runMode, classListFile, classListFileLog); } @@ -253,7 +274,7 @@ abstract public class CDSAppTester { "cds+class=debug", "cds+heap=warning", "cds+resolve=debug")); - cmdLine = addClassOrModulePath(runMode, cmdLine); + cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); return executeAndCheck(cmdLine, runMode, staticArchiveFile, staticArchiveFileLog); } @@ -271,7 +292,7 @@ abstract public class CDSAppTester { "cds+class=debug", "cds+heap=warning", "cds+resolve=debug")); - cmdLine = addClassOrModulePath(runMode, cmdLine); + cmdLine = addCommonVMArgs(runMode, cmdLine); cmdLine = StringArrayUtils.concat(cmdLine, appCommandLine(runMode)); return executeAndCheck(cmdLine, runMode, aotCacheFile, aotCacheFileLog); } @@ -317,7 +338,7 @@ abstract public class CDSAppTester { "cds+class=debug", "cds+resolve=debug", "class+load=debug")); - cmdLine = addClassOrModulePath(runMode, cmdLine); + cmdLine = addCommonVMArgs(runMode, cmdLine); } if (baseArchive != null) { cmdLine = StringArrayUtils.concat(cmdLine, "-XX:SharedArchiveFile=" + baseArchive); @@ -342,7 +363,7 @@ abstract public class CDSAppTester { "-XX:+UnlockDiagnosticVMOptions", "-XX:VerifyArchivedFields=2", // make sure archived heap objects are good. logToFile(productionRunLog(), "cds")); - cmdLine = addClassOrModulePath(runMode, cmdLine); + cmdLine = addCommonVMArgs(runMode, cmdLine); if (isStaticWorkflow()) { cmdLine = StringArrayUtils.concat(cmdLine, "-Xshare:on", "-XX:SharedArchiveFile=" + staticArchiveFile); From e87ff328d5cc66454213dee44cf2faeb0e76262f Mon Sep 17 00:00:00 2001 From: Ferenc Rakoczi Date: Wed, 9 Apr 2025 21:15:45 +0000 Subject: [PATCH 099/843] 8351034: Add AVX-512 intrinsics for ML-DSA Reviewed-by: sviswanathan, lmesnik, vpaprotski, jbhateja --- src/hotspot/cpu/x86/stubDeclarations_x86.hpp | 2 +- src/hotspot/cpu/x86/stubGenerator_x86_64.cpp | 2 + src/hotspot/cpu/x86/stubGenerator_x86_64.hpp | 3 +- .../x86/stubGenerator_x86_64_dilithium.cpp | 1034 +++++++++++++++++ .../cpu/x86/stubGenerator_x86_64_sha3.cpp | 245 +++- src/hotspot/cpu/x86/vm_version_x86.cpp | 14 + src/hotspot/share/classfile/vmIntrinsics.hpp | 2 +- .../share/runtime/stubDeclarations.hpp | 4 +- .../classes/sun/security/provider/ML_DSA.java | 6 +- .../sun/security/provider/acvp/Launcher.java | 10 + 10 files changed, 1280 insertions(+), 42 deletions(-) create mode 100644 src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp diff --git a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp index 9f6c1ec60ef..ea20976c4ea 100644 --- a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp +++ b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp @@ -85,7 +85,7 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(compiler, 20000 LP64_ONLY(+64000) WINDOWS_ONLY(+2000)) \ + do_arch_blob(compiler, 20000 LP64_ONLY(+89000) WINDOWS_ONLY(+2000)) \ do_stub(compiler, vector_float_sign_mask) \ do_arch_entry(x86, compiler, vector_float_sign_mask, \ vector_float_sign_mask, vector_float_sign_mask) \ diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 9fcb044b09a..b480c78f79d 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4204,6 +4204,8 @@ void StubGenerator::generate_compiler_stubs() { generate_chacha_stubs(); + generate_dilithium_stubs(); + generate_sha3_stubs(); // data cache line writeback diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 2263188216c..c08b0168796 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -489,8 +489,9 @@ class StubGenerator: public StubCodeGenerator { // SHA3 stubs void generate_sha3_stubs(); - address generate_sha3_implCompress(StubGenStubId stub_id); + // Dilithium stubs and helper functions + void generate_dilithium_stubs(); // BASE64 stubs address base64_shuffle_addr(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp new file mode 100644 index 00000000000..7121db2ab91 --- /dev/null +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_dilithium.cpp @@ -0,0 +1,1034 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "runtime/stubRoutines.hpp" +#include "macroAssembler_x86.hpp" +#include "stubGenerator_x86_64.hpp" + +#define __ _masm-> + +#define xmm(i) as_XMMRegister(i) + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif // PRODUCT + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +#define XMMBYTES 64 + +// Constants +// +ATTRIBUTE_ALIGNED(64) static const uint32_t dilithiumAvx512Consts[] = { + 58728449, // montQInvModR + 8380417, // dilithium_q + 2365951, // montRSquareModQ + 5373807 // Barrett addend for modular reduction +}; + +const int montQInvModRIdx = 0; +const int dilithium_qIdx = 4; +const int montRSquareModQIdx = 8; +const int barrettAddendIdx = 12; + +static address dilithiumAvx512ConstsAddr(int offset) { + return ((address) dilithiumAvx512Consts) + offset; +} + +const Register scratch = r10; +const XMMRegister montMulPerm = xmm28; +const XMMRegister montQInvModR = xmm30; +const XMMRegister dilithium_q = xmm31; + + +ATTRIBUTE_ALIGNED(64) static const uint32_t dilithiumAvx512Perms[] = { + // collect montmul results into the destination register + 17, 1, 19, 3, 21, 5, 23, 7, 25, 9, 27, 11, 29, 13, 31, 15, + // ntt + // level 4 + 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, + 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31, + // level 5 + 0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27, + 4, 5, 6, 7, 20, 21, 22, 23, 12, 13, 14, 15, 28, 29, 30, 31, + // level 6 + 0, 1, 16, 17, 4, 5, 20, 21, 8, 9, 24, 25, 12, 13, 28, 29, + 2, 3, 18, 19, 6, 7, 22, 23, 10, 11, 26, 27, 14, 15, 30, 31, + // level 7 + 0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30, + 1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31, + 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23, + 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31, + + // ntt inverse + // level 0 + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + // level 1 + 0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30, + 1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31, + // level 2 + 0, 1, 16, 17, 4, 5, 20, 21, 8, 9, 24, 25, 12, 13, 28, 29, + 2, 3, 18, 19, 6, 7, 22, 23, 10, 11, 26, 27, 14, 15, 30, 31, + // level 3 + 0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27, + 4, 5, 6, 7, 20, 21, 22, 23, 12, 13, 14, 15, 28, 29, 30, 31, + // level 4 + 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, + 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31 +}; + +const int montMulPermsIdx = 0; +const int nttL4PermsIdx = 64; +const int nttL5PermsIdx = 192; +const int nttL6PermsIdx = 320; +const int nttL7PermsIdx = 448; +const int nttInvL0PermsIdx = 704; +const int nttInvL1PermsIdx = 832; +const int nttInvL2PermsIdx = 960; +const int nttInvL3PermsIdx = 1088; +const int nttInvL4PermsIdx = 1216; + +static address dilithiumAvx512PermsAddr() { + return (address) dilithiumAvx512Perms; +} + +// We do Montgomery multiplications of two vectors of 16 ints each in 4 steps: +// 1. Do the multiplications of the corresponding even numbered slots into +// the odd numbered slots of a third register. +// 2. Swap the even and odd numbered slots of the original input registers. +// 3. Similar to step 1, but into a different output register. +// 4. Combine the outputs of step 1 and step 3 into the output of the Montgomery +// multiplication. +// (For levels 0-6 in the Ntt and levels 1-7 of the inverse Ntt we only swap the +// odd-even slots of the first multiplicand as in the second (zetas) the +// odd slots contain the same number as the corresponding even one.) +// The indexes of the registers to be multiplied +// are in inputRegs1[] and inputRegs[2]. +// The results go to the registers whose indexes are in outputRegs. +// scratchRegs should contain 12 different register indexes. +// The set in outputRegs should not overlap with the set of the middle four +// scratch registers. +// The sets in inputRegs1 and inputRegs2 cannot overlap with the set of the +// first eight scratch registers. +// In most of the cases, the odd and the corresponding even slices of the +// registers indexed by the numbers in inputRegs2 will contain the same number, +// this should be indicated by calling this function with +// input2NeedsShuffle=false . +// +static void montMul64(int outputRegs[], int inputRegs1[], int inputRegs2[], + int scratchRegs[], bool input2NeedsShuffle, + MacroAssembler *_masm) { + + for (int i = 0; i < 4; i++) { + __ vpmuldq(xmm(scratchRegs[i]), xmm(inputRegs1[i]), xmm(inputRegs2[i]), + Assembler::AVX_512bit); + } + for (int i = 0; i < 4; i++) { + __ vpmulld(xmm(scratchRegs[i + 4]), xmm(scratchRegs[i]), montQInvModR, + Assembler::AVX_512bit); + } + for (int i = 0; i < 4; i++) { + __ vpmuldq(xmm(scratchRegs[i + 4]), xmm(scratchRegs[i + 4]), dilithium_q, + Assembler::AVX_512bit); + } + for (int i = 0; i < 4; i++) { + __ evpsubd(xmm(scratchRegs[i + 4]), k0, xmm(scratchRegs[i]), + xmm(scratchRegs[i + 4]), false, Assembler::AVX_512bit); + } + + for (int i = 0; i < 4; i++) { + __ vpshufd(xmm(inputRegs1[i]), xmm(inputRegs1[i]), 0xB1, + Assembler::AVX_512bit); + if (input2NeedsShuffle) { + __ vpshufd(xmm(inputRegs2[i]), xmm(inputRegs2[i]), 0xB1, + Assembler::AVX_512bit); + } + } + + for (int i = 0; i < 4; i++) { + __ vpmuldq(xmm(scratchRegs[i]), xmm(inputRegs1[i]), xmm(inputRegs2[i]), + Assembler::AVX_512bit); + } + for (int i = 0; i < 4; i++) { + __ vpmulld(xmm(scratchRegs[i + 8]), xmm(scratchRegs[i]), montQInvModR, + Assembler::AVX_512bit); + } + for (int i = 0; i < 4; i++) { + __ vpmuldq(xmm(scratchRegs[i + 8]), xmm(scratchRegs[i + 8]), dilithium_q, + Assembler::AVX_512bit); + } + for (int i = 0; i < 4; i++) { + __ evpsubd(xmm(outputRegs[i]), k0, xmm(scratchRegs[i]), + xmm(scratchRegs[i + 8]), false, Assembler::AVX_512bit); + } + + for (int i = 0; i < 4; i++) { + __ evpermt2d(xmm(outputRegs[i]), montMulPerm, xmm(scratchRegs[i + 4]), + Assembler::AVX_512bit); + } +} + +static void montMul64(int outputRegs[], int inputRegs1[], int inputRegs2[], + int scratchRegs[], MacroAssembler *_masm) { + montMul64(outputRegs, inputRegs1, inputRegs2, scratchRegs, false, _masm); +} + +static void sub_add(int subResult[], int addResult[], + int input1[], int input2[], MacroAssembler *_masm) { + + for (int i = 0; i < 4; i++) { + __ evpsubd(xmm(subResult[i]), k0, xmm(input1[i]), xmm(input2[i]), false, + Assembler::AVX_512bit); + } + + for (int i = 0; i < 4; i++) { + __ evpaddd(xmm(addResult[i]), k0, xmm(input1[i]), xmm(input2[i]), false, + Assembler::AVX_512bit); + } +} + +static void loadPerm(int destinationRegs[], Register perms, + int offset, MacroAssembler *_masm) { + __ evmovdqul(xmm(destinationRegs[0]), Address(perms, offset), + Assembler::AVX_512bit); + for (int i = 1; i < 4; i++) { + __ evmovdqul(xmm(destinationRegs[i]), xmm(destinationRegs[0]), + Assembler::AVX_512bit); + } +} + +static void load4Xmms(int destinationRegs[], Register source, int offset, + MacroAssembler *_masm) { + for (int i = 0; i < 4; i++) { + __ evmovdqul(xmm(destinationRegs[i]), Address(source, offset + i * XMMBYTES), + Assembler::AVX_512bit); + } +} + +static void loadXmm29(Register source, int offset, MacroAssembler *_masm) { + __ evmovdqul(xmm29, Address(source, offset), Assembler::AVX_512bit); +} + +static void store4Xmms(Register destination, int offset, int xmmRegs[], + MacroAssembler *_masm) { + for (int i = 0; i < 4; i++) { + __ evmovdqul(Address(destination, offset + i * XMMBYTES), xmm(xmmRegs[i]), + Assembler::AVX_512bit); + } +} + +static int xmm0_3[] = {0, 1, 2, 3}; +static int xmm0145[] = {0, 1, 4, 5}; +static int xmm0246[] = {0, 2, 4, 6}; +static int xmm0426[] = {0, 4, 2, 6}; +static int xmm1357[] = {1, 3, 5, 7}; +static int xmm1537[] = {1, 5, 3, 7}; +static int xmm2367[] = {2, 3, 6, 7}; +static int xmm4_7[] = {4, 5, 6, 7}; +static int xmm8_11[] = {8, 9, 10, 11}; +static int xmm12_15[] = {12, 13, 14, 15}; +static int xmm16_19[] = {16, 17, 18, 19}; +static int xmm20_23[] = {20, 21, 22, 23}; +static int xmm20222426[] = {20, 22, 24, 26}; +static int xmm21232527[] = {21, 23, 25, 27}; +static int xmm24_27[] = {24, 25, 26, 27}; +static int xmm4_20_24[] = {4, 5, 6, 7, 20, 21, 22, 23, 24, 25, 26, 27}; +static int xmm16_27[] = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; +static int xmm29_29[] = {29, 29, 29, 29}; + +// Dilithium NTT function except for the final "normalization" to |coeff| < Q. +// Implements +// static int implDilithiumAlmostNtt(int[] coeffs, int zetas[]) {} +// +// coeffs (int[256]) = c_rarg0 +// zetas (int[256]) = c_rarg1 +// +// +static address generate_dilithiumAlmostNtt_avx512(StubGenerator *stubgen, + MacroAssembler *_masm) { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = dilithiumAlmostNtt_id; + StubCodeMark mark(stubgen, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop, L_end; + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + const Register iterations = c_rarg2; + + const Register perms = r11; + + __ lea(perms, ExternalAddress(dilithiumAvx512PermsAddr())); + + __ evmovdqul(montMulPerm, Address(perms, montMulPermsIdx), Assembler::AVX_512bit); + + // Each level represents one iteration of the outer for loop of the Java version + // In each of these iterations half of the coefficients are (Montgomery) + // multiplied by a zeta corresponding to the coefficient and then these + // products will be added to and subtracted from the other half of the + // coefficients. In each level we just collect the coefficients (using + // evpermi2d() instructions where necessary, i.e. in levels 4-7) that need to + // be multiplied by the zetas in one set, the rest to another set of vector + // registers, then redistribute the addition/substraction results. + + // For levels 0 and 1 the zetas are not different within the 4 xmm registers + // that we would use for them, so we use only one, xmm29. + loadXmm29(zetas, 0, _masm); + __ vpbroadcastd(montQInvModR, + ExternalAddress(dilithiumAvx512ConstsAddr(montQInvModRIdx)), + Assembler::AVX_512bit, scratch); // q^-1 mod 2^32 + __ vpbroadcastd(dilithium_q, + ExternalAddress(dilithiumAvx512ConstsAddr(dilithium_qIdx)), + Assembler::AVX_512bit, scratch); // q + + // load all coefficients into the vector registers Zmm_0-Zmm_15, + // 16 coefficients into each + load4Xmms(xmm0_3, coeffs, 0, _masm); + load4Xmms(xmm4_7, coeffs, 4 * XMMBYTES, _masm); + load4Xmms(xmm8_11, coeffs, 8 * XMMBYTES, _masm); + load4Xmms(xmm12_15, coeffs, 12 * XMMBYTES, _masm); + + // level 0 and 1 can be done entirely in registers as the zetas on these + // levels are the same for all the montmuls that we can do in parallel + + // level 0 + montMul64(xmm16_19, xmm8_11, xmm29_29, xmm16_27, _masm); + sub_add(xmm8_11, xmm0_3, xmm0_3, xmm16_19, _masm); + montMul64(xmm16_19, xmm12_15, xmm29_29, xmm16_27, _masm); + loadXmm29(zetas, 512, _masm); // for level 1 + sub_add(xmm12_15, xmm4_7, xmm4_7, xmm16_19, _masm); + + // level 1 + + montMul64(xmm16_19, xmm4_7, xmm29_29, xmm16_27, _masm); + loadXmm29(zetas, 768, _masm); + sub_add(xmm4_7, xmm0_3, xmm0_3, xmm16_19, _masm); + montMul64(xmm16_19, xmm12_15, xmm29_29, xmm16_27, _masm); + sub_add(xmm12_15, xmm8_11, xmm8_11, xmm16_19, _masm); + + // levels 2 to 7 are done in 2 batches, by first saving half of the coefficients + // from level 1 into memory, doing all the level 2 to level 7 computations + // on the remaining half in the vector registers, saving the result to + // memory after level 7, then loading back the coefficients that we saved after + // level 1 and do the same computation with those + + store4Xmms(coeffs, 8 * XMMBYTES, xmm8_11, _masm); + store4Xmms(coeffs, 12 * XMMBYTES, xmm12_15, _masm); + + __ movl(iterations, 2); + + __ align(OptoLoopAlignment); + __ BIND(L_loop); + + __ subl(iterations, 1); + + // level 2 + load4Xmms(xmm12_15, zetas, 2 * 512, _masm); + montMul64(xmm16_19, xmm2367, xmm12_15, xmm16_27, _masm); + load4Xmms(xmm12_15, zetas, 3 * 512, _masm); // for level 3 + sub_add(xmm2367, xmm0145, xmm0145, xmm16_19, _masm); + + // level 3 + + montMul64(xmm16_19, xmm1357, xmm12_15, xmm16_27, _masm); + sub_add(xmm1357, xmm0246, xmm0246, xmm16_19, _masm); + + // level 4 + loadPerm(xmm16_19, perms, nttL4PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttL4PermsIdx + 64, _masm); + load4Xmms(xmm24_27, zetas, 4 * 512, _masm); + + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i/2 + 16), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i / 2 + 12), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + + montMul64(xmm12_15, xmm12_15, xmm24_27, xmm4_20_24, _masm); + sub_add(xmm1357, xmm0246, xmm16_19, xmm12_15, _masm); + + // level 5 + loadPerm(xmm16_19, perms, nttL5PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttL5PermsIdx + 64, _masm); + load4Xmms(xmm24_27, zetas, 5 * 512, _masm); + + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i/2 + 16), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i / 2 + 12), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + + montMul64(xmm12_15, xmm12_15, xmm24_27, xmm4_20_24, _masm); + sub_add(xmm1357, xmm0246, xmm16_19, xmm12_15, _masm); + + // level 6 + loadPerm(xmm16_19, perms, nttL6PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttL6PermsIdx + 64, _masm); + load4Xmms(xmm24_27, zetas, 6 * 512, _masm); + + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i/2 + 16), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i / 2 + 12), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + + montMul64(xmm12_15, xmm12_15, xmm24_27, xmm4_20_24, _masm); + sub_add(xmm1357, xmm0246, xmm16_19, xmm12_15, _masm); + + // level 7 + loadPerm(xmm16_19, perms, nttL7PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttL7PermsIdx + 64, _masm); + load4Xmms(xmm24_27, zetas, 7 * 512, _masm); + + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i / 2 + 16), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i / 2 + 12), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + + montMul64(xmm12_15, xmm12_15, xmm24_27, xmm4_20_24, true, _masm); + loadPerm(xmm0246, perms, nttL7PermsIdx + 2 * XMMBYTES, _masm); + loadPerm(xmm1357, perms, nttL7PermsIdx + 3 * XMMBYTES, _masm); + sub_add(xmm21232527, xmm20222426, xmm16_19, xmm12_15, _masm); + + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i), xmm(i + 20), xmm(i + 21), Assembler::AVX_512bit); + __ evpermi2d(xmm(i + 1), xmm(i + 20), xmm(i + 21), Assembler::AVX_512bit); + } + + __ cmpl(iterations, 0); + __ jcc(Assembler::equal, L_end); + + store4Xmms(coeffs, 0, xmm0_3, _masm); + store4Xmms(coeffs, 4 * XMMBYTES, xmm4_7, _masm); + + load4Xmms(xmm0_3, coeffs, 8 * XMMBYTES, _masm); + load4Xmms(xmm4_7, coeffs, 12 * XMMBYTES, _masm); + + __ addptr(zetas, 4 * XMMBYTES); + + __ jmp(L_loop); + + __ BIND(L_end); + + store4Xmms(coeffs, 8 * XMMBYTES, xmm0_3, _masm); + store4Xmms(coeffs, 12 * XMMBYTES, xmm4_7, _masm); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov64(rax, 0); // return 0 + __ ret(0); + + return start; +} + +// Dilithium Inverse NTT function except the final mod Q division by 2^256. +// Implements +// static int implDilithiumAlmostInverseNtt(int[] coeffs, int[] zetas) {} +// +// coeffs (int[256]) = c_rarg0 +// zetas (int[256]) = c_rarg1 +static address generate_dilithiumAlmostInverseNtt_avx512(StubGenerator *stubgen, + MacroAssembler *_masm) { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = dilithiumAlmostInverseNtt_id; + StubCodeMark mark(stubgen, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop, L_end; + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + + const Register iterations = c_rarg2; + + const Register perms = r11; + + __ lea(perms, ExternalAddress(dilithiumAvx512PermsAddr())); + + __ evmovdqul(montMulPerm, Address(perms, montMulPermsIdx), Assembler::AVX_512bit); + __ vpbroadcastd(montQInvModR, + ExternalAddress(dilithiumAvx512ConstsAddr(montQInvModRIdx)), + Assembler::AVX_512bit, scratch); // q^-1 mod 2^32 + __ vpbroadcastd(dilithium_q, + ExternalAddress(dilithiumAvx512ConstsAddr(dilithium_qIdx)), + Assembler::AVX_512bit, scratch); // q + + // Each level represents one iteration of the outer for loop of the + // Java version. + // In each of these iterations half of the coefficients are added to and + // subtracted from the other half of the coefficients then the result of + // the substartion is (Montgomery) multiplied by the corresponding zetas. + // In each level we just collect the coefficients (using evpermi2d() + // instructions where necessary, i.e. on levels 0-4) so that the results of + // the additions and subtractions go to the vector registers so that they + // align with each other and the zetas. + + // We do levels 0-6 in two batches, each batch entirely in the vector registers + load4Xmms(xmm0_3, coeffs, 0, _masm); + load4Xmms(xmm4_7, coeffs, 4 * XMMBYTES, _masm); + + __ movl(iterations, 2); + + __ align(OptoLoopAlignment); + __ BIND(L_loop); + + __ subl(iterations, 1); + + // level 0 + loadPerm(xmm8_11, perms, nttInvL0PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttInvL0PermsIdx + 64, _masm); + + for (int i = 0; i < 8; i += 2) { + __ evpermi2d(xmm(i / 2 + 8), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + __ evpermi2d(xmm(i / 2 + 12), xmm(i), xmm(i + 1), Assembler::AVX_512bit); + } + + load4Xmms(xmm4_7, zetas, 0, _masm); + sub_add(xmm24_27, xmm0_3, xmm8_11, xmm12_15, _masm); + montMul64(xmm4_7, xmm4_7, xmm24_27, xmm16_27, true, _masm); + + // level 1 + loadPerm(xmm8_11, perms, nttInvL1PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttInvL1PermsIdx + 64, _masm); + + for (int i = 0; i < 4; i++) { + __ evpermi2d(xmm(i + 8), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + __ evpermi2d(xmm(i + 12), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + } + + load4Xmms(xmm4_7, zetas, 512, _masm); + sub_add(xmm24_27, xmm0_3, xmm8_11, xmm12_15, _masm); + montMul64(xmm4_7, xmm24_27, xmm4_7, xmm16_27, _masm); + + // level 2 + loadPerm(xmm8_11, perms, nttInvL2PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttInvL2PermsIdx + 64, _masm); + + for (int i = 0; i < 4; i++) { + __ evpermi2d(xmm(i + 8), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + __ evpermi2d(xmm(i + 12), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + } + + load4Xmms(xmm4_7, zetas, 2 * 512, _masm); + sub_add(xmm24_27, xmm0_3, xmm8_11, xmm12_15, _masm); + montMul64(xmm4_7, xmm24_27, xmm4_7, xmm16_27, _masm); + + // level 3 + loadPerm(xmm8_11, perms, nttInvL3PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttInvL3PermsIdx + 64, _masm); + + for (int i = 0; i < 4; i++) { + __ evpermi2d(xmm(i + 8), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + __ evpermi2d(xmm(i + 12), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + } + + load4Xmms(xmm4_7, zetas, 3 * 512, _masm); + sub_add(xmm24_27, xmm0_3, xmm8_11, xmm12_15, _masm); + montMul64(xmm4_7, xmm24_27, xmm4_7, xmm16_27, _masm); + + // level 4 + loadPerm(xmm8_11, perms, nttInvL4PermsIdx, _masm); + loadPerm(xmm12_15, perms, nttInvL4PermsIdx + 64, _masm); + + for (int i = 0; i < 4; i++) { + __ evpermi2d(xmm(i + 8), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + __ evpermi2d(xmm(i + 12), xmm(i), xmm(i + 4), Assembler::AVX_512bit); + } + + load4Xmms(xmm4_7, zetas, 4 * 512, _masm); + sub_add(xmm24_27, xmm0_3, xmm8_11, xmm12_15, _masm); + montMul64(xmm4_7, xmm24_27, xmm4_7, xmm16_27, _masm); + + // level 5 + load4Xmms(xmm12_15, zetas, 5 * 512, _masm); + sub_add(xmm8_11, xmm0_3, xmm0426, xmm1537, _masm); + montMul64(xmm4_7, xmm8_11, xmm12_15, xmm16_27, _masm); + + // level 6 + load4Xmms(xmm12_15, zetas, 6 * 512, _masm); + sub_add(xmm8_11, xmm0_3, xmm0145, xmm2367, _masm); + montMul64(xmm4_7, xmm8_11, xmm12_15, xmm16_27, _masm); + + __ cmpl(iterations, 0); + __ jcc(Assembler::equal, L_end); + + // save the coefficients of the first batch, adjust the zetas + // and load the second batch of coefficients + store4Xmms(coeffs, 0, xmm0_3, _masm); + store4Xmms(coeffs, 4 * XMMBYTES, xmm4_7, _masm); + + __ addptr(zetas, 4 * XMMBYTES); + + load4Xmms(xmm0_3, coeffs, 8 * XMMBYTES, _masm); + load4Xmms(xmm4_7, coeffs, 12 * XMMBYTES, _masm); + + __ jmp(L_loop); + + __ BIND(L_end); + + // load the coeffs of the first batch of coefficients that were saved after + // level 6 into Zmm_8-Zmm_15 and do the last level entirely in the vector + // registers + load4Xmms(xmm8_11, coeffs, 0, _masm); + load4Xmms(xmm12_15, coeffs, 4 * XMMBYTES, _masm); + + // level 7 + + loadXmm29(zetas, 7 * 512, _masm); + + for (int i = 0; i < 8; i++) { + __ evpaddd(xmm(i + 16), k0, xmm(i), xmm(i + 8), false, Assembler::AVX_512bit); + } + + for (int i = 0; i < 8; i++) { + __ evpsubd(xmm(i), k0, xmm(i + 8), xmm(i), false, Assembler::AVX_512bit); + } + + store4Xmms(coeffs, 0, xmm16_19, _masm); + store4Xmms(coeffs, 4 * XMMBYTES, xmm20_23, _masm); + montMul64(xmm0_3, xmm0_3, xmm29_29, xmm16_27, _masm); + montMul64(xmm4_7, xmm4_7, xmm29_29, xmm16_27, _masm); + store4Xmms(coeffs, 8 * XMMBYTES, xmm0_3, _masm); + store4Xmms(coeffs, 12 * XMMBYTES, xmm4_7, _masm); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov64(rax, 0); // return 0 + __ ret(0); + + return start; +} + +// Dilithium multiply polynomials in the NTT domain. +// Implements +// static int implDilithiumNttMult( +// int[] result, int[] ntta, int[] nttb {} +// +// result (int[256]) = c_rarg0 +// poly1 (int[256]) = c_rarg1 +// poly2 (int[256]) = c_rarg2 +static address generate_dilithiumNttMult_avx512(StubGenerator *stubgen, + MacroAssembler *_masm) { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = dilithiumNttMult_id; + StubCodeMark mark(stubgen, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register result = c_rarg0; + const Register poly1 = c_rarg1; + const Register poly2 = c_rarg2; + + const Register perms = r10; // scratch reused after not needed any more + const Register len = r11; + + const XMMRegister montRSquareModQ = xmm29; + + __ vpbroadcastd(montQInvModR, + ExternalAddress(dilithiumAvx512ConstsAddr(montQInvModRIdx)), + Assembler::AVX_512bit, scratch); // q^-1 mod 2^32 + __ vpbroadcastd(dilithium_q, + ExternalAddress(dilithiumAvx512ConstsAddr(dilithium_qIdx)), + Assembler::AVX_512bit, scratch); // q + __ vpbroadcastd(montRSquareModQ, + ExternalAddress(dilithiumAvx512ConstsAddr(montRSquareModQIdx)), + Assembler::AVX_512bit, scratch); // 2^64 mod q + + __ lea(perms, ExternalAddress(dilithiumAvx512PermsAddr())); + __ evmovdqul(montMulPerm, Address(perms, montMulPermsIdx), Assembler::AVX_512bit); + + __ movl(len, 4); + + __ align(OptoLoopAlignment); + __ BIND(L_loop); + + load4Xmms(xmm4_7, poly2, 0, _masm); + load4Xmms(xmm0_3, poly1, 0, _masm); + montMul64(xmm4_7, xmm4_7, xmm29_29, xmm16_27, _masm); + montMul64(xmm0_3, xmm0_3, xmm4_7, xmm16_27, true, _masm); + store4Xmms(result, 0, xmm0_3, _masm); + + __ subl(len, 1); + __ addptr(poly1, 4 * XMMBYTES); + __ addptr(poly2, 4 * XMMBYTES); + __ addptr(result, 4 * XMMBYTES); + __ cmpl(len, 0); + __ jcc(Assembler::notEqual, L_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov64(rax, 0); // return 0 + __ ret(0); + + return start; +} + +// Dilithium Motgomery multiply an array by a constant. +// Implements +// static int implDilithiumMontMulByConstant(int[] coeffs, int constant) {} +// +// coeffs (int[256]) = c_rarg0 +// constant (int) = c_rarg1 +static address generate_dilithiumMontMulByConstant_avx512(StubGenerator *stubgen, + MacroAssembler *_masm) { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = dilithiumMontMulByConstant_id; + StubCodeMark mark(stubgen, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register coeffs = c_rarg0; + const Register rConstant = c_rarg1; + + const Register perms = c_rarg2; // not used for argument + const Register len = r11; + + const XMMRegister constant = xmm29; + + __ lea(perms, ExternalAddress(dilithiumAvx512PermsAddr())); + + // the following four vector registers are used in montMul64 + __ vpbroadcastd(montQInvModR, + ExternalAddress(dilithiumAvx512ConstsAddr(montQInvModRIdx)), + Assembler::AVX_512bit, scratch); // q^-1 mod 2^32 + __ vpbroadcastd(dilithium_q, + ExternalAddress(dilithiumAvx512ConstsAddr(dilithium_qIdx)), + Assembler::AVX_512bit, scratch); // q + __ evmovdqul(montMulPerm, Address(perms, montMulPermsIdx), Assembler::AVX_512bit); + __ evpbroadcastd(constant, rConstant, Assembler::AVX_512bit); // constant multiplier + + __ movl(len, 2); + + __ align(OptoLoopAlignment); + __ BIND(L_loop); + + load4Xmms(xmm0_3, coeffs, 0, _masm); + load4Xmms(xmm4_7, coeffs, 4 * XMMBYTES, _masm); + montMul64(xmm0_3, xmm0_3, xmm29_29, xmm16_27, _masm); + montMul64(xmm4_7, xmm4_7, xmm29_29, xmm16_27, _masm); + store4Xmms(coeffs, 0, xmm0_3, _masm); + store4Xmms(coeffs, 4 * XMMBYTES, xmm4_7, _masm); + + __ subl(len, 1); + __ addptr(coeffs, 512); + __ cmpl(len, 0); + __ jcc(Assembler::notEqual, L_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov64(rax, 0); // return 0 + __ ret(0); + + return start; +} + +// Dilithium decompose poly. +// Implements +// static int implDilithiumDecomposePoly(int[] coeffs, int constant) {} +// +// input (int[256]) = c_rarg0 +// lowPart (int[256]) = c_rarg1 +// highPart (int[256]) = c_rarg2 +// twoGamma2 (int) = c_rarg3 +// multiplier (int) = c_rarg4 +static address generate_dilithiumDecomposePoly_avx512(StubGenerator *stubgen, + MacroAssembler *_masm) { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = dilithiumDecomposePoly_id; + StubCodeMark mark(stubgen, stub_id); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register input = c_rarg0; + const Register lowPart = c_rarg1; + const Register highPart = c_rarg2; + const Register rTwoGamma2 = c_rarg3; + + const Register len = r11; + const XMMRegister zero = xmm24; + const XMMRegister one = xmm25; + const XMMRegister qMinus1 = xmm26; + const XMMRegister gamma2 = xmm27; + const XMMRegister twoGamma2 = xmm28; + const XMMRegister barrettMultiplier = xmm29; + const XMMRegister barrettAddend = xmm30; + + __ vpxor(zero, zero, zero, Assembler::AVX_512bit); // 0 + __ vpternlogd(xmm0, 0xff, xmm0, xmm0, Assembler::AVX_512bit); // -1 + __ vpsubd(one, zero, xmm0, Assembler::AVX_512bit); // 1 + __ vpbroadcastd(dilithium_q, + ExternalAddress(dilithiumAvx512ConstsAddr(dilithium_qIdx)), + Assembler::AVX_512bit, scratch); // q + __ vpbroadcastd(barrettAddend, + ExternalAddress(dilithiumAvx512ConstsAddr(barrettAddendIdx)), + Assembler::AVX_512bit, scratch); // addend for Barrett reduction + + __ evpbroadcastd(twoGamma2, rTwoGamma2, Assembler::AVX_512bit); // 2 * gamma2 + + #ifndef _WIN64 + const Register rMultiplier = c_rarg4; + #else + const Address multiplier_mem(rbp, 6 * wordSize); + const Register rMultiplier = c_rarg3; // arg3 is already consumed, reused here + __ movptr(rMultiplier, multiplier_mem); + #endif + __ evpbroadcastd(barrettMultiplier, rMultiplier, + Assembler::AVX_512bit); // multiplier for mod 2 * gamma2 reduce + + __ evpsubd(qMinus1, k0, dilithium_q, one, false, Assembler::AVX_512bit); // q - 1 + __ evpsrad(gamma2, k0, twoGamma2, 1, false, Assembler::AVX_512bit); // gamma2 + + __ movl(len, 1024); + + __ align(OptoLoopAlignment); + __ BIND(L_loop); + + load4Xmms(xmm0_3, input, 0, _masm); + + __ addptr(input, 4 * XMMBYTES); + + // rplus in xmm0 + // rplus = rplus - ((rplus + 5373807) >> 23) * dilithium_q; + __ evpaddd(xmm4, k0, xmm0, barrettAddend, false, Assembler::AVX_512bit); + __ evpaddd(xmm5, k0, xmm1, barrettAddend, false, Assembler::AVX_512bit); + __ evpaddd(xmm6, k0, xmm2, barrettAddend, false, Assembler::AVX_512bit); + __ evpaddd(xmm7, k0, xmm3, barrettAddend, false, Assembler::AVX_512bit); + + __ evpsrad(xmm4, k0, xmm4, 23, false, Assembler::AVX_512bit); + __ evpsrad(xmm5, k0, xmm5, 23, false, Assembler::AVX_512bit); + __ evpsrad(xmm6, k0, xmm6, 23, false, Assembler::AVX_512bit); + __ evpsrad(xmm7, k0, xmm7, 23, false, Assembler::AVX_512bit); + + __ evpmulld(xmm4, k0, xmm4, dilithium_q, false, Assembler::AVX_512bit); + __ evpmulld(xmm5, k0, xmm5, dilithium_q, false, Assembler::AVX_512bit); + __ evpmulld(xmm6, k0, xmm6, dilithium_q, false, Assembler::AVX_512bit); + __ evpmulld(xmm7, k0, xmm7, dilithium_q, false, Assembler::AVX_512bit); + + __ evpsubd(xmm0, k0, xmm0, xmm4, false, Assembler::AVX_512bit); + __ evpsubd(xmm1, k0, xmm1, xmm5, false, Assembler::AVX_512bit); + __ evpsubd(xmm2, k0, xmm2, xmm6, false, Assembler::AVX_512bit); + __ evpsubd(xmm3, k0, xmm3, xmm7, false, Assembler::AVX_512bit); + // rplus in xmm0 + // rplus = rplus + ((rplus >> 31) & dilithium_q); + __ evpsrad(xmm4, k0, xmm0, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm5, k0, xmm1, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm6, k0, xmm2, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm7, k0, xmm3, 31, false, Assembler::AVX_512bit); + + __ evpandd(xmm4, k0, xmm4, dilithium_q, false, Assembler::AVX_512bit); + __ evpandd(xmm5, k0, xmm5, dilithium_q, false, Assembler::AVX_512bit); + __ evpandd(xmm6, k0, xmm6, dilithium_q, false, Assembler::AVX_512bit); + __ evpandd(xmm7, k0, xmm7, dilithium_q, false, Assembler::AVX_512bit); + + __ evpaddd(xmm0, k0, xmm0, xmm4, false, Assembler::AVX_512bit); + __ evpaddd(xmm1, k0, xmm1, xmm5, false, Assembler::AVX_512bit); + __ evpaddd(xmm2, k0, xmm2, xmm6, false, Assembler::AVX_512bit); + __ evpaddd(xmm3, k0, xmm3, xmm7, false, Assembler::AVX_512bit); + // rplus in xmm0 + // int quotient = (rplus * barrettMultiplier) >> 22; + __ evpmulld(xmm4, k0, xmm0, barrettMultiplier, false, Assembler::AVX_512bit); + __ evpmulld(xmm5, k0, xmm1, barrettMultiplier, false, Assembler::AVX_512bit); + __ evpmulld(xmm6, k0, xmm2, barrettMultiplier, false, Assembler::AVX_512bit); + __ evpmulld(xmm7, k0, xmm3, barrettMultiplier, false, Assembler::AVX_512bit); + + __ evpsrad(xmm4, k0, xmm4, 22, false, Assembler::AVX_512bit); + __ evpsrad(xmm5, k0, xmm5, 22, false, Assembler::AVX_512bit); + __ evpsrad(xmm6, k0, xmm6, 22, false, Assembler::AVX_512bit); + __ evpsrad(xmm7, k0, xmm7, 22, false, Assembler::AVX_512bit); + // quotient in xmm4 + // int r0 = rplus - quotient * twoGamma2; + __ evpmulld(xmm8, k0, xmm4, twoGamma2, false, Assembler::AVX_512bit); + __ evpmulld(xmm9, k0, xmm5, twoGamma2, false, Assembler::AVX_512bit); + __ evpmulld(xmm10, k0, xmm6, twoGamma2, false, Assembler::AVX_512bit); + __ evpmulld(xmm11, k0, xmm7, twoGamma2, false, Assembler::AVX_512bit); + + __ evpsubd(xmm8, k0, xmm0, xmm8, false, Assembler::AVX_512bit); + __ evpsubd(xmm9, k0, xmm1, xmm9, false, Assembler::AVX_512bit); + __ evpsubd(xmm10, k0, xmm2, xmm10, false, Assembler::AVX_512bit); + __ evpsubd(xmm11, k0, xmm3, xmm11, false, Assembler::AVX_512bit); + // r0 in xmm8 + // int mask = (twoGamma2 - r0) >> 22; + __ evpsubd(xmm12, k0, twoGamma2, xmm8, false, Assembler::AVX_512bit); + __ evpsubd(xmm13, k0, twoGamma2, xmm9, false, Assembler::AVX_512bit); + __ evpsubd(xmm14, k0, twoGamma2, xmm10, false, Assembler::AVX_512bit); + __ evpsubd(xmm15, k0, twoGamma2, xmm11, false, Assembler::AVX_512bit); + + __ evpsrad(xmm12, k0, xmm12, 22, false, Assembler::AVX_512bit); + __ evpsrad(xmm13, k0, xmm13, 22, false, Assembler::AVX_512bit); + __ evpsrad(xmm14, k0, xmm14, 22, false, Assembler::AVX_512bit); + __ evpsrad(xmm15, k0, xmm15, 22, false, Assembler::AVX_512bit); + // mask in xmm12 + // r0 -= (mask & twoGamma2); + __ evpandd(xmm16, k0, xmm12, twoGamma2, false, Assembler::AVX_512bit); + __ evpandd(xmm17, k0, xmm13, twoGamma2, false, Assembler::AVX_512bit); + __ evpandd(xmm18, k0, xmm14, twoGamma2, false, Assembler::AVX_512bit); + __ evpandd(xmm19, k0, xmm15, twoGamma2, false, Assembler::AVX_512bit); + + __ evpsubd(xmm8, k0, xmm8, xmm16, false, Assembler::AVX_512bit); + __ evpsubd(xmm9, k0, xmm9, xmm17, false, Assembler::AVX_512bit); + __ evpsubd(xmm10, k0, xmm10, xmm18, false, Assembler::AVX_512bit); + __ evpsubd(xmm11, k0, xmm11, xmm19, false, Assembler::AVX_512bit); + // r0 in xmm8 + // quotient += (mask & 1); + __ evpandd(xmm16, k0, xmm12, one, false, Assembler::AVX_512bit); + __ evpandd(xmm17, k0, xmm13, one, false, Assembler::AVX_512bit); + __ evpandd(xmm18, k0, xmm14, one, false, Assembler::AVX_512bit); + __ evpandd(xmm19, k0, xmm15, one, false, Assembler::AVX_512bit); + + __ evpaddd(xmm4, k0, xmm4, xmm16, false, Assembler::AVX_512bit); + __ evpaddd(xmm5, k0, xmm5, xmm17, false, Assembler::AVX_512bit); + __ evpaddd(xmm6, k0, xmm6, xmm18, false, Assembler::AVX_512bit); + __ evpaddd(xmm7, k0, xmm7, xmm19, false, Assembler::AVX_512bit); + + // mask = (twoGamma2 / 2 - r0) >> 31; + __ evpsubd(xmm12, k0, gamma2, xmm8, false, Assembler::AVX_512bit); + __ evpsubd(xmm13, k0, gamma2, xmm9, false, Assembler::AVX_512bit); + __ evpsubd(xmm14, k0, gamma2, xmm10, false, Assembler::AVX_512bit); + __ evpsubd(xmm15, k0, gamma2, xmm11, false, Assembler::AVX_512bit); + + __ evpsrad(xmm12, k0, xmm12, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm13, k0, xmm13, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm14, k0, xmm14, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm15, k0, xmm15, 31, false, Assembler::AVX_512bit); + + // r0 -= (mask & twoGamma2); + __ evpandd(xmm16, k0, xmm12, twoGamma2, false, Assembler::AVX_512bit); + __ evpandd(xmm17, k0, xmm13, twoGamma2, false, Assembler::AVX_512bit); + __ evpandd(xmm18, k0, xmm14, twoGamma2, false, Assembler::AVX_512bit); + __ evpandd(xmm19, k0, xmm15, twoGamma2, false, Assembler::AVX_512bit); + + __ evpsubd(xmm8, k0, xmm8, xmm16, false, Assembler::AVX_512bit); + __ evpsubd(xmm9, k0, xmm9, xmm17, false, Assembler::AVX_512bit); + __ evpsubd(xmm10, k0, xmm10, xmm18, false, Assembler::AVX_512bit); + __ evpsubd(xmm11, k0, xmm11, xmm19, false, Assembler::AVX_512bit); + // r0 in xmm8 + // quotient += (mask & 1); + __ evpandd(xmm16, k0, xmm12, one, false, Assembler::AVX_512bit); + __ evpandd(xmm17, k0, xmm13, one, false, Assembler::AVX_512bit); + __ evpandd(xmm18, k0, xmm14, one, false, Assembler::AVX_512bit); + __ evpandd(xmm19, k0, xmm15, one, false, Assembler::AVX_512bit); + + __ evpaddd(xmm4, k0, xmm4, xmm16, false, Assembler::AVX_512bit); + __ evpaddd(xmm5, k0, xmm5, xmm17, false, Assembler::AVX_512bit); + __ evpaddd(xmm6, k0, xmm6, xmm18, false, Assembler::AVX_512bit); + __ evpaddd(xmm7, k0, xmm7, xmm19, false, Assembler::AVX_512bit); + // quotient in xmm4 + // int r1 = rplus - r0 - (dilithium_q - 1); + __ evpsubd(xmm16, k0, xmm0, xmm8, false, Assembler::AVX_512bit); + __ evpsubd(xmm17, k0, xmm1, xmm9, false, Assembler::AVX_512bit); + __ evpsubd(xmm18, k0, xmm2, xmm10, false, Assembler::AVX_512bit); + __ evpsubd(xmm19, k0, xmm3, xmm11, false, Assembler::AVX_512bit); + + __ evpsubd(xmm16, k0, xmm16, xmm26, false, Assembler::AVX_512bit); + __ evpsubd(xmm17, k0, xmm17, xmm26, false, Assembler::AVX_512bit); + __ evpsubd(xmm18, k0, xmm18, xmm26, false, Assembler::AVX_512bit); + __ evpsubd(xmm19, k0, xmm19, xmm26, false, Assembler::AVX_512bit); + // r1 in xmm16 + // r1 = (r1 | (-r1)) >> 31; // 0 if rplus - r0 == (dilithium_q - 1), -1 otherwise + __ evpsubd(xmm20, k0, zero, xmm16, false, Assembler::AVX_512bit); + __ evpsubd(xmm21, k0, zero, xmm17, false, Assembler::AVX_512bit); + __ evpsubd(xmm22, k0, zero, xmm18, false, Assembler::AVX_512bit); + __ evpsubd(xmm23, k0, zero, xmm19, false, Assembler::AVX_512bit); + + __ evporq(xmm16, k0, xmm16, xmm20, false, Assembler::AVX_512bit); + __ evporq(xmm17, k0, xmm17, xmm21, false, Assembler::AVX_512bit); + __ evporq(xmm18, k0, xmm18, xmm22, false, Assembler::AVX_512bit); + __ evporq(xmm19, k0, xmm19, xmm23, false, Assembler::AVX_512bit); + + __ evpsubd(xmm12, k0, zero, one, false, Assembler::AVX_512bit); // -1 + + __ evpsrad(xmm0, k0, xmm16, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm1, k0, xmm17, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm2, k0, xmm18, 31, false, Assembler::AVX_512bit); + __ evpsrad(xmm3, k0, xmm19, 31, false, Assembler::AVX_512bit); + // r1 in xmm0 + // r0 += ~r1; + __ evpxorq(xmm20, k0, xmm0, xmm12, false, Assembler::AVX_512bit); + __ evpxorq(xmm21, k0, xmm1, xmm12, false, Assembler::AVX_512bit); + __ evpxorq(xmm22, k0, xmm2, xmm12, false, Assembler::AVX_512bit); + __ evpxorq(xmm23, k0, xmm3, xmm12, false, Assembler::AVX_512bit); + + __ evpaddd(xmm8, k0, xmm8, xmm20, false, Assembler::AVX_512bit); + __ evpaddd(xmm9, k0, xmm9, xmm21, false, Assembler::AVX_512bit); + __ evpaddd(xmm10, k0, xmm10, xmm22, false, Assembler::AVX_512bit); + __ evpaddd(xmm11, k0, xmm11, xmm23, false, Assembler::AVX_512bit); + // r0 in xmm8 + // r1 = r1 & quotient; + __ evpandd(xmm0, k0, xmm4, xmm0, false, Assembler::AVX_512bit); + __ evpandd(xmm1, k0, xmm5, xmm1, false, Assembler::AVX_512bit); + __ evpandd(xmm2, k0, xmm6, xmm2, false, Assembler::AVX_512bit); + __ evpandd(xmm3, k0, xmm7, xmm3, false, Assembler::AVX_512bit); + // r1 in xmm0 + // lowPart[m] = r0; + // highPart[m] = r1; + store4Xmms(highPart, 0, xmm0_3, _masm); + store4Xmms(lowPart, 0, xmm8_11, _masm); + + __ addptr(highPart, 4 * XMMBYTES); + __ addptr(lowPart, 4 * XMMBYTES); + __ subl(len, 4 * XMMBYTES); + __ jcc(Assembler::notEqual, L_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov64(rax, 0); // return 0 + __ ret(0); + + return start; +} + +void StubGenerator::generate_dilithium_stubs() { + // Generate Dilithium intrinsics code + if (UseDilithiumIntrinsics) { + StubRoutines::_dilithiumAlmostNtt = + generate_dilithiumAlmostNtt_avx512(this, _masm); + StubRoutines::_dilithiumAlmostInverseNtt = + generate_dilithiumAlmostInverseNtt_avx512(this, _masm); + StubRoutines::_dilithiumNttMult = + generate_dilithiumNttMult_avx512(this, _masm); + StubRoutines::_dilithiumMontMulByConstant = + generate_dilithiumMontMulByConstant_avx512(this, _masm); + StubRoutines::_dilithiumDecomposePoly = + generate_dilithiumDecomposePoly_avx512(this, _masm); + } +} diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp index 7d1051711f2..9f13233f1d2 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp @@ -38,6 +38,8 @@ #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") +#define xmm(i) as_XMMRegister(i) + // Constants ATTRIBUTE_ALIGNED(64) static const uint64_t round_consts_arr[24] = { 0x0000000000000001L, 0x0000000000008082L, 0x800000000000808AL, @@ -79,13 +81,6 @@ static address permsAndRotsAddr() { return (address) permsAndRots; } -void StubGenerator::generate_sha3_stubs() { - if (UseSHA3Intrinsics) { - StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id); - StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id); - } -} - // Arguments: // // Inputs: @@ -95,7 +90,9 @@ void StubGenerator::generate_sha3_stubs() { // c_rarg3 - int offset // c_rarg4 - int limit // -address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { +static address generate_sha3_implCompress(StubGenStubId stub_id, + StubGenerator *stubgen, + MacroAssembler *_masm) { bool multiBlock; switch(stub_id) { case sha3_implCompress_id: @@ -109,7 +106,7 @@ address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { } __ align(CodeEntryAlignment); - StubCodeMark mark(this, stub_id); + StubCodeMark mark(stubgen, stub_id); address start = __ pc(); const Register buf = c_rarg0; @@ -154,29 +151,16 @@ address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { __ kshiftrwl(k1, k5, 4); // load the state - __ evmovdquq(xmm0, k5, Address(state, 0), false, Assembler::AVX_512bit); - __ evmovdquq(xmm1, k5, Address(state, 40), false, Assembler::AVX_512bit); - __ evmovdquq(xmm2, k5, Address(state, 80), false, Assembler::AVX_512bit); - __ evmovdquq(xmm3, k5, Address(state, 120), false, Assembler::AVX_512bit); - __ evmovdquq(xmm4, k5, Address(state, 160), false, Assembler::AVX_512bit); + for (int i = 0; i < 5; i++) { + __ evmovdquq(xmm(i), k5, Address(state, i * 40), false, Assembler::AVX_512bit); + } // load the permutation and rotation constants - __ evmovdquq(xmm17, Address(permsAndRots, 0), Assembler::AVX_512bit); - __ evmovdquq(xmm18, Address(permsAndRots, 64), Assembler::AVX_512bit); - __ evmovdquq(xmm19, Address(permsAndRots, 128), Assembler::AVX_512bit); - __ evmovdquq(xmm20, Address(permsAndRots, 192), Assembler::AVX_512bit); - __ evmovdquq(xmm21, Address(permsAndRots, 256), Assembler::AVX_512bit); - __ evmovdquq(xmm22, Address(permsAndRots, 320), Assembler::AVX_512bit); - __ evmovdquq(xmm23, Address(permsAndRots, 384), Assembler::AVX_512bit); - __ evmovdquq(xmm24, Address(permsAndRots, 448), Assembler::AVX_512bit); - __ evmovdquq(xmm25, Address(permsAndRots, 512), Assembler::AVX_512bit); - __ evmovdquq(xmm26, Address(permsAndRots, 576), Assembler::AVX_512bit); - __ evmovdquq(xmm27, Address(permsAndRots, 640), Assembler::AVX_512bit); - __ evmovdquq(xmm28, Address(permsAndRots, 704), Assembler::AVX_512bit); - __ evmovdquq(xmm29, Address(permsAndRots, 768), Assembler::AVX_512bit); - __ evmovdquq(xmm30, Address(permsAndRots, 832), Assembler::AVX_512bit); - __ evmovdquq(xmm31, Address(permsAndRots, 896), Assembler::AVX_512bit); + for (int i = 0; i < 15; i++) { + __ evmovdquq(xmm(i + 17), Address(permsAndRots, i * 64), Assembler::AVX_512bit); + } + __ align(OptoLoopAlignment); __ BIND(sha3_loop); // there will be 24 keccak rounds @@ -231,6 +215,7 @@ address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { // The implementation closely follows the Java version, with the state // array "rows" in the lowest 5 64-bit slots of zmm0 - zmm4, i.e. // each row of the SHA3 specification is located in one zmm register. + __ align(OptoLoopAlignment); __ BIND(rounds24_loop); __ subl(roundsLeft, 1); @@ -257,7 +242,7 @@ address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { // Do the cyclical permutation of the 24 moving state elements // and the required rotations within each element (the combined - // rho and sigma steps). + // rho and pi steps). __ evpermt2q(xmm4, xmm17, xmm3, Assembler::AVX_512bit); __ evpermt2q(xmm3, xmm18, xmm2, Assembler::AVX_512bit); __ evpermt2q(xmm2, xmm17, xmm1, Assembler::AVX_512bit); @@ -279,7 +264,7 @@ address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { __ evpermt2q(xmm2, xmm24, xmm4, Assembler::AVX_512bit); __ evpermt2q(xmm3, xmm25, xmm4, Assembler::AVX_512bit); __ evpermt2q(xmm4, xmm26, xmm5, Assembler::AVX_512bit); - // The combined rho and sigma steps are done. + // The combined rho and pi steps are done. // Do the chi step (the same operation on all 5 rows). // vpternlogq(x, 180, y, z) does x = x ^ (y & ~z). @@ -320,11 +305,9 @@ address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { } // store the state - __ evmovdquq(Address(state, 0), k5, xmm0, true, Assembler::AVX_512bit); - __ evmovdquq(Address(state, 40), k5, xmm1, true, Assembler::AVX_512bit); - __ evmovdquq(Address(state, 80), k5, xmm2, true, Assembler::AVX_512bit); - __ evmovdquq(Address(state, 120), k5, xmm3, true, Assembler::AVX_512bit); - __ evmovdquq(Address(state, 160), k5, xmm4, true, Assembler::AVX_512bit); + for (int i = 0; i < 5; i++) { + __ evmovdquq(Address(state, i * 40), k5, xmm(i), true, Assembler::AVX_512bit); + } __ pop(r14); __ pop(r13); @@ -335,3 +318,193 @@ address StubGenerator::generate_sha3_implCompress(StubGenStubId stub_id) { return start; } + +// Inputs: +// c_rarg0 - long[] state0 +// c_rarg1 - long[] state1 +// +// Performs two keccak() computations in parallel. The steps of the +// two computations are executed interleaved. +static address generate_double_keccak(StubGenerator *stubgen, MacroAssembler *_masm) { + __ align(CodeEntryAlignment); + StubGenStubId stub_id = double_keccak_id; + StubCodeMark mark(stubgen, stub_id); + address start = __ pc(); + + const Register state0 = c_rarg0; + const Register state1 = c_rarg1; + + const Register permsAndRots = c_rarg2; + const Register round_consts = c_rarg3; + const Register constant2use = r10; + const Register roundsLeft = r11; + + Label rounds24_loop; + + __ enter(); + + __ lea(permsAndRots, ExternalAddress(permsAndRotsAddr())); + __ lea(round_consts, ExternalAddress(round_constsAddr())); + + // set up the masks + __ movl(rax, 0x1F); + __ kmovwl(k5, rax); + __ kshiftrwl(k4, k5, 1); + __ kshiftrwl(k3, k5, 2); + __ kshiftrwl(k2, k5, 3); + __ kshiftrwl(k1, k5, 4); + + // load the states + for (int i = 0; i < 5; i++) { + __ evmovdquq(xmm(i), k5, Address(state0, i * 40), false, Assembler::AVX_512bit); + } + for (int i = 0; i < 5; i++) { + __ evmovdquq(xmm(10 + i), k5, Address(state1, i * 40), false, Assembler::AVX_512bit); + } + + // load the permutation and rotation constants + + for (int i = 0; i < 15; i++) { + __ evmovdquq(xmm(17 + i), Address(permsAndRots, i * 64), Assembler::AVX_512bit); + } + + // there will be 24 keccak rounds + // The same operations as the ones in generate_sha3_implCompress are + // performed, but in parallel for two states: one in regs z0-z5, using z6 + // as the scratch register and the other in z10-z15, using z16 as the + // scratch register. + // The permutation and rotation constants, that are loaded into z17-z31, + // are shared between the two computations. + __ movl(roundsLeft, 24); + // load round_constants base + __ movptr(constant2use, round_consts); + + __ align(OptoLoopAlignment); + __ BIND(rounds24_loop); + __ subl( roundsLeft, 1); + + __ evmovdquw(xmm5, xmm0, Assembler::AVX_512bit); + __ evmovdquw(xmm15, xmm10, Assembler::AVX_512bit); + __ vpternlogq(xmm5, 150, xmm1, xmm2, Assembler::AVX_512bit); + __ vpternlogq(xmm15, 150, xmm11, xmm12, Assembler::AVX_512bit); + __ vpternlogq(xmm5, 150, xmm3, xmm4, Assembler::AVX_512bit); + __ vpternlogq(xmm15, 150, xmm13, xmm14, Assembler::AVX_512bit); + __ evprolq(xmm6, xmm5, 1, Assembler::AVX_512bit); + __ evprolq(xmm16, xmm15, 1, Assembler::AVX_512bit); + __ evpermt2q(xmm5, xmm30, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm15, xmm30, xmm15, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm6, Assembler::AVX_512bit); + __ evpermt2q(xmm16, xmm31, xmm16, Assembler::AVX_512bit); + __ vpternlogq(xmm0, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm10, 150, xmm15, xmm16, Assembler::AVX_512bit); + __ vpternlogq(xmm1, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm11, 150, xmm15, xmm16, Assembler::AVX_512bit); + __ vpternlogq(xmm2, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm12, 150, xmm15, xmm16, Assembler::AVX_512bit); + __ vpternlogq(xmm3, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm13, 150, xmm15, xmm16, Assembler::AVX_512bit); + __ vpternlogq(xmm4, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm14, 150, xmm15, xmm16, Assembler::AVX_512bit); + __ evpermt2q(xmm4, xmm17, xmm3, Assembler::AVX_512bit); + __ evpermt2q(xmm14, xmm17, xmm13, Assembler::AVX_512bit); + __ evpermt2q(xmm3, xmm18, xmm2, Assembler::AVX_512bit); + __ evpermt2q(xmm13, xmm18, xmm12, Assembler::AVX_512bit); + __ evpermt2q(xmm2, xmm17, xmm1, Assembler::AVX_512bit); + __ evpermt2q(xmm12, xmm17, xmm11, Assembler::AVX_512bit); + __ evpermt2q(xmm1, xmm19, xmm0, Assembler::AVX_512bit); + __ evpermt2q(xmm11, xmm19, xmm10, Assembler::AVX_512bit); + __ evpermt2q(xmm4, xmm20, xmm2, Assembler::AVX_512bit); + __ evpermt2q(xmm14, xmm20, xmm12, Assembler::AVX_512bit); + __ evprolvq(xmm1, xmm1, xmm27, Assembler::AVX_512bit); + __ evprolvq(xmm11, xmm11, xmm27, Assembler::AVX_512bit); + __ evprolvq(xmm3, xmm3, xmm28, Assembler::AVX_512bit); + __ evprolvq(xmm13, xmm13, xmm28, Assembler::AVX_512bit); + __ evprolvq(xmm4, xmm4, xmm29, Assembler::AVX_512bit); + __ evprolvq(xmm14, xmm14, xmm29, Assembler::AVX_512bit); + __ evmovdquw(xmm2, xmm1, Assembler::AVX_512bit); + __ evmovdquw(xmm12, xmm11, Assembler::AVX_512bit); + __ evmovdquw(xmm5, xmm3, Assembler::AVX_512bit); + __ evmovdquw(xmm15, xmm13, Assembler::AVX_512bit); + __ evpermt2q(xmm0, xmm21, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm10, xmm21, xmm14, Assembler::AVX_512bit); + __ evpermt2q(xmm1, xmm22, xmm3, Assembler::AVX_512bit); + __ evpermt2q(xmm11, xmm22, xmm13, Assembler::AVX_512bit); + __ evpermt2q(xmm5, xmm22, xmm2, Assembler::AVX_512bit); + __ evpermt2q(xmm15, xmm22, xmm12, Assembler::AVX_512bit); + __ evmovdquw(xmm3, xmm1, Assembler::AVX_512bit); + __ evmovdquw(xmm13, xmm11, Assembler::AVX_512bit); + __ evmovdquw(xmm2, xmm5, Assembler::AVX_512bit); + __ evmovdquw(xmm12, xmm15, Assembler::AVX_512bit); + __ evpermt2q(xmm1, xmm23, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm11, xmm23, xmm14, Assembler::AVX_512bit); + __ evpermt2q(xmm2, xmm24, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm12, xmm24, xmm14, Assembler::AVX_512bit); + __ evpermt2q(xmm3, xmm25, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm13, xmm25, xmm14, Assembler::AVX_512bit); + __ evpermt2q(xmm4, xmm26, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm14, xmm26, xmm15, Assembler::AVX_512bit); + + __ evpermt2q(xmm5, xmm31, xmm0, Assembler::AVX_512bit); + __ evpermt2q(xmm15, xmm31, xmm10, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm16, xmm31, xmm15, Assembler::AVX_512bit); + __ vpternlogq(xmm0, 180, xmm6, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm10, 180, xmm16, xmm15, Assembler::AVX_512bit); + + __ evpermt2q(xmm5, xmm31, xmm1, Assembler::AVX_512bit); + __ evpermt2q(xmm15, xmm31, xmm11, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm16, xmm31, xmm15, Assembler::AVX_512bit); + __ vpternlogq(xmm1, 180, xmm6, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm11, 180, xmm16, xmm15, Assembler::AVX_512bit); + + __ evpxorq(xmm0, k1, xmm0, Address(constant2use, 0), true, Assembler::AVX_512bit); + __ evpxorq(xmm10, k1, xmm10, Address(constant2use, 0), true, Assembler::AVX_512bit); + __ addptr(constant2use, 8); + + __ evpermt2q(xmm5, xmm31, xmm2, Assembler::AVX_512bit); + __ evpermt2q(xmm15, xmm31, xmm12, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm16, xmm31, xmm15, Assembler::AVX_512bit); + __ vpternlogq(xmm2, 180, xmm6, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm12, 180, xmm16, xmm15, Assembler::AVX_512bit); + + __ evpermt2q(xmm5, xmm31, xmm3, Assembler::AVX_512bit); + __ evpermt2q(xmm15, xmm31, xmm13, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm16, xmm31, xmm15, Assembler::AVX_512bit); + __ vpternlogq(xmm3, 180, xmm6, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm13, 180, xmm16, xmm15, Assembler::AVX_512bit); + __ evpermt2q(xmm5, xmm31, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm15, xmm31, xmm14, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm16, xmm31, xmm15, Assembler::AVX_512bit); + __ vpternlogq(xmm4, 180, xmm6, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm14, 180, xmm16, xmm15, Assembler::AVX_512bit); + __ cmpl(roundsLeft, 0); + __ jcc(Assembler::notEqual, rounds24_loop); + + // store the states + for (int i = 0; i < 5; i++) { + __ evmovdquq(Address(state0, i * 40), k5, xmm(i), true, Assembler::AVX_512bit); + } + for (int i = 0; i < 5; i++) { + __ evmovdquq(Address(state1, i * 40), k5, xmm(10 + i), true, Assembler::AVX_512bit); + } + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; +} + +void StubGenerator::generate_sha3_stubs() { + if (UseSHA3Intrinsics) { + StubRoutines::_sha3_implCompress = + generate_sha3_implCompress(StubGenStubId::sha3_implCompress_id, this, _masm); + StubRoutines::_double_keccak = + generate_double_keccak(this, _masm); + StubRoutines::_sha3_implCompressMB = + generate_sha3_implCompress(StubGenStubId::sha3_implCompressMB_id, this, _masm); + } +} diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 4b9c1c3416a..c320d4e8a0d 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1246,6 +1246,20 @@ void VM_Version::get_processor_features() { } #endif // _LP64 + // Dilithium Intrinsics + // Currently we only have them for AVX512 +#ifdef _LP64 + if (supports_evex() && supports_avx512bw()) { + if (FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { + UseDilithiumIntrinsics = true; + } + } else +#endif + if (UseDilithiumIntrinsics) { + warning("Intrinsics for ML-DSA are not available on this CPU."); + FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false); + } + // Base64 Intrinsics (Check the condition for which the intrinsic will be active) if (UseAVX >= 2) { if (FLAG_IS_DEFAULT(UseBASE64Intrinsics)) { diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 93b67301b4b..49446b53b98 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -570,7 +570,7 @@ class methodHandle; do_signature(chacha20Block_signature, "([I[B)I") \ \ /* support for sun.security.provider.ML_DSA */ \ - do_class(sun_security_provider_ML_DSA, "sun/security/provider/ML_DSA") \ + do_class(sun_security_provider_ML_DSA, "sun/security/provider/ML_DSA") \ do_signature(IaII_signature, "([II)I") \ do_signature(IaIaI_signature, "([I[I)I") \ do_signature(IaIaIaI_signature, "([I[I[I)I") \ diff --git a/src/hotspot/share/runtime/stubDeclarations.hpp b/src/hotspot/share/runtime/stubDeclarations.hpp index fd86f2ced3f..c061d0b5daf 100644 --- a/src/hotspot/share/runtime/stubDeclarations.hpp +++ b/src/hotspot/share/runtime/stubDeclarations.hpp @@ -740,11 +740,11 @@ do_stub(compiler, sha3_implCompress) \ do_entry(compiler, sha3_implCompress, sha3_implCompress, \ sha3_implCompress) \ + do_stub(compiler, double_keccak) \ + do_entry(compiler, double_keccak, double_keccak, double_keccak) \ do_stub(compiler, sha3_implCompressMB) \ do_entry(compiler, sha3_implCompressMB, sha3_implCompressMB, \ sha3_implCompressMB) \ - do_stub(compiler, double_keccak) \ - do_entry(compiler, double_keccak, double_keccak, double_keccak) \ do_stub(compiler, updateBytesAdler32) \ do_entry(compiler, updateBytesAdler32, updateBytesAdler32, \ updateBytesAdler32) \ diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA.java b/src/java.base/share/classes/sun/security/provider/ML_DSA.java index 969b8fffa39..238b5e9d46a 100644 --- a/src/java.base/share/classes/sun/security/provider/ML_DSA.java +++ b/src/java.base/share/classes/sun/security/provider/ML_DSA.java @@ -26,7 +26,6 @@ package sun.security.provider; import jdk.internal.vm.annotation.IntrinsicCandidate; -import sun.security.provider.SHA3.SHAKE128; import sun.security.provider.SHA3.SHAKE256; import sun.security.provider.SHA3Parallel.Shake128Parallel; @@ -1317,6 +1316,7 @@ public class ML_DSA { */ public static void mlDsaNtt(int[] coeffs) { + assert coeffs.length == ML_DSA_N; implDilithiumAlmostNtt(coeffs, MONT_ZETAS_FOR_VECTOR_NTT); implDilithiumMontMulByConstant(coeffs, MONT_R_MOD_Q); } @@ -1343,6 +1343,7 @@ public class ML_DSA { } public static void mlDsaInverseNtt(int[] coeffs) { + assert coeffs.length == ML_DSA_N; implDilithiumAlmostInverseNtt(coeffs, MONT_ZETAS_FOR_VECTOR_INVERSE_NTT); implDilithiumMontMulByConstant(coeffs, MONT_DIM_INVERSE); } @@ -1382,6 +1383,7 @@ public class ML_DSA { } public static void mlDsaNttMultiply(int[] product, int[] coeffs1, int[] coeffs2) { + assert (coeffs1.length == ML_DSA_N) && (coeffs2.length == ML_DSA_N); implDilithiumNttMult(product, coeffs1, coeffs2); } @@ -1412,6 +1414,8 @@ public class ML_DSA { public static void mlDsaDecomposePoly(int[] input, int[] lowPart, int[] highPart, int twoGamma2, int multiplier) { + assert (input.length == ML_DSA_N) && (lowPart.length == ML_DSA_N) + && (highPart.length == ML_DSA_N); implDilithiumDecomposePoly(input, lowPart, highPart,twoGamma2, multiplier); } diff --git a/test/jdk/sun/security/provider/acvp/Launcher.java b/test/jdk/sun/security/provider/acvp/Launcher.java index 0dfa16678d8..c07b7929d89 100644 --- a/test/jdk/sun/security/provider/acvp/Launcher.java +++ b/test/jdk/sun/security/provider/acvp/Launcher.java @@ -37,6 +37,16 @@ import java.util.zip.ZipFile; * @bug 8342442 8345057 * @library /test/lib * @modules java.base/sun.security.provider + * @run main Launcher + */ + +/* + * @test + * @summary Test verifying the intrinsic implementation. + * @bug 8342442 8345057 + * @library /test/lib + * @modules java.base/sun.security.provider + * @run main/othervm -Xcomp Launcher */ /// This test runs on `internalProjection.json`-style files generated by NIST's From 5c438c5e6b636a7992cbd737de0735070e480061 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Wed, 9 Apr 2025 22:58:44 +0000 Subject: [PATCH 100/843] 8352748: Remove com.sun.tools.classfile from the JDK Reviewed-by: ihse, jlahoda, vromero --- make/modules/jdk.compiler/Gendata.gmk | 2 +- make/modules/jdk.javadoc/Gendata.gmk | 2 +- .../com/sun/tools/javac/code/TargetType.java | 3 +- .../javac/code/TypeAnnotationPosition.java | 3 +- .../com/sun/tools/classfile/AccessFlags.java | 259 ---- .../com/sun/tools/classfile/Annotation.java | 276 ----- .../AnnotationDefault_attribute.java | 61 - .../com/sun/tools/classfile/Attribute.java | 222 ---- .../tools/classfile/AttributeException.java | 41 - .../com/sun/tools/classfile/Attributes.java | 112 -- .../classfile/BootstrapMethods_attribute.java | 90 -- .../CharacterRangeTable_attribute.java | 90 -- .../com/sun/tools/classfile/ClassFile.java | 189 --- .../com/sun/tools/classfile/ClassReader.java | 115 -- .../sun/tools/classfile/ClassTranslator.java | 469 -------- .../com/sun/tools/classfile/ClassWriter.java | 1011 ---------------- .../sun/tools/classfile/Code_attribute.java | 154 --- .../classfile/CompilationID_attribute.java | 63 - .../com/sun/tools/classfile/ConstantPool.java | 1053 ----------------- .../classfile/ConstantPoolException.java | 41 - .../classfile/ConstantValue_attribute.java | 59 - .../sun/tools/classfile/DefaultAttribute.java | 64 - .../tools/classfile/Deprecated_attribute.java | 55 - .../com/sun/tools/classfile/Descriptor.java | 198 ---- .../tools/classfile/DescriptorException.java | 36 - .../classfile/EnclosingMethod_attribute.java | 73 -- .../tools/classfile/Exceptions_attribute.java | 69 -- .../com/sun/tools/classfile/FatalError.java | 40 - .../com/sun/tools/classfile/Field.java | 65 - .../classfile/InnerClasses_attribute.java | 109 -- .../com/sun/tools/classfile/Instruction.java | 357 ------ .../classfile/LineNumberTable_attribute.java | 78 -- .../LocalVariableTable_attribute.java | 84 -- .../LocalVariableTypeTable_attribute.java | 84 -- .../com/sun/tools/classfile/Method.java | 65 - .../classfile/MethodParameters_attribute.java | 92 -- .../classfile/ModuleHashes_attribute.java | 95 -- .../classfile/ModuleMainClass_attribute.java | 64 - .../classfile/ModulePackages_attribute.java | 77 -- .../classfile/ModuleResolution_attribute.java | 69 -- .../classfile/ModuleTarget_attribute.java | 55 - .../sun/tools/classfile/Module_attribute.java | 230 ---- .../tools/classfile/NestHost_attribute.java | 63 - .../classfile/NestMembers_attribute.java | 70 -- .../com/sun/tools/classfile/Opcode.java | 472 -------- .../PermittedSubclasses_attribute.java | 65 - .../sun/tools/classfile/Record_attribute.java | 82 -- .../sun/tools/classfile/ReferenceFinder.java | 253 ---- .../RuntimeAnnotations_attribute.java | 61 - ...RuntimeInvisibleAnnotations_attribute.java | 56 - ...visibleParameterAnnotations_attribute.java | 56 - ...imeInvisibleTypeAnnotations_attribute.java | 56 - ...RuntimeParameterAnnotations_attribute.java | 70 -- .../RuntimeTypeAnnotations_attribute.java | 61 - .../RuntimeVisibleAnnotations_attribute.java | 56 - ...VisibleParameterAnnotations_attribute.java | 56 - ...ntimeVisibleTypeAnnotations_attribute.java | 56 - .../com/sun/tools/classfile/Signature.java | 272 ----- .../tools/classfile/Signature_attribute.java | 67 -- .../SourceDebugExtension_attribute.java | 69 -- .../tools/classfile/SourceFile_attribute.java | 63 - .../tools/classfile/SourceID_attribute.java | 62 - .../classfile/StackMapTable_attribute.java | 380 ------ .../tools/classfile/StackMap_attribute.java | 70 -- .../tools/classfile/Synthetic_attribute.java | 55 - .../classes/com/sun/tools/classfile/Type.java | 378 ------ .../sun/tools/classfile/TypeAnnotation.java | 654 ---------- .../com/sun/tools/classfile/package-info.java | 36 - src/jdk.jdeps/share/classes/module-info.java | 4 +- ...ildcardBoundsNotReadFromClassFileTest.java | 4 +- 70 files changed, 6 insertions(+), 10015 deletions(-) delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Annotation.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/AnnotationDefault_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/AttributeException.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attributes.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/BootstrapMethods_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/CharacterRangeTable_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassFile.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassReader.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Code_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/CompilationID_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPoolException.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantValue_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/DefaultAttribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Deprecated_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Descriptor.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/DescriptorException.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/EnclosingMethod_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Exceptions_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/FatalError.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Field.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/InnerClasses_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Instruction.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/LineNumberTable_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTable_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTypeTable_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Method.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleHashes_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleMainClass_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModulePackages_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleTarget_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestHost_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestMembers_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Opcode.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/PermittedSubclasses_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Record_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleParameterAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeParameterAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleParameterAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceDebugExtension_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceFile_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceID_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMap_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Synthetic_attribute.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/Type.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java delete mode 100644 src/jdk.jdeps/share/classes/com/sun/tools/classfile/package-info.java diff --git a/make/modules/jdk.compiler/Gendata.gmk b/make/modules/jdk.compiler/Gendata.gmk index 5bbd28b8037..2afc6e98e37 100644 --- a/make/modules/jdk.compiler/Gendata.gmk +++ b/make/modules/jdk.compiler/Gendata.gmk @@ -60,7 +60,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \ TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK), \ COMPILER := buildjdk, \ SRC := $(TOPDIR)/make/langtools/src/classes, \ - INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \ + INCLUDES := build/tools/symbolgenerator, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javac, \ DISABLED_WARNINGS := options, \ JAVAC_FLAGS := \ diff --git a/make/modules/jdk.javadoc/Gendata.gmk b/make/modules/jdk.javadoc/Gendata.gmk index 2cd812de779..a97342ffd04 100644 --- a/make/modules/jdk.javadoc/Gendata.gmk +++ b/make/modules/jdk.javadoc/Gendata.gmk @@ -51,7 +51,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \ TARGET_RELEASE := $(TARGET_RELEASE_BOOTJDK), \ SRC := $(TOPDIR)/make/langtools/src/classes \ $(TOPDIR)/src/jdk.jdeps/share/classes, \ - INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \ + INCLUDES := build/tools/symbolgenerator, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols_javadoc, \ DISABLED_WARNINGS := options, \ JAVAC_FLAGS := \ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TargetType.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TargetType.java index 08767493354..bdb08091aa5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TargetType.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TargetType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,6 @@ import com.sun.tools.javac.util.Assert; * This code and its internal interfaces are subject to change or * deletion without notice. */ -// Code duplicated in com.sun.tools.classfile.TypeAnnotation.TargetType public enum TargetType { /** For annotations on a class type parameter declaration. */ CLASS_TYPE_PARAMETER(0x00), diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java index 92fe41adb5b..8c88dec5106 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,6 @@ import com.sun.tools.javac.util.*; * This code and its internal interfaces are subject to change or * deletion without notice. */ -// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position public class TypeAnnotationPosition { public enum TypePathEntryKind { diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java deleted file mode 100644 index 5e9b6853a4d..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * See JVMS, sections 4.2, 4.6, 4.7. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class AccessFlags { - public static final int ACC_PUBLIC = 0x0001; // class, inner, field, method - public static final int ACC_PRIVATE = 0x0002; // inner, field, method - public static final int ACC_PROTECTED = 0x0004; // inner, field, method - public static final int ACC_STATIC = 0x0008; // inner, field, method - public static final int ACC_FINAL = 0x0010; // class, inner, field, method - public static final int ACC_SUPER = 0x0020; // class - public static final int ACC_SYNCHRONIZED = 0x0020; // method - public static final int ACC_VOLATILE = 0x0040; // field - public static final int ACC_BRIDGE = 0x0040; // method - public static final int ACC_TRANSIENT = 0x0080; // field - public static final int ACC_VARARGS = 0x0080; // method - public static final int ACC_NATIVE = 0x0100; // method - public static final int ACC_INTERFACE = 0x0200; // class, inner - public static final int ACC_ABSTRACT = 0x0400; // class, inner, method - public static final int ACC_STRICT = 0x0800; // method - public static final int ACC_SYNTHETIC = 0x1000; // class, inner, field, method - public static final int ACC_ANNOTATION = 0x2000; // class, inner - public static final int ACC_ENUM = 0x4000; // class, inner, field - public static final int ACC_MANDATED = 0x8000; // method parameter - public static final int ACC_MODULE = 0x8000; // class - - public static enum Kind { Class, InnerClass, Field, Method} - - AccessFlags(ClassReader cr) throws IOException { - this(cr.readUnsignedShort()); - } - - public AccessFlags(int flags) { - this.flags = flags; - } - - public AccessFlags ignore(int mask) { - return new AccessFlags(flags & ~mask); - } - - public boolean is(int mask) { - return (flags & mask) != 0; - } - - public int byteLength() { - return 2; - } - - private static final int[] classModifiers = { - ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT - }; - - private static final int[] classFlags = { - ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT, - ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE - }; - - public Set getClassModifiers() { - int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags); - return getModifiers(f, classModifiers, Kind.Class); - } - - public Set getClassFlags() { - return getFlags(classFlags, Kind.Class); - } - - private static final int[] innerClassModifiers = { - ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_ABSTRACT - }; - - private static final int[] innerClassFlags = { - ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER, - ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM - }; - - public Set getInnerClassModifiers() { - int f = ((flags & ACC_INTERFACE) != 0 ? flags & ~ACC_ABSTRACT : flags); - return getModifiers(f, innerClassModifiers, Kind.InnerClass); - } - - public Set getInnerClassFlags() { - return getFlags(innerClassFlags, Kind.InnerClass); - } - - private static final int[] fieldModifiers = { - ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_VOLATILE, ACC_TRANSIENT - }; - - private static final int[] fieldFlags = { - ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM - }; - - public Set getFieldModifiers() { - return getModifiers(fieldModifiers, Kind.Field); - } - - public Set getFieldFlags() { - return getFlags(fieldFlags, Kind.Field); - } - - private static final int[] methodModifiers = { - ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT - }; - - private static final int[] methodFlags = { - ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT, - ACC_STRICT, ACC_SYNTHETIC - }; - - public Set getMethodModifiers() { - return getModifiers(methodModifiers, Kind.Method); - } - - public Set getMethodFlags() { - return getFlags(methodFlags, Kind.Method); - } - - private Set getModifiers(int[] modifierFlags, Kind t) { - return getModifiers(flags, modifierFlags, t); - } - - private static Set getModifiers(int flags, int[] modifierFlags, Kind t) { - Set s = new LinkedHashSet<>(); - for (int m: modifierFlags) { - if ((flags & m) != 0) - s.add(flagToModifier(m, t)); - } - return s; - } - - private Set getFlags(int[] expectedFlags, Kind t) { - Set s = new LinkedHashSet<>(); - int f = flags; - for (int e: expectedFlags) { - if ((f & e) != 0) { - s.add(flagToName(e, t)); - f = f & ~e; - } - } - while (f != 0) { - int bit = Integer.highestOneBit(f); - s.add("0x" + Integer.toHexString(bit)); - f = f & ~bit; - } - return s; - } - - private static String flagToModifier(int flag, Kind t) { - switch (flag) { - case ACC_PUBLIC: - return "public"; - case ACC_PRIVATE: - return "private"; - case ACC_PROTECTED: - return "protected"; - case ACC_STATIC: - return "static"; - case ACC_FINAL: - return "final"; - case ACC_SYNCHRONIZED: - return "synchronized"; - case 0x80: - return (t == Kind.Field ? "transient" : null); - case ACC_VOLATILE: - return "volatile"; - case ACC_NATIVE: - return "native"; - case ACC_ABSTRACT: - return "abstract"; - case ACC_STRICT: - return "strictfp"; - case ACC_MANDATED: - return "mandated"; - default: - return null; - } - } - - private static String flagToName(int flag, Kind t) { - switch (flag) { - case ACC_PUBLIC: - return "ACC_PUBLIC"; - case ACC_PRIVATE: - return "ACC_PRIVATE"; - case ACC_PROTECTED: - return "ACC_PROTECTED"; - case ACC_STATIC: - return "ACC_STATIC"; - case ACC_FINAL: - return "ACC_FINAL"; - case 0x20: - return (t == Kind.Class ? "ACC_SUPER" : "ACC_SYNCHRONIZED"); - case 0x40: - return (t == Kind.Field ? "ACC_VOLATILE" : "ACC_BRIDGE"); - case 0x80: - return (t == Kind.Field ? "ACC_TRANSIENT" : "ACC_VARARGS"); - case ACC_NATIVE: - return "ACC_NATIVE"; - case ACC_INTERFACE: - return "ACC_INTERFACE"; - case ACC_ABSTRACT: - return "ACC_ABSTRACT"; - case ACC_STRICT: - return "ACC_STRICT"; - case ACC_SYNTHETIC: - return "ACC_SYNTHETIC"; - case ACC_ANNOTATION: - return "ACC_ANNOTATION"; - case ACC_ENUM: - return "ACC_ENUM"; - case 0x8000: - return (t == Kind.Class ? "ACC_MODULE" : "ACC_MANDATED"); - default: - return null; - } - } - - public final int flags; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Annotation.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Annotation.java deleted file mode 100644 index caf148944ab..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Annotation.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.16. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Annotation { - static class InvalidAnnotation extends AttributeException { - private static final long serialVersionUID = -4620480740735772708L; - InvalidAnnotation(String msg) { - super(msg); - } - } - - Annotation(ClassReader cr) throws IOException, InvalidAnnotation { - type_index = cr.readUnsignedShort(); - num_element_value_pairs = cr.readUnsignedShort(); - element_value_pairs = new element_value_pair[num_element_value_pairs]; - for (int i = 0; i < element_value_pairs.length; i++) - element_value_pairs[i] = new element_value_pair(cr); - } - - public Annotation(ConstantPool constant_pool, - int type_index, - element_value_pair[] element_value_pairs) { - this.type_index = type_index; - num_element_value_pairs = element_value_pairs.length; - this.element_value_pairs = element_value_pairs; - } - - public int length() { - int n = 2 /*type_index*/ + 2 /*num_element_value_pairs*/; - for (element_value_pair pair: element_value_pairs) - n += pair.length(); - return n; - } - - public final int type_index; - public final int num_element_value_pairs; - public final element_value_pair element_value_pairs[]; - - /** - * See JVMS, section 4.8.16.1. - */ - public abstract static class element_value { - public static element_value read(ClassReader cr) - throws IOException, InvalidAnnotation { - int tag = cr.readUnsignedByte(); - switch (tag) { - case 'B': - case 'C': - case 'D': - case 'F': - case 'I': - case 'J': - case 'S': - case 'Z': - case 's': - return new Primitive_element_value(cr, tag); - - case 'e': - return new Enum_element_value(cr, tag); - - case 'c': - return new Class_element_value(cr, tag); - - case '@': - return new Annotation_element_value(cr, tag); - - case '[': - return new Array_element_value(cr, tag); - - default: - throw new InvalidAnnotation("unrecognized tag: " + tag); - } - } - - protected element_value(int tag) { - this.tag = tag; - } - - public abstract int length(); - - public abstract R accept(Visitor visitor, P p); - - public interface Visitor { - R visitPrimitive(Primitive_element_value ev, P p); - R visitEnum(Enum_element_value ev, P p); - R visitClass(Class_element_value ev, P p); - R visitAnnotation(Annotation_element_value ev, P p); - R visitArray(Array_element_value ev, P p); - } - - public final int tag; - } - - public static class Primitive_element_value extends element_value { - Primitive_element_value(ClassReader cr, int tag) throws IOException { - super(tag); - const_value_index = cr.readUnsignedShort(); - } - - public Primitive_element_value(int const_value_index, int tag) { - super(tag); - this.const_value_index = const_value_index; - } - - @Override - public int length() { - return 2; - } - - public R accept(Visitor visitor, P p) { - return visitor.visitPrimitive(this, p); - } - - public final int const_value_index; - - } - - public static class Enum_element_value extends element_value { - Enum_element_value(ClassReader cr, int tag) throws IOException { - super(tag); - type_name_index = cr.readUnsignedShort(); - const_name_index = cr.readUnsignedShort(); - } - - public Enum_element_value(int type_name_index, int const_name_index, int tag) { - super(tag); - this.type_name_index = type_name_index; - this.const_name_index = const_name_index; - } - - @Override - public int length() { - return 4; - } - - public R accept(Visitor visitor, P p) { - return visitor.visitEnum(this, p); - } - - public final int type_name_index; - public final int const_name_index; - } - - public static class Class_element_value extends element_value { - Class_element_value(ClassReader cr, int tag) throws IOException { - super(tag); - class_info_index = cr.readUnsignedShort(); - } - - public Class_element_value(int class_info_index, int tag) { - super(tag); - this.class_info_index = class_info_index; - } - - @Override - public int length() { - return 2; - } - - public R accept(Visitor visitor, P p) { - return visitor.visitClass(this, p); - } - - public final int class_info_index; - } - - public static class Annotation_element_value extends element_value { - Annotation_element_value(ClassReader cr, int tag) - throws IOException, InvalidAnnotation { - super(tag); - annotation_value = new Annotation(cr); - } - - public Annotation_element_value(Annotation annotation_value, int tag) { - super(tag); - this.annotation_value = annotation_value; - } - - @Override - public int length() { - return annotation_value.length(); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitAnnotation(this, p); - } - - public final Annotation annotation_value; - } - - public static class Array_element_value extends element_value { - Array_element_value(ClassReader cr, int tag) - throws IOException, InvalidAnnotation { - super(tag); - num_values = cr.readUnsignedShort(); - values = new element_value[num_values]; - for (int i = 0; i < values.length; i++) - values[i] = element_value.read(cr); - } - - public Array_element_value(element_value[] values, int tag) { - super(tag); - this.num_values = values.length; - this.values = values; - } - - @Override - public int length() { - int n = 2; - for (int i = 0; i < values.length; i++) - n += values[i].length(); - return n; - } - - public R accept(Visitor visitor, P p) { - return visitor.visitArray(this, p); - } - - public final int num_values; - public final element_value[] values; - } - - public static class element_value_pair { - element_value_pair(ClassReader cr) - throws IOException, InvalidAnnotation { - element_name_index = cr.readUnsignedShort(); - value = element_value.read(cr); - } - - public element_value_pair(int element_name_index, element_value value) { - this.element_name_index = element_name_index; - this.value = value; - } - - public int length() { - return 2 + value.length(); - } - - public final int element_name_index; - public final element_value value; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AnnotationDefault_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AnnotationDefault_attribute.java deleted file mode 100644 index 1ca7fc4565c..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AnnotationDefault_attribute.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.15. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class AnnotationDefault_attribute extends Attribute { - AnnotationDefault_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(name_index, length); - default_value = Annotation.element_value.read(cr); - } - - public AnnotationDefault_attribute(ConstantPool constant_pool, Annotation.element_value default_value) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.AnnotationDefault), default_value); - } - - public AnnotationDefault_attribute(int name_index, Annotation.element_value default_value) { - super(name_index, default_value.length()); - this.default_value = default_value; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitAnnotationDefault(this, data); - } - - public final Annotation.element_value default_value; -} - diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java deleted file mode 100644 index 3ab3fce1863..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2007, 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. - */ - -package com.sun.tools.classfile; - -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.util.HashMap; -import java.util.Map; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ - -public abstract class Attribute { - public static final String AnnotationDefault = "AnnotationDefault"; - public static final String BootstrapMethods = "BootstrapMethods"; - public static final String CharacterRangeTable = "CharacterRangeTable"; - public static final String Code = "Code"; - public static final String ConstantValue = "ConstantValue"; - public static final String CompilationID = "CompilationID"; - public static final String Deprecated = "Deprecated"; - public static final String EnclosingMethod = "EnclosingMethod"; - public static final String Exceptions = "Exceptions"; - public static final String InnerClasses = "InnerClasses"; - public static final String LineNumberTable = "LineNumberTable"; - public static final String LocalVariableTable = "LocalVariableTable"; - public static final String LocalVariableTypeTable = "LocalVariableTypeTable"; - public static final String MethodParameters = "MethodParameters"; - public static final String Module = "Module"; - public static final String ModuleHashes = "ModuleHashes"; - public static final String ModuleMainClass = "ModuleMainClass"; - public static final String ModulePackages = "ModulePackages"; - public static final String ModuleResolution = "ModuleResolution"; - public static final String ModuleTarget = "ModuleTarget"; - public static final String NestHost = "NestHost"; - public static final String NestMembers = "NestMembers"; - public static final String Record = "Record"; - public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations"; - public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations"; - public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations"; - public static final String RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations"; - public static final String RuntimeVisibleTypeAnnotations = "RuntimeVisibleTypeAnnotations"; - public static final String RuntimeInvisibleTypeAnnotations = "RuntimeInvisibleTypeAnnotations"; - public static final String PermittedSubclasses = "PermittedSubclasses"; - public static final String Signature = "Signature"; - public static final String SourceDebugExtension = "SourceDebugExtension"; - public static final String SourceFile = "SourceFile"; - public static final String SourceID = "SourceID"; - public static final String StackMap = "StackMap"; - public static final String StackMapTable = "StackMapTable"; - public static final String Synthetic = "Synthetic"; - - public static class Factory { - public Factory() { - // defer init of standardAttributeClasses until after options set up - } - - public Attribute createAttribute(ClassReader cr, int name_index, byte[] data) - throws IOException { - if (standardAttributes == null) { - init(); - } - - ConstantPool cp = cr.getConstantPool(); - String reasonForDefaultAttr; - try { - String name = cp.getUTF8Value(name_index); - Class attrClass = standardAttributes.get(name); - if (attrClass != null) { - try { - Class[] constrArgTypes = {ClassReader.class, int.class, int.class}; - Constructor constr = attrClass.getDeclaredConstructor(constrArgTypes); - return constr.newInstance(cr, name_index, data.length); - } catch (Throwable t) { - reasonForDefaultAttr = t.toString(); - // fall through and use DefaultAttribute - // t.printStackTrace(); - } - } else { - reasonForDefaultAttr = "unknown attribute"; - } - } catch (ConstantPoolException e) { - reasonForDefaultAttr = e.toString(); - // fall through and use DefaultAttribute - } - return new DefaultAttribute(cr, name_index, data, reasonForDefaultAttr); - } - - protected void init() { - standardAttributes = new HashMap<>(); - standardAttributes.put(AnnotationDefault, AnnotationDefault_attribute.class); - standardAttributes.put(BootstrapMethods, BootstrapMethods_attribute.class); - standardAttributes.put(CharacterRangeTable, CharacterRangeTable_attribute.class); - standardAttributes.put(Code, Code_attribute.class); - standardAttributes.put(CompilationID, CompilationID_attribute.class); - standardAttributes.put(ConstantValue, ConstantValue_attribute.class); - standardAttributes.put(Deprecated, Deprecated_attribute.class); - standardAttributes.put(EnclosingMethod, EnclosingMethod_attribute.class); - standardAttributes.put(Exceptions, Exceptions_attribute.class); - standardAttributes.put(InnerClasses, InnerClasses_attribute.class); - standardAttributes.put(LineNumberTable, LineNumberTable_attribute.class); - standardAttributes.put(LocalVariableTable, LocalVariableTable_attribute.class); - standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class); - standardAttributes.put(MethodParameters, MethodParameters_attribute.class); - standardAttributes.put(Module, Module_attribute.class); - standardAttributes.put(ModuleHashes, ModuleHashes_attribute.class); - standardAttributes.put(ModuleMainClass, ModuleMainClass_attribute.class); - standardAttributes.put(ModulePackages, ModulePackages_attribute.class); - standardAttributes.put(ModuleResolution, ModuleResolution_attribute.class); - standardAttributes.put(ModuleTarget, ModuleTarget_attribute.class); - standardAttributes.put(NestHost, NestHost_attribute.class); - standardAttributes.put(NestMembers, NestMembers_attribute.class); - standardAttributes.put(Record, Record_attribute.class); - standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class); - standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class); - standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class); - standardAttributes.put(RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations_attribute.class); - standardAttributes.put(RuntimeVisibleTypeAnnotations, RuntimeVisibleTypeAnnotations_attribute.class); - standardAttributes.put(RuntimeInvisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations_attribute.class); - standardAttributes.put(PermittedSubclasses, PermittedSubclasses_attribute.class); - standardAttributes.put(Signature, Signature_attribute.class); - standardAttributes.put(SourceDebugExtension, SourceDebugExtension_attribute.class); - standardAttributes.put(SourceFile, SourceFile_attribute.class); - standardAttributes.put(SourceID, SourceID_attribute.class); - standardAttributes.put(StackMap, StackMap_attribute.class); - standardAttributes.put(StackMapTable, StackMapTable_attribute.class); - standardAttributes.put(Synthetic, Synthetic_attribute.class); - } - - private Map> standardAttributes; - } - - public static Attribute read(ClassReader cr) throws IOException { - return cr.readAttribute(); - } - - protected Attribute(int name_index, int length) { - attribute_name_index = name_index; - attribute_length = length; - } - - public String getName(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(attribute_name_index); - } - - public abstract R accept(Attribute.Visitor visitor, D data); - - public int byteLength() { - return 6 + attribute_length; - } - - public final int attribute_name_index; - public final int attribute_length; - - - public interface Visitor { - R visitBootstrapMethods(BootstrapMethods_attribute attr, P p); - R visitDefault(DefaultAttribute attr, P p); - R visitAnnotationDefault(AnnotationDefault_attribute attr, P p); - R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p); - R visitCode(Code_attribute attr, P p); - R visitCompilationID(CompilationID_attribute attr, P p); - R visitConstantValue(ConstantValue_attribute attr, P p); - R visitDeprecated(Deprecated_attribute attr, P p); - R visitEnclosingMethod(EnclosingMethod_attribute attr, P p); - R visitExceptions(Exceptions_attribute attr, P p); - R visitInnerClasses(InnerClasses_attribute attr, P p); - R visitLineNumberTable(LineNumberTable_attribute attr, P p); - R visitLocalVariableTable(LocalVariableTable_attribute attr, P p); - R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p); - R visitMethodParameters(MethodParameters_attribute attr, P p); - R visitModule(Module_attribute attr, P p); - R visitModuleHashes(ModuleHashes_attribute attr, P p); - R visitModuleMainClass(ModuleMainClass_attribute attr, P p); - R visitModulePackages(ModulePackages_attribute attr, P p); - R visitModuleResolution(ModuleResolution_attribute attr, P p); - R visitModuleTarget(ModuleTarget_attribute attr, P p); - R visitNestHost(NestHost_attribute attr, P p); - R visitNestMembers(NestMembers_attribute attr, P p); - R visitRecord(Record_attribute attr, P p); - R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p); - R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p); - R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p); - R visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, P p); - R visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, P p); - R visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, P p); - R visitPermittedSubclasses(PermittedSubclasses_attribute attr, P p); - R visitSignature(Signature_attribute attr, P p); - R visitSourceDebugExtension(SourceDebugExtension_attribute attr, P p); - R visitSourceFile(SourceFile_attribute attr, P p); - R visitSourceID(SourceID_attribute attr, P p); - R visitStackMap(StackMap_attribute attr, P p); - R visitStackMapTable(StackMapTable_attribute attr, P p); - R visitSynthetic(Synthetic_attribute attr, P p); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AttributeException.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AttributeException.java deleted file mode 100644 index a4682c02515..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AttributeException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class AttributeException extends Exception { - private static final long serialVersionUID = -4231486387714867770L; - AttributeException() { } - - AttributeException(String msg) { - super(msg); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attributes.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attributes.java deleted file mode 100644 index 0bc75ac1a24..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attributes.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Attributes implements Iterable { - - public final Attribute[] attrs; - public final Map map; - - Attributes(ClassReader cr) throws IOException { - map = new HashMap<>(); - int attrs_count = cr.readUnsignedShort(); - attrs = new Attribute[attrs_count]; - for (int i = 0; i < attrs_count; i++) { - Attribute attr = Attribute.read(cr); - attrs[i] = attr; - try { - map.put(attr.getName(cr.getConstantPool()), attr); - } catch (ConstantPoolException e) { - // don't enter invalid names in map - } - } - } - - public Attributes(ConstantPool constant_pool, Attribute[] attrs) { - this.attrs = attrs; - map = new HashMap<>(); - for (Attribute attr : attrs) { - try { - map.put(attr.getName(constant_pool), attr); - } catch (ConstantPoolException e) { - // don't enter invalid names in map - } - } - } - - public Attributes(Map attributes) { - this.attrs = attributes.values().toArray(new Attribute[attributes.size()]); - map = attributes; - } - - public Iterator iterator() { - return Arrays.asList(attrs).iterator(); - } - - public Attribute get(int index) { - return attrs[index]; - } - - public Attribute get(String name) { - return map.get(name); - } - - public int getIndex(ConstantPool constant_pool, String name) { - for (int i = 0; i < attrs.length; i++) { - Attribute attr = attrs[i]; - try { - if (attr != null && attr.getName(constant_pool).equals(name)) - return i; - } catch (ConstantPoolException e) { - // ignore invalid entries - } - } - return -1; - } - - public int size() { - return attrs.length; - } - - public int byteLength() { - int length = 2; - for (Attribute a: attrs) - length += a.byteLength(); - return length; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/BootstrapMethods_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/BootstrapMethods_attribute.java deleted file mode 100644 index 69d034788cc..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/BootstrapMethods_attribute.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS 4.7.21 - * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.21 - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class BootstrapMethods_attribute extends Attribute { - public final BootstrapMethodSpecifier[] bootstrap_method_specifiers; - - BootstrapMethods_attribute(ClassReader cr, int name_index, int length) - throws IOException, AttributeException { - super(name_index, length); - int bootstrap_method_count = cr.readUnsignedShort(); - bootstrap_method_specifiers = new BootstrapMethodSpecifier[bootstrap_method_count]; - for (int i = 0; i < bootstrap_method_specifiers.length; i++) - bootstrap_method_specifiers[i] = new BootstrapMethodSpecifier(cr); - } - - public BootstrapMethods_attribute(int name_index, BootstrapMethodSpecifier[] bootstrap_method_specifiers) { - super(name_index, length(bootstrap_method_specifiers)); - this.bootstrap_method_specifiers = bootstrap_method_specifiers; - } - - public static int length(BootstrapMethodSpecifier[] bootstrap_method_specifiers) { - int n = 2; - for (BootstrapMethodSpecifier b : bootstrap_method_specifiers) - n += b.length(); - return n; - } - - @Override - public R accept(Visitor visitor, P p) { - return visitor.visitBootstrapMethods(this, p); - } - - public static class BootstrapMethodSpecifier { - public int bootstrap_method_ref; - public int[] bootstrap_arguments; - - public BootstrapMethodSpecifier(int bootstrap_method_ref, int[] bootstrap_arguments) { - this.bootstrap_method_ref = bootstrap_method_ref; - this.bootstrap_arguments = bootstrap_arguments; - } - BootstrapMethodSpecifier(ClassReader cr) throws IOException { - bootstrap_method_ref = cr.readUnsignedShort(); - int method_count = cr.readUnsignedShort(); - bootstrap_arguments = new int[method_count]; - for (int i = 0; i < bootstrap_arguments.length; i++) { - bootstrap_arguments[i] = cr.readUnsignedShort(); - } - } - - int length() { - // u2 (method_ref) + u2 (argc) + u2 * argc - return 2 + 2 + (bootstrap_arguments.length * 2); - } - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CharacterRangeTable_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CharacterRangeTable_attribute.java deleted file mode 100644 index 2b1425789f4..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CharacterRangeTable_attribute.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class CharacterRangeTable_attribute extends Attribute { - public static final int CRT_STATEMENT = 0x0001; - public static final int CRT_BLOCK = 0x0002; - public static final int CRT_ASSIGNMENT = 0x0004; - public static final int CRT_FLOW_CONTROLLER = 0x0008; - public static final int CRT_FLOW_TARGET = 0x0010; - public static final int CRT_INVOKE = 0x0020; - public static final int CRT_CREATE = 0x0040; - public static final int CRT_BRANCH_TRUE = 0x0080; - public static final int CRT_BRANCH_FALSE = 0x0100; - - CharacterRangeTable_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - int character_range_table_length = cr.readUnsignedShort(); - character_range_table = new Entry[character_range_table_length]; - for (int i = 0; i < character_range_table_length; i++) - character_range_table[i] = new Entry(cr); - } - - public CharacterRangeTable_attribute(ConstantPool constant_pool, Entry[] character_range_table) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.CharacterRangeTable), character_range_table); - } - - public CharacterRangeTable_attribute(int name_index, Entry[] character_range_table) { - super(name_index, 2 + character_range_table.length * Entry.length()); - this.character_range_table = character_range_table; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitCharacterRangeTable(this, data); - } - - public final Entry[] character_range_table; - - public static class Entry { - Entry(ClassReader cr) throws IOException { - start_pc = cr.readUnsignedShort(); - end_pc = cr.readUnsignedShort(); - character_range_start = cr.readInt(); - character_range_end = cr.readInt(); - flags = cr.readUnsignedShort(); - } - - public static int length() { - return 14; - } - - public final int start_pc; - public final int end_pc; - public final int character_range_start; - public final int character_range_end; - public final int flags; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassFile.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassFile.java deleted file mode 100644 index 52aefca5469..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassFile.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; - -import static com.sun.tools.classfile.AccessFlags.*; - -/** - * See JVMS, section 4.2. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ClassFile { - public static ClassFile read(File file) - throws IOException, ConstantPoolException { - return read(file.toPath(), new Attribute.Factory()); - } - - public static ClassFile read(Path input) - throws IOException, ConstantPoolException { - return read(input, new Attribute.Factory()); - } - - public static ClassFile read(Path input, Attribute.Factory attributeFactory) - throws IOException, ConstantPoolException { - try (InputStream in = Files.newInputStream(input)) { - return new ClassFile(in, attributeFactory); - } - } - - public static ClassFile read(File file, Attribute.Factory attributeFactory) - throws IOException, ConstantPoolException { - return read(file.toPath(), attributeFactory); - } - - public static ClassFile read(InputStream in) - throws IOException, ConstantPoolException { - return new ClassFile(in, new Attribute.Factory()); - } - - public static ClassFile read(InputStream in, Attribute.Factory attributeFactory) - throws IOException, ConstantPoolException { - return new ClassFile(in, attributeFactory); - } - - ClassFile(InputStream in, Attribute.Factory attributeFactory) throws IOException, ConstantPoolException { - ClassReader cr = new ClassReader(this, in, attributeFactory); - magic = cr.readInt(); - minor_version = cr.readUnsignedShort(); - major_version = cr.readUnsignedShort(); - constant_pool = new ConstantPool(cr); - access_flags = new AccessFlags(cr); - this_class = cr.readUnsignedShort(); - super_class = cr.readUnsignedShort(); - - int interfaces_count = cr.readUnsignedShort(); - interfaces = new int[interfaces_count]; - for (int i = 0; i < interfaces_count; i++) - interfaces[i] = cr.readUnsignedShort(); - - int fields_count = cr.readUnsignedShort(); - fields = new Field[fields_count]; - for (int i = 0; i < fields_count; i++) - fields[i] = new Field(cr); - - int methods_count = cr.readUnsignedShort(); - methods = new Method[methods_count]; - for (int i = 0; i < methods_count; i++) - methods[i] = new Method(cr); - - attributes = new Attributes(cr); - } - - public ClassFile(int magic, int minor_version, int major_version, - ConstantPool constant_pool, AccessFlags access_flags, - int this_class, int super_class, int[] interfaces, - Field[] fields, Method[] methods, Attributes attributes) { - this.magic = magic; - this.minor_version = minor_version; - this.major_version = major_version; - this.constant_pool = constant_pool; - this.access_flags = access_flags; - this.this_class = this_class; - this.super_class = super_class; - this.interfaces = interfaces; - this.fields = fields; - this.methods = methods; - this.attributes = attributes; - } - - public String getName() throws ConstantPoolException { - return constant_pool.getClassInfo(this_class).getName(); - } - - public String getSuperclassName() throws ConstantPoolException { - return constant_pool.getClassInfo(super_class).getName(); - } - - public String getInterfaceName(int i) throws ConstantPoolException { - return constant_pool.getClassInfo(interfaces[i]).getName(); - } - - public Attribute getAttribute(String name) { - return attributes.get(name); - } - - public boolean isClass() { - return !isInterface(); - } - - public boolean isInterface() { - return access_flags.is(ACC_INTERFACE); - } - - public int byteLength() { - return 4 + // magic - 2 + // minor - 2 + // major - constant_pool.byteLength() + - 2 + // access flags - 2 + // this_class - 2 + // super_class - byteLength(interfaces) + - byteLength(fields) + - byteLength(methods) + - attributes.byteLength(); - } - - private int byteLength(int[] indices) { - return 2 + 2 * indices.length; - } - - private int byteLength(Field[] fields) { - int length = 2; - for (Field f: fields) - length += f.byteLength(); - return length; - } - - private int byteLength(Method[] methods) { - int length = 2; - for (Method m: methods) - length += m.byteLength(); - return length; - } - - public final int magic; - public final int minor_version; - public final int major_version; - public final ConstantPool constant_pool; - public final AccessFlags access_flags; - public final int this_class; - public final int super_class; - public final int[] interfaces; - public final Field[] fields; - public final Method[] methods; - public final Attributes attributes; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassReader.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassReader.java deleted file mode 100644 index 6511d0f905c..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassReader.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2007, 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. - */ - -package com.sun.tools.classfile; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Objects; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ClassReader { - ClassReader(ClassFile classFile, InputStream in, Attribute.Factory attributeFactory) throws IOException { - this.classFile = Objects.requireNonNull(classFile); - this.attributeFactory = Objects.requireNonNull(attributeFactory); - this.in = new DataInputStream(new BufferedInputStream(in)); - } - - ClassFile getClassFile() { - return classFile; - } - - ConstantPool getConstantPool() { - return classFile.constant_pool; - } - - public Attribute readAttribute() throws IOException { - int name_index = readUnsignedShort(); - int length = readInt(); - if (length < 0) { // we have an overflow as max_value(u4) > max_value(int) - String attrName; - try { - attrName = getConstantPool().getUTF8Value(name_index); - } catch (ConstantPool.InvalidIndex | ConstantPool.UnexpectedEntry e) { - attrName = ""; - } - throw new FatalError(String.format("attribute %s too big to handle", attrName)); - } - byte[] data = new byte[length]; - readFully(data); - - DataInputStream prev = in; - in = new DataInputStream(new ByteArrayInputStream(data)); - try { - return attributeFactory.createAttribute(this, name_index, data); - } finally { - in = prev; - } - } - - public void readFully(byte[] b) throws IOException { - in.readFully(b); - } - - public int readUnsignedByte() throws IOException { - return in.readUnsignedByte(); - } - - public int readUnsignedShort() throws IOException { - return in.readUnsignedShort(); - } - - public int readInt() throws IOException { - return in.readInt(); - } - - public long readLong() throws IOException { - return in.readLong(); - } - - public float readFloat() throws IOException { - return in.readFloat(); - } - - public double readDouble() throws IOException { - return in.readDouble(); - } - - public String readUTF() throws IOException { - return in.readUTF(); - } - - private DataInputStream in; - private ClassFile classFile; - private Attribute.Factory attributeFactory; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java deleted file mode 100644 index 2725fc3d418..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.util.Map; - -import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Dynamic_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Fieldref_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Integer_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_InterfaceMethodref_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Long_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodType_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Module_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Package_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; -import com.sun.tools.classfile.ConstantPool.CPInfo; - -/** - * Rewrites a class file using a map of translations. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ClassTranslator - implements ConstantPool.Visitor> { - /** - * Create a new ClassFile from {@code cf}, such that for all entries - * {@code k -\> v} in {@code translations}, - * each occurrence of {@code k} in {@code cf} will be replaced by {@code v}. - * in - * @param cf the class file to be processed - * @param translations the set of translations to be applied - * @return a copy of {@code} with the values in {@code translations} substituted - */ - public ClassFile translate(ClassFile cf, Map translations) { - ClassFile cf2 = (ClassFile) translations.get(cf); - if (cf2 == null) { - ConstantPool constant_pool2 = translate(cf.constant_pool, translations); - Field[] fields2 = translate(cf.fields, cf.constant_pool, translations); - Method[] methods2 = translateMethods(cf.methods, cf.constant_pool, translations); - Attributes attributes2 = translateAttributes(cf.attributes, cf.constant_pool, - translations); - - if (constant_pool2 == cf.constant_pool && - fields2 == cf.fields && - methods2 == cf.methods && - attributes2 == cf.attributes) - cf2 = cf; - else - cf2 = new ClassFile( - cf.magic, - cf.minor_version, - cf.major_version, - constant_pool2, - cf.access_flags, - cf.this_class, - cf.super_class, - cf.interfaces, - fields2, - methods2, - attributes2); - translations.put(cf, cf2); - } - return cf2; - } - - ConstantPool translate(ConstantPool cp, Map translations) { - ConstantPool cp2 = (ConstantPool) translations.get(cp); - if (cp2 == null) { - ConstantPool.CPInfo[] pool2 = new ConstantPool.CPInfo[cp.size()]; - boolean eq = true; - for (int i = 0; i < cp.size(); ) { - ConstantPool.CPInfo cpInfo; - try { - cpInfo = cp.get(i); - } catch (ConstantPool.InvalidIndex e) { - throw new IllegalStateException(e); - } - ConstantPool.CPInfo cpInfo2 = translate(cpInfo, translations); - eq &= (cpInfo == cpInfo2); - pool2[i] = cpInfo2; - if (cpInfo.getTag() != cpInfo2.getTag()) - throw new IllegalStateException(); - i += cpInfo.size(); - } - - if (eq) - cp2 = cp; - else - cp2 = new ConstantPool(pool2); - - translations.put(cp, cp2); - } - return cp2; - } - - ConstantPool.CPInfo translate(ConstantPool.CPInfo cpInfo, Map translations) { - ConstantPool.CPInfo cpInfo2 = (ConstantPool.CPInfo) translations.get(cpInfo); - if (cpInfo2 == null) { - cpInfo2 = cpInfo.accept(this, translations); - translations.put(cpInfo, cpInfo2); - } - return cpInfo2; - } - - Field[] translate(Field[] fields, ConstantPool constant_pool, Map translations) { - Field[] fields2 = (Field[]) translations.get(fields); - if (fields2 == null) { - fields2 = new Field[fields.length]; - for (int i = 0; i < fields.length; i++) - fields2[i] = translate(fields[i], constant_pool, translations); - if (equal(fields, fields2)) - fields2 = fields; - translations.put(fields, fields2); - } - return fields2; - } - - Field translate(Field field, ConstantPool constant_pool, Map translations) { - Field field2 = (Field) translations.get(field); - if (field2 == null) { - Attributes attributes2 = translateAttributes(field.attributes, constant_pool, - translations); - - if (attributes2 == field.attributes) - field2 = field; - else - field2 = new Field( - field.access_flags, - field.name_index, - field.descriptor, - attributes2); - translations.put(field, field2); - } - return field2; - } - - Method[] translateMethods(Method[] methods, ConstantPool constant_pool, Map translations) { - Method[] methods2 = (Method[]) translations.get(methods); - if (methods2 == null) { - methods2 = new Method[methods.length]; - for (int i = 0; i < methods.length; i++) - methods2[i] = translate(methods[i], constant_pool, translations); - if (equal(methods, methods2)) - methods2 = methods; - translations.put(methods, methods2); - } - return methods2; - } - - Method translate(Method method, ConstantPool constant_pool, Map translations) { - Method method2 = (Method) translations.get(method); - if (method2 == null) { - Attributes attributes2 = translateAttributes(method.attributes, constant_pool, - translations); - - if (attributes2 == method.attributes) - method2 = method; - else - method2 = new Method( - method.access_flags, - method.name_index, - method.descriptor, - attributes2); - translations.put(method, method2); - } - return method2; - } - - Attributes translateAttributes(Attributes attributes, - ConstantPool constant_pool, Map translations) { - Attributes attributes2 = (Attributes) translations.get(attributes); - if (attributes2 == null) { - Attribute[] attrArray2 = new Attribute[attributes.size()]; - ConstantPool constant_pool2 = translate(constant_pool, translations); - boolean attrsEqual = true; - for (int i = 0; i < attributes.size(); i++) { - Attribute attr = attributes.get(i); - Attribute attr2 = translate(attr, translations); - if (attr2 != attr) - attrsEqual = false; - attrArray2[i] = attr2; - } - if ((constant_pool2 == constant_pool) && attrsEqual) - attributes2 = attributes; - else - attributes2 = new Attributes(constant_pool2, attrArray2); - translations.put(attributes, attributes2); - } - return attributes2; - } - - Attribute translate(Attribute attribute, Map translations) { - Attribute attribute2 = (Attribute) translations.get(attribute); - if (attribute2 == null) { - attribute2 = attribute; // don't support translation within attributes yet - // (what about Code attribute) - translations.put(attribute, attribute2); - } - return attribute2; - } - - private static boolean equal(T[] a1, T[] a2) { - if (a1 == null || a2 == null) - return (a1 == a2); - if (a1.length != a2.length) - return false; - for (int i = 0; i < a1.length; i++) { - if (a1[i] != a2[i]) - return false; - } - return true; - } - - @Override - public CPInfo visitClass(CONSTANT_Class_info info, Map translations) { - CONSTANT_Class_info info2 = (CONSTANT_Class_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_Class_info(cp2, info.name_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitDouble(CONSTANT_Double_info info, Map translations) { - CONSTANT_Double_info info2 = (CONSTANT_Double_info) translations.get(info); - if (info2 == null) { - info2 = info; - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitFieldref(CONSTANT_Fieldref_info info, Map translations) { - CONSTANT_Fieldref_info info2 = (CONSTANT_Fieldref_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_Fieldref_info(cp2, info.class_index, info.name_and_type_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitFloat(CONSTANT_Float_info info, Map translations) { - CONSTANT_Float_info info2 = (CONSTANT_Float_info) translations.get(info); - if (info2 == null) { - info2 = info; - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitInteger(CONSTANT_Integer_info info, Map translations) { - CONSTANT_Integer_info info2 = (CONSTANT_Integer_info) translations.get(info); - if (info2 == null) { - info2 = info; - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Map translations) { - CONSTANT_InterfaceMethodref_info info2 = (CONSTANT_InterfaceMethodref_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_InterfaceMethodref_info(cp2, info.class_index, info.name_and_type_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Map translations) { - CONSTANT_InvokeDynamic_info info2 = (CONSTANT_InvokeDynamic_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) { - info2 = info; - } else { - info2 = new CONSTANT_InvokeDynamic_info(cp2, info.bootstrap_method_attr_index, info.name_and_type_index); - } - translations.put(info, info2); - } - return info; - } - - public CPInfo visitDynamicConstant(CONSTANT_Dynamic_info info, Map translations) { - CONSTANT_Dynamic_info info2 = (CONSTANT_Dynamic_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) { - info2 = info; - } else { - info2 = new CONSTANT_Dynamic_info(cp2, info.bootstrap_method_attr_index, info.name_and_type_index); - } - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitLong(CONSTANT_Long_info info, Map translations) { - CONSTANT_Long_info info2 = (CONSTANT_Long_info) translations.get(info); - if (info2 == null) { - info2 = info; - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitMethodref(CONSTANT_Methodref_info info, Map translations) { - CONSTANT_Methodref_info info2 = (CONSTANT_Methodref_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_Methodref_info(cp2, info.class_index, info.name_and_type_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitMethodHandle(CONSTANT_MethodHandle_info info, Map translations) { - CONSTANT_MethodHandle_info info2 = (CONSTANT_MethodHandle_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) { - info2 = info; - } else { - info2 = new CONSTANT_MethodHandle_info(cp2, info.reference_kind, info.reference_index); - } - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitMethodType(CONSTANT_MethodType_info info, Map translations) { - CONSTANT_MethodType_info info2 = (CONSTANT_MethodType_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) { - info2 = info; - } else { - info2 = new CONSTANT_MethodType_info(cp2, info.descriptor_index); - } - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitModule(CONSTANT_Module_info info, Map translations) { - CONSTANT_Module_info info2 = (CONSTANT_Module_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_Module_info(cp2, info.name_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitNameAndType(CONSTANT_NameAndType_info info, Map translations) { - CONSTANT_NameAndType_info info2 = (CONSTANT_NameAndType_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_NameAndType_info(cp2, info.name_index, info.type_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitPackage(CONSTANT_Package_info info, Map translations) { - CONSTANT_Package_info info2 = (CONSTANT_Package_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_Package_info(cp2, info.name_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitString(CONSTANT_String_info info, Map translations) { - CONSTANT_String_info info2 = (CONSTANT_String_info) translations.get(info); - if (info2 == null) { - ConstantPool cp2 = translate(info.cp, translations); - if (cp2 == info.cp) - info2 = info; - else - info2 = new CONSTANT_String_info(cp2, info.string_index); - translations.put(info, info2); - } - return info; - } - - @Override - public CPInfo visitUtf8(CONSTANT_Utf8_info info, Map translations) { - CONSTANT_Utf8_info info2 = (CONSTANT_Utf8_info) translations.get(info); - if (info2 == null) { - info2 = info; - translations.put(info, info2); - } - return info; - } - -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java deleted file mode 100644 index a24fb837f43..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * Copyright (c) 2008, 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. - */ - - -package com.sun.tools.classfile; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import static com.sun.tools.classfile.Annotation.*; -import static com.sun.tools.classfile.ConstantPool.*; -import static com.sun.tools.classfile.StackMapTable_attribute.*; -import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*; - -/** - * Write a ClassFile data structure to a file or stream. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ClassWriter { - public ClassWriter() { - attributeWriter = new AttributeWriter(); - constantPoolWriter = new ConstantPoolWriter(); - out = new ClassOutputStream(); - } - - /** - * Write a ClassFile data structure to a file. - * @param classFile the classfile object to be written - * @param f the file - * @throws IOException if an error occurs while writing the file - */ - public void write(ClassFile classFile, File f) throws IOException { - try (FileOutputStream f_out = new FileOutputStream(f)) { - write(classFile, f_out); - } - } - - /** - * Write a ClassFile data structure to a stream. - * @param classFile the classfile object to be written - * @param s the stream - * @throws IOException if an error occurs while writing the file - */ - public void write(ClassFile classFile, OutputStream s) throws IOException { - this.classFile = classFile; - out.reset(); - write(); - out.writeTo(s); - } - - protected void write() throws IOException { - writeHeader(); - writeConstantPool(); - writeAccessFlags(classFile.access_flags); - writeClassInfo(); - writeFields(); - writeMethods(); - writeAttributes(classFile.attributes); - } - - protected void writeHeader() { - out.writeInt(classFile.magic); - out.writeShort(classFile.minor_version); - out.writeShort(classFile.major_version); - } - - protected void writeAccessFlags(AccessFlags flags) { - out.writeShort(flags.flags); - } - - protected void writeAttributes(Attributes attributes) { - int size = attributes.size(); - out.writeShort(size); - for (Attribute attr: attributes) - attributeWriter.write(attr, out); - } - - protected void writeClassInfo() { - out.writeShort(classFile.this_class); - out.writeShort(classFile.super_class); - int[] interfaces = classFile.interfaces; - out.writeShort(interfaces.length); - for (int i: interfaces) - out.writeShort(i); - } - - protected void writeDescriptor(Descriptor d) { - out.writeShort(d.index); - } - - protected void writeConstantPool() { - ConstantPool pool = classFile.constant_pool; - int size = pool.size(); - out.writeShort(size); - for (CPInfo cpInfo: pool.entries()) - constantPoolWriter.write(cpInfo, out); - } - - protected void writeFields() throws IOException { - Field[] fields = classFile.fields; - out.writeShort(fields.length); - for (Field f: fields) - writeField(f); - } - - protected void writeField(Field f) throws IOException { - writeAccessFlags(f.access_flags); - out.writeShort(f.name_index); - writeDescriptor(f.descriptor); - writeAttributes(f.attributes); - } - - protected void writeMethods() throws IOException { - Method[] methods = classFile.methods; - out.writeShort(methods.length); - for (Method m: methods) { - writeMethod(m); - } - } - - protected void writeMethod(Method m) throws IOException { - writeAccessFlags(m.access_flags); - out.writeShort(m.name_index); - writeDescriptor(m.descriptor); - writeAttributes(m.attributes); - } - - protected ClassFile classFile; - protected ClassOutputStream out; - protected AttributeWriter attributeWriter; - protected ConstantPoolWriter constantPoolWriter; - - /** - * Subtype of ByteArrayOutputStream with the convenience methods of - * a DataOutputStream. Since ByteArrayOutputStream does not throw - * IOException, there are no exceptions from the additional - * convenience methods either, - */ - protected static class ClassOutputStream extends ByteArrayOutputStream { - public ClassOutputStream() { - d = new DataOutputStream(this); - } - - public void writeByte(int value) { - try { - d.writeByte(value); - } catch (IOException ignore) { - } - } - - public void writeShort(int value) { - try { - d.writeShort(value); - } catch (IOException ignore) { - } - } - - public void writeInt(int value) { - try { - d.writeInt(value); - } catch (IOException ignore) { - } - } - - public void writeLong(long value) { - try { - d.writeLong(value); - } catch (IOException ignore) { - } - } - - public void writeFloat(float value) { - try { - d.writeFloat(value); - } catch (IOException ignore) { - } - } - - public void writeDouble(double value) { - try { - d.writeDouble(value); - } catch (IOException ignore) { - } - } - - public void writeUTF(String value) { - try { - d.writeUTF(value); - } catch (IOException ignore) { - } - } - - public void writeTo(ClassOutputStream s) { - try { - super.writeTo(s); - } catch (IOException ignore) { - } - } - - private final DataOutputStream d; - } - - /** - * Writer for the entries in the constant pool. - */ - protected static class ConstantPoolWriter - implements ConstantPool.Visitor { - protected int write(CPInfo info, ClassOutputStream out) { - out.writeByte(info.getTag()); - return info.accept(this, out); - } - - @Override - public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) { - out.writeShort(info.name_index); - return 1; - } - - @Override - public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) { - out.writeDouble(info.value); - return 2; - } - - @Override - public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) { - writeRef(info, out); - return 1; - } - - @Override - public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) { - out.writeFloat(info.value); - return 1; - } - - @Override - public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) { - out.writeInt(info.value); - return 1; - } - - @Override - public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) { - writeRef(info, out); - return 1; - } - - @Override - public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ClassOutputStream out) { - out.writeShort(info.bootstrap_method_attr_index); - out.writeShort(info.name_and_type_index); - return 1; - } - - public Integer visitDynamicConstant(CONSTANT_Dynamic_info info, ClassOutputStream out) { - out.writeShort(info.bootstrap_method_attr_index); - out.writeShort(info.name_and_type_index); - return 1; - } - - @Override - public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) { - out.writeLong(info.value); - return 2; - } - - @Override - public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, ClassOutputStream out) { - out.writeByte(info.reference_kind.tag); - out.writeShort(info.reference_index); - return 1; - } - - @Override - public Integer visitMethodType(CONSTANT_MethodType_info info, ClassOutputStream out) { - out.writeShort(info.descriptor_index); - return 1; - } - - @Override - public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) { - return writeRef(info, out); - } - - @Override - public Integer visitModule(CONSTANT_Module_info info, ClassOutputStream out) { - out.writeShort(info.name_index); - return 1; - } - - @Override - public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) { - out.writeShort(info.name_index); - out.writeShort(info.type_index); - return 1; - } - - @Override - public Integer visitPackage(CONSTANT_Package_info info, ClassOutputStream out) { - out.writeShort(info.name_index); - return 1; - } - - @Override - public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) { - out.writeShort(info.string_index); - return 1; - } - - @Override - public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) { - out.writeUTF(info.value); - return 1; - } - - protected Integer writeRef(CPRefInfo info, ClassOutputStream out) { - out.writeShort(info.class_index); - out.writeShort(info.name_and_type_index); - return 1; - } - } - - /** - * Writer for the different types of attribute. - */ - protected static class AttributeWriter implements Attribute.Visitor { - public void write(Attributes attributes, ClassOutputStream out) { - int size = attributes.size(); - out.writeShort(size); - for (Attribute a: attributes) - write(a, out); - } - - public void write(Attribute attr, ClassOutputStream out) { - out.writeShort(attr.attribute_name_index); - ClassOutputStream nestedOut = new ClassOutputStream(); - attr.accept(this, nestedOut); - out.writeInt(nestedOut.size()); - nestedOut.writeTo(out); - } - - protected AnnotationWriter annotationWriter = new AnnotationWriter(); - - @Override - public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) { - out.write(attr.info, 0, attr.info.length); - return null; - } - - @Override - public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) { - annotationWriter.write(attr.default_value, out); - return null; - } - - @Override - public Void visitBootstrapMethods(BootstrapMethods_attribute attr, ClassOutputStream out) { - out.writeShort(attr.bootstrap_method_specifiers.length); - for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : attr.bootstrap_method_specifiers) { - out.writeShort(bsm.bootstrap_method_ref); - int bsm_args_count = bsm.bootstrap_arguments.length; - out.writeShort(bsm_args_count); - for (int i : bsm.bootstrap_arguments) { - out.writeShort(i); - } - } - return null; - } - - @Override - public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) { - out.writeShort(attr.character_range_table.length); - for (CharacterRangeTable_attribute.Entry e: attr.character_range_table) - writeCharacterRangeTableEntry(e, out); - return null; - } - - protected void writeCharacterRangeTableEntry(CharacterRangeTable_attribute.Entry entry, ClassOutputStream out) { - out.writeShort(entry.start_pc); - out.writeShort(entry.end_pc); - out.writeInt(entry.character_range_start); - out.writeInt(entry.character_range_end); - out.writeShort(entry.flags); - } - - @Override - public Void visitCode(Code_attribute attr, ClassOutputStream out) { - out.writeShort(attr.max_stack); - out.writeShort(attr.max_locals); - out.writeInt(attr.code.length); - out.write(attr.code, 0, attr.code.length); - out.writeShort(attr.exception_table.length); - for (Code_attribute.Exception_data e: attr.exception_table) - writeExceptionTableEntry(e, out); - new AttributeWriter().write(attr.attributes, out); - return null; - } - - protected void writeExceptionTableEntry(Code_attribute.Exception_data exception_data, ClassOutputStream out) { - out.writeShort(exception_data.start_pc); - out.writeShort(exception_data.end_pc); - out.writeShort(exception_data.handler_pc); - out.writeShort(exception_data.catch_type); - } - - @Override - public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) { - out.writeShort(attr.compilationID_index); - return null; - } - - @Override - public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) { - out.writeShort(attr.constantvalue_index); - return null; - } - - @Override - public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) { - return null; - } - - @Override - public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) { - out.writeShort(attr.class_index); - out.writeShort(attr.method_index); - return null; - } - - @Override - public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) { - out.writeShort(attr.exception_index_table.length); - for (int i: attr.exception_index_table) - out.writeShort(i); - return null; - } - - @Override - public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) { - out.writeShort(attr.classes.length); - for (InnerClasses_attribute.Info info: attr.classes) - writeInnerClassesInfo(info, out); - return null; - } - - protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) { - out.writeShort(info.inner_class_info_index); - out.writeShort(info.outer_class_info_index); - out.writeShort(info.inner_name_index); - writeAccessFlags(info.inner_class_access_flags, out); - } - - @Override - public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) { - out.writeShort(attr.line_number_table.length); - for (LineNumberTable_attribute.Entry e: attr.line_number_table) - writeLineNumberTableEntry(e, out); - return null; - } - - protected void writeLineNumberTableEntry(LineNumberTable_attribute.Entry entry, ClassOutputStream out) { - out.writeShort(entry.start_pc); - out.writeShort(entry.line_number); - } - - @Override - public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) { - out.writeShort(attr.local_variable_table.length); - for (LocalVariableTable_attribute.Entry e: attr.local_variable_table) - writeLocalVariableTableEntry(e, out); - return null; - } - - protected void writeLocalVariableTableEntry(LocalVariableTable_attribute.Entry entry, ClassOutputStream out) { - out.writeShort(entry.start_pc); - out.writeShort(entry.length); - out.writeShort(entry.name_index); - out.writeShort(entry.descriptor_index); - out.writeShort(entry.index); - } - - @Override - public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) { - out.writeShort(attr.local_variable_table.length); - for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table) - writeLocalVariableTypeTableEntry(e, out); - return null; - } - - protected void writeLocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry, ClassOutputStream out) { - out.writeShort(entry.start_pc); - out.writeShort(entry.length); - out.writeShort(entry.name_index); - out.writeShort(entry.signature_index); - out.writeShort(entry.index); - } - - @Override - public Void visitNestHost(NestHost_attribute attr, ClassOutputStream out) { - out.writeShort(attr.top_index); - return null; - } - - @Override - public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) { - out.writeByte(attr.method_parameter_table.length); - for (MethodParameters_attribute.Entry e : attr.method_parameter_table) { - out.writeShort(e.name_index); - out.writeShort(e.flags); - } - return null; - } - - @Override - public Void visitModule(Module_attribute attr, ClassOutputStream out) { - out.writeShort(attr.module_name); - out.writeShort(attr.module_flags); - out.writeShort(attr.module_version_index); - - out.writeShort(attr.requires.length); - for (Module_attribute.RequiresEntry e: attr.requires) { - out.writeShort(e.requires_index); - out.writeShort(e.requires_flags); - out.writeShort(e.requires_version_index); - } - - out.writeShort(attr.exports.length); - for (Module_attribute.ExportsEntry e: attr.exports) { - out.writeShort(e.exports_index); - out.writeShort(e.exports_flags); - out.writeShort(e.exports_to_index.length); - for (int index: e.exports_to_index) - out.writeShort(index); - } - - out.writeShort(attr.opens.length); - for (Module_attribute.OpensEntry e: attr.opens) { - out.writeShort(e.opens_index); - out.writeShort(e.opens_flags); - out.writeShort(e.opens_to_index.length); - for (int index: e.opens_to_index) - out.writeShort(index); - } - - out.writeShort(attr.uses_index.length); - for (int index: attr.uses_index) { - out.writeShort(index); - } - - out.writeShort(attr.provides.length); - for (Module_attribute.ProvidesEntry e: attr.provides) { - out.writeShort(e.provides_index); - out.writeShort(e.with_count); - for (int with : e.with_index) { - out.writeShort(with); - } - } - - return null; - } - - @Override - public Void visitModuleHashes(ModuleHashes_attribute attr, ClassOutputStream out) { - out.writeShort(attr.algorithm_index); - out.writeShort(attr.hashes_table.length); - for (ModuleHashes_attribute.Entry e: attr.hashes_table) { - out.writeShort(e.module_name_index); - out.writeShort(e.hash.length); - for (byte b: e.hash) { - out.writeByte(b); - } - } - return null; - } - - @Override - public Void visitModuleMainClass(ModuleMainClass_attribute attr, ClassOutputStream out) { - out.writeShort(attr.main_class_index); - return null; - } - - @Override - public Void visitModulePackages(ModulePackages_attribute attr, ClassOutputStream out) { - out.writeShort(attr.packages_count); - for (int i: attr.packages_index) - out.writeShort(i); - return null; - } - - @Override - public Void visitModuleResolution(ModuleResolution_attribute attr, ClassOutputStream out) { - out.writeShort(attr.resolution_flags); - return null; - } - - @Override - public Void visitModuleTarget(ModuleTarget_attribute attr, ClassOutputStream out) { - out.writeShort(attr.target_platform_index); - return null; - } - - @Override - public Void visitNestMembers(NestMembers_attribute attr, ClassOutputStream out) { - out.writeShort(attr.members_indexes.length); - for (int i : attr.members_indexes) { - out.writeShort(i); - } - return null; - } - - @Override - public Void visitRecord(Record_attribute attr, ClassOutputStream out) { - out.writeShort(attr.component_count); - for (Record_attribute.ComponentInfo info: attr.component_info_arr) { - out.writeShort(info.name_index); - out.writeShort(info.descriptor.index); - int size = info.attributes.size(); - out.writeShort(size); - for (Attribute componentAttr: info.attributes) - write(componentAttr, out); - } - return null; - } - - @Override - public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) { - annotationWriter.write(attr.annotations, out); - return null; - } - - @Override - public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) { - out.writeByte(attr.parameter_annotations.length); - for (Annotation[] annos: attr.parameter_annotations) - annotationWriter.write(annos, out); - return null; - } - - @Override - public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) { - annotationWriter.write(attr.annotations, out); - return null; - } - - @Override - public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) { - annotationWriter.write(attr.annotations, out); - return null; - } - - @Override - public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) { - out.writeByte(attr.parameter_annotations.length); - for (Annotation[] annos: attr.parameter_annotations) - annotationWriter.write(annos, out); - return null; - } - - @Override - public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) { - annotationWriter.write(attr.annotations, out); - return null; - } - - @Override - public Void visitPermittedSubclasses(PermittedSubclasses_attribute attr, ClassOutputStream out) { - int n = attr.subtypes.length; - out.writeShort(n); - for (int i = 0 ; i < n ; i++) { - out.writeShort(attr.subtypes[i]); - } - return null; - } - - @Override - public Void visitSignature(Signature_attribute attr, ClassOutputStream out) { - out.writeShort(attr.signature_index); - return null; - } - - @Override - public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) { - out.write(attr.debug_extension, 0, attr.debug_extension.length); - return null; - } - - @Override - public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) { - out.writeShort(attr.sourcefile_index); - return null; - } - - @Override - public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) { - out.writeShort(attr.sourceID_index); - return null; - } - - @Override - public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) { - if (stackMapWriter == null) - stackMapWriter = new StackMapTableWriter(); - - out.writeShort(attr.entries.length); - for (stack_map_frame f: attr.entries) - stackMapWriter.write(f, out); - return null; - } - - @Override - public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) { - if (stackMapWriter == null) - stackMapWriter = new StackMapTableWriter(); - - out.writeShort(attr.entries.length); - for (stack_map_frame f: attr.entries) - stackMapWriter.write(f, out); - return null; - } - - @Override - public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) { - return null; - } - - protected void writeAccessFlags(AccessFlags flags, ClassOutputStream out) { - out.writeShort(flags.flags); - } - - protected StackMapTableWriter stackMapWriter; - } - - /** - * Writer for the frames of StackMap and StackMapTable attributes. - */ - protected static class StackMapTableWriter - implements stack_map_frame.Visitor { - - public void write(stack_map_frame frame, ClassOutputStream out) { - out.write(frame.frame_type); - frame.accept(this, out); - } - - @Override - public Void visit_same_frame(same_frame frame, ClassOutputStream p) { - return null; - } - - @Override - public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) { - writeVerificationTypeInfo(frame.stack[0], out); - return null; - } - - @Override - public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) { - out.writeShort(frame.offset_delta); - writeVerificationTypeInfo(frame.stack[0], out); - return null; - } - - @Override - public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) { - out.writeShort(frame.offset_delta); - return null; - } - - @Override - public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) { - out.writeShort(frame.offset_delta); - return null; - } - - @Override - public Void visit_append_frame(append_frame frame, ClassOutputStream out) { - out.writeShort(frame.offset_delta); - for (verification_type_info l: frame.locals) - writeVerificationTypeInfo(l, out); - return null; - } - - @Override - public Void visit_full_frame(full_frame frame, ClassOutputStream out) { - out.writeShort(frame.offset_delta); - out.writeShort(frame.locals.length); - for (verification_type_info l: frame.locals) - writeVerificationTypeInfo(l, out); - out.writeShort(frame.stack.length); - for (verification_type_info s: frame.stack) - writeVerificationTypeInfo(s, out); - return null; - } - - protected void writeVerificationTypeInfo(verification_type_info info, - ClassOutputStream out) { - out.write(info.tag); - switch (info.tag) { - case ITEM_Top: - case ITEM_Integer: - case ITEM_Float: - case ITEM_Long: - case ITEM_Double: - case ITEM_Null: - case ITEM_UninitializedThis: - break; - - case ITEM_Object: - Object_variable_info o = (Object_variable_info) info; - out.writeShort(o.cpool_index); - break; - - case ITEM_Uninitialized: - Uninitialized_variable_info u = (Uninitialized_variable_info) info; - out.writeShort(u.offset); - break; - - default: - throw new Error(); - } - } - } - - /** - * Writer for annotations and the values they contain. - */ - protected static class AnnotationWriter - implements Annotation.element_value.Visitor { - public void write(Annotation[] annos, ClassOutputStream out) { - out.writeShort(annos.length); - for (Annotation anno: annos) - write(anno, out); - } - - public void write(TypeAnnotation[] annos, ClassOutputStream out) { - out.writeShort(annos.length); - for (TypeAnnotation anno: annos) - write(anno, out); - } - - public void write(Annotation anno, ClassOutputStream out) { - out.writeShort(anno.type_index); - out.writeShort(anno.element_value_pairs.length); - for (element_value_pair p: anno.element_value_pairs) - write(p, out); - } - - public void write(TypeAnnotation anno, ClassOutputStream out) { - write(anno.position, out); - write(anno.annotation, out); - } - - public void write(element_value_pair pair, ClassOutputStream out) { - out.writeShort(pair.element_name_index); - write(pair.value, out); - } - - public void write(element_value ev, ClassOutputStream out) { - out.writeByte(ev.tag); - ev.accept(this, out); - } - - @Override - public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) { - out.writeShort(ev.const_value_index); - return null; - } - - @Override - public Void visitEnum(Enum_element_value ev, ClassOutputStream out) { - out.writeShort(ev.type_name_index); - out.writeShort(ev.const_name_index); - return null; - } - - @Override - public Void visitClass(Class_element_value ev, ClassOutputStream out) { - out.writeShort(ev.class_info_index); - return null; - } - - @Override - public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) { - write(ev.annotation_value, out); - return null; - } - - @Override - public Void visitArray(Array_element_value ev, ClassOutputStream out) { - out.writeShort(ev.num_values); - for (element_value v: ev.values) - write(v, out); - return null; - } - - // TODO: Move this to TypeAnnotation to be closer with similar logic? - private void write(TypeAnnotation.Position p, ClassOutputStream out) { - out.writeByte(p.type.targetTypeValue()); - switch (p.type) { - // instanceof - case INSTANCEOF: - // new expression - case NEW: - // constructor/method reference receiver - case CONSTRUCTOR_REFERENCE: - case METHOD_REFERENCE: - out.writeShort(p.offset); - break; - // local variable - case LOCAL_VARIABLE: - // resource variable - case RESOURCE_VARIABLE: - int table_length = p.lvarOffset.length; - out.writeShort(table_length); - for (int i = 0; i < table_length; ++i) { - out.writeShort(1); // for table length - out.writeShort(p.lvarOffset[i]); - out.writeShort(p.lvarLength[i]); - out.writeShort(p.lvarIndex[i]); - } - break; - // exception parameter - case EXCEPTION_PARAMETER: - out.writeShort(p.exception_index); - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - out.writeByte(p.parameter_index); - break; - // type parameters bounds - case CLASS_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND: - out.writeByte(p.parameter_index); - out.writeByte(p.bound_index); - break; - // class extends or implements clause - case CLASS_EXTENDS: - out.writeShort(p.type_index); - break; - // throws - case THROWS: - out.writeShort(p.type_index); - break; - // method parameter - case METHOD_FORMAL_PARAMETER: - out.writeByte(p.parameter_index); - break; - // type cast - case CAST: - // method/constructor/reference type argument - case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: - case METHOD_INVOCATION_TYPE_ARGUMENT: - case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: - case METHOD_REFERENCE_TYPE_ARGUMENT: - out.writeShort(p.offset); - out.writeByte(p.type_index); - break; - // We don't need to worry about these - case METHOD_RETURN: - case FIELD: - break; - case UNKNOWN: - throw new AssertionError("ClassWriter: UNKNOWN target type should never occur!"); - default: - throw new AssertionError("ClassWriter: Unknown target type for position: " + p); - } - - { // Append location data for generics/arrays. - // TODO: check for overrun? - out.writeByte((byte)p.location.size()); - for (int i : TypeAnnotation.Position.getBinaryFromTypePath(p.location)) - out.writeByte((byte)i); - } - } - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Code_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Code_attribute.java deleted file mode 100644 index dc19fc564aa..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Code_attribute.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * See JVMS, section 4.8.3. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Code_attribute extends Attribute { - public static class InvalidIndex extends AttributeException { - private static final long serialVersionUID = -8904527774589382802L; - InvalidIndex(int index) { - this.index = index; - } - - @Override - public String getMessage() { - // i18n - return "invalid index " + index + " in Code attribute"; - } - - public final int index; - } - - Code_attribute(ClassReader cr, int name_index, int length) - throws IOException, ConstantPoolException { - super(name_index, length); - max_stack = cr.readUnsignedShort(); - max_locals = cr.readUnsignedShort(); - code_length = cr.readInt(); - code = new byte[code_length]; - cr.readFully(code); - exception_table_length = cr.readUnsignedShort(); - exception_table = new Exception_data[exception_table_length]; - for (int i = 0; i < exception_table_length; i++) - exception_table[i] = new Exception_data(cr); - attributes = new Attributes(cr); - } - - public int getByte(int offset) throws InvalidIndex { - if (offset < 0 || offset >= code.length) - throw new InvalidIndex(offset); - return code[offset]; - } - - public int getUnsignedByte(int offset) throws InvalidIndex { - if (offset < 0 || offset >= code.length) - throw new InvalidIndex(offset); - return code[offset] & 0xff; - } - - public int getShort(int offset) throws InvalidIndex { - if (offset < 0 || offset + 1 >= code.length) - throw new InvalidIndex(offset); - return (code[offset] << 8) | (code[offset + 1] & 0xFF); - } - - public int getUnsignedShort(int offset) throws InvalidIndex { - if (offset < 0 || offset + 1 >= code.length) - throw new InvalidIndex(offset); - return ((code[offset] << 8) | (code[offset + 1] & 0xFF)) & 0xFFFF; - } - - public int getInt(int offset) throws InvalidIndex { - if (offset < 0 || offset + 3 >= code.length) - throw new InvalidIndex(offset); - return (getShort(offset) << 16) | (getShort(offset + 2) & 0xFFFF); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitCode(this, data); - } - - public Iterable getInstructions() { - return () -> new Iterator() { - - public boolean hasNext() { - return (next != null); - } - - public Instruction next() { - if (next == null) - throw new NoSuchElementException(); - - current = next; - pc += current.length(); - next = (pc < code.length ? new Instruction(code, pc) : null); - return current; - } - - public void remove() { - throw new UnsupportedOperationException("Not supported."); - } - - Instruction current = null; - int pc = 0; - Instruction next = (pc < code.length ? new Instruction(code, pc) : null); - - }; - } - - public final int max_stack; - public final int max_locals; - public final int code_length; - public final byte[] code; - public final int exception_table_length; - public final Exception_data[] exception_table; - public final Attributes attributes; - - public static class Exception_data { - Exception_data(ClassReader cr) throws IOException { - start_pc = cr.readUnsignedShort(); - end_pc = cr.readUnsignedShort(); - handler_pc = cr.readUnsignedShort(); - catch_type = cr.readUnsignedShort(); - } - - public final int start_pc; - public final int end_pc; - public final int handler_pc; - public final int catch_type; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CompilationID_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CompilationID_attribute.java deleted file mode 100644 index 6f2d70508b3..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CompilationID_attribute.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class CompilationID_attribute extends Attribute { - - CompilationID_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - compilationID_index = cr.readUnsignedShort(); - } - - public CompilationID_attribute(ConstantPool constant_pool, int compilationID_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.CompilationID), compilationID_index); - } - - public CompilationID_attribute(int name_index, int compilationID_index) { - super(name_index, 2); - this.compilationID_index = compilationID_index; - } - - String getCompilationID(ConstantPool constant_pool) - throws ConstantPoolException { - return constant_pool.getUTF8Value(compilationID_index); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitCompilationID(this, data); - } - - public final int compilationID_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java deleted file mode 100644 index 801220a026c..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 com.sun.tools.classfile; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Iterator; - -/** - * See JVMS, section 4.5. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ConstantPool { - - public static class InvalidIndex extends ConstantPoolException { - private static final long serialVersionUID = -4350294289300939730L; - InvalidIndex(int index) { - super(index); - } - - @Override - public String getMessage() { - // i18n - return "invalid index #" + index; - } - } - - public static class UnexpectedEntry extends ConstantPoolException { - private static final long serialVersionUID = 6986335935377933211L; - UnexpectedEntry(int index, int expected_tag, int found_tag) { - super(index); - this.expected_tag = expected_tag; - this.found_tag = found_tag; - } - - @Override - public String getMessage() { - // i18n? - return "unexpected entry at #" + index + " -- expected tag " + expected_tag + ", found " + found_tag; - } - - public final int expected_tag; - public final int found_tag; - } - - public static class InvalidEntry extends ConstantPoolException { - private static final long serialVersionUID = 1000087545585204447L; - InvalidEntry(int index, int tag) { - super(index); - this.tag = tag; - } - - @Override - public String getMessage() { - // i18n? - return "unexpected tag at #" + index + ": " + tag; - } - - public final int tag; - } - - public static class EntryNotFound extends ConstantPoolException { - private static final long serialVersionUID = 2885537606468581850L; - EntryNotFound(Object value) { - super(-1); - this.value = value; - } - - @Override - public String getMessage() { - // i18n? - return "value not found: " + value; - } - - @SuppressWarnings("serial") // Type of field is not Serializable - public final Object value; - } - - public static final int CONSTANT_Utf8 = 1; - public static final int CONSTANT_Integer = 3; - public static final int CONSTANT_Float = 4; - public static final int CONSTANT_Long = 5; - public static final int CONSTANT_Double = 6; - public static final int CONSTANT_Class = 7; - public static final int CONSTANT_String = 8; - public static final int CONSTANT_Fieldref = 9; - public static final int CONSTANT_Methodref = 10; - public static final int CONSTANT_InterfaceMethodref = 11; - public static final int CONSTANT_NameAndType = 12; - public static final int CONSTANT_MethodHandle = 15; - public static final int CONSTANT_MethodType = 16; - public static final int CONSTANT_Dynamic = 17; - public static final int CONSTANT_InvokeDynamic = 18; - public static final int CONSTANT_Module = 19; - public static final int CONSTANT_Package = 20; - - public static enum RefKind { - REF_getField(1), - REF_getStatic(2), - REF_putField(3), - REF_putStatic(4), - REF_invokeVirtual(5), - REF_invokeStatic(6), - REF_invokeSpecial(7), - REF_newInvokeSpecial(8), - REF_invokeInterface(9); - - public final int tag; - - RefKind(int tag) { - this.tag = tag; - } - - static RefKind getRefkind(int tag) { - switch(tag) { - case 1: - return REF_getField; - case 2: - return REF_getStatic; - case 3: - return REF_putField; - case 4: - return REF_putStatic; - case 5: - return REF_invokeVirtual; - case 6: - return REF_invokeStatic; - case 7: - return REF_invokeSpecial; - case 8: - return REF_newInvokeSpecial; - case 9: - return REF_invokeInterface; - default: - return null; - } - } - } - - ConstantPool(ClassReader cr) throws IOException, InvalidEntry { - int count = cr.readUnsignedShort(); - pool = new CPInfo[count]; - for (int i = 1; i < count; i++) { - int tag = cr.readUnsignedByte(); - switch (tag) { - case CONSTANT_Class: - pool[i] = new CONSTANT_Class_info(this, cr); - break; - - case CONSTANT_Double: - pool[i] = new CONSTANT_Double_info(cr); - i++; - break; - - case CONSTANT_Fieldref: - pool[i] = new CONSTANT_Fieldref_info(this, cr); - break; - - case CONSTANT_Float: - pool[i] = new CONSTANT_Float_info(cr); - break; - - case CONSTANT_Integer: - pool[i] = new CONSTANT_Integer_info(cr); - break; - - case CONSTANT_InterfaceMethodref: - pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr); - break; - - case CONSTANT_InvokeDynamic: - pool[i] = new CONSTANT_InvokeDynamic_info(this, cr); - break; - - case CONSTANT_Dynamic: - pool[i] = new CONSTANT_Dynamic_info(this, cr); - break; - - case CONSTANT_Long: - pool[i] = new CONSTANT_Long_info(cr); - i++; - break; - - case CONSTANT_MethodHandle: - pool[i] = new CONSTANT_MethodHandle_info(this, cr); - break; - - case CONSTANT_MethodType: - pool[i] = new CONSTANT_MethodType_info(this, cr); - break; - - case CONSTANT_Methodref: - pool[i] = new CONSTANT_Methodref_info(this, cr); - break; - - case CONSTANT_Module: - pool[i] = new CONSTANT_Module_info(this, cr); - break; - - case CONSTANT_NameAndType: - pool[i] = new CONSTANT_NameAndType_info(this, cr); - break; - - case CONSTANT_Package: - pool[i] = new CONSTANT_Package_info(this, cr); - break; - - case CONSTANT_String: - pool[i] = new CONSTANT_String_info(this, cr); - break; - - case CONSTANT_Utf8: - pool[i] = new CONSTANT_Utf8_info(cr); - break; - - default: - throw new InvalidEntry(i, tag); - } - } - } - - public ConstantPool(CPInfo[] pool) { - this.pool = pool; - } - - public int size() { - return pool.length; - } - - public int byteLength() { - int length = 2; - for (int i = 1; i < size(); ) { - CPInfo cpInfo = pool[i]; - length += cpInfo.byteLength(); - i += cpInfo.size(); - } - return length; - } - - public CPInfo get(int index) throws InvalidIndex { - if (index <= 0 || index >= pool.length) - throw new InvalidIndex(index); - CPInfo info = pool[index]; - if (info == null) { - // this occurs for indices referencing the "second half" of an - // 8 byte constant, such as CONSTANT_Double or CONSTANT_Long - throw new InvalidIndex(index); - } - return pool[index]; - } - - private CPInfo get(int index, int expected_type) throws InvalidIndex, UnexpectedEntry { - CPInfo info = get(index); - if (info.getTag() != expected_type) - throw new UnexpectedEntry(index, expected_type, info.getTag()); - return info; - } - - public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry { - return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8)); - } - - public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry { - return ((CONSTANT_Class_info) get(index, CONSTANT_Class)); - } - - public CONSTANT_Module_info getModuleInfo(int index) throws InvalidIndex, UnexpectedEntry { - return ((CONSTANT_Module_info) get(index, CONSTANT_Module)); - } - - public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry { - return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType)); - } - - public CONSTANT_Package_info getPackageInfo(int index) throws InvalidIndex, UnexpectedEntry { - return ((CONSTANT_Package_info) get(index, CONSTANT_Package)); - } - - public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry { - return getUTF8Info(index).value; - } - - public int getUTF8Index(String value) throws EntryNotFound { - for (int i = 1; i < pool.length; i++) { - CPInfo info = pool[i]; - if (info instanceof CONSTANT_Utf8_info && - ((CONSTANT_Utf8_info) info).value.equals(value)) - return i; - } - throw new EntryNotFound(value); - } - - public Iterable entries() { - return () -> new Iterator() { - - public boolean hasNext() { - return next < pool.length; - } - - public CPInfo next() { - current = pool[next]; - switch (current.getTag()) { - case CONSTANT_Double: - case CONSTANT_Long: - next += 2; - break; - default: - next += 1; - } - return current; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - private CPInfo current; - private int next = 1; - - }; - } - - private CPInfo[] pool; - - public interface Visitor { - R visitClass(CONSTANT_Class_info info, P p); - R visitDouble(CONSTANT_Double_info info, P p); - R visitFieldref(CONSTANT_Fieldref_info info, P p); - R visitFloat(CONSTANT_Float_info info, P p); - R visitInteger(CONSTANT_Integer_info info, P p); - R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p); - R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p); - R visitDynamicConstant(CONSTANT_Dynamic_info info, P p); - R visitLong(CONSTANT_Long_info info, P p); - R visitMethodref(CONSTANT_Methodref_info info, P p); - R visitMethodHandle(CONSTANT_MethodHandle_info info, P p); - R visitMethodType(CONSTANT_MethodType_info info, P p); - R visitModule(CONSTANT_Module_info info, P p); - R visitNameAndType(CONSTANT_NameAndType_info info, P p); - R visitPackage(CONSTANT_Package_info info, P p); - R visitString(CONSTANT_String_info info, P p); - R visitUtf8(CONSTANT_Utf8_info info, P p); - } - - public abstract static class CPInfo { - CPInfo() { - this.cp = null; - } - - CPInfo(ConstantPool cp) { - this.cp = cp; - } - - public abstract int getTag(); - - /** The number of slots in the constant pool used by this entry. - * 2 for CONSTANT_Double and CONSTANT_Long; 1 for everything else. */ - public int size() { - return 1; - } - - public abstract int byteLength(); - - public abstract R accept(Visitor visitor, D data); - - protected final ConstantPool cp; - } - - public abstract static class CPRefInfo extends CPInfo { - protected CPRefInfo(ConstantPool cp, ClassReader cr, int tag) throws IOException { - super(cp); - this.tag = tag; - class_index = cr.readUnsignedShort(); - name_and_type_index = cr.readUnsignedShort(); - } - - protected CPRefInfo(ConstantPool cp, int tag, int class_index, int name_and_type_index) { - super(cp); - this.tag = tag; - this.class_index = class_index; - this.name_and_type_index = name_and_type_index; - } - - public int getTag() { - return tag; - } - - public int byteLength() { - return 5; - } - - public CONSTANT_Class_info getClassInfo() throws ConstantPoolException { - return cp.getClassInfo(class_index); - } - - public String getClassName() throws ConstantPoolException { - return cp.getClassInfo(class_index).getName(); - } - - public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException { - return cp.getNameAndTypeInfo(name_and_type_index); - } - - public final int tag; - public final int class_index; - public final int name_and_type_index; - } - - public static class CONSTANT_Class_info extends CPInfo { - CONSTANT_Class_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - name_index = cr.readUnsignedShort(); - } - - public CONSTANT_Class_info(ConstantPool cp, int name_index) { - super(cp); - this.name_index = name_index; - } - - public int getTag() { - return CONSTANT_Class; - } - - public int byteLength() { - return 3; - } - - /** - * Get the raw value of the class referenced by this constant pool entry. - * This will either be the name of the class, in internal form, or a - * descriptor for an array class. - * @return the raw value of the class - */ - public String getName() throws ConstantPoolException { - return cp.getUTF8Value(name_index); - } - - /** - * If this constant pool entry identifies either a class or interface type, - * or a possibly multi-dimensional array of a class of interface type, - * return the name of the class or interface in internal form. Otherwise, - * (i.e. if this is a possibly multi-dimensional array of a primitive type), - * return null. - * @return the base class or interface name - */ - public String getBaseName() throws ConstantPoolException { - String name = getName(); - if (name.startsWith("[")) { - int index = name.indexOf("[L"); - if (index == -1) - return null; - return name.substring(index + 2, name.length() - 1); - } else - return name; - } - - public int getDimensionCount() throws ConstantPoolException { - String name = getName(); - int count = 0; - while (name.charAt(count) == '[') - count++; - return count; - } - - @Override - public String toString() { - return "CONSTANT_Class_info[name_index: " + name_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitClass(this, data); - } - - public final int name_index; - } - - public static class CONSTANT_Double_info extends CPInfo { - CONSTANT_Double_info(ClassReader cr) throws IOException { - value = cr.readDouble(); - } - - public CONSTANT_Double_info(double value) { - this.value = value; - } - - public int getTag() { - return CONSTANT_Double; - } - - public int byteLength() { - return 9; - } - - @Override - public int size() { - return 2; - } - - @Override - public String toString() { - return "CONSTANT_Double_info[value: " + value + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitDouble(this, data); - } - - public final double value; - } - - public static class CONSTANT_Fieldref_info extends CPRefInfo { - CONSTANT_Fieldref_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp, cr, CONSTANT_Fieldref); - } - - public CONSTANT_Fieldref_info(ConstantPool cp, int class_index, int name_and_type_index) { - super(cp, CONSTANT_Fieldref, class_index, name_and_type_index); - } - - @Override - public String toString() { - return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitFieldref(this, data); - } - } - - public static class CONSTANT_Float_info extends CPInfo { - CONSTANT_Float_info(ClassReader cr) throws IOException { - value = cr.readFloat(); - } - - public CONSTANT_Float_info(float value) { - this.value = value; - } - - public int getTag() { - return CONSTANT_Float; - } - - public int byteLength() { - return 5; - } - - @Override - public String toString() { - return "CONSTANT_Float_info[value: " + value + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitFloat(this, data); - } - - public final float value; - } - - public static class CONSTANT_Integer_info extends CPInfo { - CONSTANT_Integer_info(ClassReader cr) throws IOException { - value = cr.readInt(); - } - - public CONSTANT_Integer_info(int value) { - this.value = value; - } - - public int getTag() { - return CONSTANT_Integer; - } - - public int byteLength() { - return 5; - } - - @Override - public String toString() { - return "CONSTANT_Integer_info[value: " + value + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitInteger(this, data); - } - - public final int value; - } - - public static class CONSTANT_InterfaceMethodref_info extends CPRefInfo { - CONSTANT_InterfaceMethodref_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp, cr, CONSTANT_InterfaceMethodref); - } - - public CONSTANT_InterfaceMethodref_info(ConstantPool cp, int class_index, int name_and_type_index) { - super(cp, CONSTANT_InterfaceMethodref, class_index, name_and_type_index); - } - - @Override - public String toString() { - return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitInterfaceMethodref(this, data); - } - } - - public static class CONSTANT_InvokeDynamic_info extends CPInfo { - CONSTANT_InvokeDynamic_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - bootstrap_method_attr_index = cr.readUnsignedShort(); - name_and_type_index = cr.readUnsignedShort(); - } - - public CONSTANT_InvokeDynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) { - super(cp); - this.bootstrap_method_attr_index = bootstrap_method_index; - this.name_and_type_index = name_and_type_index; - } - - public int getTag() { - return CONSTANT_InvokeDynamic; - } - - public int byteLength() { - return 5; - } - - @Override - public String toString() { - return "CONSTANT_InvokeDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitInvokeDynamic(this, data); - } - - public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException { - return cp.getNameAndTypeInfo(name_and_type_index); - } - - public final int bootstrap_method_attr_index; - public final int name_and_type_index; - } - - public static class CONSTANT_Long_info extends CPInfo { - CONSTANT_Long_info(ClassReader cr) throws IOException { - value = cr.readLong(); - } - - public CONSTANT_Long_info(long value) { - this.value = value; - } - - public int getTag() { - return CONSTANT_Long; - } - - @Override - public int size() { - return 2; - } - - public int byteLength() { - return 9; - } - - @Override - public String toString() { - return "CONSTANT_Long_info[value: " + value + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitLong(this, data); - } - - public final long value; - } - - public static class CONSTANT_MethodHandle_info extends CPInfo { - CONSTANT_MethodHandle_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - reference_kind = RefKind.getRefkind(cr.readUnsignedByte()); - reference_index = cr.readUnsignedShort(); - } - - public CONSTANT_MethodHandle_info(ConstantPool cp, RefKind ref_kind, int member_index) { - super(cp); - this.reference_kind = ref_kind; - this.reference_index = member_index; - } - - public int getTag() { - return CONSTANT_MethodHandle; - } - - public int byteLength() { - return 4; - } - - @Override - public String toString() { - return "CONSTANT_MethodHandle_info[ref_kind: " + reference_kind + ", member_index: " + reference_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitMethodHandle(this, data); - } - - public CPRefInfo getCPRefInfo() throws ConstantPoolException { - int expected = CONSTANT_Methodref; - int actual = cp.get(reference_index).getTag(); - // allow these tag types also: - switch (actual) { - case CONSTANT_Fieldref: - case CONSTANT_InterfaceMethodref: - expected = actual; - } - return (CPRefInfo) cp.get(reference_index, expected); - } - - public final RefKind reference_kind; - public final int reference_index; - } - - public static class CONSTANT_MethodType_info extends CPInfo { - CONSTANT_MethodType_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - descriptor_index = cr.readUnsignedShort(); - } - - public CONSTANT_MethodType_info(ConstantPool cp, int signature_index) { - super(cp); - this.descriptor_index = signature_index; - } - - public int getTag() { - return CONSTANT_MethodType; - } - - public int byteLength() { - return 3; - } - - @Override - public String toString() { - return "CONSTANT_MethodType_info[signature_index: " + descriptor_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitMethodType(this, data); - } - - public String getType() throws ConstantPoolException { - return cp.getUTF8Value(descriptor_index); - } - - public final int descriptor_index; - } - - public static class CONSTANT_Methodref_info extends CPRefInfo { - CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp, cr, CONSTANT_Methodref); - } - - public CONSTANT_Methodref_info(ConstantPool cp, int class_index, int name_and_type_index) { - super(cp, CONSTANT_Methodref, class_index, name_and_type_index); - } - - @Override - public String toString() { - return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitMethodref(this, data); - } - } - - public static class CONSTANT_Module_info extends CPInfo { - CONSTANT_Module_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - name_index = cr.readUnsignedShort(); - } - - public CONSTANT_Module_info(ConstantPool cp, int name_index) { - super(cp); - this.name_index = name_index; - } - - public int getTag() { - return CONSTANT_Module; - } - - public int byteLength() { - return 3; - } - - /** - * Get the raw value of the module name referenced by this constant pool entry. - * This will be the name of the module. - * @return the raw value of the module name - */ - public String getName() throws ConstantPoolException { - return cp.getUTF8Value(name_index); - } - - @Override - public String toString() { - return "CONSTANT_Module_info[name_index: " + name_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitModule(this, data); - } - - public final int name_index; - } - - public static class CONSTANT_NameAndType_info extends CPInfo { - CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - name_index = cr.readUnsignedShort(); - type_index = cr.readUnsignedShort(); - } - - public CONSTANT_NameAndType_info(ConstantPool cp, int name_index, int type_index) { - super(cp); - this.name_index = name_index; - this.type_index = type_index; - } - - public int getTag() { - return CONSTANT_NameAndType; - } - - public int byteLength() { - return 5; - } - - public String getName() throws ConstantPoolException { - return cp.getUTF8Value(name_index); - } - - public String getType() throws ConstantPoolException { - return cp.getUTF8Value(type_index); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitNameAndType(this, data); - } - - @Override - public String toString() { - return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]"; - } - - public final int name_index; - public final int type_index; - } - - public static class CONSTANT_Dynamic_info extends CPInfo { - CONSTANT_Dynamic_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - bootstrap_method_attr_index = cr.readUnsignedShort(); - name_and_type_index = cr.readUnsignedShort(); - } - - public CONSTANT_Dynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) { - super(cp); - this.bootstrap_method_attr_index = bootstrap_method_index; - this.name_and_type_index = name_and_type_index; - } - - public int getTag() { - return CONSTANT_Dynamic; - } - - public int byteLength() { - return 5; - } - - @Override - public String toString() { - return "CONSTANT_Dynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitDynamicConstant(this, data); - } - - public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException { - return cp.getNameAndTypeInfo(name_and_type_index); - } - - public final int bootstrap_method_attr_index; - public final int name_and_type_index; - } - - public static class CONSTANT_Package_info extends CPInfo { - CONSTANT_Package_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - name_index = cr.readUnsignedShort(); - } - - public CONSTANT_Package_info(ConstantPool cp, int name_index) { - super(cp); - this.name_index = name_index; - } - - public int getTag() { - return CONSTANT_Package; - } - - public int byteLength() { - return 3; - } - - /** - * Get the raw value of the package name referenced by this constant pool entry. - * This will be the name of the package, in internal form. - * @return the raw value of the module name - */ - public String getName() throws ConstantPoolException { - return cp.getUTF8Value(name_index); - } - - @Override - public String toString() { - return "CONSTANT_Package_info[name_index: " + name_index + "]"; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitPackage(this, data); - } - - public final int name_index; - } - - public static class CONSTANT_String_info extends CPInfo { - CONSTANT_String_info(ConstantPool cp, ClassReader cr) throws IOException { - super(cp); - string_index = cr.readUnsignedShort(); - } - - public CONSTANT_String_info(ConstantPool cp, int string_index) { - super(cp); - this.string_index = string_index; - } - - public int getTag() { - return CONSTANT_String; - } - - public int byteLength() { - return 3; - } - - public String getString() throws ConstantPoolException { - return cp.getUTF8Value(string_index); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitString(this, data); - } - - @Override - public String toString() { - return "CONSTANT_String_info[class_index: " + string_index + "]"; - } - - public final int string_index; - } - - public static class CONSTANT_Utf8_info extends CPInfo { - CONSTANT_Utf8_info(ClassReader cr) throws IOException { - value = cr.readUTF(); - } - - public CONSTANT_Utf8_info(String value) { - this.value = value; - } - - public int getTag() { - return CONSTANT_Utf8; - } - - public int byteLength() { - class SizeOutputStream extends OutputStream { - @Override - public void write(int b) { - size++; - } - int size; - } - SizeOutputStream sizeOut = new SizeOutputStream(); - DataOutputStream out = new DataOutputStream(sizeOut); - try { out.writeUTF(value); } catch (IOException ignore) { } - return 1 + sizeOut.size; - } - - @Override - public String toString() { - if (value.length() < 32 && isPrintableAscii(value)) - return "CONSTANT_Utf8_info[value: \"" + value + "\"]"; - else - return "CONSTANT_Utf8_info[value: (" + value.length() + " chars)]"; - } - - static boolean isPrintableAscii(String s) { - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c < 32 || c >= 127) - return false; - } - return true; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitUtf8(this, data); - } - - public final String value; - } - -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPoolException.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPoolException.java deleted file mode 100644 index 50a9e9b8d88..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPoolException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ConstantPoolException extends Exception { - private static final long serialVersionUID = -2324397349644754565L; - ConstantPoolException(int index) { - this.index = index; - } - - public final int index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantValue_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantValue_attribute.java deleted file mode 100644 index df40defa4f7..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantValue_attribute.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.2. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ConstantValue_attribute extends Attribute { - ConstantValue_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - constantvalue_index = cr.readUnsignedShort(); - } - - public ConstantValue_attribute(ConstantPool constant_pool, int constantvalue_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.ConstantValue), constantvalue_index); - } - - public ConstantValue_attribute(int name_index, int constantvalue_index) { - super(name_index, 2); - this.constantvalue_index = constantvalue_index; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitConstantValue(this, data); - } - - public final int constantvalue_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DefaultAttribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DefaultAttribute.java deleted file mode 100644 index 16fdeb9824d..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DefaultAttribute.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class DefaultAttribute extends Attribute { - DefaultAttribute(ClassReader cr, int name_index, byte[] data) { - this(cr, name_index, data, null); - } - - DefaultAttribute(ClassReader cr, int name_index, byte[] data, String reason) { - super(name_index, data.length); - info = data; - this.reason = reason; - } - - public DefaultAttribute(ConstantPool constant_pool, int name_index, byte[] info) { - this(constant_pool, name_index, info, null); - } - - public DefaultAttribute(ConstantPool constant_pool, int name_index, - byte[] info, String reason) { - super(name_index, info.length); - this.info = info; - this.reason = reason; - } - - public R accept(Visitor visitor, P p) { - return visitor.visitDefault(this, p); - } - - public final byte[] info; - /** Why did we need to generate a DefaultAttribute - */ - public final String reason; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Deprecated_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Deprecated_attribute.java deleted file mode 100644 index dbf6442f202..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Deprecated_attribute.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.15. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Deprecated_attribute extends Attribute { - Deprecated_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - } - - public Deprecated_attribute(ConstantPool constant_pool) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.Deprecated)); - } - - public Deprecated_attribute(int name_index) { - super(name_index, 0); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitDeprecated(this, data); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Descriptor.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Descriptor.java deleted file mode 100644 index fed0f3010a9..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Descriptor.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.4. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Descriptor { - public static class InvalidDescriptor extends DescriptorException { - private static final long serialVersionUID = 1L; - InvalidDescriptor(String desc) { - this.desc = desc; - this.index = -1; - } - - InvalidDescriptor(String desc, int index) { - this.desc = desc; - this.index = index; - } - - @Override - public String getMessage() { - // i18n - if (index == -1) - return "invalid descriptor \"" + desc + "\""; - else - return "descriptor is invalid at offset " + index + " in \"" + desc + "\""; - } - - public final String desc; - public final int index; - - } - - public Descriptor(ClassReader cr) throws IOException { - this(cr.readUnsignedShort()); - } - - public Descriptor(int index) { - this.index = index; - - } - - public String getValue(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(index); - } - - public int getParameterCount(ConstantPool constant_pool) - throws ConstantPoolException, InvalidDescriptor { - String desc = getValue(constant_pool); - int end = desc.indexOf(")"); - if (end == -1) - throw new InvalidDescriptor(desc); - parse(desc, 0, end + 1); - return count; - - } - - public String getParameterTypes(ConstantPool constant_pool) - throws ConstantPoolException, InvalidDescriptor { - String desc = getValue(constant_pool); - int end = desc.indexOf(")"); - if (end == -1) - throw new InvalidDescriptor(desc); - return parse(desc, 0, end + 1); - } - - public String getReturnType(ConstantPool constant_pool) - throws ConstantPoolException, InvalidDescriptor { - String desc = getValue(constant_pool); - int end = desc.indexOf(")"); - if (end == -1) - throw new InvalidDescriptor(desc); - return parse(desc, end + 1, desc.length()); - } - - public String getFieldType(ConstantPool constant_pool) - throws ConstantPoolException, InvalidDescriptor { - String desc = getValue(constant_pool); - return parse(desc, 0, desc.length()); - } - - private String parse(String desc, int start, int end) - throws InvalidDescriptor { - int p = start; - StringBuilder sb = new StringBuilder(); - int dims = 0; - count = 0; - - while (p < end) { - String type; - char ch; - switch (ch = desc.charAt(p++)) { - case '(': - sb.append('('); - continue; - - case ')': - sb.append(')'); - continue; - - case '[': - dims++; - continue; - - case 'B': - type = "byte"; - break; - - case 'C': - type = "char"; - break; - - case 'D': - type = "double"; - break; - - case 'F': - type = "float"; - break; - - case 'I': - type = "int"; - break; - - case 'J': - type = "long"; - break; - - case 'L': - int sep = desc.indexOf(';', p); - if (sep == -1) - throw new InvalidDescriptor(desc, p - 1); - type = desc.substring(p, sep).replace('/', '.'); - p = sep + 1; - break; - - case 'S': - type = "short"; - break; - - case 'Z': - type = "boolean"; - break; - - case 'V': - type = "void"; - break; - - default: - throw new InvalidDescriptor(desc, p - 1); - } - - if (sb.length() > 1 && sb.charAt(0) == '(') - sb.append(", "); - sb.append(type); - for ( ; dims > 0; dims-- ) - sb.append("[]"); - - count++; - } - - return sb.toString(); - } - - public final int index; - private int count; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DescriptorException.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DescriptorException.java deleted file mode 100644 index 0a91e36a914..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DescriptorException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class DescriptorException extends Exception { - private static final long serialVersionUID = 2411890273788901032L; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/EnclosingMethod_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/EnclosingMethod_attribute.java deleted file mode 100644 index 4cbf1eba912..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/EnclosingMethod_attribute.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.7. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class EnclosingMethod_attribute extends Attribute { - EnclosingMethod_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - class_index = cr.readUnsignedShort(); - method_index = cr.readUnsignedShort(); - } - - public EnclosingMethod_attribute(ConstantPool constant_pool, int class_index, int method_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.EnclosingMethod), class_index, method_index); - } - - public EnclosingMethod_attribute(int name_index, int class_index, int method_index) { - super(name_index, 4); - this.class_index = class_index; - this.method_index = method_index; - } - - public String getClassName(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getClassInfo(class_index).getName(); - } - - public String getMethodName(ConstantPool constant_pool) throws ConstantPoolException { - if (method_index == 0) - return ""; - return constant_pool.getNameAndTypeInfo(method_index).getName(); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitEnclosingMethod(this, data); - } - - public final int class_index; - public final int method_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Exceptions_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Exceptions_attribute.java deleted file mode 100644 index a56db00b371..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Exceptions_attribute.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.5. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Exceptions_attribute extends Attribute { - Exceptions_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - number_of_exceptions = cr.readUnsignedShort(); - exception_index_table = new int[number_of_exceptions]; - for (int i = 0; i < number_of_exceptions; i++) - exception_index_table[i] = cr.readUnsignedShort(); - } - - public Exceptions_attribute(ConstantPool constant_pool, int[] exception_index_table) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.Exceptions), exception_index_table); - } - - public Exceptions_attribute(int name_index, int[] exception_index_table) { - super(name_index, 2 + 2 * exception_index_table.length); - this.number_of_exceptions = exception_index_table.length; - this.exception_index_table = exception_index_table; - } - - public String getException(int index, ConstantPool constant_pool) throws ConstantPoolException { - int exception_index = exception_index_table[index]; - return constant_pool.getClassInfo(exception_index).getName(); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitExceptions(this, data); - } - - public final int number_of_exceptions; - public final int[] exception_index_table; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/FatalError.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/FatalError.java deleted file mode 100644 index 1f7ad56ef9d..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/FatalError.java +++ /dev/null @@ -1,40 +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. - */ - -package com.sun.tools.classfile; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class FatalError extends Error { - private static final long serialVersionUID = 8114054446416187030L; - - FatalError(String message) { - super(message); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Field.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Field.java deleted file mode 100644 index 89e313f6fc8..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Field.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Field { - Field(ClassReader cr) throws IOException { - access_flags = new AccessFlags(cr); - name_index = cr.readUnsignedShort(); - descriptor = new Descriptor(cr); - attributes = new Attributes(cr); - } - - public Field(AccessFlags access_flags, - int name_index, Descriptor descriptor, - Attributes attributes) { - this.access_flags = access_flags; - this.name_index = name_index; - this.descriptor = descriptor; - this.attributes = attributes; - } - - public int byteLength() { - return 6 + attributes.byteLength(); - } - - public String getName(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(name_index); - } - - public final AccessFlags access_flags; - public final int name_index; - public final Descriptor descriptor; - public final Attributes attributes; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/InnerClasses_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/InnerClasses_attribute.java deleted file mode 100644 index b7ae9ab5d51..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/InnerClasses_attribute.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -import com.sun.tools.classfile.ConstantPool.*; - -/** - * See JVMS, section 4.8.6. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class InnerClasses_attribute extends Attribute { - InnerClasses_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - number_of_classes = cr.readUnsignedShort(); - classes = new Info[number_of_classes]; - for (int i = 0; i < number_of_classes; i++) - classes[i] = new Info(cr); - } - - public InnerClasses_attribute(ConstantPool constant_pool, Info[] classes) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.InnerClasses), classes); - } - - public InnerClasses_attribute(int name_index, Info[] classes) { - super(name_index, 2 + Info.length() * classes.length); - this.number_of_classes = classes.length; - this.classes = classes; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitInnerClasses(this, data); - } - - public final int number_of_classes; - public final Info[] classes; - - public static class Info { - Info(ClassReader cr) throws IOException { - inner_class_info_index = cr.readUnsignedShort(); - outer_class_info_index = cr.readUnsignedShort(); - inner_name_index = cr.readUnsignedShort(); - inner_class_access_flags = new AccessFlags(cr.readUnsignedShort()); - } - - public Info(int inner_class_info_index, int outer_class_info_index, int inner_name_index, AccessFlags inner_class_access_flags) { - this.inner_class_info_index = inner_class_info_index; - this.outer_class_info_index = outer_class_info_index; - this.inner_name_index = inner_name_index; - this.inner_class_access_flags = inner_class_access_flags; - } - - public CONSTANT_Class_info getInnerClassInfo(ConstantPool constant_pool) throws ConstantPoolException { - if (inner_class_info_index == 0) - return null; - return constant_pool.getClassInfo(inner_class_info_index); - } - - public CONSTANT_Class_info getOuterClassInfo(ConstantPool constant_pool) throws ConstantPoolException { - if (outer_class_info_index == 0) - return null; - return constant_pool.getClassInfo(outer_class_info_index); - } - - public String getInnerName(ConstantPool constant_pool) throws ConstantPoolException { - if (inner_name_index == 0) - return null; - return constant_pool.getUTF8Value(inner_name_index); - } - - public static int length() { - return 8; - } - - public final int inner_class_info_index; - public final int outer_class_info_index; - public final int inner_name_index; - public final AccessFlags inner_class_access_flags; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Instruction.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Instruction.java deleted file mode 100644 index 0f5f15eed39..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Instruction.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.util.Locale; - -/** - * See JVMS, chapter 6. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - * - * @see Code_attribute#getInstructions - */ -public class Instruction { - /** The kind of an instruction, as determined by the position, size and - * types of its operands. */ - public static enum Kind { - /** Opcode is not followed by any operands. */ - NO_OPERANDS(1), - /** Opcode is followed by a byte indicating a type. */ - ATYPE(2), - /** Opcode is followed by a 2-byte branch offset. */ - BRANCH(3), - /** Opcode is followed by a 4-byte branch offset. */ - BRANCH_W(5), - /** Opcode is followed by a signed byte value. */ - BYTE(2), - /** Opcode is followed by a 1-byte index into the constant pool. */ - CPREF(2), - /** Opcode is followed by a 2-byte index into the constant pool. */ - CPREF_W(3), - /** Opcode is followed by a 2-byte index into the constant pool, - * an unsigned byte value. */ - CPREF_W_UBYTE(4), - /** Opcode is followed by a 2-byte index into the constant pool., - * an unsigned byte value, and a zero byte. */ - CPREF_W_UBYTE_ZERO(5), - /** Opcode is followed by variable number of operands, depending - * on the instruction.*/ - DYNAMIC(-1), - /** Opcode is followed by a 1-byte reference to a local variable. */ - LOCAL(2), - /** Opcode is followed by a 1-byte reference to a local variable, - * and a signed byte value. */ - LOCAL_BYTE(3), - /** Opcode is followed by a signed short value. */ - SHORT(3), - /** Wide opcode is not followed by any operands. */ - WIDE_NO_OPERANDS(2), - /** Wide opcode is followed by a 2-byte index into the local variables array. */ - WIDE_LOCAL(4), - /** Wide opcode is followed by a 2-byte index into the constant pool. */ - WIDE_CPREF_W(4), - /** Wide opcode is followed by a 2-byte index into the constant pool, - * and a signed short value. */ - WIDE_CPREF_W_SHORT(6), - /** Wide opcode is followed by a 2-byte reference to a local variable, - * and a signed short value. */ - WIDE_LOCAL_SHORT(6), - /** Opcode was not recognized. */ - UNKNOWN(1); - - Kind(int length) { - this.length = length; - } - - /** The length, in bytes, of this kind of instruction, or -1 is the - * length depends on the specific instruction. */ - public final int length; - } - - /** A utility visitor to help decode the operands of an instruction. - * @see Instruction#accept */ - public interface KindVisitor { - /** See {@link Kind#NO_OPERANDS}, {@link Kind#WIDE_NO_OPERANDS}. */ - R visitNoOperands(Instruction instr, P p); - /** See {@link Kind#ATYPE}. */ - R visitArrayType(Instruction instr, TypeKind kind, P p); - /** See {@link Kind#BRANCH}, {@link Kind#BRANCH_W}. */ - R visitBranch(Instruction instr, int offset, P p); - /** See {@link Kind#CPREF}, {@link Kind#CPREF_W}, {@link Kind#WIDE_CPREF_W}. */ - R visitConstantPoolRef(Instruction instr, int index, P p); - /** See {@link Kind#CPREF_W_UBYTE}, {@link Kind#CPREF_W_UBYTE_ZERO}, {@link Kind#WIDE_CPREF_W_SHORT}. */ - R visitConstantPoolRefAndValue(Instruction instr, int index, int value, P p); - /** See {@link Kind#LOCAL}, {@link Kind#WIDE_LOCAL}. */ - R visitLocal(Instruction instr, int index, P p); - /** See {@link Kind#LOCAL_BYTE}. */ - R visitLocalAndValue(Instruction instr, int index, int value, P p); - /** See {@link Kind#DYNAMIC}. */ - R visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, P p); - /** See {@link Kind#DYNAMIC}. */ - R visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, P p); - /** See {@link Kind#BYTE}, {@link Kind#SHORT}. */ - R visitValue(Instruction instr, int value, P p); - /** Instruction is unrecognized. */ - R visitUnknown(Instruction instr, P p); - - } - - /** The kind of primitive array type to create. - * See JVMS chapter 6, newarray. */ - public static enum TypeKind { - T_BOOLEAN(4, "boolean"), - T_CHAR(5, "char"), - T_FLOAT(6, "float"), - T_DOUBLE(7, "double"), - T_BYTE(8, "byte"), - T_SHORT(9, "short"), - T_INT (10, "int"), - T_LONG (11, "long"); - TypeKind(int value, String name) { - this.value = value; - this.name = name; - } - - public static TypeKind get(int value) { - switch (value) { - case 4: return T_BOOLEAN; - case 5: return T_CHAR; - case 6: return T_FLOAT; - case 7: return T_DOUBLE; - case 8: return T_BYTE; - case 9: return T_SHORT; - case 10: return T_INT; - case 11: return T_LONG; - default: return null; - } - } - - public final int value; - public final String name; - } - - /** An instruction is defined by its position in a bytecode array. */ - public Instruction(byte[] bytes, int pc) { - this.bytes = bytes; - this.pc = pc; - } - - /** Get the position of the instruction within the bytecode array. */ - public int getPC() { - return pc; - } - - /** Get a byte value, relative to the start of this instruction. */ - public int getByte(int offset) { - return bytes[pc + offset]; - } - - /** Get an unsigned byte value, relative to the start of this instruction. */ - public int getUnsignedByte(int offset) { - return getByte(offset) & 0xff; - } - - /** Get a 2-byte value, relative to the start of this instruction. */ - public int getShort(int offset) { - return (getByte(offset) << 8) | getUnsignedByte(offset + 1); - } - - /** Get a unsigned 2-byte value, relative to the start of this instruction. */ - public int getUnsignedShort(int offset) { - return getShort(offset) & 0xFFFF; - } - - /** Get a 4-byte value, relative to the start of this instruction. */ - public int getInt(int offset) { - return (getShort(offset) << 16) | (getUnsignedShort(offset + 2)); - } - - /** Get the Opcode for this instruction, or null if the instruction is - * unrecognized. */ - public Opcode getOpcode() { - int b = getUnsignedByte(0); - switch (b) { - case Opcode.NONPRIV: - case Opcode.PRIV: - case Opcode.WIDE: - return Opcode.get(b, getUnsignedByte(1)); - } - return Opcode.get(b); - } - - /** Get the mnemonic for this instruction, or a default string if the - * instruction is unrecognized. */ - public String getMnemonic() { - Opcode opcode = getOpcode(); - if (opcode == null) - return "bytecode " + getUnsignedByte(0); - else - return opcode.toString().toLowerCase(Locale.US); - } - - /** Get the length, in bytes, of this instruction, including the opcode - * and all its operands. */ - public int length() { - Opcode opcode = getOpcode(); - if (opcode == null) - return 1; - - switch (opcode) { - case TABLESWITCH: { - int pad = align(pc + 1) - pc; - int low = getInt(pad + 4); - int high = getInt(pad + 8); - return pad + 12 + 4 * (high - low + 1); - } - case LOOKUPSWITCH: { - int pad = align(pc + 1) - pc; - int npairs = getInt(pad + 4); - return pad + 8 + 8 * npairs; - - } - default: - return opcode.kind.length; - } - } - - /** Get the {@link Kind} of this instruction. */ - public Kind getKind() { - Opcode opcode = getOpcode(); - return (opcode != null ? opcode.kind : Kind.UNKNOWN); - } - - /** Invoke a method on the visitor according to the kind of this - * instruction, passing in the decoded operands for the instruction. */ - public R accept(KindVisitor visitor, P p) { - switch (getKind()) { - case NO_OPERANDS: - return visitor.visitNoOperands(this, p); - - case ATYPE: - return visitor.visitArrayType( - this, TypeKind.get(getUnsignedByte(1)), p); - - case BRANCH: - return visitor.visitBranch(this, getShort(1), p); - - case BRANCH_W: - return visitor.visitBranch(this, getInt(1), p); - - case BYTE: - return visitor.visitValue(this, getByte(1), p); - - case CPREF: - return visitor.visitConstantPoolRef(this, getUnsignedByte(1), p); - - case CPREF_W: - return visitor.visitConstantPoolRef(this, getUnsignedShort(1), p); - - case CPREF_W_UBYTE: - case CPREF_W_UBYTE_ZERO: - return visitor.visitConstantPoolRefAndValue( - this, getUnsignedShort(1), getUnsignedByte(3), p); - - case DYNAMIC: { - switch (getOpcode()) { - case TABLESWITCH: { - int pad = align(pc + 1) - pc; - int default_ = getInt(pad); - int low = getInt(pad + 4); - int high = getInt(pad + 8); - if (low > high) - throw new IllegalStateException(); - int[] values = new int[high - low + 1]; - for (int i = 0; i < values.length; i++) - values[i] = getInt(pad + 12 + 4 * i); - return visitor.visitTableSwitch( - this, default_, low, high, values, p); - } - case LOOKUPSWITCH: { - int pad = align(pc + 1) - pc; - int default_ = getInt(pad); - int npairs = getInt(pad + 4); - if (npairs < 0) - throw new IllegalStateException(); - int[] matches = new int[npairs]; - int[] offsets = new int[npairs]; - for (int i = 0; i < npairs; i++) { - matches[i] = getInt(pad + 8 + i * 8); - offsets[i] = getInt(pad + 12 + i * 8); - } - return visitor.visitLookupSwitch( - this, default_, npairs, matches, offsets, p); - } - default: - throw new IllegalStateException(); - } - } - - case LOCAL: - return visitor.visitLocal(this, getUnsignedByte(1), p); - - case LOCAL_BYTE: - return visitor.visitLocalAndValue( - this, getUnsignedByte(1), getByte(2), p); - - case SHORT: - return visitor.visitValue(this, getShort(1), p); - - case WIDE_NO_OPERANDS: - return visitor.visitNoOperands(this, p); - - case WIDE_LOCAL: - return visitor.visitLocal(this, getUnsignedShort(2), p); - - case WIDE_CPREF_W: - return visitor.visitConstantPoolRef(this, getUnsignedShort(2), p); - - case WIDE_CPREF_W_SHORT: - return visitor.visitConstantPoolRefAndValue( - this, getUnsignedShort(2), getUnsignedByte(4), p); - - case WIDE_LOCAL_SHORT: - return visitor.visitLocalAndValue( - this, getUnsignedShort(2), getShort(4), p); - - case UNKNOWN: - return visitor.visitUnknown(this, p); - - default: - throw new IllegalStateException(); - } - } - - private static int align(int n) { - return (n + 3) & ~3; - } - - private byte[] bytes; - private int pc; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LineNumberTable_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LineNumberTable_attribute.java deleted file mode 100644 index 58595b7d058..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LineNumberTable_attribute.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.12. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class LineNumberTable_attribute extends Attribute { - LineNumberTable_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - line_number_table_length = cr.readUnsignedShort(); - line_number_table = new Entry[line_number_table_length]; - for (int i = 0; i < line_number_table_length; i++) - line_number_table[i] = new Entry(cr); - } - - public LineNumberTable_attribute(ConstantPool constant_pool, Entry[] line_number_table) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.LineNumberTable), line_number_table); - } - - public LineNumberTable_attribute(int name_index, Entry[] line_number_table) { - super(name_index, 2 + line_number_table.length * Entry.length()); - this.line_number_table_length = line_number_table.length; - this.line_number_table = line_number_table; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitLineNumberTable(this, data); - } - - public final int line_number_table_length; - public final Entry[] line_number_table; - - public static class Entry { - Entry(ClassReader cr) throws IOException { - start_pc = cr.readUnsignedShort(); - line_number = cr.readUnsignedShort(); - } - - public static int length() { - return 4; - } - - public final int start_pc; - public final int line_number; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTable_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTable_attribute.java deleted file mode 100644 index 1e4465f2f7c..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTable_attribute.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.13. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class LocalVariableTable_attribute extends Attribute { - LocalVariableTable_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - local_variable_table_length = cr.readUnsignedShort(); - local_variable_table = new Entry[local_variable_table_length]; - for (int i = 0; i < local_variable_table_length; i++) - local_variable_table[i] = new Entry(cr); - } - - public LocalVariableTable_attribute(ConstantPool constant_pool, Entry[] local_variable_table) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.LocalVariableTable), local_variable_table); - } - - public LocalVariableTable_attribute(int name_index, Entry[] local_variable_table) { - super(name_index, 2 + local_variable_table.length * Entry.length()); - this.local_variable_table_length = local_variable_table.length; - this.local_variable_table = local_variable_table; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitLocalVariableTable(this, data); - } - - public final int local_variable_table_length; - public final Entry[] local_variable_table; - - public static class Entry { - Entry(ClassReader cr) throws IOException { - start_pc = cr.readUnsignedShort(); - length = cr.readUnsignedShort(); - name_index = cr.readUnsignedShort(); - descriptor_index = cr.readUnsignedShort(); - index = cr.readUnsignedShort(); - } - - public static int length() { - return 10; - } - - public final int start_pc; - public final int length; - public final int name_index; - public final int descriptor_index; - public final int index; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTypeTable_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTypeTable_attribute.java deleted file mode 100644 index 8332cbec577..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/LocalVariableTypeTable_attribute.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.14. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class LocalVariableTypeTable_attribute extends Attribute { - LocalVariableTypeTable_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - local_variable_table_length = cr.readUnsignedShort(); - local_variable_table = new Entry[local_variable_table_length]; - for (int i = 0; i < local_variable_table_length; i++) - local_variable_table[i] = new Entry(cr); - } - - public LocalVariableTypeTable_attribute(ConstantPool constant_pool, Entry[] local_variable_table) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.LocalVariableTypeTable), local_variable_table); - } - - public LocalVariableTypeTable_attribute(int name_index, Entry[] local_variable_table) { - super(name_index, 2 + local_variable_table.length * Entry.length()); - this.local_variable_table_length = local_variable_table.length; - this.local_variable_table = local_variable_table; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitLocalVariableTypeTable(this, data); - } - - public final int local_variable_table_length; - public final Entry[] local_variable_table; - - public static class Entry { - Entry(ClassReader cr) throws IOException { - start_pc = cr.readUnsignedShort(); - length = cr.readUnsignedShort(); - name_index = cr.readUnsignedShort(); - signature_index = cr.readUnsignedShort(); - index = cr.readUnsignedShort(); - } - - public static int length() { - return 10; - } - - public final int start_pc; - public final int length; - public final int name_index; - public final int signature_index; - public final int index; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Method.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Method.java deleted file mode 100644 index 5345d54ccdf..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Method.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/* - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Method { - Method(ClassReader cr) throws IOException { - access_flags = new AccessFlags(cr); - name_index = cr.readUnsignedShort(); - descriptor = new Descriptor(cr); - attributes = new Attributes(cr); - } - - public Method(AccessFlags access_flags, - int name_index, Descriptor descriptor, - Attributes attributes) { - this.access_flags = access_flags; - this.name_index = name_index; - this.descriptor = descriptor; - this.attributes = attributes; - } - - public int byteLength() { - return 6 + attributes.byteLength(); - } - - public String getName(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(name_index); - } - - public final AccessFlags access_flags; - public final int name_index; - public final Descriptor descriptor; - public final Attributes attributes; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java deleted file mode 100644 index 942f8f00c04..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MethodParameters_attribute.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.13. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class MethodParameters_attribute extends Attribute { - - public final int method_parameter_table_length; - public final Entry[] method_parameter_table; - - MethodParameters_attribute(ClassReader cr, - int name_index, - int length) - throws IOException { - super(name_index, length); - - method_parameter_table_length = cr.readUnsignedByte(); - method_parameter_table = new Entry[method_parameter_table_length]; - for (int i = 0; i < method_parameter_table_length; i++) - method_parameter_table[i] = new Entry(cr); - } - - public MethodParameters_attribute(ConstantPool constant_pool, - Entry[] method_parameter_table) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.MethodParameters), - method_parameter_table); - } - - public MethodParameters_attribute(int name_index, - Entry[] method_parameter_table) { - super(name_index, 1 + method_parameter_table.length * Entry.length()); - this.method_parameter_table_length = method_parameter_table.length; - this.method_parameter_table = method_parameter_table; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitMethodParameters(this, data); - } - - public static class Entry { - Entry(ClassReader cr) throws IOException { - name_index = cr.readUnsignedShort(); - flags = cr.readUnsignedShort(); - } - - public Entry(int name_index, int flags) { - this.name_index = name_index; - this.flags = flags; - } - - public static int length() { - return 6; - } - - public final int name_index; - public final int flags; - } - -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleHashes_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleHashes_attribute.java deleted file mode 100644 index c227f3df8b7..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleHashes_attribute.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.15. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ModuleHashes_attribute extends Attribute { - ModuleHashes_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - algorithm_index = cr.readUnsignedShort(); - hashes_table_length = cr.readUnsignedShort(); - hashes_table = new Entry[hashes_table_length]; - for (int i = 0; i < hashes_table_length; i++) - hashes_table[i] = new Entry(cr); - } - - public ModuleHashes_attribute(ConstantPool constant_pool, int algorithm_index, Entry[] hashes_table) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.ModuleHashes), algorithm_index, hashes_table); - } - - public ModuleHashes_attribute(int name_index, int algorithm_index, Entry[] hashes_table) { - super(name_index, 2 + 2 + length(hashes_table)); - this.algorithm_index = algorithm_index; - this.hashes_table_length = hashes_table.length; - this.hashes_table = hashes_table; - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitModuleHashes(this, data); - } - - private static int length(Entry[] hashes_table) { - int len = 0; - for (Entry e: hashes_table) { - len += e.length(); - } - return len; - } - - public final int algorithm_index; - public final int hashes_table_length; - public final Entry[] hashes_table; - - public static class Entry { - Entry(ClassReader cr) throws IOException { - module_name_index = cr.readUnsignedShort(); - int hash_length = cr.readUnsignedShort(); - hash = new byte[hash_length]; - for (int i=0; iThis is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ModuleMainClass_attribute extends Attribute { - ModuleMainClass_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - main_class_index = cr.readUnsignedShort(); - } - - public ModuleMainClass_attribute(ConstantPool constant_pool, int mainClass_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.ModuleMainClass), mainClass_index); - } - - public ModuleMainClass_attribute(int name_index, int mainClass_index) { - super(name_index, 2); - this.main_class_index = mainClass_index; - } - - public String getMainClassName(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getClassInfo(main_class_index).getName(); - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitModuleMainClass(this, data); - } - - public final int main_class_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModulePackages_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModulePackages_attribute.java deleted file mode 100644 index 9b3cd433bd8..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModulePackages_attribute.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -import com.sun.tools.classfile.ConstantPool.CONSTANT_Package_info; - -/** - * See JVMS, section 4.8.15. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ModulePackages_attribute extends Attribute { - ModulePackages_attribute(ClassReader cr, int name_index, int length) - throws IOException { - super(name_index, length); - packages_count = cr.readUnsignedShort(); - packages_index = new int[packages_count]; - for (int i = 0; i < packages_count; i++) - packages_index[i] = cr.readUnsignedShort(); - } - - public ModulePackages_attribute(ConstantPool constant_pool, - int[] packages_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.ModulePackages), - packages_index); - } - - public ModulePackages_attribute(int name_index, - int[] packages_index) { - super(name_index, 2 + packages_index.length * 2); - this.packages_count = packages_index.length; - this.packages_index = packages_index; - } - - public String getPackage(int index, ConstantPool constant_pool) throws ConstantPoolException { - int package_index = packages_index[index]; - CONSTANT_Package_info info = constant_pool.getPackageInfo(package_index); - return info.getName(); - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitModulePackages(this, data); - } - - public final int packages_count; - public final int[] packages_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java deleted file mode 100644 index e1ba78a3376..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleResolution_attribute.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.15. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ModuleResolution_attribute extends Attribute { - public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001; - public static final int WARN_DEPRECATED = 0x0002; - public static final int WARN_DEPRECATED_FOR_REMOVAL = 0x0004; - public static final int WARN_INCUBATING = 0x0008; - - ModuleResolution_attribute(ClassReader cr, int name_index, int length) - throws IOException { - super(name_index, length); - resolution_flags = cr.readUnsignedShort(); - } - - public ModuleResolution_attribute(ConstantPool constant_pool, - int resolution_flags) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.ModuleResolution), - resolution_flags); - } - - public ModuleResolution_attribute(int name_index, - int resolution_flags) { - super(name_index, 2); - this.resolution_flags = resolution_flags; - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitModuleResolution(this, data); - } - - public final int resolution_flags; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleTarget_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleTarget_attribute.java deleted file mode 100644 index b7d7ecc77e3..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleTarget_attribute.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 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. 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.15. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ModuleTarget_attribute extends Attribute { - ModuleTarget_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - target_platform_index = cr.readUnsignedShort(); - } - - public ModuleTarget_attribute(int name_index, int target_platform_index) { - super(name_index, 2); - this.target_platform_index = target_platform_index; - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitModuleTarget(this, data); - } - - public final int target_platform_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java deleted file mode 100644 index 6b0b525b50c..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2015, 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. 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 com.sun.tools.classfile; - -import java.io.IOException; - -import com.sun.tools.classfile.ConstantPool.CONSTANT_Module_info; - -/** - * See Jigsaw. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Module_attribute extends Attribute { - public static final int ACC_TRANSITIVE = 0x20; - public static final int ACC_STATIC_PHASE = 0x40; - public static final int ACC_OPEN = 0x20; - public static final int ACC_SYNTHETIC = 0x1000; - public static final int ACC_MANDATED = 0x8000; - - Module_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - - module_name = cr.readUnsignedShort(); - module_flags = cr.readUnsignedShort(); - - module_version_index = cr.readUnsignedShort(); - - requires_count = cr.readUnsignedShort(); - requires = new RequiresEntry[requires_count]; - for (int i = 0; i < requires_count; i++) - requires[i] = new RequiresEntry(cr); - - exports_count = cr.readUnsignedShort(); - exports = new ExportsEntry[exports_count]; - for (int i = 0; i < exports_count; i++) - exports[i] = new ExportsEntry(cr); - - opens_count = cr.readUnsignedShort(); - opens = new OpensEntry[opens_count]; - for (int i = 0; i < opens_count; i++) - opens[i] = new OpensEntry(cr); - - uses_count = cr.readUnsignedShort(); - uses_index = new int[uses_count]; - for (int i = 0; i < uses_count; i++) - uses_index[i] = cr.readUnsignedShort(); - - provides_count = cr.readUnsignedShort(); - provides = new ProvidesEntry[provides_count]; - for (int i = 0; i < provides_count; i++) - provides[i] = new ProvidesEntry(cr); - } - - public Module_attribute(int name_index, - int module_name, - int module_flags, - int module_version_index, - RequiresEntry[] requires, - ExportsEntry[] exports, - OpensEntry[] opens, - int[] uses, - ProvidesEntry[] provides) { - super(name_index, 2); - this.module_name = module_name; - this.module_flags = module_flags; - this.module_version_index = module_version_index; - requires_count = requires.length; - this.requires = requires; - exports_count = exports.length; - this.exports = exports; - opens_count = opens.length; - this.opens = opens; - uses_count = uses.length; - this.uses_index = uses; - provides_count = provides.length; - this.provides = provides; - } - - public String getUses(int index, ConstantPool constant_pool) throws ConstantPoolException { - int i = uses_index[index]; - return constant_pool.getClassInfo(i).getName(); - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitModule(this, data); - } - - public final int module_name; - public final int module_flags; - public final int module_version_index; - public final int requires_count; - public final RequiresEntry[] requires; - public final int exports_count; - public final ExportsEntry[] exports; - public final int opens_count; - public final OpensEntry[] opens; - public final int uses_count; - public final int[] uses_index; - public final int provides_count; - public final ProvidesEntry[] provides; - - public static class RequiresEntry { - RequiresEntry(ClassReader cr) throws IOException { - requires_index = cr.readUnsignedShort(); - requires_flags = cr.readUnsignedShort(); - requires_version_index = cr.readUnsignedShort(); - } - - public RequiresEntry(int index, int flags, int version_index) { - this.requires_index = index; - this.requires_flags = flags; - this.requires_version_index = version_index; - } - - public String getRequires(ConstantPool constant_pool) throws ConstantPoolException { - CONSTANT_Module_info info = constant_pool.getModuleInfo(requires_index); - return info.getName(); - } - - public static final int length = 4; - - public final int requires_index; - public final int requires_flags; - public final int requires_version_index; - } - - public static class ExportsEntry { - ExportsEntry(ClassReader cr) throws IOException { - exports_index = cr.readUnsignedShort(); - exports_flags = cr.readUnsignedShort(); - exports_to_count = cr.readUnsignedShort(); - exports_to_index = new int[exports_to_count]; - for (int i = 0; i < exports_to_count; i++) - exports_to_index[i] = cr.readUnsignedShort(); - } - - public ExportsEntry(int index, int flags, int[] to) { - this.exports_index = index; - this.exports_flags = flags; - this.exports_to_count = to.length; - this.exports_to_index = to; - } - - public int length() { - return 4 + 2 * exports_to_index.length; - } - - public final int exports_index; - public final int exports_flags; - public final int exports_to_count; - public final int[] exports_to_index; - } - - public static class OpensEntry { - OpensEntry(ClassReader cr) throws IOException { - opens_index = cr.readUnsignedShort(); - opens_flags = cr.readUnsignedShort(); - opens_to_count = cr.readUnsignedShort(); - opens_to_index = new int[opens_to_count]; - for (int i = 0; i < opens_to_count; i++) - opens_to_index[i] = cr.readUnsignedShort(); - } - - public OpensEntry(int index, int flags, int[] to) { - this.opens_index = index; - this.opens_flags = flags; - this.opens_to_count = to.length; - this.opens_to_index = to; - } - - public int length() { - return 4 + 2 * opens_to_index.length; - } - - public final int opens_index; - public final int opens_flags; - public final int opens_to_count; - public final int[] opens_to_index; - } - - public static class ProvidesEntry { - ProvidesEntry(ClassReader cr) throws IOException { - provides_index = cr.readUnsignedShort(); - with_count = cr.readUnsignedShort(); - with_index = new int[with_count]; - for (int i = 0; i < with_count; i++) - with_index[i] = cr.readUnsignedShort(); - } - - public ProvidesEntry(int provides, int[] with) { - this.provides_index = provides; - this.with_count = with.length; - this.with_index = with; - } - - public static final int length = 4; - - public final int provides_index; - public final int with_count; - public final int[] with_index; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestHost_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestHost_attribute.java deleted file mode 100644 index 0473fbf56fe..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestHost_attribute.java +++ /dev/null @@ -1,63 +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 com.sun.tools.classfile; - -import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; - -import java.io.IOException; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class NestHost_attribute extends Attribute { - NestHost_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - top_index = cr.readUnsignedShort(); - } - - public NestHost_attribute(ConstantPool constant_pool, int signature_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.Signature), signature_index); - } - - public NestHost_attribute(int name_index, int top_index) { - super(name_index, 2); - this.top_index = top_index; - } - - public CONSTANT_Class_info getNestTop(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getClassInfo(top_index); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitNestHost(this, data); - } - - public final int top_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestMembers_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestMembers_attribute.java deleted file mode 100644 index bf57a12a1a6..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestMembers_attribute.java +++ /dev/null @@ -1,70 +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 com.sun.tools.classfile; - -import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; - -import java.io.IOException; -import java.util.stream.IntStream; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class NestMembers_attribute extends Attribute { - NestMembers_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - int len = cr.readUnsignedShort(); - members_indexes = new int[len]; - for (int i = 0 ; i < len ; i++) { - members_indexes[i] = cr.readUnsignedShort(); - } - } - - public NestMembers_attribute(int name_index, int[] members_indexes) { - super(name_index, 2); - this.members_indexes = members_indexes; - } - - public CONSTANT_Class_info[] getChildren(ConstantPool constant_pool) throws ConstantPoolException { - return IntStream.of(members_indexes) - .mapToObj(i -> { - try { - return constant_pool.getClassInfo(i); - } catch (ConstantPoolException ex) { - throw new AssertionError(ex); - } - }).toArray(CONSTANT_Class_info[]::new); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitNestMembers(this, data); - } - - public final int[] members_indexes; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Opcode.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Opcode.java deleted file mode 100644 index 0f3ff043416..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Opcode.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import static com.sun.tools.classfile.Instruction.Kind.*; -import static com.sun.tools.classfile.Opcode.Set.*; - -/** - * See JVMS, chapter 6. - * - *

In addition to providing all the standard opcodes defined in JVMS, - * this class also provides legacy support for the PicoJava extensions. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public enum Opcode { - NOP(0x0), - ACONST_NULL(0x1), - ICONST_M1(0x2), - ICONST_0(0x3), - ICONST_1(0x4), - ICONST_2(0x5), - ICONST_3(0x6), - ICONST_4(0x7), - ICONST_5(0x8), - LCONST_0(0x9), - LCONST_1(0xa), - FCONST_0(0xb), - FCONST_1(0xc), - FCONST_2(0xd), - DCONST_0(0xe), - DCONST_1(0xf), - BIPUSH(0x10, BYTE), - SIPUSH(0x11, SHORT), - LDC(0x12, CPREF), - LDC_W(0x13, CPREF_W), - LDC2_W(0x14, CPREF_W), - ILOAD(0x15, LOCAL), - LLOAD(0x16, LOCAL), - FLOAD(0x17, LOCAL), - DLOAD(0x18, LOCAL), - ALOAD(0x19, LOCAL), - ILOAD_0(0x1a), - ILOAD_1(0x1b), - ILOAD_2(0x1c), - ILOAD_3(0x1d), - LLOAD_0(0x1e), - LLOAD_1(0x1f), - LLOAD_2(0x20), - LLOAD_3(0x21), - FLOAD_0(0x22), - FLOAD_1(0x23), - FLOAD_2(0x24), - FLOAD_3(0x25), - DLOAD_0(0x26), - DLOAD_1(0x27), - DLOAD_2(0x28), - DLOAD_3(0x29), - ALOAD_0(0x2a), - ALOAD_1(0x2b), - ALOAD_2(0x2c), - ALOAD_3(0x2d), - IALOAD(0x2e), - LALOAD(0x2f), - FALOAD(0x30), - DALOAD(0x31), - AALOAD(0x32), - BALOAD(0x33), - CALOAD(0x34), - SALOAD(0x35), - ISTORE(0x36, LOCAL), - LSTORE(0x37, LOCAL), - FSTORE(0x38, LOCAL), - DSTORE(0x39, LOCAL), - ASTORE(0x3a, LOCAL), - ISTORE_0(0x3b), - ISTORE_1(0x3c), - ISTORE_2(0x3d), - ISTORE_3(0x3e), - LSTORE_0(0x3f), - LSTORE_1(0x40), - LSTORE_2(0x41), - LSTORE_3(0x42), - FSTORE_0(0x43), - FSTORE_1(0x44), - FSTORE_2(0x45), - FSTORE_3(0x46), - DSTORE_0(0x47), - DSTORE_1(0x48), - DSTORE_2(0x49), - DSTORE_3(0x4a), - ASTORE_0(0x4b), - ASTORE_1(0x4c), - ASTORE_2(0x4d), - ASTORE_3(0x4e), - IASTORE(0x4f), - LASTORE(0x50), - FASTORE(0x51), - DASTORE(0x52), - AASTORE(0x53), - BASTORE(0x54), - CASTORE(0x55), - SASTORE(0x56), - POP(0x57), - POP2(0x58), - DUP(0x59), - DUP_X1(0x5a), - DUP_X2(0x5b), - DUP2(0x5c), - DUP2_X1(0x5d), - DUP2_X2(0x5e), - SWAP(0x5f), - IADD(0x60), - LADD(0x61), - FADD(0x62), - DADD(0x63), - ISUB(0x64), - LSUB(0x65), - FSUB(0x66), - DSUB(0x67), - IMUL(0x68), - LMUL(0x69), - FMUL(0x6a), - DMUL(0x6b), - IDIV(0x6c), - LDIV(0x6d), - FDIV(0x6e), - DDIV(0x6f), - IREM(0x70), - LREM(0x71), - FREM(0x72), - DREM(0x73), - INEG(0x74), - LNEG(0x75), - FNEG(0x76), - DNEG(0x77), - ISHL(0x78), - LSHL(0x79), - ISHR(0x7a), - LSHR(0x7b), - IUSHR(0x7c), - LUSHR(0x7d), - IAND(0x7e), - LAND(0x7f), - IOR(0x80), - LOR(0x81), - IXOR(0x82), - LXOR(0x83), - IINC(0x84, LOCAL_BYTE), - I2L(0x85), - I2F(0x86), - I2D(0x87), - L2I(0x88), - L2F(0x89), - L2D(0x8a), - F2I(0x8b), - F2L(0x8c), - F2D(0x8d), - D2I(0x8e), - D2L(0x8f), - D2F(0x90), - I2B(0x91), - I2C(0x92), - I2S(0x93), - LCMP(0x94), - FCMPL(0x95), - FCMPG(0x96), - DCMPL(0x97), - DCMPG(0x98), - IFEQ(0x99, BRANCH), - IFNE(0x9a, BRANCH), - IFLT(0x9b, BRANCH), - IFGE(0x9c, BRANCH), - IFGT(0x9d, BRANCH), - IFLE(0x9e, BRANCH), - IF_ICMPEQ(0x9f, BRANCH), - IF_ICMPNE(0xa0, BRANCH), - IF_ICMPLT(0xa1, BRANCH), - IF_ICMPGE(0xa2, BRANCH), - IF_ICMPGT(0xa3, BRANCH), - IF_ICMPLE(0xa4, BRANCH), - IF_ACMPEQ(0xa5, BRANCH), - IF_ACMPNE(0xa6, BRANCH), - GOTO(0xa7, BRANCH), - JSR(0xa8, BRANCH), - RET(0xa9, LOCAL), - TABLESWITCH(0xaa, DYNAMIC), - LOOKUPSWITCH(0xab, DYNAMIC), - IRETURN(0xac), - LRETURN(0xad), - FRETURN(0xae), - DRETURN(0xaf), - ARETURN(0xb0), - RETURN(0xb1), - GETSTATIC(0xb2, CPREF_W), - PUTSTATIC(0xb3, CPREF_W), - GETFIELD(0xb4, CPREF_W), - PUTFIELD(0xb5, CPREF_W), - INVOKEVIRTUAL(0xb6, CPREF_W), - INVOKESPECIAL(0xb7, CPREF_W), - INVOKESTATIC(0xb8, CPREF_W), - INVOKEINTERFACE(0xb9, CPREF_W_UBYTE_ZERO), - INVOKEDYNAMIC(0xba, CPREF_W_UBYTE_ZERO), - NEW(0xbb, CPREF_W), - NEWARRAY(0xbc, ATYPE), - ANEWARRAY(0xbd, CPREF_W), - ARRAYLENGTH(0xbe), - ATHROW(0xbf), - CHECKCAST(0xc0, CPREF_W), - INSTANCEOF(0xc1, CPREF_W), - MONITORENTER(0xc2), - MONITOREXIT(0xc3), - // wide 0xc4 - MULTIANEWARRAY(0xc5, CPREF_W_UBYTE), - IFNULL(0xc6, BRANCH), - IFNONNULL(0xc7, BRANCH), - GOTO_W(0xc8, BRANCH_W), - JSR_W(0xc9, BRANCH_W), - // impdep 0xfe: PicoJava nonpriv - // impdep 0xff: Picojava priv - - // wide opcodes - ILOAD_W(0xc415, WIDE_LOCAL), - LLOAD_W(0xc416, WIDE_LOCAL), - FLOAD_W(0xc417, WIDE_LOCAL), - DLOAD_W(0xc418, WIDE_LOCAL), - ALOAD_W(0xc419, WIDE_LOCAL), - ISTORE_W(0xc436, WIDE_LOCAL), - LSTORE_W(0xc437, WIDE_LOCAL), - FSTORE_W(0xc438, WIDE_LOCAL), - DSTORE_W(0xc439, WIDE_LOCAL), - ASTORE_W(0xc43a, WIDE_LOCAL), - IINC_W(0xc484, WIDE_LOCAL_SHORT), - RET_W(0xc4a9, WIDE_LOCAL), - - // PicoJava nonpriv instructions - LOAD_UBYTE(PICOJAVA, 0xfe00), - LOAD_BYTE(PICOJAVA, 0xfe01), - LOAD_CHAR(PICOJAVA, 0xfe02), - LOAD_SHORT(PICOJAVA, 0xfe03), - LOAD_WORD(PICOJAVA, 0xfe04), - RET_FROM_SUB(PICOJAVA, 0xfe05), - LOAD_CHAR_OE(PICOJAVA, 0xfe0a), - LOAD_SHORT_OE(PICOJAVA, 0xfe0b), - LOAD_WORD_OE(PICOJAVA, 0xfe0c), - NCLOAD_UBYTE(PICOJAVA, 0xfe10), - NCLOAD_BYTE(PICOJAVA, 0xfe11), - NCLOAD_CHAR(PICOJAVA, 0xfe12), - NCLOAD_SHORT(PICOJAVA, 0xfe13), - NCLOAD_WORD(PICOJAVA, 0xfe14), - NCLOAD_CHAR_OE(PICOJAVA, 0xfe1a), - NCLOAD_SHORT_OE(PICOJAVA, 0xfe1b), - NCLOAD_WORD_OE(PICOJAVA, 0xfe1c), - CACHE_FLUSH(PICOJAVA, 0xfe1e), - STORE_BYTE(PICOJAVA, 0xfe20), - STORE_SHORT(PICOJAVA, 0xfe22), - STORE_WORD(PICOJAVA, 0xfe24), - STORE_SHORT_OE(PICOJAVA, 0xfe2a), - STORE_WORD_OE(PICOJAVA, 0xfe2c), - NCSTORE_BYTE(PICOJAVA, 0xfe30), - NCSTORE_SHORT(PICOJAVA, 0xfe32), - NCSTORE_WORD(PICOJAVA, 0xfe34), - NCSTORE_SHORT_OE(PICOJAVA, 0xfe3a), - NCSTORE_WORD_OE(PICOJAVA, 0xfe3c), - ZERO_LINE(PICOJAVA, 0xfe3e), - ENTER_SYNC_METHOD(PICOJAVA, 0xfe3f), - - // PicoJava priv instructions - PRIV_LOAD_UBYTE(PICOJAVA, 0xff00), - PRIV_LOAD_BYTE(PICOJAVA, 0xff01), - PRIV_LOAD_CHAR(PICOJAVA, 0xff02), - PRIV_LOAD_SHORT(PICOJAVA, 0xff03), - PRIV_LOAD_WORD(PICOJAVA, 0xff04), - PRIV_RET_FROM_TRAP(PICOJAVA, 0xff05), - PRIV_READ_DCACHE_TAG(PICOJAVA, 0xff06), - PRIV_READ_DCACHE_DATA(PICOJAVA, 0xff07), - PRIV_LOAD_CHAR_OE(PICOJAVA, 0xff0a), - PRIV_LOAD_SHORT_OE(PICOJAVA, 0xff0b), - PRIV_LOAD_WORD_OE(PICOJAVA, 0xff0c), - PRIV_READ_ICACHE_TAG(PICOJAVA, 0xff0e), - PRIV_READ_ICACHE_DATA(PICOJAVA, 0xff0f), - PRIV_NCLOAD_UBYTE(PICOJAVA, 0xff10), - PRIV_NCLOAD_BYTE(PICOJAVA, 0xff11), - PRIV_NCLOAD_CHAR(PICOJAVA, 0xff12), - PRIV_NCLOAD_SHORT(PICOJAVA, 0xff13), - PRIV_NCLOAD_WORD(PICOJAVA, 0xff14), - PRIV_POWERDOWN(PICOJAVA, 0xff16), - PRIV_READ_SCACHE_DATA(PICOJAVA, 0xff17), - PRIV_NCLOAD_CHAR_OE(PICOJAVA, 0xff1a), - PRIV_NCLOAD_SHORT_OE(PICOJAVA, 0xff1b), - PRIV_NCLOAD_WORD_OE(PICOJAVA, 0xff1c), - PRIV_CACHE_FLUSH(PICOJAVA, 0xff1e), - PRIV_CACHE_INDEX_FLUSH(PICOJAVA, 0xff1f), - PRIV_STORE_BYTE(PICOJAVA, 0xff20), - PRIV_STORE_SHORT(PICOJAVA, 0xff22), - PRIV_STORE_WORD(PICOJAVA, 0xff24), - PRIV_WRITE_DCACHE_TAG(PICOJAVA, 0xff26), - PRIV_WRITE_DCACHE_DATA(PICOJAVA, 0xff27), - PRIV_STORE_SHORT_OE(PICOJAVA, 0xff2a), - PRIV_STORE_WORD_OE(PICOJAVA, 0xff2c), - PRIV_WRITE_ICACHE_TAG(PICOJAVA, 0xff2e), - PRIV_WRITE_ICACHE_DATA(PICOJAVA, 0xff2f), - PRIV_NCSTORE_BYTE(PICOJAVA, 0xff30), - PRIV_NCSTORE_SHORT(PICOJAVA, 0xff32), - PRIV_NCSTORE_WORD(PICOJAVA, 0xff34), - PRIV_RESET(PICOJAVA, 0xff36), - PRIV_WRITE_SCACHE_DATA(PICOJAVA, 0xff37), - PRIV_NCSTORE_SHORT_OE(PICOJAVA, 0xff3a), - PRIV_NCSTORE_WORD_OE(PICOJAVA, 0xff3c), - PRIV_ZERO_LINE(PICOJAVA, 0xff3e), - PRIV_READ_REG_0(PICOJAVA, 0xff40), - PRIV_READ_REG_1(PICOJAVA, 0xff41), - PRIV_READ_REG_2(PICOJAVA, 0xff42), - PRIV_READ_REG_3(PICOJAVA, 0xff43), - PRIV_READ_REG_4(PICOJAVA, 0xff44), - PRIV_READ_REG_5(PICOJAVA, 0xff45), - PRIV_READ_REG_6(PICOJAVA, 0xff46), - PRIV_READ_REG_7(PICOJAVA, 0xff47), - PRIV_READ_REG_8(PICOJAVA, 0xff48), - PRIV_READ_REG_9(PICOJAVA, 0xff49), - PRIV_READ_REG_10(PICOJAVA, 0xff4a), - PRIV_READ_REG_11(PICOJAVA, 0xff4b), - PRIV_READ_REG_12(PICOJAVA, 0xff4c), - PRIV_READ_REG_13(PICOJAVA, 0xff4d), - PRIV_READ_REG_14(PICOJAVA, 0xff4e), - PRIV_READ_REG_15(PICOJAVA, 0xff4f), - PRIV_READ_REG_16(PICOJAVA, 0xff50), - PRIV_READ_REG_17(PICOJAVA, 0xff51), - PRIV_READ_REG_18(PICOJAVA, 0xff52), - PRIV_READ_REG_19(PICOJAVA, 0xff53), - PRIV_READ_REG_20(PICOJAVA, 0xff54), - PRIV_READ_REG_21(PICOJAVA, 0xff55), - PRIV_READ_REG_22(PICOJAVA, 0xff56), - PRIV_READ_REG_23(PICOJAVA, 0xff57), - PRIV_READ_REG_24(PICOJAVA, 0xff58), - PRIV_READ_REG_25(PICOJAVA, 0xff59), - PRIV_READ_REG_26(PICOJAVA, 0xff5a), - PRIV_READ_REG_27(PICOJAVA, 0xff5b), - PRIV_READ_REG_28(PICOJAVA, 0xff5c), - PRIV_READ_REG_29(PICOJAVA, 0xff5d), - PRIV_READ_REG_30(PICOJAVA, 0xff5e), - PRIV_READ_REG_31(PICOJAVA, 0xff5f), - PRIV_WRITE_REG_0(PICOJAVA, 0xff60), - PRIV_WRITE_REG_1(PICOJAVA, 0xff61), - PRIV_WRITE_REG_2(PICOJAVA, 0xff62), - PRIV_WRITE_REG_3(PICOJAVA, 0xff63), - PRIV_WRITE_REG_4(PICOJAVA, 0xff64), - PRIV_WRITE_REG_5(PICOJAVA, 0xff65), - PRIV_WRITE_REG_6(PICOJAVA, 0xff66), - PRIV_WRITE_REG_7(PICOJAVA, 0xff67), - PRIV_WRITE_REG_8(PICOJAVA, 0xff68), - PRIV_WRITE_REG_9(PICOJAVA, 0xff69), - PRIV_WRITE_REG_10(PICOJAVA, 0xff6a), - PRIV_WRITE_REG_11(PICOJAVA, 0xff6b), - PRIV_WRITE_REG_12(PICOJAVA, 0xff6c), - PRIV_WRITE_REG_13(PICOJAVA, 0xff6d), - PRIV_WRITE_REG_14(PICOJAVA, 0xff6e), - PRIV_WRITE_REG_15(PICOJAVA, 0xff6f), - PRIV_WRITE_REG_16(PICOJAVA, 0xff70), - PRIV_WRITE_REG_17(PICOJAVA, 0xff71), - PRIV_WRITE_REG_18(PICOJAVA, 0xff72), - PRIV_WRITE_REG_19(PICOJAVA, 0xff73), - PRIV_WRITE_REG_20(PICOJAVA, 0xff74), - PRIV_WRITE_REG_21(PICOJAVA, 0xff75), - PRIV_WRITE_REG_22(PICOJAVA, 0xff76), - PRIV_WRITE_REG_23(PICOJAVA, 0xff77), - PRIV_WRITE_REG_24(PICOJAVA, 0xff78), - PRIV_WRITE_REG_25(PICOJAVA, 0xff79), - PRIV_WRITE_REG_26(PICOJAVA, 0xff7a), - PRIV_WRITE_REG_27(PICOJAVA, 0xff7b), - PRIV_WRITE_REG_28(PICOJAVA, 0xff7c), - PRIV_WRITE_REG_29(PICOJAVA, 0xff7d), - PRIV_WRITE_REG_30(PICOJAVA, 0xff7e), - PRIV_WRITE_REG_31(PICOJAVA, 0xff7f); - - Opcode(int opcode) { - this(STANDARD, opcode, NO_OPERANDS); - } - - Opcode(int opcode, Instruction.Kind kind) { - this(STANDARD, opcode, kind); - } - - Opcode(Set set, int opcode) { - this(set, opcode, (set == STANDARD ? NO_OPERANDS : WIDE_NO_OPERANDS)); - } - - Opcode(Set set, int opcode, Instruction.Kind kind) { - this.set = set; - this.opcode = opcode; - this.kind = kind; - } - - public final Set set; - public final int opcode; - public final Instruction.Kind kind; - - /** Get the Opcode for a simple standard 1-byte opcode. */ - public static Opcode get(int opcode) { - return stdOpcodes[opcode]; - } - - /** Get the Opcode for 1- or 2-byte opcode. */ - public static Opcode get(int opcodePrefix, int opcode) { - Opcode[] block = getOpcodeBlock(opcodePrefix); - return (block == null ? null : block[opcode]); - } - - private static Opcode[] getOpcodeBlock(int opcodePrefix) { - switch (opcodePrefix) { - case 0: - return stdOpcodes; - case WIDE: - return wideOpcodes; - case NONPRIV: - return nonPrivOpcodes; - case PRIV: - return privOpcodes; - default: - return null; - } - - } - - private static final Opcode[] stdOpcodes = new Opcode[256]; - private static final Opcode[] wideOpcodes = new Opcode[256]; - private static final Opcode[] nonPrivOpcodes = new Opcode[256]; - private static final Opcode[] privOpcodes = new Opcode[256]; - static { - for (Opcode o: values()) - getOpcodeBlock(o.opcode >> 8)[o.opcode & 0xff] = o; - } - - /** The byte prefix for the wide instructions. */ - public static final int WIDE = 0xc4; - /** The byte prefix for the PicoJava nonpriv instructions. */ - public static final int NONPRIV = 0xfe; - /** The byte prefix for the PicoJava priv instructions. */ - public static final int PRIV = 0xff; - - public enum Set { - /** Standard opcodes. */ - STANDARD, - /** Legacy support for PicoJava opcodes. */ - PICOJAVA } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/PermittedSubclasses_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/PermittedSubclasses_attribute.java deleted file mode 100644 index fcd680fdda4..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/PermittedSubclasses_attribute.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 - * 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 com.sun.tools.classfile; - -import java.io.IOException; -import java.util.stream.IntStream; - -import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; - -public class PermittedSubclasses_attribute extends Attribute { - - public int[] subtypes; - - PermittedSubclasses_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - int number_of_classes = cr.readUnsignedShort(); - subtypes = new int[number_of_classes]; - for (int i = 0; i < number_of_classes; i++) - subtypes[i] = cr.readUnsignedShort(); - } - - public PermittedSubclasses_attribute(int name_index, int[] subtypes) { - super(name_index, 2); - this.subtypes = subtypes; - } - - public CONSTANT_Class_info[] getSubtypes(ConstantPool constant_pool) throws ConstantPoolException { - return IntStream.of(subtypes) - .mapToObj(i -> { - try { - return constant_pool.getClassInfo(i); - } catch (ConstantPoolException ex) { - throw new AssertionError(ex); - } - }).toArray(CONSTANT_Class_info[]::new); - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitPermittedSubclasses(this, data); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Record_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Record_attribute.java deleted file mode 100644 index 8d67e6c3016..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Record_attribute.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2018, 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. 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 com.sun.tools.classfile; - -import java.io.IOException; -import com.sun.tools.classfile.Attribute.Visitor; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Record_attribute extends Attribute { - Record_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - component_count = cr.readUnsignedShort(); - component_info_arr = new ComponentInfo[component_count]; - for (int i = 0; i < component_count; i++) { - component_info_arr[i] = new ComponentInfo(cr); - } - } - - public Record_attribute(int name_index, ComponentInfo[] component_info_arr) { - super(name_index, 2); - this.component_count = component_info_arr.length; - this.component_info_arr = component_info_arr; - } - - @Override - public R accept(Visitor visitor, D data) { - return visitor.visitRecord(this, data); - } - - public final int component_count; - public final ComponentInfo[] component_info_arr; - - public static class ComponentInfo { - ComponentInfo(ClassReader cr) throws IOException { - name_index = cr.readUnsignedShort(); - descriptor = new Descriptor(cr); - attributes = new Attributes(cr); - } - - public ComponentInfo(int name_index, Descriptor descriptor, Attributes attributes) { - this.name_index = name_index; - this.descriptor = descriptor; - this.attributes = attributes; - } - - public String getName(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(name_index); - } - - public final int name_index; - public final Descriptor descriptor; - public final Attributes attributes; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java deleted file mode 100644 index a15cb40a718..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import com.sun.tools.classfile.Instruction.TypeKind; -import static com.sun.tools.classfile.ConstantPool.*; - -/** - * A utility class to find where in a ClassFile references - * a {@link CONSTANT_Methodref_info method}, - * a {@link CONSTANT_InterfaceMethodref_info interface method}, - * or a {@link CONSTANT_Fieldref_info field}. - */ -public final class ReferenceFinder { - /** - * Filter for ReferenceFinder of what constant pool entries for reference lookup. - */ - public interface Filter { - /** - * Decides if the given CPRefInfo entry should be accepted or filtered. - * - * @param cpool ConstantPool of the ClassFile being parsed - * @param cpref constant pool entry representing a reference to - * a fields method, and interface method. - * @return {@code true} if accepted; otherwise {@code false} - */ - boolean accept(ConstantPool cpool, CPRefInfo cpref); - } - - /** - * Visitor of individual method of a ClassFile that references the - * accepted field, method, or interface method references. - */ - public interface Visitor { - /** - * Invoked for a method containing one or more accepted CPRefInfo entries - * - * @param cf ClassFile - * @param method Method that does the references the accepted references - * @param refs Accepted constant pool method/field reference - */ - void visit(ClassFile cf, Method method, List refConstantPool); - } - - private final Filter filter; - private final Visitor visitor; - - /** - * Constructor. - */ - public ReferenceFinder(Filter filter, Visitor visitor) { - this.filter = Objects.requireNonNull(filter); - this.visitor = Objects.requireNonNull(visitor); - } - - /** - * Parses a given ClassFile and invoke the visitor if there is any reference - * to the constant pool entries referencing field, method, or - * interface method that are accepted. This method will return - * {@code true} if there is one or more accepted constant pool entries - * to lookup; otherwise, it will return {@code false}. - * - * @param cf ClassFile - * @return {@code true} if the given class file is processed to lookup - * references - * @throws ConstantPoolException if an error of the constant pool - */ - public boolean parse(ClassFile cf) throws ConstantPoolException { - List cprefs = new ArrayList<>(); - int index = 1; - for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) { - if (cpInfo.accept(cpVisitor, cf.constant_pool)) { - cprefs.add(index); - } - index += cpInfo.size(); - } - - if (cprefs.isEmpty()) { - return false; - } - - for (Method m : cf.methods) { - Set ids = new HashSet<>(); - Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code); - if (c_attr != null) { - for (Instruction instr : c_attr.getInstructions()) { - int idx = instr.accept(codeVisitor, cprefs); - if (idx > 0) { - ids.add(idx); - } - } - } - if (ids.size() > 0) { - List refInfos = new ArrayList<>(ids.size()); - for (int id : ids) { - refInfos.add(CPRefInfo.class.cast(cf.constant_pool.get(id))); - } - visitor.visit(cf, m, refInfos); - } - } - return true; - } - - private ConstantPool.Visitor cpVisitor = - new ConstantPool.Visitor() - { - public Boolean visitClass(CONSTANT_Class_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitFieldref(CONSTANT_Fieldref_info info, ConstantPool cpool) { - return filter.accept(cpool, info); - } - - public Boolean visitDouble(CONSTANT_Double_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitFloat(CONSTANT_Float_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitInteger(CONSTANT_Integer_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ConstantPool cpool) { - return filter.accept(cpool, info); - } - - public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ConstantPool cpool) { - return false; - } - - @Override - public Boolean visitDynamicConstant(CONSTANT_Dynamic_info info, ConstantPool constantPool) { - return false; - } - - public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitMethodref(CONSTANT_Methodref_info info, ConstantPool cpool) { - return filter.accept(cpool, info); - } - - public Boolean visitMethodType(CONSTANT_MethodType_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitModule(CONSTANT_Module_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitNameAndType(CONSTANT_NameAndType_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitPackage(CONSTANT_Package_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitString(CONSTANT_String_info info, ConstantPool cpool) { - return false; - } - - public Boolean visitUtf8(CONSTANT_Utf8_info info, ConstantPool cpool) { - return false; - } - }; - - private Instruction.KindVisitor> codeVisitor = - new Instruction.KindVisitor>() - { - public Integer visitNoOperands(Instruction instr, List p) { - return 0; - } - - public Integer visitArrayType(Instruction instr, TypeKind kind, List p) { - return 0; - } - - public Integer visitBranch(Instruction instr, int offset, List p) { - return 0; - } - - public Integer visitConstantPoolRef(Instruction instr, int index, List p) { - return p.contains(index) ? index : 0; - } - - public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List p) { - return p.contains(index) ? index : 0; - } - - public Integer visitLocal(Instruction instr, int index, List p) { - return 0; - } - - public Integer visitLocalAndValue(Instruction instr, int index, int value, List p) { - return 0; - } - - public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List p) { - return 0; - } - - public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List p) { - return 0; - } - - public Integer visitValue(Instruction instr, int value, List p) { - return 0; - } - - public Integer visitUnknown(Instruction instr, List p) { - return 0; - } - }; -} - diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeAnnotations_attribute.java deleted file mode 100644 index 859cec405da..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeAnnotations_attribute.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.16 and 4.8.17. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public abstract class RuntimeAnnotations_attribute extends Attribute { - protected RuntimeAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(name_index, length); - int num_annotations = cr.readUnsignedShort(); - annotations = new Annotation[num_annotations]; - for (int i = 0; i < annotations.length; i++) - annotations[i] = new Annotation(cr); - } - - protected RuntimeAnnotations_attribute(int name_index, Annotation[] annotations) { - super(name_index, length(annotations)); - this.annotations = annotations; - } - - private static int length(Annotation[] annos) { - int n = 2; - for (Annotation anno: annos) - n += anno.length(); - return n; - } - - public final Annotation[] annotations; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleAnnotations_attribute.java deleted file mode 100644 index ed700823cd5..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.17. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeInvisibleAnnotations_attribute extends RuntimeAnnotations_attribute { - RuntimeInvisibleAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, AttributeException { - super(cr, name_index, length); - } - - public RuntimeInvisibleAnnotations_attribute(ConstantPool cp, Annotation[] annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeInvisibleAnnotations), annotations); - } - - public RuntimeInvisibleAnnotations_attribute(int name_index, Annotation[] annotations) { - super(name_index, annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeInvisibleAnnotations(this, p); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleParameterAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleParameterAnnotations_attribute.java deleted file mode 100644 index 57de543a903..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleParameterAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.18. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeInvisibleParameterAnnotations_attribute extends RuntimeParameterAnnotations_attribute { - RuntimeInvisibleParameterAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(cr, name_index, length); - } - - public RuntimeInvisibleParameterAnnotations_attribute(ConstantPool cp, Annotation[][] parameter_annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeInvisibleParameterAnnotations), parameter_annotations); - } - - public RuntimeInvisibleParameterAnnotations_attribute(int name_index, Annotation[][] parameter_annotations) { - super(name_index, parameter_annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeInvisibleParameterAnnotations(this, p); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java deleted file mode 100644 index 672bb55420f..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JSR 308 specification, Section 3. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeInvisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute { - RuntimeInvisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(cr, name_index, length); - } - - public RuntimeInvisibleTypeAnnotations_attribute(ConstantPool cp, TypeAnnotation[] annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeInvisibleTypeAnnotations), annotations); - } - - public RuntimeInvisibleTypeAnnotations_attribute(int name_index, TypeAnnotation[] annotations) { - super(name_index, annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeInvisibleTypeAnnotations(this, p); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeParameterAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeParameterAnnotations_attribute.java deleted file mode 100644 index 904010f649f..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeParameterAnnotations_attribute.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.18 and 4.8.19. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public abstract class RuntimeParameterAnnotations_attribute extends Attribute { - RuntimeParameterAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(name_index, length); - int num_parameters = cr.readUnsignedByte(); - parameter_annotations = new Annotation[num_parameters][]; - for (int p = 0; p < parameter_annotations.length; p++) { - int num_annotations = cr.readUnsignedShort(); - Annotation[] annotations = new Annotation[num_annotations]; - for (int i = 0; i < num_annotations; i++) - annotations[i] = new Annotation(cr); - parameter_annotations[p] = annotations; - } - } - - protected RuntimeParameterAnnotations_attribute(int name_index, Annotation[][] parameter_annotations) { - super(name_index, length(parameter_annotations)); - this.parameter_annotations = parameter_annotations; - } - - private static int length(Annotation[][] anno_arrays) { - int n = 1; - for (Annotation[] anno_array: anno_arrays) { - n += 2; - for (Annotation anno: anno_array) - n += anno.length(); - } - return n; - } - - public final Annotation[][] parameter_annotations; -} - diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java deleted file mode 100644 index 162e0765c7e..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JSR 308 specification, Section 3. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public abstract class RuntimeTypeAnnotations_attribute extends Attribute { - protected RuntimeTypeAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(name_index, length); - int num_annotations = cr.readUnsignedShort(); - annotations = new TypeAnnotation[num_annotations]; - for (int i = 0; i < annotations.length; i++) - annotations[i] = new TypeAnnotation(cr); - } - - protected RuntimeTypeAnnotations_attribute(int name_index, TypeAnnotation[] annotations) { - super(name_index, length(annotations)); - this.annotations = annotations; - } - - private static int length(TypeAnnotation[] annos) { - int n = 2; - for (TypeAnnotation anno: annos) - n += anno.length(); - return n; - } - - public final TypeAnnotation[] annotations; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleAnnotations_attribute.java deleted file mode 100644 index c7a443905c6..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.16. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeVisibleAnnotations_attribute extends RuntimeAnnotations_attribute { - RuntimeVisibleAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(cr, name_index, length); - } - - public RuntimeVisibleAnnotations_attribute(ConstantPool cp, Annotation[] annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeVisibleAnnotations), annotations); - } - - public RuntimeVisibleAnnotations_attribute(int name_index, Annotation[] annotations) { - super(name_index, annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeVisibleAnnotations(this, p); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleParameterAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleParameterAnnotations_attribute.java deleted file mode 100644 index 24214e7e2a2..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleParameterAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.18. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeVisibleParameterAnnotations_attribute extends RuntimeParameterAnnotations_attribute { - RuntimeVisibleParameterAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(cr, name_index, length); - } - - public RuntimeVisibleParameterAnnotations_attribute(ConstantPool cp, Annotation[][] parameter_annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeVisibleParameterAnnotations), parameter_annotations); - } - - public RuntimeVisibleParameterAnnotations_attribute(int name_index, Annotation[][] parameter_annotations) { - super(name_index, parameter_annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeVisibleParameterAnnotations(this, p); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java deleted file mode 100644 index 851c1f7d907..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JSR 308 specification, Section 3. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeVisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute { - RuntimeVisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(cr, name_index, length); - } - - public RuntimeVisibleTypeAnnotations_attribute(ConstantPool cp, TypeAnnotation[] annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeVisibleTypeAnnotations), annotations); - } - - public RuntimeVisibleTypeAnnotations_attribute(int name_index, TypeAnnotation[] annotations) { - super(name_index, annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeVisibleTypeAnnotations(this, p); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature.java deleted file mode 100644 index 384c7080d71..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.util.ArrayList; -import java.util.List; -import com.sun.tools.classfile.Type.*; - -/** - * See JVMS 4.4.4. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Signature extends Descriptor { - - public Signature(int index) { - super(index); - } - - public Type getType(ConstantPool constant_pool) throws ConstantPoolException { - if (type == null) - type = parse(getValue(constant_pool)); - return type; - } - - @Override - public int getParameterCount(ConstantPool constant_pool) throws ConstantPoolException { - MethodType m = (MethodType) getType(constant_pool); - return m.paramTypes.size(); - } - - @Override - public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException { - MethodType m = (MethodType) getType(constant_pool); - StringBuilder sb = new StringBuilder(); - sb.append("("); - String sep = ""; - for (Type paramType: m.paramTypes) { - sb.append(sep); - sb.append(paramType); - sep = ", "; - } - sb.append(")"); - return sb.toString(); - } - - @Override - public String getReturnType(ConstantPool constant_pool) throws ConstantPoolException { - MethodType m = (MethodType) getType(constant_pool); - return m.returnType.toString(); - } - - @Override - public String getFieldType(ConstantPool constant_pool) throws ConstantPoolException { - return getType(constant_pool).toString(); - } - - private Type parse(String sig) { - this.sig = sig; - sigp = 0; - - List typeParamTypes = null; - if (sig.charAt(sigp) == '<') - typeParamTypes = parseTypeParamTypes(); - - if (sig.charAt(sigp) == '(') { - List paramTypes = parseTypeSignatures(')'); - Type returnType = parseTypeSignature(); - List throwsTypes = null; - while (sigp < sig.length() && sig.charAt(sigp) == '^') { - sigp++; - if (throwsTypes == null) - throwsTypes = new ArrayList<>(); - throwsTypes.add(parseTypeSignature()); - } - return new MethodType(typeParamTypes, paramTypes, returnType, throwsTypes); - } else { - Type t = parseTypeSignature(); - if (typeParamTypes == null && sigp == sig.length()) - return t; - Type superclass = t; - List superinterfaces = null; - while (sigp < sig.length()) { - if (superinterfaces == null) - superinterfaces = new ArrayList<>(); - superinterfaces.add(parseTypeSignature()); - } - return new ClassSigType(typeParamTypes, superclass, superinterfaces); - - } - } - - private Type parseTypeSignature() { - switch (sig.charAt(sigp)) { - case 'B': - sigp++; - return new SimpleType("byte"); - - case 'C': - sigp++; - return new SimpleType("char"); - - case 'D': - sigp++; - return new SimpleType("double"); - - case 'F': - sigp++; - return new SimpleType("float"); - - case 'I': - sigp++; - return new SimpleType("int"); - - case 'J': - sigp++; - return new SimpleType("long"); - - case 'L': - return parseClassTypeSignature(); - - case 'S': - sigp++; - return new SimpleType("short"); - - case 'T': - return parseTypeVariableSignature(); - - case 'V': - sigp++; - return new SimpleType("void"); - - case 'Z': - sigp++; - return new SimpleType("boolean"); - - case '[': - sigp++; - return new ArrayType(parseTypeSignature()); - - case '*': - sigp++; - return new WildcardType(); - - case '+': - sigp++; - return new WildcardType(WildcardType.Kind.EXTENDS, parseTypeSignature()); - - case '-': - sigp++; - return new WildcardType(WildcardType.Kind.SUPER, parseTypeSignature()); - - default: - throw new IllegalStateException(debugInfo()); - } - } - - private List parseTypeSignatures(char term) { - sigp++; - List types = new ArrayList<>(); - while (sig.charAt(sigp) != term) - types.add(parseTypeSignature()); - sigp++; - return types; - } - - private Type parseClassTypeSignature() { - assert sig.charAt(sigp) == 'L'; - sigp++; - return parseClassTypeSignatureRest(); - } - - private Type parseClassTypeSignatureRest() { - StringBuilder sb = new StringBuilder(); - List argTypes = null; - ClassType t = null; - char sigch ; - - do { - switch (sigch = sig.charAt(sigp)) { - case '<': - argTypes = parseTypeSignatures('>'); - break; - - case '.': - case ';': - sigp++; - t = new ClassType(t, sb.toString(), argTypes); - sb.setLength(0); - argTypes = null; - break; - - default: - sigp++; - sb.append(sigch); - break; - } - } while (sigch != ';'); - - return t; - } - - private List parseTypeParamTypes() { - assert sig.charAt(sigp) == '<'; - sigp++; - List types = new ArrayList<>(); - while (sig.charAt(sigp) != '>') - types.add(parseTypeParamType()); - sigp++; - return types; - } - - private TypeParamType parseTypeParamType() { - int sep = sig.indexOf(":", sigp); - String name = sig.substring(sigp, sep); - Type classBound = null; - List interfaceBounds = null; - sigp = sep + 1; - if (sig.charAt(sigp) != ':') - classBound = parseTypeSignature(); - while (sig.charAt(sigp) == ':') { - sigp++; - if (interfaceBounds == null) - interfaceBounds = new ArrayList<>(); - interfaceBounds.add(parseTypeSignature()); - } - return new TypeParamType(name, classBound, interfaceBounds); - } - - private Type parseTypeVariableSignature() { - sigp++; - int sep = sig.indexOf(';', sigp); - Type t = new SimpleType(sig.substring(sigp, sep)); - sigp = sep + 1; - return t; - } - - private String debugInfo() { - return sig.substring(0, sigp) + "!" + sig.charAt(sigp) + "!" + sig.substring(sigp+1); - } - - private String sig; - private int sigp; - - private Type type; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature_attribute.java deleted file mode 100644 index acb9475c798..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Signature_attribute.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.9. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Signature_attribute extends Attribute { - Signature_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - signature_index = cr.readUnsignedShort(); - } - - public Signature_attribute(ConstantPool constant_pool, int signature_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.Signature), signature_index); - } - - public Signature_attribute(int name_index, int signature_index) { - super(name_index, 2); - this.signature_index = signature_index; - } - - public String getSignature(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(signature_index); - } - - public Signature getParsedSignature() { - return new Signature(signature_index); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitSignature(this, data); - } - - public final int signature_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceDebugExtension_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceDebugExtension_attribute.java deleted file mode 100644 index 22e87723d2f..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceDebugExtension_attribute.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 com.sun.tools.classfile; - -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; - -import static java.nio.charset.StandardCharsets.UTF_8; - -/** - * See JVMS, section 4.8.15. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SourceDebugExtension_attribute extends Attribute { - - SourceDebugExtension_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - debug_extension = new byte[attribute_length]; - cr.readFully(debug_extension); - } - - public SourceDebugExtension_attribute(ConstantPool constant_pool, byte[] debug_extension) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.SourceDebugExtension), debug_extension); - } - - public SourceDebugExtension_attribute(int name_index, byte[] debug_extension) { - super(name_index, debug_extension.length); - this.debug_extension = debug_extension; - } - - public String getValue() { - return new String(debug_extension, UTF_8); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitSourceDebugExtension(this, data); - } - - public final byte[] debug_extension; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceFile_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceFile_attribute.java deleted file mode 100644 index c3b7509d165..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceFile_attribute.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.10. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SourceFile_attribute extends Attribute { - SourceFile_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - sourcefile_index = cr.readUnsignedShort(); - } - - public SourceFile_attribute(ConstantPool constant_pool, int sourcefile_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.SourceFile), sourcefile_index); - } - - public SourceFile_attribute(int name_index, int sourcefile_index) { - super(name_index, 2); - this.sourcefile_index = sourcefile_index; - } - - public String getSourceFile(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(sourcefile_index); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitSourceFile(this, p); - } - - public final int sourcefile_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceID_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceID_attribute.java deleted file mode 100644 index d8c1e523c9d..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceID_attribute.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SourceID_attribute extends Attribute { - - SourceID_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - sourceID_index = cr.readUnsignedShort(); - } - - public SourceID_attribute(ConstantPool constant_pool, int sourceID_index) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.SourceID), sourceID_index); - } - - public SourceID_attribute(int name_index, int sourceID_index) { - super(name_index, 2); - this.sourceID_index = sourceID_index; - } - - String getSourceID(ConstantPool constant_pool) throws ConstantPoolException { - return constant_pool.getUTF8Value(sourceID_index); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitSourceID(this, data); - } - - public final int sourceID_index; -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java deleted file mode 100644 index a0f94f1bbd5..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.4. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class StackMapTable_attribute extends Attribute { - static class InvalidStackMap extends AttributeException { - private static final long serialVersionUID = -5659038410855089780L; - InvalidStackMap(String msg) { - super(msg); - } - } - - StackMapTable_attribute(ClassReader cr, int name_index, int length) - throws IOException, InvalidStackMap { - super(name_index, length); - number_of_entries = cr.readUnsignedShort(); - entries = new stack_map_frame[number_of_entries]; - for (int i = 0; i < number_of_entries; i++) - entries[i] = stack_map_frame.read(cr); - } - - public StackMapTable_attribute(ConstantPool constant_pool, stack_map_frame[] entries) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.StackMapTable), entries); - } - - public StackMapTable_attribute(int name_index, stack_map_frame[] entries) { - super(name_index, length(entries)); - this.number_of_entries = entries.length; - this.entries = entries; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitStackMapTable(this, data); - } - - static int length(stack_map_frame[] entries) { - int n = 2; - for (stack_map_frame entry: entries) - n += entry.length(); - return n; - } - - public final int number_of_entries; - public final stack_map_frame entries[]; - - public abstract static class stack_map_frame { - static stack_map_frame read(ClassReader cr) - throws IOException, InvalidStackMap { - int frame_type = cr.readUnsignedByte(); - if (frame_type <= 63) - return new same_frame(frame_type); - else if (frame_type <= 127) - return new same_locals_1_stack_item_frame(frame_type, cr); - else if (frame_type <= 246) - throw new Error("unknown frame_type " + frame_type); - else if (frame_type == 247) - return new same_locals_1_stack_item_frame_extended(frame_type, cr); - else if (frame_type <= 250) - return new chop_frame(frame_type, cr); - else if (frame_type == 251) - return new same_frame_extended(frame_type, cr); - else if (frame_type <= 254) - return new append_frame(frame_type, cr); - else - return new full_frame(frame_type, cr); - } - - protected stack_map_frame(int frame_type) { - this.frame_type = frame_type; - } - - public int length() { - return 1; - } - - public abstract int getOffsetDelta(); - - public abstract R accept(Visitor visitor, D data); - - public final int frame_type; - - public static interface Visitor { - R visit_same_frame(same_frame frame, P p); - R visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, P p); - R visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, P p); - R visit_chop_frame(chop_frame frame, P p); - R visit_same_frame_extended(same_frame_extended frame, P p); - R visit_append_frame(append_frame frame, P p); - R visit_full_frame(full_frame frame, P p); - } - } - - public static class same_frame extends stack_map_frame { - same_frame(int frame_type) { - super(frame_type); - } - - public R accept(Visitor visitor, D data) { - return visitor.visit_same_frame(this, data); - } - - public int getOffsetDelta() { - return frame_type; - } - } - - public static class same_locals_1_stack_item_frame extends stack_map_frame { - same_locals_1_stack_item_frame(int frame_type, ClassReader cr) - throws IOException, InvalidStackMap { - super(frame_type); - stack = new verification_type_info[1]; - stack[0] = verification_type_info.read(cr); - } - - @Override - public int length() { - return super.length() + stack[0].length(); - } - - public R accept(Visitor visitor, D data) { - return visitor.visit_same_locals_1_stack_item_frame(this, data); - } - - public int getOffsetDelta() { - return frame_type - 64; - } - - public final verification_type_info[] stack; - } - - public static class same_locals_1_stack_item_frame_extended extends stack_map_frame { - same_locals_1_stack_item_frame_extended(int frame_type, ClassReader cr) - throws IOException, InvalidStackMap { - super(frame_type); - offset_delta = cr.readUnsignedShort(); - stack = new verification_type_info[1]; - stack[0] = verification_type_info.read(cr); - } - - @Override - public int length() { - return super.length() + 2 + stack[0].length(); - } - - public R accept(Visitor visitor, D data) { - return visitor.visit_same_locals_1_stack_item_frame_extended(this, data); - } - - public int getOffsetDelta() { - return offset_delta; - } - - public final int offset_delta; - public final verification_type_info[] stack; - } - - public static class chop_frame extends stack_map_frame { - chop_frame(int frame_type, ClassReader cr) throws IOException { - super(frame_type); - offset_delta = cr.readUnsignedShort(); - } - - @Override - public int length() { - return super.length() + 2; - } - - public R accept(Visitor visitor, D data) { - return visitor.visit_chop_frame(this, data); - } - - public int getOffsetDelta() { - return offset_delta; - } - - public final int offset_delta; - } - - public static class same_frame_extended extends stack_map_frame { - same_frame_extended(int frame_type, ClassReader cr) throws IOException { - super(frame_type); - offset_delta = cr.readUnsignedShort(); - } - - @Override - public int length() { - return super.length() + 2; - } - - public R accept(Visitor visitor, D data) { - return visitor.visit_same_frame_extended(this, data); - } - - public int getOffsetDelta() { - return offset_delta; - } - - public final int offset_delta; - } - - public static class append_frame extends stack_map_frame { - append_frame(int frame_type, ClassReader cr) - throws IOException, InvalidStackMap { - super(frame_type); - offset_delta = cr.readUnsignedShort(); - locals = new verification_type_info[frame_type - 251]; - for (int i = 0; i < locals.length; i++) - locals[i] = verification_type_info.read(cr); - } - - @Override - public int length() { - int n = super.length() + 2; - for (verification_type_info local: locals) - n += local.length(); - return n; - } - - public R accept(Visitor visitor, D data) { - return visitor.visit_append_frame(this, data); - } - - public int getOffsetDelta() { - return offset_delta; - } - - public final int offset_delta; - public final verification_type_info[] locals; - } - - public static class full_frame extends stack_map_frame { - full_frame(int frame_type, ClassReader cr) - throws IOException, InvalidStackMap { - super(frame_type); - offset_delta = cr.readUnsignedShort(); - number_of_locals = cr.readUnsignedShort(); - locals = new verification_type_info[number_of_locals]; - for (int i = 0; i < locals.length; i++) - locals[i] = verification_type_info.read(cr); - number_of_stack_items = cr.readUnsignedShort(); - stack = new verification_type_info[number_of_stack_items]; - for (int i = 0; i < stack.length; i++) - stack[i] = verification_type_info.read(cr); - } - - @Override - public int length() { - int n = super.length() + 2; - for (verification_type_info local: locals) - n += local.length(); - n += 2; - for (verification_type_info item: stack) - n += item.length(); - return n; - } - - public R accept(Visitor visitor, D data) { - return visitor.visit_full_frame(this, data); - } - - public int getOffsetDelta() { - return offset_delta; - } - - public final int offset_delta; - public final int number_of_locals; - public final verification_type_info[] locals; - public final int number_of_stack_items; - public final verification_type_info[] stack; - } - - public static class verification_type_info { - public static final int ITEM_Top = 0; - public static final int ITEM_Integer = 1; - public static final int ITEM_Float = 2; - public static final int ITEM_Long = 4; - public static final int ITEM_Double = 3; - public static final int ITEM_Null = 5; - public static final int ITEM_UninitializedThis = 6; - public static final int ITEM_Object = 7; - public static final int ITEM_Uninitialized = 8; - - static verification_type_info read(ClassReader cr) - throws IOException, InvalidStackMap { - int tag = cr.readUnsignedByte(); - switch (tag) { - case ITEM_Top: - case ITEM_Integer: - case ITEM_Float: - case ITEM_Long: - case ITEM_Double: - case ITEM_Null: - case ITEM_UninitializedThis: - return new verification_type_info(tag); - - case ITEM_Object: - return new Object_variable_info(cr); - - case ITEM_Uninitialized: - return new Uninitialized_variable_info(cr); - - default: - throw new InvalidStackMap("unrecognized verification_type_info tag"); - } - } - - protected verification_type_info(int tag) { - this.tag = tag; - } - - public int length() { - return 1; - } - - public final int tag; - } - - public static class Object_variable_info extends verification_type_info { - Object_variable_info(ClassReader cr) throws IOException { - super(ITEM_Object); - cpool_index = cr.readUnsignedShort(); - } - - @Override - public int length() { - return super.length() + 2; - } - - public final int cpool_index; - } - - public static class Uninitialized_variable_info extends verification_type_info { - Uninitialized_variable_info(ClassReader cr) throws IOException { - super(ITEM_Uninitialized); - offset = cr.readUnsignedShort(); - } - - @Override - public int length() { - return super.length() + 2; - } - - public final int offset; - - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMap_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMap_attribute.java deleted file mode 100644 index e57a24bfa98..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/StackMap_attribute.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class StackMap_attribute extends Attribute { - StackMap_attribute(ClassReader cr, int name_index, int length) - throws IOException, StackMapTable_attribute.InvalidStackMap { - super(name_index, length); - number_of_entries = cr.readUnsignedShort(); - entries = new stack_map_frame[number_of_entries]; - for (int i = 0; i < number_of_entries; i++) - entries[i] = new stack_map_frame(cr); - } - - public StackMap_attribute(ConstantPool constant_pool, stack_map_frame[] entries) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.StackMap), entries); - } - - public StackMap_attribute(int name_index, stack_map_frame[] entries) { - super(name_index, StackMapTable_attribute.length(entries)); - this.number_of_entries = entries.length; - this.entries = entries; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitStackMap(this, data); - } - - public final int number_of_entries; - public final stack_map_frame entries[]; - - public static class stack_map_frame extends StackMapTable_attribute.full_frame { - stack_map_frame(ClassReader cr) - throws IOException, StackMapTable_attribute.InvalidStackMap { - super(255, cr); - } - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Synthetic_attribute.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Synthetic_attribute.java deleted file mode 100644 index 0b7f933d787..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Synthetic_attribute.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JVMS, section 4.8.8. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Synthetic_attribute extends Attribute { - Synthetic_attribute(ClassReader cr, int name_index, int length) throws IOException { - super(name_index, length); - } - - public Synthetic_attribute(ConstantPool constant_pool) - throws ConstantPoolException { - this(constant_pool.getUTF8Index(Attribute.Synthetic)); - } - - public Synthetic_attribute(int name_index) { - super(name_index, 0); - } - - public R accept(Visitor visitor, D data) { - return visitor.visitSynthetic(this, data); - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Type.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Type.java deleted file mode 100644 index 478d1607324..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Type.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. - * 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 com.sun.tools.classfile; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/* - * Family of classes used to represent the parsed form of a {@link Descriptor} - * or {@link Signature}. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public abstract class Type { - protected Type() { } - - public boolean isObject() { - return false; - } - - public abstract R accept(Visitor visitor, D data); - - protected static void append(StringBuilder sb, String prefix, List types, String suffix) { - sb.append(prefix); - String sep = ""; - for (Type t: types) { - sb.append(sep); - sb.append(t); - sep = ", "; - } - sb.append(suffix); - } - - protected static void appendIfNotEmpty(StringBuilder sb, String prefix, List types, String suffix) { - if (types != null && types.size() > 0) - append(sb, prefix, types, suffix); - } - - public interface Visitor { - R visitSimpleType(SimpleType type, P p); - R visitArrayType(ArrayType type, P p); - R visitMethodType(MethodType type, P p); - R visitClassSigType(ClassSigType type, P p); - R visitClassType(ClassType type, P p); - R visitTypeParamType(TypeParamType type, P p); - R visitWildcardType(WildcardType type, P p); - } - - /** - * Represents a type signature with a simple name. The name may be that of a - * primitive type, such "{@code int}, {@code float}, etc - * or that of a type argument, such as {@code T}, {@code K}, {@code V}, etc. - * - * See: - * JVMS 4.3.2 - * BaseType: - * {@code B}, {@code C}, {@code D}, {@code F}, {@code I}, - * {@code J}, {@code S}, {@code Z}; - * VoidDescriptor: - * {@code V}; - * JVMS 4.3.4 - * TypeVariableSignature: - * {@code T} Identifier {@code ;} - */ - public static class SimpleType extends Type { - public SimpleType(String name) { - this.name = name; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitSimpleType(this, data); - } - - public boolean isPrimitiveType() { - return primitiveTypes.contains(name); - } - // where - private static final Set primitiveTypes = new HashSet<>(Arrays.asList( - "boolean", "byte", "char", "double", "float", "int", "long", "short", "void")); - - @Override - public String toString() { - return name; - } - - public final String name; - } - - /** - * Represents an array type signature. - * - * See: - * JVMS 4.3.4 - * ArrayTypeSignature: - * {@code [} TypeSignature {@code ]} - */ - public static class ArrayType extends Type { - public ArrayType(Type elemType) { - this.elemType = elemType; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitArrayType(this, data); - } - - @Override - public String toString() { - return elemType + "[]"; - } - - public final Type elemType; - } - - /** - * Represents a method type signature. - * - * See; - * JVMS 4.3.4 - * MethodTypeSignature: - * FormalTypeParameters_opt {@code (} TypeSignature* {@code)} ReturnType - * ThrowsSignature* - */ - public static class MethodType extends Type { - public MethodType(List paramTypes, Type resultType) { - this(null, paramTypes, resultType, null); - } - - public MethodType(List typeParamTypes, - List paramTypes, - Type returnType, - List throwsTypes) { - this.typeParamTypes = typeParamTypes; - this.paramTypes = paramTypes; - this.returnType = returnType; - this.throwsTypes = throwsTypes; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitMethodType(this, data); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - appendIfNotEmpty(sb, "<", typeParamTypes, "> "); - sb.append(returnType); - append(sb, " (", paramTypes, ")"); - appendIfNotEmpty(sb, " throws ", throwsTypes, ""); - return sb.toString(); - } - - public final List typeParamTypes; - public final List paramTypes; - public final Type returnType; - public final List throwsTypes; - } - - /** - * Represents a class signature. These describe the signature of - * a class that has type arguments. - * - * See: - * JVMS 4.3.4 - * ClassSignature: - * FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature* - */ - public static class ClassSigType extends Type { - public ClassSigType(List typeParamTypes, Type superclassType, - List superinterfaceTypes) { - this.typeParamTypes = typeParamTypes; - this.superclassType = superclassType; - this.superinterfaceTypes = superinterfaceTypes; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitClassSigType(this, data); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - appendIfNotEmpty(sb, "<", typeParamTypes, ">"); - if (superclassType != null) { - sb.append(" extends "); - sb.append(superclassType); - } - appendIfNotEmpty(sb, " implements ", superinterfaceTypes, ""); - return sb.toString(); - } - - public final List typeParamTypes; - public final Type superclassType; - public final List superinterfaceTypes; - } - - /** - * Represents a class type signature. This is used to represent a - * reference to a class, such as in a field, parameter, return type, etc. - * - * See: - * JVMS 4.3.4 - * ClassTypeSignature: - * {@code L} PackageSpecifier_opt SimpleClassTypeSignature - * ClassTypeSignatureSuffix* {@code ;} - * PackageSpecifier: - * Identifier {@code /} PackageSpecifier* - * SimpleClassTypeSignature: - * Identifier TypeArguments_opt } - * ClassTypeSignatureSuffix: - * {@code .} SimpleClassTypeSignature - */ - public static class ClassType extends Type { - public ClassType(ClassType outerType, String name, List typeArgs) { - this.outerType = outerType; - this.name = name; - this.typeArgs = typeArgs; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitClassType(this, data); - } - - public String getBinaryName() { - if (outerType == null) - return name; - else - return (outerType.getBinaryName() + "$" + name); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - if (outerType != null) { - sb.append(outerType); - sb.append("."); - } - sb.append(name); - appendIfNotEmpty(sb, "<", typeArgs, ">"); - return sb.toString(); - } - - @Override - public boolean isObject() { - return (outerType == null) - && name.equals("java/lang/Object") - && (typeArgs == null || typeArgs.isEmpty()); - } - - public final ClassType outerType; - public final String name; - public final List typeArgs; - } - - /** - * Represents a FormalTypeParameter. These are used to declare the type - * parameters for generic classes and methods. - * - * See: - * JVMS 4.3.4 - * FormalTypeParameters: - * {@code <} FormalTypeParameter+ {@code >} - * FormalTypeParameter: - * Identifier ClassBound InterfaceBound* - * ClassBound: - * {@code :} FieldTypeSignature_opt - * InterfaceBound: - * {@code :} FieldTypeSignature - */ - public static class TypeParamType extends Type { - public TypeParamType(String name, Type classBound, List interfaceBounds) { - this.name = name; - this.classBound = classBound; - this.interfaceBounds = interfaceBounds; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitTypeParamType(this, data); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(name); - String sep = " extends "; - if (classBound != null) { - sb.append(sep); - sb.append(classBound); - sep = " & "; - } - if (interfaceBounds != null) { - for (Type bound: interfaceBounds) { - sb.append(sep); - sb.append(bound); - sep = " & "; - } - } - return sb.toString(); - } - - public final String name; - public final Type classBound; - public final List interfaceBounds; - } - - /** - * Represents a wildcard type argument. A type argument that is not a - * wildcard type argument will be represented by a ClassType, ArrayType, etc. - * - * See: - * JVMS 4.3.4 - * TypeArgument: - * WildcardIndicator_opt FieldTypeSignature - * {@code *} - * WildcardIndicator: - * {@code +} - * {@code -} - */ - public static class WildcardType extends Type { - public enum Kind { UNBOUNDED, EXTENDS, SUPER } - - public WildcardType() { - this(Kind.UNBOUNDED, null); - } - public WildcardType(Kind kind, Type boundType) { - this.kind = kind; - this.boundType = boundType; - } - - public R accept(Visitor visitor, D data) { - return visitor.visitWildcardType(this, data); - } - - @Override - public String toString() { - switch (kind) { - case UNBOUNDED: - return "?"; - case EXTENDS: - return "? extends " + boundType; - case SUPER: - return "? super " + boundType; - default: - throw new AssertionError(); - } - } - - public final Kind kind; - public final Type boundType; - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java deleted file mode 100644 index 65876d02b8d..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java +++ /dev/null @@ -1,654 +0,0 @@ -/* - * Copyright (c) 2009, 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 - * 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 com.sun.tools.classfile; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.sun.tools.classfile.TypeAnnotation.Position.TypePathEntry; - -/** - * See JSR 308 specification, Section 3. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class TypeAnnotation { - TypeAnnotation(ClassReader cr) throws IOException, Annotation.InvalidAnnotation { - constant_pool = cr.getConstantPool(); - position = read_position(cr); - annotation = new Annotation(cr); - } - - public TypeAnnotation(ConstantPool constant_pool, - Annotation annotation, Position position) { - this.constant_pool = constant_pool; - this.position = position; - this.annotation = annotation; - } - - public int length() { - int n = annotation.length(); - n += position_length(position); - return n; - } - - @Override - public String toString() { - try { - return "@" + constant_pool.getUTF8Value(annotation.type_index).substring(1) + - " pos: " + position.toString(); - } catch (Exception e) { - e.printStackTrace(); - return e.toString(); - } - } - - public final ConstantPool constant_pool; - public final Position position; - public final Annotation annotation; - - private static Position read_position(ClassReader cr) throws IOException, Annotation.InvalidAnnotation { - // Copied from ClassReader - int tag = cr.readUnsignedByte(); // TargetType tag is a byte - if (!TargetType.isValidTargetTypeValue(tag)) - throw new Annotation.InvalidAnnotation("TypeAnnotation: Invalid type annotation target type value: " + String.format("0x%02X", tag)); - - TargetType type = TargetType.fromTargetTypeValue(tag); - - Position position = new Position(); - position.type = type; - - switch (type) { - // instanceof - case INSTANCEOF: - // new expression - case NEW: - // constructor/method reference receiver - case CONSTRUCTOR_REFERENCE: - case METHOD_REFERENCE: - position.offset = cr.readUnsignedShort(); - break; - // local variable - case LOCAL_VARIABLE: - // resource variable - case RESOURCE_VARIABLE: - int table_length = cr.readUnsignedShort(); - position.lvarOffset = new int[table_length]; - position.lvarLength = new int[table_length]; - position.lvarIndex = new int[table_length]; - for (int i = 0; i < table_length; ++i) { - position.lvarOffset[i] = cr.readUnsignedShort(); - position.lvarLength[i] = cr.readUnsignedShort(); - position.lvarIndex[i] = cr.readUnsignedShort(); - } - break; - // exception parameter - case EXCEPTION_PARAMETER: - position.exception_index = cr.readUnsignedShort(); - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameter - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - position.parameter_index = cr.readUnsignedByte(); - break; - // type parameter bound - case CLASS_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND: - position.parameter_index = cr.readUnsignedByte(); - position.bound_index = cr.readUnsignedByte(); - break; - // class extends or implements clause - case CLASS_EXTENDS: - position.type_index = cr.readUnsignedShort(); - break; - // throws - case THROWS: - position.type_index = cr.readUnsignedShort(); - break; - // method parameter - case METHOD_FORMAL_PARAMETER: - position.parameter_index = cr.readUnsignedByte(); - break; - // type cast - case CAST: - // method/constructor/reference type argument - case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: - case METHOD_INVOCATION_TYPE_ARGUMENT: - case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: - case METHOD_REFERENCE_TYPE_ARGUMENT: - position.offset = cr.readUnsignedShort(); - position.type_index = cr.readUnsignedByte(); - break; - // We don't need to worry about these - case METHOD_RETURN: - case FIELD: - break; - case UNKNOWN: - throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!"); - default: - throw new AssertionError("TypeAnnotation: Unknown target type: " + type); - } - - { // Write type path - int len = cr.readUnsignedByte(); - List loc = new ArrayList<>(len); - for (int i = 0; i < len * TypePathEntry.bytesPerEntry; ++i) - loc.add(cr.readUnsignedByte()); - position.location = Position.getTypePathFromBinary(loc); - } - return position; - } - - private static int position_length(Position pos) { - int n = 0; - n += 1; // TargetType tag is a byte - switch (pos.type) { - // instanceof - case INSTANCEOF: - // new expression - case NEW: - // constructor/method reference receiver - case CONSTRUCTOR_REFERENCE: - case METHOD_REFERENCE: - n += 2; // offset - break; - // local variable - case LOCAL_VARIABLE: - // resource variable - case RESOURCE_VARIABLE: - n += 2; // table_length; - int table_length = pos.lvarOffset.length; - n += 2 * table_length; // offset - n += 2 * table_length; // length - n += 2 * table_length; // index - break; - // exception parameter - case EXCEPTION_PARAMETER: - n += 2; // exception_index - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameter - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - n += 1; // parameter_index - break; - // type parameter bound - case CLASS_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND: - n += 1; // parameter_index - n += 1; // bound_index - break; - // class extends or implements clause - case CLASS_EXTENDS: - n += 2; // type_index - break; - // throws - case THROWS: - n += 2; // type_index - break; - // method parameter - case METHOD_FORMAL_PARAMETER: - n += 1; // parameter_index - break; - // type cast - case CAST: - // method/constructor/reference type argument - case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: - case METHOD_INVOCATION_TYPE_ARGUMENT: - case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: - case METHOD_REFERENCE_TYPE_ARGUMENT: - n += 2; // offset - n += 1; // type index - break; - // We don't need to worry about these - case METHOD_RETURN: - case FIELD: - break; - case UNKNOWN: - throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!"); - default: - throw new AssertionError("TypeAnnotation: Unknown target type: " + pos.type); - } - - { - n += 1; // length - n += TypePathEntry.bytesPerEntry * pos.location.size(); // bytes for actual array - } - - return n; - } - - // Code duplicated from com.sun.tools.javac.code.TypeAnnotationPosition - public static class Position { - public enum TypePathEntryKind { - ARRAY(0), - INNER_TYPE(1), - WILDCARD(2), - TYPE_ARGUMENT(3); - - public final int tag; - - private TypePathEntryKind(int tag) { - this.tag = tag; - } - } - - public static class TypePathEntry { - /** The fixed number of bytes per TypePathEntry. */ - public static final int bytesPerEntry = 2; - - public final TypePathEntryKind tag; - public final int arg; - - public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY); - public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE); - public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD); - - private TypePathEntry(TypePathEntryKind tag) { - if (!(tag == TypePathEntryKind.ARRAY || - tag == TypePathEntryKind.INNER_TYPE || - tag == TypePathEntryKind.WILDCARD)) { - throw new AssertionError("Invalid TypePathEntryKind: " + tag); - } - this.tag = tag; - this.arg = 0; - } - - public TypePathEntry(TypePathEntryKind tag, int arg) { - if (tag != TypePathEntryKind.TYPE_ARGUMENT) { - throw new AssertionError("Invalid TypePathEntryKind: " + tag); - } - this.tag = tag; - this.arg = arg; - } - - public static TypePathEntry fromBinary(int tag, int arg) { - if (arg != 0 && tag != TypePathEntryKind.TYPE_ARGUMENT.tag) { - throw new AssertionError("Invalid TypePathEntry tag/arg: " + tag + "/" + arg); - } - switch (tag) { - case 0: - return ARRAY; - case 1: - return INNER_TYPE; - case 2: - return WILDCARD; - case 3: - return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg); - default: - throw new AssertionError("Invalid TypePathEntryKind tag: " + tag); - } - } - - @Override - public String toString() { - return tag.toString() + - (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : ""); - } - - @Override - public boolean equals(Object other) { - if (! (other instanceof TypePathEntry)) { - return false; - } - TypePathEntry tpe = (TypePathEntry) other; - return this.tag == tpe.tag && this.arg == tpe.arg; - } - - @Override - public int hashCode() { - return this.tag.hashCode() * 17 + this.arg; - } - } - - public TargetType type = TargetType.UNKNOWN; - - // For generic/array types. - // TODO: or should we use null? No one will use this object. - public List location = new ArrayList<>(0); - - // Tree position. - public int pos = -1; - - // For typecasts, type tests, new (and locals, as start_pc). - public boolean isValidOffset = false; - public int offset = -1; - - // For locals. arrays same length - public int[] lvarOffset = null; - public int[] lvarLength = null; - public int[] lvarIndex = null; - - // For type parameter bound - public int bound_index = Integer.MIN_VALUE; - - // For type parameter and method parameter - public int parameter_index = Integer.MIN_VALUE; - - // For class extends, implements, and throws clauses - public int type_index = Integer.MIN_VALUE; - - // For exception parameters, index into exception table - public int exception_index = Integer.MIN_VALUE; - - public Position() {} - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - sb.append(type); - - switch (type) { - // instanceof - case INSTANCEOF: - // new expression - case NEW: - // constructor/method reference receiver - case CONSTRUCTOR_REFERENCE: - case METHOD_REFERENCE: - sb.append(", offset = "); - sb.append(offset); - break; - // local variable - case LOCAL_VARIABLE: - // resource variable - case RESOURCE_VARIABLE: - if (lvarOffset == null) { - sb.append(", lvarOffset is null!"); - break; - } - sb.append(", {"); - for (int i = 0; i < lvarOffset.length; ++i) { - if (i != 0) sb.append("; "); - sb.append("start_pc = "); - sb.append(lvarOffset[i]); - sb.append(", length = "); - sb.append(lvarLength[i]); - sb.append(", index = "); - sb.append(lvarIndex[i]); - } - sb.append("}"); - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameter - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - sb.append(", param_index = "); - sb.append(parameter_index); - break; - // type parameter bound - case CLASS_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND: - sb.append(", param_index = "); - sb.append(parameter_index); - sb.append(", bound_index = "); - sb.append(bound_index); - break; - // class extends or implements clause - case CLASS_EXTENDS: - sb.append(", type_index = "); - sb.append(type_index); - break; - // throws - case THROWS: - sb.append(", type_index = "); - sb.append(type_index); - break; - // exception parameter - case EXCEPTION_PARAMETER: - sb.append(", exception_index = "); - sb.append(exception_index); - break; - // method parameter - case METHOD_FORMAL_PARAMETER: - sb.append(", param_index = "); - sb.append(parameter_index); - break; - // type cast - case CAST: - // method/constructor/reference type argument - case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: - case METHOD_INVOCATION_TYPE_ARGUMENT: - case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: - case METHOD_REFERENCE_TYPE_ARGUMENT: - sb.append(", offset = "); - sb.append(offset); - sb.append(", type_index = "); - sb.append(type_index); - break; - // We don't need to worry about these - case METHOD_RETURN: - case FIELD: - break; - case UNKNOWN: - sb.append(", position UNKNOWN!"); - break; - default: - throw new AssertionError("Unknown target type: " + type); - } - - // Append location data for generics/arrays. - if (!location.isEmpty()) { - sb.append(", location = ("); - sb.append(location); - sb.append(")"); - } - - sb.append(", pos = "); - sb.append(pos); - - sb.append(']'); - return sb.toString(); - } - - /** - * Indicates whether the target tree of the annotation has been optimized - * away from classfile or not. - * @return true if the target has not been optimized away - */ - public boolean emitToClassfile() { - return !type.isLocal() || isValidOffset; - } - - /** - * Decode the binary representation for a type path and set - * the {@code location} field. - * - * @param list The bytecode representation of the type path. - */ - public static List getTypePathFromBinary(List list) { - List loc = new ArrayList<>(list.size() / TypePathEntry.bytesPerEntry); - int idx = 0; - while (idx < list.size()) { - if (idx + 1 == list.size()) { - throw new AssertionError("Could not decode type path: " + list); - } - loc.add(TypePathEntry.fromBinary(list.get(idx), list.get(idx + 1))); - idx += 2; - } - return loc; - } - - public static List getBinaryFromTypePath(List locs) { - List loc = new ArrayList<>(locs.size() * TypePathEntry.bytesPerEntry); - for (TypePathEntry tpe : locs) { - loc.add(tpe.tag.tag); - loc.add(tpe.arg); - } - return loc; - } - } - - // Code duplicated from com.sun.tools.javac.code.TargetType - // The IsLocal flag could be removed here. - public enum TargetType { - /** For annotations on a class type parameter declaration. */ - CLASS_TYPE_PARAMETER(0x00), - - /** For annotations on a method type parameter declaration. */ - METHOD_TYPE_PARAMETER(0x01), - - /** For annotations on the type of an "extends" or "implements" clause. */ - CLASS_EXTENDS(0x10), - - /** For annotations on a bound of a type parameter of a class. */ - CLASS_TYPE_PARAMETER_BOUND(0x11), - - /** For annotations on a bound of a type parameter of a method. */ - METHOD_TYPE_PARAMETER_BOUND(0x12), - - /** For annotations on a field. */ - FIELD(0x13), - - /** For annotations on a method return type. */ - METHOD_RETURN(0x14), - - /** For annotations on the method receiver. */ - METHOD_RECEIVER(0x15), - - /** For annotations on a method parameter. */ - METHOD_FORMAL_PARAMETER(0x16), - - /** For annotations on a throws clause in a method declaration. */ - THROWS(0x17), - - /** For annotations on a local variable. */ - LOCAL_VARIABLE(0x40, true), - - /** For annotations on a resource variable. */ - RESOURCE_VARIABLE(0x41, true), - - /** For annotations on an exception parameter. */ - EXCEPTION_PARAMETER(0x42, true), - - /** For annotations on a type test. */ - INSTANCEOF(0x43, true), - - /** For annotations on an object creation expression. */ - NEW(0x44, true), - - /** For annotations on a constructor reference receiver. */ - CONSTRUCTOR_REFERENCE(0x45, true), - - /** For annotations on a method reference receiver. */ - METHOD_REFERENCE(0x46, true), - - /** For annotations on a typecast. */ - CAST(0x47, true), - - /** For annotations on a type argument of an object creation expression. */ - CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x48, true), - - /** For annotations on a type argument of a method call. */ - METHOD_INVOCATION_TYPE_ARGUMENT(0x49, true), - - /** For annotations on a type argument of a constructor reference. */ - CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(0x4A, true), - - /** For annotations on a type argument of a method reference. */ - METHOD_REFERENCE_TYPE_ARGUMENT(0x4B, true), - - /** For annotations with an unknown target. */ - UNKNOWN(0xFF); - - private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x4B; - - private final int targetTypeValue; - private final boolean isLocal; - - private TargetType(int targetTypeValue) { - this(targetTypeValue, false); - } - - private TargetType(int targetTypeValue, boolean isLocal) { - if (targetTypeValue < 0 - || targetTypeValue > 255) - throw new AssertionError("Attribute type value needs to be an unsigned byte: " + String.format("0x%02X", targetTypeValue)); - this.targetTypeValue = targetTypeValue; - this.isLocal = isLocal; - } - - /** - * Returns whether or not this TargetType represents an annotation whose - * target is exclusively a tree in a method body - * - * Note: wildcard bound targets could target a local tree and a class - * member declaration signature tree - */ - public boolean isLocal() { - return isLocal; - } - - public int targetTypeValue() { - return this.targetTypeValue; - } - - private static final TargetType[] targets; - - static { - targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1]; - TargetType[] alltargets = values(); - for (TargetType target : alltargets) { - if (target.targetTypeValue != UNKNOWN.targetTypeValue) - targets[target.targetTypeValue] = target; - } - for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i) { - if (targets[i] == null) - targets[i] = UNKNOWN; - } - } - - public static boolean isValidTargetTypeValue(int tag) { - if (tag == UNKNOWN.targetTypeValue) - return true; - return (tag >= 0 && tag < targets.length); - } - - public static TargetType fromTargetTypeValue(int tag) { - if (tag == UNKNOWN.targetTypeValue) - return UNKNOWN; - - if (tag < 0 || tag >= targets.length) - throw new AssertionError("Unknown TargetType: " + tag); - return targets[tag]; - } - } -} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/package-info.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/package-info.java deleted file mode 100644 index 505c1a7e03d..00000000000 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/package-info.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. - * 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. - */ - -/** - A minimalist library to read and write class files into objects closely - based on the corresponding definitions in - The Java Virtual Machine Specification (JVMS). - -

This is NOT part of any supported API. - If you write code that depends on this, you do so at your own risk. - This code and its internal interfaces are subject to change or - deletion without notice. -*/ -package com.sun.tools.classfile; diff --git a/src/jdk.jdeps/share/classes/module-info.java b/src/jdk.jdeps/share/classes/module-info.java index 3fdd3ca32d2..3c15c3330c7 100644 --- a/src/jdk.jdeps/share/classes/module-info.java +++ b/src/jdk.jdeps/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,8 +70,6 @@ module jdk.jdeps { uses com.sun.tools.javac.platform.PlatformProvider; - exports com.sun.tools.classfile to jdk.jlink; - provides java.util.spi.ToolProvider with com.sun.tools.javap.Main.JavapToolProvider, com.sun.tools.jdeps.Main.JDepsToolProvider, diff --git a/test/langtools/tools/javac/generics/wildcards/separate_compilation/WildcardBoundsNotReadFromClassFileTest.java b/test/langtools/tools/javac/generics/wildcards/separate_compilation/WildcardBoundsNotReadFromClassFileTest.java index 6d44f7ccf1e..ec28c274e7d 100644 --- a/test/langtools/tools/javac/generics/wildcards/separate_compilation/WildcardBoundsNotReadFromClassFileTest.java +++ b/test/langtools/tools/javac/generics/wildcards/separate_compilation/WildcardBoundsNotReadFromClassFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file * jdk.compiler/com.sun.tools.javac.main - * jdk.jdeps/com.sun.tools.classfile * @build toolbox.ToolBox toolbox.JavacTask * @run main WildcardBoundsNotReadFromClassFileTest */ @@ -42,7 +41,6 @@ import java.nio.file.Paths; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.util.Assert; -import com.sun.tools.classfile.ClassFile; import toolbox.TestRunner; import toolbox.ToolBox; From 45b7c748737f38c33c4666d17101b051b2fbe2ae Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 10 Apr 2025 01:38:47 +0000 Subject: [PATCH 101/843] 8341641: Make %APPDATA% and %LOCALAPPDATA% env variables available in *.cfg files Reviewed-by: almatvee --- .../jpackage/internal/util/TokenReplace.java | 16 +- src/jdk.jpackage/share/man/jpackage.md | 23 ++ .../share/native/applauncher/AppLauncher.cpp | 8 +- .../share/native/applauncher/CfgFile.cpp | 89 +++++-- .../share/native/applauncher/CfgFile.h | 9 +- .../native/applauncher/StringProcessing.cpp | 182 +++++++++++++ .../native/applauncher/StringProcessing.h | 83 ++++++ .../jdk/jpackage/test/AdditionalLauncher.java | 22 +- .../jdk/jpackage/test/JPackageCommand.java | 26 ++ .../jpackage/share/AppLauncherSubstTest.java | 249 ++++++++++++++++++ 10 files changed, 659 insertions(+), 48 deletions(-) create mode 100644 src/jdk.jpackage/share/native/applauncher/StringProcessing.cpp create mode 100644 src/jdk.jpackage/share/native/applauncher/StringProcessing.h create mode 100644 test/jdk/tools/jpackage/share/AppLauncherSubstTest.java diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/TokenReplace.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/TokenReplace.java index 24c13db1aa7..7c213851b9b 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/TokenReplace.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/TokenReplace.java @@ -42,6 +42,12 @@ import java.util.regex.Pattern; import java.util.stream.IntStream; import java.util.stream.Stream; +/** + * Class to replace tokens in strings. + *

+ * Single instance holds a list of tokens. Tokens can be substrings of each other. + * The implementation performs greedy replacement: longer tokens are replaced first. + */ public final class TokenReplace { private record TokenCut(String[] main, String[] sub) { @@ -103,7 +109,7 @@ public final class TokenReplace { this.tokens = tokens; regexps = new ArrayList<>(); - for(;;) { + for (;;) { final var tokenCut = TokenCut.createFromOrderedTokens(tokens); regexps.add(Pattern.compile(Stream.of(tokenCut.main()).map(Pattern::quote).collect(joining("|", "(", ")")))); @@ -153,12 +159,12 @@ public final class TokenReplace { @Override public boolean equals(Object obj) { // Auto generated code - if (this == obj) + if (this == obj) { return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) + } + if ((obj == null) || (getClass() != obj.getClass())) { return false; + } TokenReplace other = (TokenReplace) obj; return Arrays.equals(tokens, other.tokens); } diff --git a/src/jdk.jpackage/share/man/jpackage.md b/src/jdk.jpackage/share/man/jpackage.md index 61b671579da..c50370c9641 100644 --- a/src/jdk.jpackage/share/man/jpackage.md +++ b/src/jdk.jpackage/share/man/jpackage.md @@ -219,12 +219,35 @@ The `jpackage` tool will take as input a Java application and a Java run-time im This option can be used multiple times. + Value can contain substrings that will be expanded at runtime. + Two types of such substrings are supported: environment variables + and "APPDIR", "BINDIR", and "ROOTDIR" tokens. + + An expandable substring should be enclosed between the dollar + sign character ($) and the first following non-alphanumeric + character. Alternatively, it can be enclosed between "${" and "}" + substrings. + + Expandable substrings are case-sensitive on Unix and + case-insensitive on Windows. No string expansion occurs if the + referenced environment variable is undefined. + + Environment variables with names "APPDIR", "BINDIR", and "ROOTDIR" + will be ignored, and these expandable substrings will be + replaced by values calculated by the app launcher. + + Prefix the dollar sign character with the backslash character (\) + to prevent substring expansion. + `--java-options` *options* : Options to pass to the Java runtime This option can be used multiple times. + Value can contain substrings that will be substituted at runtime, + such as for the --arguments option. + `--main-class` *class-name* : Qualified name of the application main class to execute diff --git a/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp b/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp index 96e8885e6ab..fd1d07e92e0 100644 --- a/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp +++ b/src/jdk.jpackage/share/native/applauncher/AppLauncher.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -164,9 +164,9 @@ CfgFile* AppLauncher::createCfgFile() const { << cfgFilePath << "\""); CfgFile::Macros macros; - macros[_T("$APPDIR")] = appDirPath; - macros[_T("$BINDIR")] = FileUtils::dirname(launcherPath); - macros[_T("$ROOTDIR")] = imageRoot; + macros[_T("APPDIR")] = appDirPath; + macros[_T("BINDIR")] = FileUtils::dirname(launcherPath); + macros[_T("ROOTDIR")] = imageRoot; std::unique_ptr dummy(new CfgFile()); CfgFile::load(cfgFilePath).expandMacros(macros).swap(*dummy); return dummy.release(); diff --git a/src/jdk.jpackage/share/native/applauncher/CfgFile.cpp b/src/jdk.jpackage/share/native/applauncher/CfgFile.cpp index b5049334b64..0e99d131e69 100644 --- a/src/jdk.jpackage/share/native/applauncher/CfgFile.cpp +++ b/src/jdk.jpackage/share/native/applauncher/CfgFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,16 @@ #include "kludge_c++11.h" +#include #include #include #include "CfgFile.h" +#include "SysInfo.h" #include "Log.h" #include "Toolbox.h" #include "FileUtils.h" #include "ErrorHandling.h" +#include "StringProcessing.h" const CfgFile::Properties& CfgFile::getProperties( @@ -60,38 +63,82 @@ CfgFile& CfgFile::setPropertyValue(const SectionName& sectionName, namespace { -tstring expandMacros(const tstring& str, const CfgFile::Macros& macros) { - tstring reply = str; - CfgFile::Macros::const_iterator it = macros.begin(); - const CfgFile::Macros::const_iterator end = macros.end(); - for (; it != end; ++it) { - reply = tstrings::replace(reply, it->first, it->second); +template +void iterateProperties(CfgFileType& cfgFile, OpType& op) { + for (auto mapIt = cfgFile.begin(), mapEnd = cfgFile.end(); mapIt != mapEnd; ++mapIt) { + for (auto propertyIt = mapIt->second.begin(), propertyEnd = mapIt->second.end(); propertyIt != propertyEnd; ++propertyIt) { + for (auto strIt = propertyIt->second.begin(), strEnd = propertyIt->second.end(); strIt != strEnd; ++strIt) { + op(strIt); + } + } } - return reply; } +struct tokenize_strings { + void operator () (tstring_array::const_iterator& strIt) { + const auto tokens = StringProcessing::tokenize(*strIt); + values.push_back(tokens); + } + + std::set variableNames() const { + std::set allVariableNames; + for (auto it = values.begin(), end = values.end(); it != end; ++it) { + const auto variableNames = StringProcessing::extractVariableNames(*it); + allVariableNames.insert(variableNames.begin(), variableNames.end()); + } + + return allVariableNames; + } + + std::vector values; +}; + +class expand_macros { +public: + expand_macros(const CfgFile::Macros& m, + std::vector::iterator iter) : macros(m), curTokenizedString(iter) { + } + + void operator () (tstring_array::iterator& strIt) { + StringProcessing::expandVariables(*curTokenizedString, macros); + auto newStr = StringProcessing::stringify(*curTokenizedString); + ++curTokenizedString; + if (*strIt != newStr) { + LOG_TRACE(tstrings::any() << "Map [" << *strIt << "] into [" << newStr << "]"); + } + strIt->swap(newStr); + } + +private: + const CfgFile::Macros& macros; + std::vector::iterator curTokenizedString; +}; + } // namespace CfgFile CfgFile::expandMacros(const Macros& macros) const { CfgFile copyCfgFile = *this; - PropertyMap::iterator mapIt = copyCfgFile.data.begin(); - const PropertyMap::iterator mapEnd = copyCfgFile.data.end(); - for (; mapIt != mapEnd; ++mapIt) { - Properties::iterator propertyIt = mapIt->second.begin(); - const Properties::iterator propertyEnd = mapIt->second.end(); - for (; propertyIt != propertyEnd; ++propertyIt) { - tstring_array::iterator strIt = propertyIt->second.begin(); - const tstring_array::iterator strEnd = propertyIt->second.end(); - for (; strIt != strEnd; ++strIt) { - tstring newValue; - while ((newValue = ::expandMacros(*strIt, macros)) != *strIt) { - strIt->swap(newValue); - } + tokenize_strings tokenizedStrings; + iterateProperties(static_cast(copyCfgFile.data), tokenizedStrings); + + Macros allMacros(macros); + + const auto variableNames = tokenizedStrings.variableNames(); + for (auto it = variableNames.begin(), end = variableNames.end(); it != end; ++it) { + if (macros.find(*it) == macros.end()) { + // Not one of the reserved macro names. Assuming an environment variable. + const auto envVarName = *it; + if (SysInfo::isEnvVariableSet(envVarName)) { + const auto envVarValue = SysInfo::getEnvVariable(envVarName); + allMacros[envVarName] = envVarValue; } } } + expand_macros expandMacros(allMacros, tokenizedStrings.values.begin()); + iterateProperties(copyCfgFile.data, expandMacros); + return copyCfgFile; } diff --git a/src/jdk.jpackage/share/native/applauncher/CfgFile.h b/src/jdk.jpackage/share/native/applauncher/CfgFile.h index 03f70d94fde..0ab4ccc06a1 100644 --- a/src/jdk.jpackage/share/native/applauncher/CfgFile.h +++ b/src/jdk.jpackage/share/native/applauncher/CfgFile.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,7 @@ #ifndef CfgFile_h #define CfgFile_h -#include -#include "tstrings.h" +#include "StringProcessing.h" class CfgFile { @@ -90,10 +89,10 @@ public: std::swap(empty, other.empty); } - typedef std::map Macros; + typedef StringProcessing::VariableValues Macros; /** - * Returns copy of this instance with the given macros expanded. + * Returns copy of this instance with the given macros and environment variables expanded. */ CfgFile expandMacros(const Macros& macros) const; diff --git a/src/jdk.jpackage/share/native/applauncher/StringProcessing.cpp b/src/jdk.jpackage/share/native/applauncher/StringProcessing.cpp new file mode 100644 index 00000000000..207db25fd94 --- /dev/null +++ b/src/jdk.jpackage/share/native/applauncher/StringProcessing.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 "kludge_c++11.h" + +#include +#include "StringProcessing.h" + + +namespace StringProcessing { + +namespace { + +class TokenBuilder { +public: + TokenBuilder(const tstring& v): cur(v.c_str()) { + } + + void addNextToken(tstring::const_pointer end, TokenType type, TokenizedString& tokens) { + if (end != cur) { + const auto value = tstring(cur, end - cur); + cur = end; + tokens.push_back(Token(type, value)); + } + } + +private: + tstring::const_pointer cur; +}; + +bool isValidVariableFirstChar(tstring::value_type chr) { + if ('A' <= chr && chr <= 'Z') { + return true; + } else if ('a' <= chr && chr <= 'z') { + return true; + } else if ('_' == chr) { + return true; + } else { + return false; + } +} + +bool isValidVariableOtherChar(tstring::value_type chr) { + if (isValidVariableFirstChar(chr)) { + return true; + } else if ('0' <= chr && chr <= '9') { + return true; + } else { + return false; + } +} + +} // namespace + +TokenizedString tokenize(const tstring& str) { + TokenizedString tokens; + TokenBuilder tb(str); + tstring::const_pointer cur = str.c_str(); + const tstring::const_pointer end = cur + str.length(); + while (cur != end) { + if (*cur == '\\' && cur + 1 != end) { + const auto maybeNextToken = cur++; + if (*cur == '\\' || *cur == '$') { + tb.addNextToken(maybeNextToken, STRING, tokens); + tb.addNextToken(++cur, ESCAPED_CHAR, tokens); + continue; + } + } else if (*cur == '$' && cur + 1 != end) { + const auto maybeNextToken = cur++; + bool variableFound = false; + if (*cur == '{') { + do { + cur++; + } while (cur != end && *cur != '}'); + if (cur != end) { + variableFound = true; + cur++; + } + } else if (isValidVariableFirstChar(*cur)) { + variableFound = true; + do { + cur++; + } while (cur != end && isValidVariableOtherChar(*cur)); + } else { + continue; + } + if (variableFound) { + tb.addNextToken(maybeNextToken, STRING, tokens); + tb.addNextToken(cur, VARIABLE, tokens); + } + } else { + ++cur; + } + } + tb.addNextToken(cur, STRING, tokens); + return tokens; +} + + +tstring stringify(const TokenizedString& tokens) { + tstringstream ss; + TokenizedString::const_iterator it = tokens.begin(); + const TokenizedString::const_iterator end = tokens.end(); + for (; it != end; ++it) { + if (it->type() == ESCAPED_CHAR) { + ss << it->value().substr(1); + } else { + ss << it->value(); + } + } + return ss.str(); +} + + +namespace { + +tstring getVariableName(const tstring& str) { + if (tstrings::endsWith(str, _T("}"))) { + // ${VAR} + return str.substr(2, str.length() - 3); + } else { + // $VAR + return str.substr(1); + } +} + +} // namespace + +VariableNameList extractVariableNames(const TokenizedString& tokens) { + VariableNameList reply; + + TokenizedString::const_iterator it = tokens.begin(); + const TokenizedString::const_iterator end = tokens.end(); + for (; it != end; ++it) { + if (it->type() == VARIABLE) { + reply.push_back(getVariableName(it->value())); + } + } + + std::sort(reply.begin(), reply.end()); + reply.erase(std::unique(reply.begin(), reply.end()), reply.end()); + return reply; +} + + +void expandVariables(TokenizedString& tokens, const VariableValues& variableValues) { + TokenizedString::iterator it = tokens.begin(); + const TokenizedString::iterator end = tokens.end(); + for (; it != end; ++it) { + if (it->type() == VARIABLE) { + const auto entry = variableValues.find(getVariableName(it->value())); + if (entry != variableValues.end()) { + auto newToken = Token(STRING, entry->second); + std::swap(*it, newToken); + } + } + } +} + +} // namespace StringProcessing diff --git a/src/jdk.jpackage/share/native/applauncher/StringProcessing.h b/src/jdk.jpackage/share/native/applauncher/StringProcessing.h new file mode 100644 index 00000000000..85b14ae55d4 --- /dev/null +++ b/src/jdk.jpackage/share/native/applauncher/StringProcessing.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + + +#ifndef StringProcessor_h +#define StringProcessor_h + +#include +#include "tstrings.h" + + +namespace StringProcessing { + +enum TokenType { + STRING, + VARIABLE, + ESCAPED_CHAR +}; + +class Token { +public: + Token(TokenType type, const tstring& str): theType(type), theStr(str) { + } + + TokenType type() const { + return theType; + } + + const tstring& value() const { + return theStr; + } + +private: + TokenType theType; + tstring theStr; +}; + +typedef std::vector TokenizedString; +typedef std::vector VariableNameList; +#ifdef _WIN32 +struct less_ignore_case { + bool operator() (const tstring& x, const tstring& y) const { + return std::less()(tstrings::toLower(x), tstrings::toLower(y)); + } +}; +typedef std::map VariableValues; +#else +typedef std::map VariableValues; +#endif + +TokenizedString tokenize(const tstring& str); + +tstring stringify(const TokenizedString& tokens); + +VariableNameList extractVariableNames(const TokenizedString& tokens); + +void expandVariables(TokenizedString& tokens, const VariableValues& variableValues); + +} // namespace StringProcessing + +#endif // StringProcessor_h diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java index 5089dc0c602..f10939555e5 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java @@ -22,6 +22,9 @@ */ package jdk.jpackage.test; +import static java.util.stream.Collectors.toMap; +import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -35,11 +38,8 @@ import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import java.util.stream.Stream; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; import jdk.jpackage.internal.util.function.ThrowingBiConsumer; -import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; public class AdditionalLauncher { @@ -393,11 +393,9 @@ public class AdditionalLauncher { PropertyFile(Path path) throws IOException { data = Files.readAllLines(path).stream().map(str -> { return str.split("=", 2); - }).collect( - Collectors.toMap(tokens -> tokens[0], tokens -> tokens[1], - (oldValue, newValue) -> { - return newValue; - })); + }).collect(toMap(tokens -> tokens[0], tokens -> tokens[1], (oldValue, newValue) -> { + return newValue; + })); } public boolean isPropertySet(String name) { @@ -419,11 +417,9 @@ public class AdditionalLauncher { } private static String resolveVariables(JPackageCommand cmd, String str) { - var map = Map.of( - "$APPDIR", cmd.appLayout().appDirectory(), - "$ROOTDIR", - cmd.isImagePackageType() ? cmd.outputBundle() : cmd.appInstallationDirectory(), - "$BINDIR", cmd.appLayout().launchersDirectory()); + var map = Stream.of(JPackageCommand.Macro.values()).collect(toMap(x -> { + return String.format("$%s", x.name()); + }, cmd::macroValue)); for (var e : map.entrySet()) { str = str.replaceAll(Pattern.quote(e.getKey()), Matcher.quoteReplacement(e.getValue().toString())); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index 77e3b772cfa..b4d2d1872eb 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -859,6 +859,32 @@ public class JPackageCommand extends CommandArguments { return this; } + public static enum Macro { + APPDIR(cmd -> { + return cmd.appLayout().appDirectory().toString(); + }), + BINDIR(cmd -> { + return cmd.appLayout().launchersDirectory().toString(); + }), + ROOTDIR(cmd -> { + return (cmd.isImagePackageType() ? cmd.outputBundle() : cmd.appInstallationDirectory()).toString(); + }); + + private Macro(Function getValue) { + this.getValue = Objects.requireNonNull(getValue); + } + + String value(JPackageCommand cmd) { + return getValue.apply(cmd); + } + + private final Function getValue; + } + + public String macroValue(Macro macro) { + return macro.value(this); + } + public static enum AppLayoutAssert { APP_IMAGE_FILE(JPackageCommand::assertAppImageFile), PACKAGE_FILE(JPackageCommand::assertPackageFile), diff --git a/test/jdk/tools/jpackage/share/AppLauncherSubstTest.java b/test/jdk/tools/jpackage/share/AppLauncherSubstTest.java new file mode 100644 index 00000000000..abd1288e024 --- /dev/null +++ b/test/jdk/tools/jpackage/share/AppLauncherSubstTest.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.internal.util.OperatingSystem.WINDOWS; +import static jdk.jpackage.test.HelloApp.configureAndExecute; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import jdk.jpackage.internal.util.TokenReplace; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Executor; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageCommand.Macro; +import jdk.jpackage.test.TKit; + +/* + * @test + * @summary Tests environment variables substitution by jpackage launcher + * @bug 8341641 + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @build AppLauncherSubstTest + * @run main/othervm -Xmx512m jdk.jpackage.test.Main + * --jpt-run=AppLauncherSubstTest + */ +public class AppLauncherSubstTest { + + record TestSpec(String str, String expectedStr, Map env) { + + static class Builder { + + Builder str(String v) { + str = v; + return this; + } + + Builder expect(String v) { + expectedStr = v; + return this; + } + + Builder var(String name, String value) { + env.put(name, value); + return this; + } + + TestSpec create() { + return new TestSpec(str, Optional.ofNullable(expectedStr).orElse(str), env); + } + + private String str; + private String expectedStr; + private Map env = new LinkedHashMap<>(); + } + + public TestSpec { + Objects.requireNonNull(str); + Objects.requireNonNull(expectedStr); + Objects.requireNonNull(env); + env.entrySet().forEach(Objects::requireNonNull); + } + + public String resolveExpectedStr(JPackageCommand cmd) { + return MACROS.applyTo(expectedStr, token -> { + // @@APPDIR@@ -> APPDIR + final var macro = token.substring(2, token.length() - 2); + return Path.of(cmd.macroValue(Macro.valueOf(macro))).toAbsolutePath(); + }); + } + + @Override + public String toString() { + final var sb = new StringBuilder(); + sb.append("str=").append(str); + sb.append(", expect=").append(expectedStr); + if (!env.isEmpty()) { + sb.append(", env=").append(env); + } + return sb.toString(); + } + + private final static TokenReplace MACROS = new TokenReplace(Stream.of(Macro.values()).map(macro -> { + return String.format("@@%s@@", macro); + }).toArray(String[]::new)); + } + + @Test + @ParameterSupplier + @ParameterSupplier(value = "testCaseSensitive", ifNotOS = WINDOWS) + @ParameterSupplier(value = "testCaseInsensitive", ifOS = WINDOWS) + public static void test(TestSpec spec) throws IOException { + final var cmd = JPackageCommand.helloAppImage(TEST_APP_JAVA + "*Hello") + .ignoreFakeRuntime() + .setArgumentValue("--java-options", "-D" + TEST_PROP + "="); + + cmd.execute(); + + // Manually edit main launcher config file. Don't do it directly because + // jpackage doesn't pass the value of `--java-options` option as-is into the config file. + final var cfgFile = cmd.appLauncherCfgPath(null); + TKit.createTextFile(cfgFile, Files.readAllLines(cfgFile).stream().map(line -> { + return TEST_PROP_REGEXP.matcher(line).replaceFirst(Matcher.quoteReplacement(spec.str())); + })); + + final var launcherExec = new Executor() + .saveOutput() + .dumpOutput() + .setExecutable(cmd.appLauncherPath().toAbsolutePath()) + .addArguments("--print-sys-prop=" + TEST_PROP); + + spec.env().forEach(launcherExec::setEnvVar); + + final var resolvedExpectedStr = spec.resolveExpectedStr(cmd); + final var actualStr = configureAndExecute(0, launcherExec).getFirstLineOfOutput().substring((TEST_PROP + "=").length()); + + if (TKit.isWindows() && !resolvedExpectedStr.equals(spec.expectedStr())) { + TKit.assertEquals(resolvedExpectedStr.toLowerCase(), actualStr.toLowerCase(), "Check the property value is as expected [lowercase]"); + } else { + TKit.assertEquals(resolvedExpectedStr, actualStr, "Check the property value is as expected"); + } + } + + public static Collection test() { + return Stream.of( + testSpec(""), + testSpec("$ONE ${TWO} ${ONE} $TWO ONE TWO").expect("one two one two ONE TWO").var("ONE", "one").var("TWO", "two"), + testSpec("\\$FOO\\\\$FOO\\${FOO}\\\\${FOO}").expect("$FOO\\BAR${FOO}\\BAR").var("FOO", "BAR"), + testSpec("$FOO-$BAR").expect("$FOO-").var("BAR", ""), + testSpec("${BINDIR}${APPDIR}${ROOTDIR}").expect("@@BINDIR@@@@APPDIR@@@@ROOTDIR@@").var("BINDIR", "a").var("APPDIR", "b").var("ROOTDIR", "c"), + testSpec("$BINDIR$APPDIR$ROOTDIR").expect("@@BINDIR@@@@APPDIR@@@@ROOTDIR@@"), + testSpec("$BINDIR2$APPDIR2$ROOTDIR2").expect("$BINDIR2$APPDIR2$ROOTDIR2") + ).map(TestSpec.Builder::create).map(v -> { + return new Object[] {v}; + }).toList(); + } + + public static Collection testCaseSensitive() { + final List testCases = new ArrayList<>(); + for (final var macro : Macro.values()) { + testCases.addAll(createTestCases(macro, true)); + } + + testCases.addAll(Stream.of( + testSpec("$ALPHA $alpha").expect("A a").var("ALPHA", "A").var("alpha", "a"), + testSpec("$ALPHA $alpha").expect("$ALPHA a").var("alpha", "a"), + testSpec("$ALPHA $alpha").expect("A $alpha").var("ALPHA", "A") + ).map(TestSpec.Builder::create).toList()); + + return testCases.stream().map(v -> { + return new Object[] {v}; + }).toList(); + } + + public static Collection testCaseInsensitive() { + final List testCases = new ArrayList<>(); + for (final var macro : Macro.values()) { + testCases.addAll(createTestCases(macro, false)); + } + + testCases.addAll(Stream.of( + testSpec("$ALPHA $alpha").expect("A A").var("AlphA", "A"), + testSpec("$ALPHA $alpha").expect("a a").var("alpha", "a"), + testSpec("$ALPHA $alpha").expect("A A").var("ALPHA", "A") + ).map(TestSpec.Builder::create).toList()); + + return testCases.stream().map(v -> { + return new Object[] {v}; + }).toList(); + } + + private static List createTestCases(Macro macro, boolean caseSensitive) { + final var name = macro.name(); + final var name2 = name.transform(str -> { + final var chars = name.toCharArray(); + for (int i = 0; i < chars.length; i += 2) { + chars[i] = Character.toLowerCase(chars[i]); + } + return new String(chars); + }); + + if (name.equals(name2)) { + throw new UnsupportedOperationException(); + } + + final var testSpec = testSpec(String.format("${%s}${%s}", name, name2)).var(name, "A").var(name2, "[foo]"); + if (caseSensitive) { + testSpec.expect(String.format("@@%s@@[foo]", name, name2)); + } else { + testSpec.expect(String.format("@@%s@@@@%s@@", name, name)); + } + + final var testSpec2 = testSpec(String.format("${%s}${%s}", name, name2)).var(name, "A"); + if (caseSensitive) { + testSpec2.expect(String.format("@@%s@@${%s}", name, name2)); + } else { + testSpec2.expect(String.format("@@%s@@@@%s@@", name, name)); + } + + final var testSpec3 = testSpec(String.format("${%s}${%s}", name, name2)); + if (caseSensitive) { + testSpec3.expect(String.format("@@%s@@${%s}", name, name2)); + } else { + testSpec3.expect(String.format("@@%s@@@@%s@@", name, name)); + } + + return Stream.of(testSpec, testSpec2).map(TestSpec.Builder::create).toList(); + } + + private static TestSpec.Builder testSpec(String str) { + return new TestSpec.Builder().str(str); + } + + private static final Path TEST_APP_JAVA = TKit.TEST_SRC_ROOT.resolve("apps/PrintEnv.java"); + + private static final String TEST_PROP = "jdk.jpackage.test.Property"; + private static final Pattern TEST_PROP_REGEXP = Pattern.compile("(?<=" + Pattern.quote(TEST_PROP) + "=).*"); +} From bcac42aabce5b57525f776037d73b51d0afcbaf5 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 10 Apr 2025 07:04:15 +0000 Subject: [PATCH 102/843] 8349479: C2: when a Type node becomes dead, make CFG path that uses it unreachable Reviewed-by: chagedorn, vlivanov --- src/hotspot/cpu/aarch64/aarch64.ad | 3 +- src/hotspot/cpu/arm/arm.ad | 3 +- src/hotspot/cpu/ppc/ppc.ad | 3 +- src/hotspot/cpu/riscv/riscv.ad | 3 +- src/hotspot/cpu/s390/s390.ad | 3 +- src/hotspot/cpu/x86/x86.ad | 3 +- .../share/nmt/nativeCallStackPrinter.cpp | 5 +- src/hotspot/share/opto/c2_globals.hpp | 6 ++ src/hotspot/share/opto/castnode.cpp | 10 ++- src/hotspot/share/opto/connode.hpp | 4 + src/hotspot/share/opto/convertnode.cpp | 18 ++++- src/hotspot/share/opto/movenode.cpp | 4 + src/hotspot/share/opto/node.cpp | 75 +++++++++++++++++++ src/hotspot/share/opto/node.hpp | 6 ++ src/hotspot/share/opto/phaseX.cpp | 17 +++++ src/hotspot/share/opto/phaseX.hpp | 1 + src/hotspot/share/utilities/ostream.cpp | 7 ++ src/hotspot/share/utilities/ostream.hpp | 1 + .../c2/TestGuardOfCastIIDoesntFold.java | 73 ++++++++++++++++++ .../assertion/TestAssertionPredicates.java | 15 ++++ 20 files changed, 246 insertions(+), 14 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestGuardOfCastIIDoesntFold.java diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 5bfe697d12c..76e3c92ddc2 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -16297,7 +16297,8 @@ instruct ShouldNotReachHere() %{ ins_encode %{ if (is_reachable()) { - __ stop(_halt_reason); + const char* str = __ code_string(_halt_reason); + __ stop(str); } %} diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 486d51ac463..f3b97d23ad3 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -8992,7 +8992,8 @@ instruct ShouldNotReachHere( ) format %{ "ShouldNotReachHere" %} ins_encode %{ if (is_reachable()) { - __ stop(_halt_reason); + const char* str = __ code_string(_halt_reason); + __ stop(str); } %} ins_pipe(tail_call); diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 022a70d52a2..07d681e8982 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -14699,7 +14699,8 @@ instruct ShouldNotReachHere() %{ format %{ "ShouldNotReachHere" %} ins_encode %{ if (is_reachable()) { - __ stop(_halt_reason); + const char* str = __ code_string(_halt_reason); + __ stop(str); } %} ins_pipe(pipe_class_default); diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 4ebfdf9f16c..aca2f4dd488 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -10893,7 +10893,8 @@ instruct ShouldNotReachHere() %{ ins_encode %{ if (is_reachable()) { - __ stop(_halt_reason); + const char* str = __ code_string(_halt_reason); + __ stop(str); } %} diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index ea1bdb9e231..c32064be86d 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -10080,7 +10080,8 @@ instruct ShouldNotReachHere() %{ format %{ "ILLTRAP; ShouldNotReachHere" %} ins_encode %{ if (is_reachable()) { - __ stop(_halt_reason); + const char* str = __ code_string(_halt_reason); + __ stop(str); } %} ins_pipe(pipe_class_dummy); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 2d7548c37a8..7bde4ced2ba 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2874,7 +2874,8 @@ instruct ShouldNotReachHere() %{ format %{ "stop\t# ShouldNotReachHere" %} ins_encode %{ if (is_reachable()) { - __ stop(_halt_reason); + const char* str = __ code_string(_halt_reason); + __ stop(str); } %} ins_pipe(pipe_slow); diff --git a/src/hotspot/share/nmt/nativeCallStackPrinter.cpp b/src/hotspot/share/nmt/nativeCallStackPrinter.cpp index c2a54961abe..59a5bf99142 100644 --- a/src/hotspot/share/nmt/nativeCallStackPrinter.cpp +++ b/src/hotspot/share/nmt/nativeCallStackPrinter.cpp @@ -44,10 +44,7 @@ void NativeCallStackPrinter::print_stack(const NativeCallStack* stack) const { if (created) { stringStream ss(4 * K); stack->print_frame(&ss, pc); - const size_t len = ss.size(); - char* store = NEW_ARENA_ARRAY(&_text_storage, char, len + 1); - memcpy(store, ss.base(), len + 1); - (*cached_frame_text) = store; + (*cached_frame_text) = ss.as_string(&_text_storage); } _out->print_raw_cr(*cached_frame_text); } diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index ad88554fedd..41b08161097 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -820,6 +820,12 @@ product(bool, UseStoreStoreForCtor, true, DIAGNOSTIC, \ "Use StoreStore barrier instead of Release barrier at the end " \ "of constructors") \ + \ + develop(bool, KillPathsReachableByDeadTypeNode, true, \ + "When a Type node becomes top, make paths where the node is " \ + "used dead by replacing them with a Halt node. Turning this off " \ + "could corrupt the graph in rare cases and should be used with " \ + "care.") \ // end of C2_FLAGS diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp index 68ba291986b..198634af71b 100644 --- a/src/hotspot/share/opto/castnode.cpp +++ b/src/hotspot/share/opto/castnode.cpp @@ -96,8 +96,14 @@ const Type* ConstraintCastNode::Value(PhaseGVN* phase) const { //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Strip out // control copies -Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape) { - return (in(0) && remove_dead_region(phase, can_reshape)) ? this : nullptr; +Node* ConstraintCastNode::Ideal(PhaseGVN* phase, bool can_reshape) { + if (in(0) != nullptr && remove_dead_region(phase, can_reshape)) { + return this; + } + if (in(1) != nullptr && phase->type(in(1)) != Type::TOP) { + return TypeNode::Ideal(phase, can_reshape); + } + return nullptr; } uint ConstraintCastNode::hash() const { diff --git a/src/hotspot/share/opto/connode.hpp b/src/hotspot/share/opto/connode.hpp index 3b7657320e2..47888587960 100644 --- a/src/hotspot/share/opto/connode.hpp +++ b/src/hotspot/share/opto/connode.hpp @@ -46,6 +46,10 @@ public: virtual const RegMask &out_RegMask() const { return RegMask::Empty; } virtual const RegMask &in_RegMask(uint) const { return RegMask::Empty; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) { + return Node::Ideal(phase, can_reshape); + } + // Polymorphic factory method: static ConNode* make(const Type *t); }; diff --git a/src/hotspot/share/opto/convertnode.cpp b/src/hotspot/share/opto/convertnode.cpp index 3e99277d903..5df79a36edb 100644 --- a/src/hotspot/share/opto/convertnode.cpp +++ b/src/hotspot/share/opto/convertnode.cpp @@ -689,7 +689,14 @@ bool Compile::push_thru_add(PhaseGVN* phase, Node* z, const TypeInteger* tz, con //------------------------------Ideal------------------------------------------ -Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* ConvI2LNode::Ideal(PhaseGVN* phase, bool can_reshape) { + if (in(1) != nullptr && phase->type(in(1)) != Type::TOP) { + Node* progress = TypeNode::Ideal(phase, can_reshape); + if (progress != nullptr) { + return progress; + } + } + const TypeLong* this_type = this->type()->is_long(); if (can_reshape && !phase->C->post_loop_opts_phase()) { // makes sure we run ::Value to potentially remove type assertion after loop opts @@ -791,7 +798,14 @@ const Type* ConvL2INode::Value(PhaseGVN* phase) const { //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. // Blow off prior masking to int -Node *ConvL2INode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* ConvL2INode::Ideal(PhaseGVN* phase, bool can_reshape) { + if (in(1) != nullptr && phase->type(in(1)) != Type::TOP) { + Node* progress = TypeNode::Ideal(phase, can_reshape); + if (progress != nullptr) { + return progress; + } + } + Node *andl = in(1); uint andl_op = andl->Opcode(); if( andl_op == Op_AndL ) { diff --git a/src/hotspot/share/opto/movenode.cpp b/src/hotspot/share/opto/movenode.cpp index b0db9c1d350..66db1df339b 100644 --- a/src/hotspot/share/opto/movenode.cpp +++ b/src/hotspot/share/opto/movenode.cpp @@ -90,6 +90,10 @@ Node *CMoveNode::Ideal(PhaseGVN *phase, bool can_reshape) { phase->type(in(IfTrue)) == Type::TOP) { return nullptr; } + Node* progress = TypeNode::Ideal(phase, can_reshape); + if (progress != nullptr) { + return progress; + } // Check for Min/Max patterns. This is called before constants are pushed to the right input, as that transform can // make BoolTests non-canonical. diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 37f6e95d502..d00bd3d3943 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -3076,3 +3076,78 @@ const Type* TypeNode::Value(PhaseGVN* phase) const { return _type; } uint TypeNode::ideal_reg() const { return _type->ideal_reg(); } + +void TypeNode::make_path_dead(PhaseIterGVN* igvn, PhaseIdealLoop* loop, Node* ctrl_use, uint j, const char* phase_str) { + Node* c = ctrl_use->in(j); + if (igvn->type(c) != Type::TOP) { + igvn->replace_input_of(ctrl_use, j, igvn->C->top()); + create_halt_path(igvn, c, loop, phase_str); + } +} + +// This Type node is dead. It could be because the type that it captures and the type of the node computed from its +// inputs do not intersect anymore. That node has some uses along some control flow paths. Those control flow paths must +// be unreachable as using a dead value makes no sense. For the Type node to capture a narrowed down type, some control +// flow construct must guard the Type node (an If node usually). When the Type node becomes dead, the guard usually +// constant folds and the control flow that leads to the Type node becomes unreachable. There are cases where that +// doesn't happen, however. They are handled here by following uses of the Type node until a CFG or a Phi to find dead +// paths. The dead paths are then replaced by a Halt node. +void TypeNode::make_paths_from_here_dead(PhaseIterGVN* igvn, PhaseIdealLoop* loop, const char* phase_str) { + Unique_Node_List wq; + wq.push(this); + for (uint i = 0; i < wq.size(); ++i) { + Node* n = wq.at(i); + for (DUIterator_Fast kmax, k = n->fast_outs(kmax); k < kmax; k++) { + Node* u = n->fast_out(k); + if (u->is_CFG()) { + assert(!u->is_Region(), "Can't reach a Region without going through a Phi"); + make_path_dead(igvn, loop, u, 0, phase_str); + } else if (u->is_Phi()) { + Node* r = u->in(0); + assert(r->is_Region() || r->is_top(), "unexpected Phi's control"); + if (r->is_Region()) { + for (uint j = 1; j < u->req(); ++j) { + if (u->in(j) == n) { + make_path_dead(igvn, loop, r, j, phase_str); + } + } + } + } else { + wq.push(u); + } + } + } +} + +void TypeNode::create_halt_path(PhaseIterGVN* igvn, Node* c, PhaseIdealLoop* loop, const char* phase_str) const { + Node* frame = new ParmNode(igvn->C->start(), TypeFunc::FramePtr); + if (loop == nullptr) { + igvn->register_new_node_with_optimizer(frame); + } else { + loop->register_new_node(frame, igvn->C->start()); + } + + stringStream ss; + ss.print("dead path discovered by TypeNode during %s", phase_str); + + Node* halt = new HaltNode(c, frame, ss.as_string(igvn->C->comp_arena())); + if (loop == nullptr) { + igvn->register_new_node_with_optimizer(halt); + } else { + loop->register_control(halt, loop->ltree_root(), c); + } + igvn->add_input_to(igvn->C->root(), halt); +} + +Node* TypeNode::Ideal(PhaseGVN* phase, bool can_reshape) { + if (KillPathsReachableByDeadTypeNode && can_reshape && Value(phase) == Type::TOP) { + PhaseIterGVN* igvn = phase->is_IterGVN(); + Node* top = igvn->C->top(); + ResourceMark rm; + make_paths_from_here_dead(igvn, nullptr, "igvn"); + return top; + } + + return Node::Ideal(phase, can_reshape); +} + diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 562e090a41b..1cb9009ef27 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -155,6 +155,7 @@ class ParsePredicateNode; class PCTableNode; class PhaseCCP; class PhaseGVN; +class PhaseIdealLoop; class PhaseIterGVN; class PhaseRegAlloc; class PhaseTransform; @@ -2044,12 +2045,17 @@ public: init_class_id(Class_Type); } virtual const Type* Value(PhaseGVN* phase) const; + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); virtual const Type *bottom_type() const; virtual uint ideal_reg() const; + + void make_path_dead(PhaseIterGVN* igvn, PhaseIdealLoop* loop, Node* ctrl_use, uint j, const char* phase_str); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; virtual void dump_compact_spec(outputStream *st) const; #endif + void make_paths_from_here_dead(PhaseIterGVN* igvn, PhaseIdealLoop* loop, const char* phase_str); + void create_halt_path(PhaseIterGVN* igvn, Node* c, PhaseIdealLoop* loop, const char* phase_str) const; }; #include "opto/opcodes.hpp" diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index ae6e49e2c4e..90bc9231873 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1835,6 +1835,11 @@ void PhaseCCP::analyze() { set_type(n, new_type); push_child_nodes_to_worklist(worklist, n); } + if (KillPathsReachableByDeadTypeNode && n->is_Type() && new_type == Type::TOP) { + // Keep track of Type nodes to kill CFG paths that use Type + // nodes that become dead. + _maybe_top_type_nodes.push(n); + } } DEBUG_ONLY(verify_analyze(worklist_verify);) } @@ -2065,6 +2070,18 @@ Node *PhaseCCP::transform( Node *n ) { // track all visited nodes, so that we can remove the complement Unique_Node_List useful; + if (KillPathsReachableByDeadTypeNode) { + for (uint i = 0; i < _maybe_top_type_nodes.size(); ++i) { + Node* type_node = _maybe_top_type_nodes.at(i); + if (type(type_node) == Type::TOP) { + ResourceMark rm; + type_node->as_Type()->make_paths_from_here_dead(this, nullptr, "ccp"); + } + } + } else { + assert(_maybe_top_type_nodes.size() == 0, "we don't need type nodes"); + } + // Initialize the traversal. // This CCP pass may prove that no exit test for a loop ever succeeds (i.e. the loop is infinite). In that case, // the logic below doesn't follow any path from Root to the loop body: there's at least one such path but it's proven diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 7843bd39aea..c2a0f0dbb77 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -608,6 +608,7 @@ protected: // Should be replaced with combined CCP & GVN someday. class PhaseCCP : public PhaseIterGVN { Unique_Node_List _root_and_safepoints; + Unique_Node_List _maybe_top_type_nodes; // Non-recursive. Use analysis to transform single Node. virtual Node* transform_once(Node* n); diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index 66fc3103a53..e95bc776ce5 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -437,6 +437,13 @@ char* stringStream::as_string(bool c_heap) const { return copy; } +char* stringStream::as_string(Arena* arena) const { + char* copy = NEW_ARENA_ARRAY(arena, char, _written + 1); + ::memcpy(copy, _buffer, _written); + copy[_written] = '\0'; // terminating null + return copy; +} + stringStream::~stringStream() { if (!_is_fixed && _buffer != _small_buffer) { FREE_C_HEAP_ARRAY(char, _buffer); diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp index 9faaf32fb6b..46bd0b673c1 100644 --- a/src/hotspot/share/utilities/ostream.hpp +++ b/src/hotspot/share/utilities/ostream.hpp @@ -270,6 +270,7 @@ class stringStream : public outputStream { bool is_empty() const { return _buffer[0] == '\0'; } // Copy to a resource, or C-heap, array as requested char* as_string(bool c_heap = false) const; + char* as_string(Arena* arena) const; }; class fileStream : public outputStream { diff --git a/test/hotspot/jtreg/compiler/c2/TestGuardOfCastIIDoesntFold.java b/test/hotspot/jtreg/compiler/c2/TestGuardOfCastIIDoesntFold.java new file mode 100644 index 00000000000..1751b117034 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestGuardOfCastIIDoesntFold.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8349479 + * @summary C2: when a Type node becomes dead, make CFG path that uses it unreachable + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement + * -XX:CompileCommand=dontinline,TestGuardOfCastIIDoesntFold::notInlined + * TestGuardOfCastIIDoesntFold + * @run main TestGuardOfCastIIDoesntFold + */ + +public class TestGuardOfCastIIDoesntFold { + private static volatile int volatileField; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test1(1, 0, 0, false); + helper1(1, 0, 0, true); + helper2(0, 0); + } + } + + private static int test1(int i, int j, int k, boolean flag) { + int l; + for (l = 0; l < 10; l++) { + } + j = helper2(j, l); + return helper1(i, j, k, flag); + } + + private static int helper2(int j, int l) { + if (l == 10) { + j = Integer.MAX_VALUE-1; + } + return j; + } + + private static int helper1(int i, int j, int k, boolean flag) { + if (flag) { + k = Integer.max(k, -2); + int[] array = new int[i + k]; + notInlined(array); + return array[j]; + } + volatileField = 42; + return volatileField; + } + + private static void notInlined(int[] array) { + } +} diff --git a/test/hotspot/jtreg/compiler/predicates/assertion/TestAssertionPredicates.java b/test/hotspot/jtreg/compiler/predicates/assertion/TestAssertionPredicates.java index ea8c627187d..f7f2f1f20f6 100644 --- a/test/hotspot/jtreg/compiler/predicates/assertion/TestAssertionPredicates.java +++ b/test/hotspot/jtreg/compiler/predicates/assertion/TestAssertionPredicates.java @@ -33,6 +33,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates Xbatch */ @@ -43,6 +44,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates NoTieredCompilation */ @@ -54,6 +56,7 @@ * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=inline,compiler.predicates.assertion.TestAssertionPredicates::inline + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates Xcomp */ @@ -65,6 +68,7 @@ * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=inline,compiler.predicates.assertion.TestAssertionPredicates::inline + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates XcompNoTiered */ @@ -76,6 +80,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates LoopMaxUnroll0 */ @@ -87,6 +92,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates LoopMaxUnroll2 */ @@ -98,6 +104,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates LoopUnrollLimit40 */ @@ -109,6 +116,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates LoopUnrollLimit150 */ @@ -120,6 +128,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates NoProfiledLoopPredicate */ @@ -131,6 +140,7 @@ * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates DataUpdate */ @@ -141,6 +151,7 @@ * @run main/othervm -Xcomp -XX:-BlockLayoutByFrequency -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates CloneDown */ @@ -152,6 +163,7 @@ * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:+StressGCM -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates Stress */ @@ -163,6 +175,7 @@ * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:+StressGCM -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates Stress */ @@ -174,6 +187,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates NoLoopPredication */ @@ -185,6 +199,7 @@ * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure * -XX:CompileCommand=compileonly,compiler.predicates.assertion.TestAssertionPredicates::* * -XX:CompileCommand=dontinline,compiler.predicates.assertion.TestAssertionPredicates::* + * -XX:+IgnoreUnrecognizedVMOptions -XX:-KillPathsReachableByDeadTypeNode * compiler.predicates.assertion.TestAssertionPredicates NoLoopPredication */ From 4f80437ee05e4a3f755a166140669c0fd631f56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Thu, 10 Apr 2025 07:24:45 +0000 Subject: [PATCH 103/843] 8353842: C2: Add graph dumps before and after loop opts phase Reviewed-by: chagedorn, epeter --- src/hotspot/share/opto/compile.cpp | 7 +++++++ src/hotspot/share/opto/phasetype.hpp | 4 +++- .../jtreg/compiler/lib/ir_framework/CompilePhase.java | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 8a059d0852f..c830d0c854b 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -1857,6 +1857,9 @@ void Compile::process_for_post_loop_opts_igvn(PhaseIterGVN& igvn) { // at least to this point, even if no loop optimizations were done. PhaseIdealLoop::verify(igvn); + if (has_loops() || _loop_opts_cnt > 0) { + print_method(PHASE_AFTER_LOOP_OPTS, 2); + } C->set_post_loop_opts_phase(); // no more loop opts allowed assert(!C->major_progress(), "not cleared"); @@ -2377,6 +2380,10 @@ void Compile::Optimize() { if (failing()) return; + if (has_loops()) { + print_method(PHASE_BEFORE_LOOP_OPTS, 2); + } + // Perform escape analysis if (do_escape_analysis() && ConnectionGraph::has_candidates(this)) { if (has_loops()) { diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index 318a01e3bd8..b3076dd8091 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ flags(ELIMINATE_VBOX_ALLOC, "Eliminate VectorBoxAllocate") \ flags(ITER_GVN_BEFORE_EA, "Iter GVN before EA") \ flags(ITER_GVN_AFTER_VECTOR, "Iter GVN after vector box elimination") \ + flags(BEFORE_LOOP_OPTS, "Before Loop Optimizations") \ flags(BEFORE_BEAUTIFY_LOOPS, "Before beautify loops") \ flags(AFTER_BEAUTIFY_LOOPS, "After beautify loops") \ flags(BEFORE_LOOP_UNROLLING, "Before Loop Unrolling") \ @@ -88,6 +89,7 @@ flags(CCP1, "PhaseCCP 1") \ flags(ITER_GVN2, "Iter GVN 2") \ flags(PHASEIDEALLOOP_ITERATIONS, "PhaseIdealLoop iterations") \ + flags(AFTER_LOOP_OPTS, "After Loop Optimizations") \ flags(AFTER_MERGE_STORES, "After Merge Stores") \ flags(BEFORE_MACRO_EXPANSION , "Before Macro Expansion") \ flags(AFTER_MACRO_EXPANSION_STEP, "After Macro Expansion Step") \ diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java index 6f4410a0220..ad32f6a94b9 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,7 @@ public enum CompilePhase { ELIMINATE_VBOX_ALLOC("Eliminate VectorBoxAllocate"), ITER_GVN_BEFORE_EA("Iter GVN before EA"), ITER_GVN_AFTER_VECTOR("Iter GVN after vector box elimination"), + BEFORE_LOOP_OPTS("Before Loop Optimizations"), BEFORE_BEAUTIFY_LOOPS("Before beautify loops"), AFTER_BEAUTIFY_LOOPS("After beautify loops"), BEFORE_LOOP_UNROLLING("Before Loop Unrolling"), @@ -95,6 +96,7 @@ public enum CompilePhase { CCP1("PhaseCCP 1"), ITER_GVN2("Iter GVN 2"), PHASEIDEALLOOP_ITERATIONS("PhaseIdealLoop iterations"), + AFTER_LOOP_OPTS("After Loop Optimizations"), AFTER_MERGE_STORES("After Merge Stores"), BEFORE_MACRO_EXPANSION("Before Macro Expansion"), AFTER_MACRO_EXPANSION_STEP("After Macro Expansion Step"), From c447a10225576bc59e1ba9477417367d2ac28511 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 10 Apr 2025 07:42:40 +0000 Subject: [PATCH 104/843] 8353856: Deprecate FlighRecorderPermission class for removal Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/EventSettings.java | 117 ++++++++++++++++- .../jdk/jfr/FlightRecorderPermission.java | 123 +----------------- .../jdk/jfr/internal/PrivateAccess.java | 4 +- 3 files changed, 120 insertions(+), 124 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java b/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java index 17ce98d166c..6ed20f124d9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/EventSettings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,15 @@ package jdk.jfr; import java.time.Duration; +import java.util.List; import java.util.Map; import java.util.Objects; +import jdk.jfr.internal.PlatformEventType; +import jdk.jfr.internal.PlatformRecorder; +import jdk.jfr.internal.PlatformRecording; +import jdk.jfr.internal.PrivateAccess; +import jdk.jfr.internal.Type; import jdk.jfr.internal.management.EventSettingsModifier; /** @@ -46,6 +52,115 @@ import jdk.jfr.internal.management.EventSettingsModifier; */ public abstract class EventSettings { + // Purpose of InternalAccess is to give classes in jdk.jfr.internal + // access to package private methods in this package (jdk.jfr). + // + // The initialization could be done in any class in this package, + // but this one was chosen because it is lightweight. + static { + PrivateAccess.setPrivateAccess(new InternalAccess()); + } + + private static final class InternalAccess extends PrivateAccess { + + @Override + public Type getType(Object o) { + if (o instanceof AnnotationElement ae) { + return ae.getType(); + } + if (o instanceof EventType et) { + return et.getType(); + } + if (o instanceof ValueDescriptor vd) { + return vd.getType(); + } + if (o instanceof SettingDescriptor sd) { + return sd.getType(); + } + throw new Error("Unknown type " + o.getClass()); + } + + @Override + public Configuration newConfiguration(String name, String label, String description, String provider, Map settings, String contents) { + return new Configuration(name, label, description, provider, settings, contents); + } + + @Override + public EventType newEventType(PlatformEventType platformEventType) { + return new EventType(platformEventType); + } + + @Override + public AnnotationElement newAnnotation(Type annotationType, List values, boolean boot) { + return new AnnotationElement(annotationType, values, boot); + } + + @Override + public ValueDescriptor newValueDescriptor(String name, Type fieldType, List annos, int dimension, boolean constantPool, String fieldName) { + return new ValueDescriptor(fieldType, name, annos, dimension, constantPool, fieldName); + } + + @Override + public PlatformRecording getPlatformRecording(Recording r) { + return r.getInternal(); + } + + @Override + public PlatformEventType getPlatformEventType(EventType eventType) { + return eventType.getPlatformEventType(); + } + + @Override + public boolean isConstantPool(ValueDescriptor v) { + return v.isConstantPool(); + } + + @Override + public void setAnnotations(ValueDescriptor v, List a) { + v.setAnnotations(a); + } + + @Override + public void setAnnotations(SettingDescriptor s, List a) { + s.setAnnotations(a); + } + + @Override + public String getFieldName(ValueDescriptor v) { + return v.getJavaFieldName(); + } + + @Override + public ValueDescriptor newValueDescriptor(Class type, String name) { + return new ValueDescriptor(type, name, List.of(), true); + } + + @Override + public SettingDescriptor newSettingDescriptor(Type type, String name, String defaultValue, List annotations) { + return new SettingDescriptor(type, name, defaultValue, annotations); + } + + @Override + public boolean isUnsigned(ValueDescriptor v) { + return v.isUnsigned(); + } + + @Override + public PlatformRecorder getPlatformRecorder() { + return FlightRecorder.getFlightRecorder().getInternal(); + } + + @Override + public EventSettings newEventSettings(EventSettingsModifier esm) { + return new EventSettings.DelegatedEventSettings(esm); + } + + @Override + public boolean isVisible(EventType t) { + return t.isVisible(); + } + } + // Used to provide EventSettings for jdk.management.jfr module static class DelegatedEventSettings extends EventSettings { private final EventSettingsModifier delegate; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java index 67e844ac269..8b0d7f42279 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java @@ -25,21 +25,12 @@ package jdk.jfr; -import java.util.List; -import java.util.Map; import java.util.Objects; -import jdk.jfr.internal.PlatformEventType; -import jdk.jfr.internal.PlatformRecorder; -import jdk.jfr.internal.PlatformRecording; -import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.Type; -import jdk.jfr.internal.management.EventSettingsModifier; - /** * Permission for controlling access to Flight Recorder. * - * @apiNote + * @deprecated * This permission cannot be used for controlling access to resources * as the Security Manager is no longer supported. * @@ -53,118 +44,8 @@ import jdk.jfr.internal.management.EventSettingsModifier; * */ @SuppressWarnings("serial") +@Deprecated(since="25", forRemoval=true) public final class FlightRecorderPermission extends java.security.BasicPermission { - - // Purpose of InternalAccess is to give classes in jdk.jfr.internal - // access to package private methods in this package (jdk.jfr). - // - // The initialization could be done in any class in this package, - // but this one was chosen because it is light weight and - // lacks dependencies on other public classes. - static { - PrivateAccess.setPrivateAccess(new InternalAccess()); - } - - private static final class InternalAccess extends PrivateAccess { - - @Override - public Type getType(Object o) { - if (o instanceof AnnotationElement ae) { - return ae.getType(); - } - if (o instanceof EventType et) { - return et.getType(); - } - if (o instanceof ValueDescriptor vd) { - return vd.getType(); - } - if (o instanceof SettingDescriptor sd) { - return sd.getType(); - } - throw new Error("Unknown type " + o.getClass()); - } - - @Override - public Configuration newConfiguration(String name, String label, String description, String provider, Map settings, String contents) { - return new Configuration(name, label, description, provider, settings, contents); - } - - @Override - public EventType newEventType(PlatformEventType platformEventType) { - return new EventType(platformEventType); - } - - @Override - public AnnotationElement newAnnotation(Type annotationType, List values, boolean boot) { - return new AnnotationElement(annotationType, values, boot); - } - - @Override - public ValueDescriptor newValueDescriptor(String name, Type fieldType, List annos, int dimension, boolean constantPool, String fieldName) { - return new ValueDescriptor(fieldType, name, annos, dimension, constantPool, fieldName); - } - - @Override - public PlatformRecording getPlatformRecording(Recording r) { - return r.getInternal(); - } - - @Override - public PlatformEventType getPlatformEventType(EventType eventType) { - return eventType.getPlatformEventType(); - } - - @Override - public boolean isConstantPool(ValueDescriptor v) { - return v.isConstantPool(); - } - - @Override - public void setAnnotations(ValueDescriptor v, List a) { - v.setAnnotations(a); - } - - @Override - public void setAnnotations(SettingDescriptor s, List a) { - s.setAnnotations(a); - } - - @Override - public String getFieldName(ValueDescriptor v) { - return v.getJavaFieldName(); - } - - @Override - public ValueDescriptor newValueDescriptor(Class type, String name) { - return new ValueDescriptor(type, name, List.of(), true); - } - - @Override - public SettingDescriptor newSettingDescriptor(Type type, String name, String defaultValue, List annotations) { - return new SettingDescriptor(type, name, defaultValue, annotations); - } - - @Override - public boolean isUnsigned(ValueDescriptor v) { - return v.isUnsigned(); - } - - @Override - public PlatformRecorder getPlatformRecorder() { - return FlightRecorder.getFlightRecorder().getInternal(); - } - - @Override - public EventSettings newEventSettings(EventSettingsModifier esm) { - return new EventSettings.DelegatedEventSettings(esm); - } - - @Override - public boolean isVisible(EventType t) { - return t.isVisible(); - } - } - /** * Constructs a {@code FlightRecorderPermission} with the specified name. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java index e9945f71158..95dbd0986dc 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java @@ -56,9 +56,9 @@ public abstract class PrivateAccess { // deadlock with FlightRecorderPermission. if (instance == null) { // Will trigger - // FlightRecorderPermission. + // EventSettings. // which will call PrivateAccess.setPrivateAccess - new FlightRecorderPermission("accessFlightRecorder"); + SecuritySupport.ensureClassIsInitialized(EventSettings.class); } return instance; } From 73c8c755ea638c09147d28080646ee8887ee8283 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 10 Apr 2025 07:54:00 +0000 Subject: [PATCH 105/843] 8351157: Clean up x86 GC barriers after 32-bit x86 removal Reviewed-by: kbarrett, wkemper, tschatzl --- src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 2 +- .../x86/gc/g1/g1BarrierSetAssembler_x86.cpp | 103 ++------ .../x86/gc/g1/g1BarrierSetAssembler_x86.hpp | 6 +- src/hotspot/cpu/x86/gc/g1/g1_x86_64.ad | 4 +- .../x86/gc/shared/barrierSetAssembler_x86.cpp | 113 +-------- .../x86/gc/shared/barrierSetAssembler_x86.hpp | 8 +- .../x86/gc/shared/barrierSetNMethod_x86.cpp | 37 --- .../cardTableBarrierSetAssembler_x86.cpp | 12 - .../shared/modRefBarrierSetAssembler_x86.cpp | 16 +- .../c1/shenandoahBarrierSetC1_x86.cpp | 5 +- .../shenandoahBarrierSetAssembler_x86.cpp | 230 +++--------------- .../shenandoahBarrierSetAssembler_x86.hpp | 4 +- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp | 5 +- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp | 3 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 32 ++- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 9 +- src/hotspot/cpu/x86/methodHandles_x86.cpp | 12 +- src/hotspot/cpu/x86/stubGenerator_x86_64.cpp | 2 +- .../x86/templateInterpreterGenerator_x86.cpp | 2 +- src/hotspot/cpu/x86/templateTable_x86.cpp | 54 ++-- 20 files changed, 117 insertions(+), 542 deletions(-) diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index dd8c075cb87..66defb59702 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -147,7 +147,7 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_ // Defines obj, preserves var_size_in_bytes void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) { if (UseTLAB) { - tlab_allocate(noreg, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); + tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); } else { jmp(slow_case); } diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp index 4aa02c4d627..bc5d6a233d3 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp @@ -49,11 +49,7 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; if (!dest_uninitialized) { - Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); -#ifndef _LP64 - __ push(thread); - __ get_thread(thread); -#endif + Register thread = r15_thread; Label filtered; Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); @@ -65,12 +61,9 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm __ cmpb(in_progress, 0); } - NOT_LP64(__ pop(thread);) - __ jcc(Assembler::equal, filtered); __ push_call_clobbered_registers(false /* save_fpu */); -#ifdef _LP64 if (count == c_rarg0) { if (addr == c_rarg1) { // exactly backwards!! @@ -88,10 +81,6 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm } else { __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), 2); } -#else - __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), - addr, count); -#endif __ pop_call_clobbered_registers(false /* save_fpu */); __ bind(filtered); @@ -101,7 +90,6 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) { __ push_call_clobbered_registers(false /* save_fpu */); -#ifdef _LP64 if (c_rarg0 == count) { // On win64 c_rarg0 == rcx assert_different_registers(c_rarg1, addr); __ mov(c_rarg1, count); @@ -112,53 +100,26 @@ void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* mas __ mov(c_rarg1, count); } __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2); -#else - __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), - addr, count); -#endif __ pop_call_clobbered_registers(false /* save_fpu */); + } void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Register dst, Address src, Register tmp1, Register tmp_thread) { + Register dst, Address src, Register tmp1) { bool on_oop = is_reference_type(type); bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; bool on_reference = on_weak || on_phantom; - ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1); if (on_oop && on_reference) { - Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); - -#ifndef _LP64 - // Work around the x86_32 bug that only manifests with Loom for some reason. - // MacroAssembler::resolve_weak_handle calls this barrier with tmp_thread == noreg. - if (thread == noreg) { - if (dst != rcx && tmp1 != rcx) { - thread = rcx; - } else if (dst != rdx && tmp1 != rdx) { - thread = rdx; - } else if (dst != rdi && tmp1 != rdi) { - thread = rdi; - } - } - assert_different_registers(dst, tmp1, thread); - __ push(thread); - __ get_thread(thread); -#endif - // Generate the G1 pre-barrier code to log the value of // the referent field in an SATB buffer. g1_write_barrier_pre(masm /* masm */, noreg /* obj */, dst /* pre_val */, - thread /* thread */, tmp1 /* tmp */, true /* tosca_live */, true /* expand_call */); - -#ifndef _LP64 - __ pop(thread); -#endif } } @@ -199,7 +160,7 @@ static void generate_pre_barrier_slow_path(MacroAssembler* masm, Label& runtime) { // Do we need to load the previous value? if (obj != noreg) { - __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW); + __ load_heap_oop(pre_val, Address(obj, 0), noreg, AS_RAW); } // Is the previous value null? __ cmpptr(pre_val, NULL_WORD); @@ -215,7 +176,6 @@ static void generate_pre_barrier_slow_path(MacroAssembler* masm, void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, bool tosca_live, bool expand_call) { @@ -223,9 +183,7 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, // directly to skip generating the check by // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. -#ifdef _LP64 - assert(thread == r15_thread, "must be"); -#endif // _LP64 + const Register thread = r15_thread; Label done; Label runtime; @@ -260,18 +218,13 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, // expand_call should be passed true. if (expand_call) { - LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) -#ifdef _LP64 + assert(pre_val != c_rarg1, "smashed arg"); if (c_rarg1 != thread) { __ mov(c_rarg1, thread); } if (c_rarg0 != pre_val) { __ mov(c_rarg0, pre_val); } -#else - __ push(thread); - __ push(pre_val); -#endif __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2); } else { __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); @@ -333,12 +286,9 @@ static void generate_post_barrier_slow_path(MacroAssembler* masm, void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, - Register thread, Register tmp, Register tmp2) { -#ifdef _LP64 - assert(thread == r15_thread, "must be"); -#endif // _LP64 + const Register thread = r15_thread; Label done; Label runtime; @@ -350,7 +300,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, __ bind(runtime); // save the live input values - RegSet saved = RegSet::of(store_addr NOT_LP64(COMMA thread)); + RegSet saved = RegSet::of(store_addr); __ push_set(saved); __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), tmp, thread); __ pop_set(saved); @@ -361,7 +311,6 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, #if defined(COMPILER2) static void generate_c2_barrier_runtime_call(MacroAssembler* masm, G1BarrierStubC2* stub, const Register arg, const address runtime_path) { -#ifdef _LP64 SaveLiveRegisters save_registers(masm, stub); if (c_rarg0 != arg) { __ mov(c_rarg0, arg); @@ -373,20 +322,15 @@ static void generate_c2_barrier_runtime_call(MacroAssembler* masm, G1BarrierStub // call. If it did not contain any live value, it is free to be used. In // either case, it is safe to use it here as a call scratch register. __ call(RuntimeAddress(runtime_path), rax); -#else - Unimplemented(); -#endif // _LP64 } void G1BarrierSetAssembler::g1_write_barrier_pre_c2(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, G1PreBarrierStubC2* stub) { -#ifdef _LP64 - assert(thread == r15_thread, "must be"); -#endif // _LP64 + const Register thread = r15_thread; + assert(pre_val != noreg, "check this code"); if (obj != noreg) { assert_different_registers(obj, pre_val, tmp); @@ -422,14 +366,10 @@ void G1BarrierSetAssembler::generate_c2_pre_barrier_stub(MacroAssembler* masm, void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm, Register store_addr, Register new_val, - Register thread, Register tmp, Register tmp2, G1PostBarrierStubC2* stub) { -#ifdef _LP64 - assert(thread == r15_thread, "must be"); -#endif // _LP64 - + const Register thread = r15_thread; stub->initialize_registers(thread, tmp, tmp2); bool new_val_may_be_null = (stub->barrier_data() & G1C2BarrierPostNotNull) == 0; @@ -467,7 +407,6 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco bool needs_pre_barrier = as_normal; bool needs_post_barrier = val != noreg && in_heap; - Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); // flatten object address if needed // We do it regardless of precise because we need the registers if (dst.index() == noreg && dst.disp() == 0) { @@ -478,18 +417,10 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco __ lea(tmp1, dst); } -#ifndef _LP64 - InterpreterMacroAssembler *imasm = static_cast(masm); -#endif - - NOT_LP64(__ get_thread(rcx)); - NOT_LP64(imasm->save_bcp()); - if (needs_pre_barrier) { g1_write_barrier_pre(masm /*masm*/, tmp1 /* obj */, tmp2 /* pre_val */, - rthread /* thread */, tmp3 /* tmp */, val != noreg /* tosca_live */, false /* expand_call */); @@ -510,12 +441,10 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco g1_write_barrier_post(masm /*masm*/, tmp1 /* store_adr */, new_val /* new_val */, - rthread /* thread */, tmp3 /* tmp */, tmp2 /* tmp2 */); } } - NOT_LP64(imasm->restore_bcp()); } #ifdef COMPILER1 @@ -575,11 +504,9 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* __ push(rdx); const Register pre_val = rax; - const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); + const Register thread = r15_thread; const Register tmp = rdx; - NOT_LP64(__ get_thread(thread);) - Address queue_active(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); Address queue_index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset())); Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())); @@ -641,7 +568,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* // At this point we know new_value is non-null and the new_value crosses regions. // Must check to see if card is already dirty - const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); + const Register thread = r15_thread; Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset())); Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())); @@ -659,8 +586,6 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base()); __ addptr(card_addr, cardtable); - NOT_LP64(__ get_thread(thread);) - __ cmpb(Address(card_addr, 0), G1CardTable::g1_young_card_val()); __ jcc(Assembler::equal, done); diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp index 237786a84d2..774e87b916c 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp @@ -44,7 +44,6 @@ class G1BarrierSetAssembler: public ModRefBarrierSetAssembler { void g1_write_barrier_pre(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, bool tosca_live, bool expand_call); @@ -52,7 +51,6 @@ class G1BarrierSetAssembler: public ModRefBarrierSetAssembler { void g1_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, - Register thread, Register tmp, Register tmp2); @@ -67,13 +65,12 @@ class G1BarrierSetAssembler: public ModRefBarrierSetAssembler { void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm); virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Register dst, Address src, Register tmp1, Register tmp_thread); + Register dst, Address src, Register tmp1); #ifdef COMPILER2 void g1_write_barrier_pre_c2(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, G1PreBarrierStubC2* c2_stub); void generate_c2_pre_barrier_stub(MacroAssembler* masm, @@ -81,7 +78,6 @@ class G1BarrierSetAssembler: public ModRefBarrierSetAssembler { void g1_write_barrier_post_c2(MacroAssembler* masm, Register store_addr, Register new_val, - Register thread, Register tmp, Register tmp2, G1PostBarrierStubC2* c2_stub); diff --git a/src/hotspot/cpu/x86/gc/g1/g1_x86_64.ad b/src/hotspot/cpu/x86/gc/g1/g1_x86_64.ad index 8c1559f90f4..819cd97696c 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/g1/g1_x86_64.ad @@ -52,7 +52,7 @@ static void write_barrier_pre(MacroAssembler* masm, for (RegSetIterator reg = no_preserve.begin(); *reg != noreg; ++reg) { stub->dont_preserve(*reg); } - g1_asm->g1_write_barrier_pre_c2(masm, obj, pre_val, r15_thread, tmp, stub); + g1_asm->g1_write_barrier_pre_c2(masm, obj, pre_val, tmp, stub); } static void write_barrier_post(MacroAssembler* masm, @@ -67,7 +67,7 @@ static void write_barrier_post(MacroAssembler* masm, Assembler::InlineSkippedInstructionsCounter skip_counter(masm); G1BarrierSetAssembler* g1_asm = static_cast(BarrierSet::barrier_set()->barrier_set_assembler()); G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node); - g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, r15_thread, tmp1, tmp2, stub); + g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, tmp1, tmp2, stub); } %} diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index 5962609d08e..be25326d682 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -40,7 +40,7 @@ #define __ masm-> void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Register dst, Address src, Register tmp1, Register tmp_thread) { + Register dst, Address src, Register tmp1) { bool in_heap = (decorators & IN_HEAP) != 0; bool in_native = (decorators & IN_NATIVE) != 0; bool is_not_null = (decorators & IS_NOT_NULL) != 0; @@ -50,7 +50,6 @@ void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, case T_OBJECT: case T_ARRAY: { if (in_heap) { -#ifdef _LP64 if (UseCompressedOops) { __ movl(dst, src); if (is_not_null) { @@ -58,9 +57,7 @@ void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, } else { __ decode_heap_oop(dst); } - } else -#endif - { + } else { __ movptr(dst, src); } } else { @@ -85,20 +82,7 @@ void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, break; case T_LONG: assert(dst == noreg, "only to ltos"); -#ifdef _LP64 __ movq(rax, src); -#else - if (atomic) { - __ fild_d(src); // Must load atomically - __ subptr(rsp,2*wordSize); // Make space for store - __ fistp_d(Address(rsp,0)); - __ pop(rax); - __ pop(rdx); - } else { - __ movl(rax, src); - __ movl(rdx, src.plus_disp(wordSize)); - } -#endif break; default: Unimplemented(); } @@ -117,17 +101,12 @@ void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators if (in_heap) { if (val == noreg) { assert(!is_not_null, "inconsistent access"); -#ifdef _LP64 if (UseCompressedOops) { __ movl(dst, NULL_WORD); } else { __ movslq(dst, NULL_WORD); } -#else - __ movl(dst, NULL_WORD); -#endif } else { -#ifdef _LP64 if (UseCompressedOops) { assert(!dst.uses(val), "not enough registers"); if (is_not_null) { @@ -136,9 +115,7 @@ void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators __ encode_heap_oop(val); } __ movl(dst, val); - } else -#endif - { + } else { __ movptr(dst, val); } } @@ -167,20 +144,7 @@ void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators break; case T_LONG: assert(val == noreg, "only tos"); -#ifdef _LP64 __ movq(dst, rax); -#else - if (atomic) { - __ push(rdx); - __ push(rax); // Must update atomically with FIST - __ fild_d(Address(rsp,0)); // So load into FPU register - __ fistp_d(dst); // and put into memory atomically - __ addptr(rsp, 2*wordSize); - } else { - __ movptr(dst, rax); - __ movptr(dst.plus_disp(wordSize), rdx); - } -#endif break; case T_FLOAT: assert(val == noreg, "only tos"); @@ -216,20 +180,14 @@ void BarrierSetAssembler::copy_load_at(MacroAssembler* masm, __ movl(dst, src); break; case 8: -#ifdef _LP64 __ movq(dst, src); -#else - fatal("No support for 8 bytes copy"); -#endif break; default: fatal("Unexpected size"); } -#ifdef _LP64 if ((decorators & ARRAYCOPY_CHECKCAST) != 0 && UseCompressedOops) { __ decode_heap_oop(dst); } -#endif } void BarrierSetAssembler::copy_store_at(MacroAssembler* masm, @@ -239,11 +197,9 @@ void BarrierSetAssembler::copy_store_at(MacroAssembler* masm, Address dst, Register src, Register tmp) { -#ifdef _LP64 if ((decorators & ARRAYCOPY_CHECKCAST) != 0 && UseCompressedOops) { __ encode_heap_oop(src); } -#endif assert(bytes <= 8, "can only deal with non-vector registers"); switch (bytes) { case 1: @@ -256,11 +212,7 @@ void BarrierSetAssembler::copy_store_at(MacroAssembler* masm, __ movl(dst, src); break; case 8: -#ifdef _LP64 __ movq(dst, src); -#else - fatal("No support for 8 bytes copy"); -#endif break; default: fatal("Unexpected size"); @@ -311,7 +263,7 @@ void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Re } void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, - Register thread, Register obj, + Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, @@ -320,15 +272,8 @@ void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, assert_different_registers(obj, t1, t2); assert_different_registers(obj, var_size_in_bytes, t1); Register end = t2; - if (!thread->is_valid()) { -#ifdef _LP64 - thread = r15_thread; -#else - assert(t1->is_valid(), "need temp reg"); - thread = t1; - __ get_thread(thread); -#endif - } + + const Register thread = r15_thread; __ verify_tlab(); @@ -351,7 +296,6 @@ void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, __ verify_tlab(); } -#ifdef _LP64 void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slow_path, Label* continuation) { BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); Register thread = r15_thread; @@ -375,35 +319,14 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo __ bind(done); } } -#else -void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label*, Label*) { - BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); - Label continuation; - - Register tmp = rdi; - __ push(tmp); - __ movptr(tmp, (intptr_t)bs_nm->disarmed_guard_value_address()); - Address disarmed_addr(tmp, 0); - __ align(4); - __ cmpl_imm32(disarmed_addr, 0); - __ pop(tmp); - __ jcc(Assembler::equal, continuation); - __ call(RuntimeAddress(StubRoutines::method_entry_barrier())); - __ bind(continuation); -} -#endif void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { Label bad_call; __ cmpptr(rbx, 0); // rbx contains the incoming method for c2i adapters. __ jcc(Assembler::equal, bad_call); - Register tmp1 = LP64_ONLY( rscratch1 ) NOT_LP64( rax ); - Register tmp2 = LP64_ONLY( rscratch2 ) NOT_LP64( rcx ); -#ifndef _LP64 - __ push(tmp1); - __ push(tmp2); -#endif // !_LP64 + Register tmp1 = rscratch1; + Register tmp2 = rscratch2; // Pointer chase to the method holder to find out if the method is concurrently unloading. Label method_live; @@ -419,19 +342,9 @@ void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { __ cmpptr(tmp1, 0); __ jcc(Assembler::notEqual, method_live); -#ifndef _LP64 - __ pop(tmp2); - __ pop(tmp1); -#endif - __ bind(bad_call); __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); __ bind(method_live); - -#ifndef _LP64 - __ pop(tmp2); - __ pop(tmp1); -#endif } void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error) { @@ -451,8 +364,6 @@ void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register #ifdef COMPILER2 -#ifdef _LP64 - OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { if (!OptoReg::is_reg(opto_reg)) { return OptoReg::Bad; @@ -728,12 +639,4 @@ SaveLiveRegisters::~SaveLiveRegisters() { } } -#else // !_LP64 - -OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { - Unimplemented(); // This must be implemented to support late barrier expansion. -} - -#endif // _LP64 - #endif // COMPILER2 diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp index 5dde1c7aeed..fd52379d2e2 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp @@ -44,7 +44,7 @@ public: Register src, Register dst, Register count) {} virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Register dst, Address src, Register tmp1, Register tmp_thread); + Register dst, Address src, Register tmp1); virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); @@ -93,7 +93,7 @@ public: Register obj, Register tmp, Label& slowpath); virtual void tlab_allocate(MacroAssembler* masm, - Register thread, Register obj, + Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, @@ -114,8 +114,6 @@ public: #ifdef COMPILER2 -#ifdef _LP64 - // This class saves and restores the registers that need to be preserved across // the runtime call represented by a given C2 barrier stub. Use as follows: // { @@ -160,8 +158,6 @@ public: ~SaveLiveRegisters(); }; -#endif // _LP64 - #endif // COMPILER2 #endif // CPU_X86_GC_SHARED_BARRIERSETASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp index e99774cbc40..c27af4a29cd 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetNMethod_x86.cpp @@ -39,7 +39,6 @@ class NativeNMethodCmpBarrier: public NativeInstruction { public: -#ifdef _LP64 enum Intel_specific_constants { instruction_code = 0x81, instruction_size = 8, @@ -47,14 +46,6 @@ public: instruction_rex_prefix = Assembler::REX | Assembler::REX_B, instruction_modrm = 0x7f // [r15 + offset] }; -#else - enum Intel_specific_constants { - instruction_code = 0x81, - instruction_size = 7, - imm_offset = 2, - instruction_modrm = 0x3f // [rdi] - }; -#endif address instruction_address() const { return addr_at(0); } address immediate_address() const { return addr_at(imm_offset); } @@ -70,7 +61,6 @@ public: } }; -#ifdef _LP64 bool NativeNMethodCmpBarrier::check_barrier(err_msg& msg) const { // Only require 4 byte alignment if (((uintptr_t) instruction_address()) & 0x3) { @@ -97,29 +87,6 @@ bool NativeNMethodCmpBarrier::check_barrier(err_msg& msg) const { } return true; } -#else -bool NativeNMethodCmpBarrier::check_barrier(err_msg& msg) const { - if (((uintptr_t) instruction_address()) & 0x3) { - msg.print("Addr: " INTPTR_FORMAT " not properly aligned", p2i(instruction_address())); - return false; - } - - int inst = ubyte_at(0); - if (inst != instruction_code) { - msg.print("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()), - inst); - return false; - } - - int modrm = ubyte_at(1); - if (modrm != instruction_modrm) { - msg.print("Addr: " INTPTR_FORMAT " mod/rm: 0x%x", p2i(instruction_address()), - modrm); - return false; - } - return true; -} -#endif // _LP64 void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { /* @@ -169,15 +136,11 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { // not find the expected native instruction at this offset, which needs updating. // Note that this offset is invariant of PreserveFramePointer. static int entry_barrier_offset(nmethod* nm) { -#ifdef _LP64 if (nm->is_compiled_by_c2()) { return -14; } else { return -15; } -#else - return -18; -#endif } static NativeNMethodCmpBarrier* native_nmethod_barrier(nmethod* nm) { diff --git a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp index 81284323e39..ba89b09e4dc 100644 --- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp @@ -57,7 +57,6 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ jcc(Assembler::zero, L_done); // zero count - nothing to do -#ifdef _LP64 __ leaq(end, Address(addr, count, TIMES_OOP, 0)); // end == addr+count*oop_size __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive __ shrptr(addr, CardTable::card_shift()); @@ -70,17 +69,6 @@ __ BIND(L_loop); __ movb(Address(addr, count, Address::times_1), 0); __ decrement(count); __ jcc(Assembler::greaterEqual, L_loop); -#else - __ lea(end, Address(addr, count, Address::times_ptr, -wordSize)); - __ shrptr(addr, CardTable::card_shift()); - __ shrptr(end, CardTable::card_shift()); - __ subptr(end, addr); // end --> count -__ BIND(L_loop); - Address cardtable(addr, count, Address::times_1, disp); - __ movb(cardtable, 0); - __ decrement(count); - __ jcc(Assembler::greaterEqual, L_loop); -#endif __ BIND(L_done); } diff --git a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp index 76066409a7c..42109b069f2 100644 --- a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp @@ -31,10 +31,9 @@ void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Decorat Register src, Register dst, Register count) { bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; - bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); + bool obj_int = (type == T_OBJECT) && UseCompressedOops; if (is_reference_type(type)) { -#ifdef _LP64 if (!checkcast) { if (!obj_int) { // Save count for barrier @@ -44,11 +43,6 @@ void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Decorat __ movq(r11, dst); } } -#else - if (disjoint) { - __ mov(rdx, dst); // save 'to' - } -#endif gen_write_ref_array_pre_barrier(masm, decorators, dst, count); } } @@ -57,11 +51,10 @@ void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Decorat Register src, Register dst, Register count) { bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; - bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); + bool obj_int = (type == T_OBJECT) && UseCompressedOops; Register tmp = rax; if (is_reference_type(type)) { -#ifdef _LP64 if (!checkcast) { if (!obj_int) { // Save count for barrier @@ -73,11 +66,6 @@ void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Decorat } else { tmp = rscratch1; } -#else - if (disjoint) { - __ mov(dst, rdx); // restore 'to' - } -#endif gen_write_ref_array_post_barrier(masm, decorators, dst, count, tmp); } } diff --git a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp index 063f4c2cc5d..298e5640b27 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp @@ -33,7 +33,6 @@ #define __ masm->masm()-> void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler* masm) { - NOT_LP64(assert(_addr->is_single_cpu(), "must be single");) Register addr = _addr->is_single_cpu() ? _addr->as_register() : _addr->as_register_lo(); Register newval = _new_value->as_register(); Register cmpval = _cmp_value->as_register(); @@ -46,14 +45,12 @@ void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler* masm) { assert(cmpval != addr, "cmp and addr must be in different registers"); assert(newval != addr, "new value and addr must be in different registers"); -#ifdef _LP64 if (UseCompressedOops) { __ encode_heap_oop(cmpval); __ mov(rscratch1, newval); __ encode_heap_oop(rscratch1); newval = rscratch1; } -#endif ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), result, Address(addr, 0), cmpval, newval, false, tmp1, tmp2); } @@ -105,7 +102,7 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRIt // Because we want a 2-arg form of xchg and xadd __ move(value_opr, result); - assert(type == T_INT || is_reference_type(type) LP64_ONLY( || type == T_LONG ), "unexpected type"); + assert(type == T_INT || is_reference_type(type) || type == T_LONG, "unexpected type"); __ xchg(access.resolved_addr(), result, result, LIR_OprFact::illegalOpr); if (access.is_oop()) { diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index a33ec611f55..6e1596a0e4b 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -51,10 +51,10 @@ static void save_machine_state(MacroAssembler* masm, bool handle_gpr, bool handl if (handle_fp) { // Some paths can be reached from the c2i adapter with live fp arguments in registers. - LP64_ONLY(assert(Argument::n_float_register_parameters_j == 8, "8 fp registers to save at java call")); + assert(Argument::n_float_register_parameters_j == 8, "8 fp registers to save at java call"); if (UseSSE >= 2) { - const int xmm_size = wordSize * LP64_ONLY(2) NOT_LP64(4); + const int xmm_size = wordSize * 2; __ subptr(rsp, xmm_size * 8); __ movdbl(Address(rsp, xmm_size * 0), xmm0); __ movdbl(Address(rsp, xmm_size * 1), xmm1); @@ -65,7 +65,7 @@ static void save_machine_state(MacroAssembler* masm, bool handle_gpr, bool handl __ movdbl(Address(rsp, xmm_size * 6), xmm6); __ movdbl(Address(rsp, xmm_size * 7), xmm7); } else if (UseSSE >= 1) { - const int xmm_size = wordSize * LP64_ONLY(1) NOT_LP64(2); + const int xmm_size = wordSize * 1; __ subptr(rsp, xmm_size * 8); __ movflt(Address(rsp, xmm_size * 0), xmm0); __ movflt(Address(rsp, xmm_size * 1), xmm1); @@ -84,7 +84,7 @@ static void save_machine_state(MacroAssembler* masm, bool handle_gpr, bool handl static void restore_machine_state(MacroAssembler* masm, bool handle_gpr, bool handle_fp) { if (handle_fp) { if (UseSSE >= 2) { - const int xmm_size = wordSize * LP64_ONLY(2) NOT_LP64(4); + const int xmm_size = wordSize * 2; __ movdbl(xmm0, Address(rsp, xmm_size * 0)); __ movdbl(xmm1, Address(rsp, xmm_size * 1)); __ movdbl(xmm2, Address(rsp, xmm_size * 2)); @@ -95,7 +95,7 @@ static void restore_machine_state(MacroAssembler* masm, bool handle_gpr, bool ha __ movdbl(xmm7, Address(rsp, xmm_size * 7)); __ addptr(rsp, xmm_size * 8); } else if (UseSSE >= 1) { - const int xmm_size = wordSize * LP64_ONLY(1) NOT_LP64(2); + const int xmm_size = wordSize * 1; __ movflt(xmm0, Address(rsp, xmm_size * 0)); __ movflt(xmm1, Address(rsp, xmm_size * 1)); __ movflt(xmm2, Address(rsp, xmm_size * 2)); @@ -124,11 +124,10 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec if (ShenandoahCardBarrier) { bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; - bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); + bool obj_int = (type == T_OBJECT) && UseCompressedOops; // We need to save the original element count because the array copy stub // will destroy the value and we need it for the card marking barrier. -#ifdef _LP64 if (!checkcast) { if (!obj_int) { // Save count for barrier @@ -138,30 +137,10 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec __ movq(r11, dst); } } -#else - if (disjoint) { - __ mov(rdx, dst); // save 'to' - } -#endif } if ((ShenandoahSATBBarrier && !dest_uninitialized) || ShenandoahLoadRefBarrier) { -#ifdef _LP64 Register thread = r15_thread; -#else - Register thread = rax; - if (thread == src || thread == dst || thread == count) { - thread = rbx; - } - if (thread == src || thread == dst || thread == count) { - thread = rcx; - } - if (thread == src || thread == dst || thread == count) { - thread = rdx; - } - __ push(thread); - __ get_thread(thread); -#endif assert_different_registers(src, dst, count, thread); Label L_done; @@ -182,16 +161,13 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec save_machine_state(masm, /* handle_gpr = */ true, /* handle_fp = */ false); -#ifdef _LP64 assert(src == rdi, "expected"); assert(dst == rsi, "expected"); assert(count == rdx, "expected"); if (UseCompressedOops) { __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop), src, dst, count); - } else -#endif - { + } else { __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop), src, dst, count); } @@ -199,7 +175,6 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec restore_machine_state(masm, /* handle_gpr = */ true, /* handle_fp = */ false); __ bind(L_done); - NOT_LP64(__ pop(thread);) } } @@ -211,10 +186,9 @@ void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Dec if (ShenandoahCardBarrier && is_reference_type(type)) { bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; - bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); + bool obj_int = (type == T_OBJECT) && UseCompressedOops; Register tmp = rax; -#ifdef _LP64 if (!checkcast) { if (!obj_int) { // Save count for barrier @@ -226,11 +200,6 @@ void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Dec } else { tmp = rscratch1; } -#else - if (disjoint) { - __ mov(dst, rdx); // restore 'to' - } -#endif gen_write_ref_array_post_barrier(masm, decorators, dst, count, tmp); } } @@ -238,20 +207,18 @@ void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Dec void ShenandoahBarrierSetAssembler::shenandoah_write_barrier_pre(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, bool tosca_live, bool expand_call) { if (ShenandoahSATBBarrier) { - satb_write_barrier_pre(masm, obj, pre_val, thread, tmp, tosca_live, expand_call); + satb_write_barrier_pre(masm, obj, pre_val, tmp, tosca_live, expand_call); } } void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, bool tosca_live, bool expand_call) { @@ -259,9 +226,7 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, // directly to skip generating the check by // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. -#ifdef _LP64 - assert(thread == r15_thread, "must be"); -#endif // _LP64 + const Register thread = r15_thread; Label done; Label runtime; @@ -282,7 +247,7 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, // Do we need to load the previous value? if (obj != noreg) { - __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW); + __ load_heap_oop(pre_val, Address(obj, 0), noreg, AS_RAW); } // Is the previous value null? @@ -327,9 +292,6 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, // So when we do not have have a full interpreter frame on the stack // expand_call should be passed true. - NOT_LP64( __ push(thread); ) - -#ifdef _LP64 // We move pre_val into c_rarg0 early, in order to avoid smashing it, should // pre_val be c_rarg1 (where the call prologue would copy thread argument). // Note: this should not accidentally smash thread, because thread is always r15. @@ -337,26 +299,18 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, if (c_rarg0 != pre_val) { __ mov(c_rarg0, pre_val); } -#endif if (expand_call) { - LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) -#ifdef _LP64 + assert(pre_val != c_rarg1, "smashed arg"); if (c_rarg1 != thread) { __ mov(c_rarg1, thread); } // Already moved pre_val into c_rarg0 above -#else - __ push(thread); - __ push(pre_val); -#endif __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), 2); } else { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), LP64_ONLY(c_rarg0) NOT_LP64(pre_val), thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), c_rarg0, thread); } - NOT_LP64( __ pop(thread); ) - // save the live input values if (pre_val != rax) __ pop(pre_val); @@ -383,16 +337,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, __ block_comment("load_reference_barrier { "); // Check if GC is active -#ifdef _LP64 Register thread = r15_thread; -#else - Register thread = rcx; - if (thread == dst) { - thread = rbx; - } - __ push(thread); - __ get_thread(thread); -#endif Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); int flags = ShenandoahHeap::HAS_FORWARDED; @@ -438,7 +383,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, // The rest is saved with the optimized path - uint num_saved_regs = 4 + (dst != rax ? 1 : 0) LP64_ONLY(+4); + uint num_saved_regs = 4 + (dst != rax ? 1 : 0) + 4; __ subptr(rsp, num_saved_regs * wordSize); uint slot = num_saved_regs; if (dst != rax) { @@ -448,21 +393,15 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, __ movptr(Address(rsp, (--slot) * wordSize), rdx); __ movptr(Address(rsp, (--slot) * wordSize), rdi); __ movptr(Address(rsp, (--slot) * wordSize), rsi); -#ifdef _LP64 __ movptr(Address(rsp, (--slot) * wordSize), r8); __ movptr(Address(rsp, (--slot) * wordSize), r9); __ movptr(Address(rsp, (--slot) * wordSize), r10); __ movptr(Address(rsp, (--slot) * wordSize), r11); // r12-r15 are callee saved in all calling conventions -#endif assert(slot == 0, "must use all slots"); // Shuffle registers such that dst is in c_rarg0 and addr in c_rarg1. -#ifdef _LP64 Register arg0 = c_rarg0, arg1 = c_rarg1; -#else - Register arg0 = rdi, arg1 = rsi; -#endif if (dst == arg1) { __ lea(arg0, src); __ xchgptr(arg1, arg0); @@ -489,12 +428,10 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom), arg0, arg1); } -#ifdef _LP64 __ movptr(r11, Address(rsp, (slot++) * wordSize)); __ movptr(r10, Address(rsp, (slot++) * wordSize)); __ movptr(r9, Address(rsp, (slot++) * wordSize)); __ movptr(r8, Address(rsp, (slot++) * wordSize)); -#endif __ movptr(rsi, Address(rsp, (slot++) * wordSize)); __ movptr(rdi, Address(rsp, (slot++) * wordSize)); __ movptr(rdx, Address(rsp, (slot++) * wordSize)); @@ -520,10 +457,6 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, __ bind(heap_stable); __ block_comment("} load_reference_barrier"); - -#ifndef _LP64 - __ pop(thread); -#endif } // @@ -540,10 +473,10 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, // tmp1 (if it is valid) // void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Register dst, Address src, Register tmp1, Register tmp_thread) { + Register dst, Address src, Register tmp1) { // 1: non-reference load, no additional barrier is needed if (!is_reference_type(type)) { - BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1); return; } @@ -567,7 +500,7 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d assert_different_registers(dst, src.base(), src.index()); } - BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1); load_reference_barrier(masm, dst, src, decorators); @@ -582,25 +515,19 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d dst = result_dst; } } else { - BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1); } // 3: apply keep-alive barrier if needed if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) { save_machine_state(masm, /* handle_gpr = */ true, /* handle_fp = */ true); - Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); - assert_different_registers(dst, tmp1, tmp_thread); - if (!thread->is_valid()) { - thread = rdx; - } - NOT_LP64(__ get_thread(thread)); + assert_different_registers(dst, tmp1, r15_thread); // Generate the SATB pre-barrier code to log the value of // the referent field in an SATB buffer. shenandoah_write_barrier_pre(masm /* masm */, noreg /* obj */, dst /* pre_val */, - thread /* thread */, tmp1 /* tmp */, true /* tosca_live */, true /* expand_call */); @@ -618,23 +545,8 @@ void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register o // We'll use this register as the TLS base address and also later on // to hold the byte_map_base. - Register thread = LP64_ONLY(r15_thread) NOT_LP64(rcx); - Register tmp = LP64_ONLY(rscratch1) NOT_LP64(rdx); - -#ifndef _LP64 - // The next two ifs are just to get temporary registers to use for TLS and card table base. - if (thread == obj) { - thread = rdx; - tmp = rsi; - } - if (tmp == obj) { - tmp = rsi; - } - - __ push(thread); - __ push(tmp); - __ get_thread(thread); -#endif + Register thread = r15_thread; + Register tmp = rscratch1; Address curr_ct_holder_addr(thread, in_bytes(ShenandoahThreadLocalData::card_table_offset())); __ movptr(tmp, curr_ct_holder_addr); @@ -650,11 +562,6 @@ void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register o } else { __ movb(card_addr, dirty); } - -#ifndef _LP64 - __ pop(tmp); - __ pop(thread); -#endif } void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, @@ -666,7 +573,6 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet if (on_oop && in_heap) { bool needs_pre_barrier = as_normal; - Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); // flatten object address if needed // We do it regardless of precise because we need the registers if (dst.index() == noreg && dst.disp() == 0) { @@ -677,19 +583,12 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet __ lea(tmp1, dst); } - assert_different_registers(val, tmp1, tmp2, tmp3, rthread); - -#ifndef _LP64 - __ get_thread(rthread); - InterpreterMacroAssembler *imasm = static_cast(masm); - imasm->save_bcp(); -#endif + assert_different_registers(val, tmp1, tmp2, tmp3, r15_thread); if (needs_pre_barrier) { shenandoah_write_barrier_pre(masm /*masm*/, tmp1 /* obj */, tmp2 /* pre_val */, - rthread /* thread */, tmp3 /* tmp */, val != noreg /* tosca_live */, false /* expand_call */); @@ -701,7 +600,6 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet store_check(masm, tmp1); } } - NOT_LP64(imasm->restore_bcp()); } else { BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); } @@ -736,12 +634,9 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, Label L_success, L_failure; // Remember oldval for retry logic below -#ifdef _LP64 if (UseCompressedOops) { __ movl(tmp1, oldval); - } else -#endif - { + } else { __ movptr(tmp1, oldval); } @@ -749,13 +644,10 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, // // Try to CAS with given arguments. If successful, then we are done. -#ifdef _LP64 if (UseCompressedOops) { __ lock(); __ cmpxchgl(newval, addr); - } else -#endif - { + } else { __ lock(); __ cmpxchgptr(newval, addr); } @@ -776,23 +668,15 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, __ jcc(Assembler::zero, L_failure); // Filter: when heap is stable, the failure is definitely legitimate -#ifdef _LP64 const Register thread = r15_thread; -#else - const Register thread = tmp2; - __ get_thread(thread); -#endif Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); __ testb(gc_state, ShenandoahHeap::HAS_FORWARDED); __ jcc(Assembler::zero, L_failure); -#ifdef _LP64 if (UseCompressedOops) { __ movl(tmp2, oldval); __ decode_heap_oop(tmp2); - } else -#endif - { + } else { __ movptr(tmp2, oldval); } @@ -807,11 +691,9 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, __ shrptr(tmp2, 2); __ shlptr(tmp2, 2); -#ifdef _LP64 if (UseCompressedOops) { __ decode_heap_oop(tmp1); // decode for comparison } -#endif // Now we have the forwarded offender in tmp2. // Compare and if they don't match, we have legitimate failure @@ -827,19 +709,14 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, // with to-space ptr store. We still have to do the retry, because the GC might // have updated the reference for us. -#ifdef _LP64 if (UseCompressedOops) { __ encode_heap_oop(tmp2); // previously decoded at step 2. } -#endif -#ifdef _LP64 if (UseCompressedOops) { __ lock(); __ cmpxchgl(tmp2, addr); - } else -#endif - { + } else { __ lock(); __ cmpxchgptr(tmp2, addr); } @@ -851,22 +728,16 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, // from-space ptr into memory anymore. Make sure oldval is restored, after being // garbled during retries. // -#ifdef _LP64 if (UseCompressedOops) { __ movl(oldval, tmp2); - } else -#endif - { + } else { __ movptr(oldval, tmp2); } -#ifdef _LP64 if (UseCompressedOops) { __ lock(); __ cmpxchgl(newval, addr); - } else -#endif - { + } else { __ lock(); __ cmpxchgptr(newval, addr); } @@ -918,7 +789,6 @@ void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssemb __ testl(count, count); __ jccb(Assembler::zero, L_done); -#ifdef _LP64 const Register thread = r15_thread; Address curr_ct_holder_addr(thread, in_bytes(ShenandoahThreadLocalData::card_table_offset())); __ movptr(tmp, curr_ct_holder_addr); @@ -935,26 +805,6 @@ void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssemb __ movb(Address(addr, count, Address::times_1), 0); __ decrement(count); __ jccb(Assembler::greaterEqual, L_loop); -#else - const Register thread = tmp; - __ get_thread(thread); - - Address curr_ct_holder_addr(thread, in_bytes(ShenandoahThreadLocalData::byte_map_base_offset())); - __ movptr(tmp, curr_ct_holder_addr); - - __ lea(end, Address(addr, count, Address::times_ptr, -wordSize)); - __ shrptr(addr, CardTable::card_shift()); - __ shrptr(end, CardTable::card_shift()); - __ subptr(end, addr); // end --> count - - __ addptr(addr, tmp); - - __ BIND(L_loop); - Address cardtable(addr, count, Address::times_1, 0); - __ movb(cardtable, 0); - __ decrement(count); - __ jccb(Assembler::greaterEqual, L_loop); -#endif __ BIND(L_done); } @@ -1019,15 +869,8 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble __ mov(tmp1, res); __ shrptr(tmp1, ShenandoahHeapRegion::region_size_bytes_shift_jint()); __ movptr(tmp2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr()); -#ifdef _LP64 __ movbool(tmp2, Address(tmp2, tmp1, Address::times_1)); __ testbool(tmp2); -#else - // On x86_32, C1 register allocator can give us the register without 8-bit support. - // Do the full-register access and test to avoid compilation failures. - __ movptr(tmp2, Address(tmp2, tmp1, Address::times_1)); - __ testptr(tmp2, 0xFF); -#endif __ jcc(Assembler::zero, *stub->continuation()); } @@ -1061,11 +904,9 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss __ push(rdx); const Register pre_val = rax; - const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); + const Register thread = r15_thread; const Register tmp = rdx; - NOT_LP64(__ get_thread(thread);) - Address queue_index(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset())); Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())); @@ -1120,7 +961,6 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); bool is_native = ShenandoahBarrierSet::is_native_access(decorators); -#ifdef _LP64 __ load_parameter(0, c_rarg0); __ load_parameter(1, c_rarg1); if (is_strong) { @@ -1145,18 +985,6 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s assert(is_native, "phantom must only be called off-heap"); __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom), c_rarg0, c_rarg1); } -#else - __ load_parameter(0, rax); - __ load_parameter(1, rbx); - if (is_strong) { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong), rax, rbx); - } else if (is_weak) { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak), rax, rbx); - } else { - assert(is_phantom, "only remaining strength"); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom), rax, rbx); - } -#endif __ restore_live_registers_except_rax(true); diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp index ae0ad3533e1..b0185f2dbff 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp @@ -44,7 +44,6 @@ private: void satb_write_barrier_pre(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, bool tosca_live, bool expand_call); @@ -52,7 +51,6 @@ private: void shenandoah_write_barrier_pre(MacroAssembler* masm, Register obj, Register pre_val, - Register thread, Register tmp, bool tosca_live, bool expand_call); @@ -81,7 +79,7 @@ public: virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count); virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Register dst, Address src, Register tmp1, Register tmp_thread); + Register dst, Address src, Register tmp1); virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index f7b1e25cf3b..9cdf0b229c0 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -220,11 +220,10 @@ void ZBarrierSetAssembler::load_at(MacroAssembler* masm, BasicType type, Register dst, Address src, - Register tmp1, - Register tmp_thread) { + Register tmp1) { if (!ZBarrierSet::barrier_needed(decorators, type)) { // Barrier not needed - BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1); return; } diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp index 91be2e3b945..8bb653ec5fb 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp @@ -73,8 +73,7 @@ public: BasicType type, Register dst, Address src, - Register tmp1, - Register tmp_thread); + Register tmp1); virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index a2173be609b..0f7651b9de2 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -4064,7 +4064,7 @@ void MacroAssembler::resolve_jobject(Register value, jcc(Assembler::notZero, tagged); // Resolve local handle - access_load_at(T_OBJECT, IN_NATIVE | AS_RAW, value, Address(value, 0), tmp, thread); + access_load_at(T_OBJECT, IN_NATIVE | AS_RAW, value, Address(value, 0), tmp); verify_oop(value); jmp(done); @@ -4073,14 +4073,14 @@ void MacroAssembler::resolve_jobject(Register value, jcc(Assembler::notZero, weak_tagged); // Resolve global handle - access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp, thread); + access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp); verify_oop(value); jmp(done); bind(weak_tagged); // Resolve jweak. access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, - value, Address(value, -JNIHandles::TypeTag::weak_global), tmp, thread); + value, Address(value, -JNIHandles::TypeTag::weak_global), tmp); verify_oop(value); bind(done); @@ -4106,7 +4106,7 @@ void MacroAssembler::resolve_global_jobject(Register value, #endif // Resolve global handle - access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp, thread); + access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, -JNIHandles::TypeTag::global), tmp); verify_oop(value); bind(done); @@ -4144,14 +4144,14 @@ void MacroAssembler::testptr(Register dst, Register src) { } // Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes. -void MacroAssembler::tlab_allocate(Register thread, Register obj, +void MacroAssembler::tlab_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - bs->tlab_allocate(this, thread, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); + bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); } RegSet MacroAssembler::call_clobbered_gp_registers() { @@ -5979,7 +5979,7 @@ void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // Only IN_HEAP loads require a thread_tmp register // OopHandle::resolve is an indirection like jobject. access_load_at(T_OBJECT, IN_NATIVE, - result, Address(result, 0), tmp, /*tmp_thread*/noreg); + result, Address(result, 0), tmp); } // ((WeakHandle)result).resolve(); @@ -5995,7 +5995,7 @@ void MacroAssembler::resolve_weak_handle(Register rresult, Register rtmp) { // Only IN_HEAP loads require a thread_tmp register // WeakHandle::resolve is an indirection like jweak. access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, - rresult, Address(rresult, 0), rtmp, /*tmp_thread*/noreg); + rresult, Address(rresult, 0), rtmp); bind(resolved); } @@ -6092,14 +6092,14 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi } void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, - Register tmp1, Register thread_tmp) { + Register tmp1) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { - bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); + bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1); } else { - bs->load_at(this, decorators, type, dst, src, tmp1, thread_tmp); + bs->load_at(this, decorators, type, dst, src, tmp1); } } @@ -6115,15 +6115,13 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Ad } } -void MacroAssembler::load_heap_oop(Register dst, Address src, Register tmp1, - Register thread_tmp, DecoratorSet decorators) { - access_load_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1, thread_tmp); +void MacroAssembler::load_heap_oop(Register dst, Address src, Register tmp1, DecoratorSet decorators) { + access_load_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1); } // Doesn't do verification, generates fixed size code -void MacroAssembler::load_heap_oop_not_null(Register dst, Address src, Register tmp1, - Register thread_tmp, DecoratorSet decorators) { - access_load_at(T_OBJECT, IN_HEAP | IS_NOT_NULL | decorators, dst, src, tmp1, thread_tmp); +void MacroAssembler::load_heap_oop_not_null(Register dst, Address src, Register tmp1, DecoratorSet decorators) { + access_load_at(T_OBJECT, IN_HEAP | IS_NOT_NULL | decorators, dst, src, tmp1); } void MacroAssembler::store_heap_oop(Address dst, Register val, Register tmp1, diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 79f99afded2..27c90fb866e 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -371,14 +371,12 @@ class MacroAssembler: public Assembler { void cmp_klasses_from_objects(Register obj1, Register obj2, Register tmp1, Register tmp2); void access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, - Register tmp1, Register thread_tmp); + Register tmp1); void access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); - void load_heap_oop(Register dst, Address src, Register tmp1 = noreg, - Register thread_tmp = noreg, DecoratorSet decorators = 0); - void load_heap_oop_not_null(Register dst, Address src, Register tmp1 = noreg, - Register thread_tmp = noreg, DecoratorSet decorators = 0); + void load_heap_oop(Register dst, Address src, Register tmp1 = noreg, DecoratorSet decorators = 0); + void load_heap_oop_not_null(Register dst, Address src, Register tmp1 = noreg, DecoratorSet decorators = 0); void store_heap_oop(Address dst, Register val, Register tmp1 = noreg, Register tmp2 = noreg, Register tmp3 = noreg, DecoratorSet decorators = 0); @@ -588,7 +586,6 @@ public: // allocation void tlab_allocate( - Register thread, // Current thread Register obj, // result: pointer to object after successful allocation Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise int con_size_in_bytes, // object size in bytes if known at compile time diff --git a/src/hotspot/cpu/x86/methodHandles_x86.cpp b/src/hotspot/cpu/x86/methodHandles_x86.cpp index 0d95af133fa..ed19daff37d 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.cpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp @@ -182,7 +182,7 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ access_load_at(T_ADDRESS, IN_HEAP, method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())), - noreg, noreg); + noreg); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -212,7 +212,7 @@ void MethodHandles::jump_to_native_invoker(MacroAssembler* _masm, Register nep_r __ verify_oop(nep_reg); __ access_load_at(T_ADDRESS, IN_HEAP, temp_target, Address(nep_reg, NONZERO(jdk_internal_foreign_abi_NativeEntryPoint::downcall_stub_address_offset_in_bytes())), - noreg, noreg); + noreg); __ jmp(temp_target); BLOCK_COMMENT("} jump_to_native_invoker"); @@ -420,7 +420,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } __ load_heap_oop(rbx_method, member_vmtarget); - __ access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg, noreg); + __ access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg); break; case vmIntrinsics::_linkToStatic: @@ -428,7 +428,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } __ load_heap_oop(rbx_method, member_vmtarget); - __ access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg, noreg); + __ access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg); break; case vmIntrinsics::_linkToVirtual: @@ -442,7 +442,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, // pick out the vtable index from the MemberName, and then we can discard it: Register temp2_index = temp2; - __ access_load_at(T_ADDRESS, IN_HEAP, temp2_index, member_vmindex, noreg, noreg); + __ access_load_at(T_ADDRESS, IN_HEAP, temp2_index, member_vmindex, noreg); if (VerifyMethodHandles) { Label L_index_ok; @@ -474,7 +474,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, __ verify_klass_ptr(temp3_intf); Register rbx_index = rbx_method; - __ access_load_at(T_ADDRESS, IN_HEAP, rbx_index, member_vmindex, noreg, noreg); + __ access_load_at(T_ADDRESS, IN_HEAP, rbx_index, member_vmindex, noreg); if (VerifyMethodHandles) { Label L; __ cmpl(rbx_index, 0); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index b480c78f79d..b88a2bd1f8e 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -3981,7 +3981,7 @@ address StubGenerator::generate_upcall_stub_load_target() { __ load_heap_oop(rbx, Address(rbx, java_lang_invoke_MemberName::method_offset()), rscratch1); __ access_load_at(T_ADDRESS, IN_HEAP, rbx, Address(rbx, java_lang_invoke_ResolvedMethodName::vmtarget_offset()), - noreg, noreg); + noreg); __ movptr(Address(r15_thread, JavaThread::callee_target_offset()), rbx); // just in case callee is deoptimized __ ret(0); diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index fecc804a044..bdc2ca908bd 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -654,7 +654,7 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { // Load the value of the referent field. const Address field_address(rax, referent_offset); - __ load_heap_oop(rax, field_address, /*tmp1*/ rbx, /*tmp_thread*/ rdx, ON_WEAK_OOP_REF); + __ load_heap_oop(rax, field_address, /*tmp1*/ rbx, ON_WEAK_OOP_REF); // _areturn __ pop(rdi); // get return address diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp index 1641abac923..b9637e1d7c4 100644 --- a/src/hotspot/cpu/x86/templateTable_x86.cpp +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp @@ -151,7 +151,7 @@ static void do_oop_load(InterpreterMacroAssembler* _masm, Address src, Register dst, DecoratorSet decorators = 0) { - __ load_heap_oop(dst, src, rdx, rbx, decorators); + __ load_heap_oop(dst, src, rdx, decorators); } Address TemplateTable::at_bcp(int offset) { @@ -740,7 +740,7 @@ void TemplateTable::iaload() { __ access_load_at(T_INT, IN_HEAP | IS_ARRAY, rax, Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)), - noreg, noreg); + noreg); } void TemplateTable::laload() { @@ -752,7 +752,7 @@ void TemplateTable::laload() { __ access_load_at(T_LONG, IN_HEAP | IS_ARRAY, noreg /* ltos */, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG)), - noreg, noreg); + noreg); } @@ -766,7 +766,7 @@ void TemplateTable::faload() { Address(rdx, rax, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)), - noreg, noreg); + noreg); } void TemplateTable::daload() { @@ -778,7 +778,7 @@ void TemplateTable::daload() { Address(rdx, rax, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)), - noreg, noreg); + noreg); } void TemplateTable::aaload() { @@ -801,7 +801,7 @@ void TemplateTable::baload() { index_check(rdx, rax); // kills rbx __ access_load_at(T_BYTE, IN_HEAP | IS_ARRAY, rax, Address(rdx, rax, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), - noreg, noreg); + noreg); } void TemplateTable::caload() { @@ -811,7 +811,7 @@ void TemplateTable::caload() { index_check(rdx, rax); // kills rbx __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, rax, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)), - noreg, noreg); + noreg); } // iload followed by caload frequent pair @@ -826,7 +826,7 @@ void TemplateTable::fast_icaload() { index_check(rdx, rax); // kills rbx __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, rax, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)), - noreg, noreg); + noreg); } @@ -837,7 +837,7 @@ void TemplateTable::saload() { index_check(rdx, rax); // kills rbx __ access_load_at(T_SHORT, IN_HEAP | IS_ARRAY, rax, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)), - noreg, noreg); + noreg); } void TemplateTable::iload(int n) { @@ -2566,7 +2566,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ jcc(Assembler::notZero, notByte); // btos - __ access_load_at(T_BYTE, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_BYTE, IN_HEAP, rax, field, noreg); __ push(btos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) { @@ -2579,7 +2579,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ jcc(Assembler::notEqual, notBool); // ztos (same code as btos) - __ access_load_at(T_BOOLEAN, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_BOOLEAN, IN_HEAP, rax, field, noreg); __ push(ztos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) { @@ -2603,7 +2603,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ cmpl(tos_state, itos); __ jcc(Assembler::notEqual, notInt); // itos - __ access_load_at(T_INT, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_INT, IN_HEAP, rax, field, noreg); __ push(itos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) { @@ -2615,7 +2615,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ cmpl(tos_state, ctos); __ jcc(Assembler::notEqual, notChar); // ctos - __ access_load_at(T_CHAR, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_CHAR, IN_HEAP, rax, field, noreg); __ push(ctos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) { @@ -2627,7 +2627,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ cmpl(tos_state, stos); __ jcc(Assembler::notEqual, notShort); // stos - __ access_load_at(T_SHORT, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_SHORT, IN_HEAP, rax, field, noreg); __ push(stos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) { @@ -2641,7 +2641,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr // ltos // Generate code as if volatile (x86_32). There just aren't enough registers to // save that information and this code is faster than the test. - __ access_load_at(T_LONG, IN_HEAP | MO_RELAXED, noreg /* ltos */, field, noreg, noreg); + __ access_load_at(T_LONG, IN_HEAP | MO_RELAXED, noreg /* ltos */, field, noreg); __ push(ltos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx); @@ -2652,7 +2652,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ jcc(Assembler::notEqual, notFloat); // ftos - __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg, noreg); + __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg); __ push(ftos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) { @@ -2668,7 +2668,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr #endif // dtos // MO_RELAXED: for the case of volatile field, in fact it adds no extra work for the underlying implementation - __ access_load_at(T_DOUBLE, IN_HEAP | MO_RELAXED, noreg /* dtos */, field, noreg, noreg); + __ access_load_at(T_DOUBLE, IN_HEAP | MO_RELAXED, noreg /* dtos */, field, noreg); __ push(dtos); // Rewrite bytecode to be faster if (!is_static && rc == may_rewrite) { @@ -3131,25 +3131,25 @@ void TemplateTable::fast_accessfield(TosState state) { __ verify_oop(rax); break; case Bytecodes::_fast_lgetfield: - __ access_load_at(T_LONG, IN_HEAP, noreg /* ltos */, field, noreg, noreg); + __ access_load_at(T_LONG, IN_HEAP, noreg /* ltos */, field, noreg); break; case Bytecodes::_fast_igetfield: - __ access_load_at(T_INT, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_INT, IN_HEAP, rax, field, noreg); break; case Bytecodes::_fast_bgetfield: - __ access_load_at(T_BYTE, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_BYTE, IN_HEAP, rax, field, noreg); break; case Bytecodes::_fast_sgetfield: - __ access_load_at(T_SHORT, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_SHORT, IN_HEAP, rax, field, noreg); break; case Bytecodes::_fast_cgetfield: - __ access_load_at(T_CHAR, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_CHAR, IN_HEAP, rax, field, noreg); break; case Bytecodes::_fast_fgetfield: - __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg, noreg); + __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg); break; case Bytecodes::_fast_dgetfield: - __ access_load_at(T_DOUBLE, IN_HEAP, noreg /* dtos */, field, noreg, noreg); + __ access_load_at(T_DOUBLE, IN_HEAP, noreg /* dtos */, field, noreg); break; default: ShouldNotReachHere(); @@ -3178,14 +3178,14 @@ void TemplateTable::fast_xaccess(TosState state) { const Address field = Address(rax, rbx, Address::times_1, 0*wordSize); switch (state) { case itos: - __ access_load_at(T_INT, IN_HEAP, rax, field, noreg, noreg); + __ access_load_at(T_INT, IN_HEAP, rax, field, noreg); break; case atos: do_oop_load(_masm, field, rax); __ verify_oop(rax); break; case ftos: - __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg, noreg); + __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg); break; default: ShouldNotReachHere(); @@ -3588,7 +3588,7 @@ void TemplateTable::_new() { // Go to slow path. if (UseTLAB) { - __ tlab_allocate(r15_thread, rax, rdx, 0, rcx, rbx, slow_case); + __ tlab_allocate(rax, rdx, 0, rcx, rbx, slow_case); if (ZeroTLAB) { // the fields have been already cleared __ jmp(initialize_header); From 04e2a0621d80f23cf70b4649ec4c24dad28e8e2d Mon Sep 17 00:00:00 2001 From: Saranya Natarajan Date: Thu, 10 Apr 2025 07:59:09 +0000 Subject: [PATCH 106/843] 8351660: C2: SIGFPE in unsigned_mod_value Co-authored-by: Emanuel Peter Reviewed-by: chagedorn, dfenacci, epeter --- src/hotspot/share/opto/divnode.cpp | 5 ++ .../TestUnsignedModByZero.java | 58 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/integerArithmetic/TestUnsignedModByZero.java diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index 22188446c80..a70194274a7 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -1319,6 +1319,11 @@ static const Type* unsigned_mod_value(PhaseGVN* phase, const Node* mod) { return TypeClass::ZERO; } + // Mod by zero? Throw an exception at runtime! + if (type_divisor->is_con() && type_divisor->get_con() == 0) { + return TypeClass::POS; + } + const TypeClass* type_dividend = t1->cast(); if (type_dividend->is_con() && type_divisor->is_con()) { Unsigned dividend = static_cast(type_dividend->get_con()); diff --git a/test/hotspot/jtreg/compiler/integerArithmetic/TestUnsignedModByZero.java b/test/hotspot/jtreg/compiler/integerArithmetic/TestUnsignedModByZero.java new file mode 100644 index 00000000000..27252cd53c7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/integerArithmetic/TestUnsignedModByZero.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8351660 + * @summary Test that modulo by zero throws an exception at runtime in case of unsigned values. + * @library /test/lib + * @run main/othervm -Xbatch + * -XX:CompileCommand=compileonly,compiler.integerArithmetic.TestUnsignedModByZero::testInt + * -XX:CompileCommand=compileonly,compiler.integerArithmetic.TestUnsignedModByZero::testLong + * compiler.integerArithmetic.TestUnsignedModByZero + */ + + package compiler.integerArithmetic; + + import jdk.test.lib.Asserts; + + + public class TestUnsignedModByZero { + + public static Object testInt() { + double x = 1.0; + return Integer.remainderUnsigned(1, (int)(x % x)); + } + + public static Object testLong() { + double x = 1.0; + return Long.remainderUnsigned(1, (long)(x % x)); + } + + public static void main(String[] args) { + for (int i = 0; i < 10_000; i++) { + Asserts.assertThrows(ArithmeticException.class, TestUnsignedModByZero::testInt); + Asserts.assertThrows(ArithmeticException.class, TestUnsignedModByZero::testLong); + } + } + } \ No newline at end of file From f94a4f7accd11161912ec2cdae6e290d0957666a Mon Sep 17 00:00:00 2001 From: Serhiy Sachkov Date: Thu, 10 Apr 2025 08:28:01 +0000 Subject: [PATCH 107/843] 8353847: Remove extra args to System.out.printf in open/test/jdk/java/net/httpclient tests Reviewed-by: dfuchs --- test/jdk/java/net/httpclient/AsyncShutdownNow.java | 6 +++--- test/jdk/java/net/httpclient/HttpClientShutdown.java | 8 ++++---- test/jdk/java/net/httpclient/ShutdownNow.java | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/jdk/java/net/httpclient/AsyncShutdownNow.java b/test/jdk/java/net/httpclient/AsyncShutdownNow.java index 458bd56fbd5..39c82735248 100644 --- a/test/jdk/java/net/httpclient/AsyncShutdownNow.java +++ b/test/jdk/java/net/httpclient/AsyncShutdownNow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,7 +208,7 @@ public class AsyncShutdownNow implements HttpServerAdapters { Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } var cf = bodyCF.exceptionally((t) -> { @@ -304,7 +304,7 @@ public class AsyncShutdownNow implements HttpServerAdapters { Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } bodyCF.handle((r, t) -> { diff --git a/test/jdk/java/net/httpclient/HttpClientShutdown.java b/test/jdk/java/net/httpclient/HttpClientShutdown.java index 133a3d08f27..3c77881c8aa 100644 --- a/test/jdk/java/net/httpclient/HttpClientShutdown.java +++ b/test/jdk/java/net/httpclient/HttpClientShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -192,7 +192,7 @@ public class HttpClientShutdown implements HttpServerAdapters { out.println(now() + step + ": Got response: " + response); assertEquals(response.statusCode(), 200); } catch (AssertionError error) { - out.printf(now() + "%s: Closing body due to assertion - %s", error); + out.printf(now() + "%s: Closing body due to assertion - %s", step, error); ensureClosed(this); throw error; } @@ -276,7 +276,7 @@ public class HttpClientShutdown implements HttpServerAdapters { continue; } if (i == step) { - out.printf(now() + "%d: shutting down client%n", i, sleep); + out.printf(now() + "%d: shutting down client%n", i); client.shutdown(); } var cf = bodyCF.exceptionally((t) -> { @@ -375,7 +375,7 @@ public class HttpClientShutdown implements HttpServerAdapters { continue; } if (i == step) { - out.printf(now() + "%d: shutting down client%n", i, sleep); + out.printf(now() + "%d: shutting down client%n", i); client.shutdown(); } bodyCF.handle((r, t) -> { diff --git a/test/jdk/java/net/httpclient/ShutdownNow.java b/test/jdk/java/net/httpclient/ShutdownNow.java index d175840724d..045876597a2 100644 --- a/test/jdk/java/net/httpclient/ShutdownNow.java +++ b/test/jdk/java/net/httpclient/ShutdownNow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -182,7 +182,7 @@ public class ShutdownNow implements HttpServerAdapters { Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } final int si = i; @@ -242,7 +242,7 @@ public class ShutdownNow implements HttpServerAdapters { Thread.sleep(sleep); } if (i == step) { - out.printf("%d: shutting down client now%n", i, sleep); + out.printf("%d: shutting down client now%n", i); client.shutdownNow(); } final int si = i; From 6545e0d9a39c772ead0cbdd525b624f21e252a6a Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Thu, 10 Apr 2025 08:42:47 +0000 Subject: [PATCH 108/843] 8353189: [ASAN] memory leak after 8352184 Co-authored-by: Jiangli Zhou Co-authored-by: David Holmes Reviewed-by: dholmes, jiangli --- .../share/runtime/abstract_vm_version.cpp | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 763e441fe54..e95c96b4e9c 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -137,42 +137,46 @@ const char* Abstract_VM_Version::vm_vendor() { } +// The VM info string should be a constant, but its value cannot be finalized until after VM arguments +// have been fully processed. And we want to avoid dynamic memory allocation which will cause ASAN +// report error, so we enumerate all the cases by static const string value. const char* Abstract_VM_Version::vm_info_string() { - const char* mode; switch (Arguments::mode()) { case Arguments::_int: - mode = "interpreted mode"; - break; + if (is_vm_statically_linked()) { + return CDSConfig::is_using_archive() ? "interpreted mode, static, sharing" : "interpreted mode, static"; + } else { + return CDSConfig::is_using_archive() ? "interpreted mode, sharing" : "interpreted mode"; + } case Arguments::_mixed: - if (CompilationModeFlag::quick_only()) { - mode = "mixed mode, emulated-client"; + if (is_vm_statically_linked()) { + if (CompilationModeFlag::quick_only()) { + return CDSConfig::is_using_archive() ? "mixed mode, emulated-client, static, sharing" : "mixed mode, emulated-client, static"; + } else { + return CDSConfig::is_using_archive() ? "mixed mode, static, sharing" : "mixed mode, static"; + } } else { - mode = "mixed mode"; + if (CompilationModeFlag::quick_only()) { + return CDSConfig::is_using_archive() ? "mixed mode, emulated-client, sharing" : "mixed mode, emulated-client"; + } else { + return CDSConfig::is_using_archive() ? "mixed mode, sharing" : "mixed mode"; + } } - break; case Arguments::_comp: - if (CompilationModeFlag::quick_only()) { - mode = "compiled mode, emulated-client"; + if (is_vm_statically_linked()) { + if (CompilationModeFlag::quick_only()) { + return CDSConfig::is_using_archive() ? "compiled mode, emulated-client, static, sharing" : "compiled mode, emulated-client, static"; + } + return CDSConfig::is_using_archive() ? "compiled mode, static, sharing" : "compiled mode, static"; } else { - mode = "compiled mode"; + if (CompilationModeFlag::quick_only()) { + return CDSConfig::is_using_archive() ? "compiled mode, emulated-client, sharing" : "compiled mode, emulated-client"; + } + return CDSConfig::is_using_archive() ? "compiled mode, sharing" : "compiled mode"; } - break; - default: - ShouldNotReachHere(); } - - const char* static_info = ", static"; - const char* sharing_info = ", sharing"; - size_t len = strlen(mode) + - (is_vm_statically_linked() ? strlen(static_info) : 0) + - (CDSConfig::is_using_archive() ? strlen(sharing_info) : 0) + - 1; - char* vm_info = NEW_C_HEAP_ARRAY(char, len, mtInternal); - // jio_snprintf places null character in the last character. - jio_snprintf(vm_info, len, "%s%s%s", mode, - is_vm_statically_linked() ? static_info : "", - CDSConfig::is_using_archive() ? sharing_info : ""); - return vm_info; + ShouldNotReachHere(); + return ""; } // NOTE: do *not* use stringStream. this function is called by From 9a3f9997b68a1f64e53b9711b878fb073c3c9b90 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 10 Apr 2025 09:44:58 +0000 Subject: [PATCH 109/843] 8346236: Auto vectorization support for various Float16 operations Reviewed-by: epeter, sviswanathan --- src/hotspot/cpu/x86/assembler_x86.cpp | 212 +++++++++++- src/hotspot/cpu/x86/assembler_x86.hpp | 21 ++ src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 39 ++- src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 9 +- src/hotspot/cpu/x86/x86.ad | 131 ++++++- src/hotspot/share/adlc/formssel.cpp | 20 +- src/hotspot/share/opto/classes.hpp | 8 + src/hotspot/share/opto/matcher.cpp | 4 +- src/hotspot/share/opto/superword.cpp | 5 +- .../share/opto/superwordVTransformBuilder.cpp | 6 +- src/hotspot/share/opto/vectornode.cpp | 95 ++++-- src/hotspot/share/opto/vectornode.hpp | 67 ++++ src/hotspot/share/opto/vtransform.cpp | 9 +- .../generators/AnyBitsFloat16Generator.java | 43 +++ .../compiler/lib/generators/Generators.java | 69 +++- .../lib/generators/RandomnessSource.java | 2 + .../generators/RandomnessSourceAdapter.java | 7 + .../generators/UniformFloat16Generator.java | 51 +++ .../compiler/lib/ir_framework/IRNode.java | 40 +++ .../TestFloat16VectorOperations.java | 321 ++++++++++++++++++ .../tests/MockRandomnessSource.java | 12 + .../generators/tests/TestGenerators.java | 28 +- .../vector/Float16OperationsBenchmark.java | 35 +- 23 files changed, 1150 insertions(+), 84 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/lib/generators/AnyBitsFloat16Generator.java create mode 100644 test/hotspot/jtreg/compiler/lib/generators/UniformFloat16Generator.java create mode 100644 test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 29e4fcee2f6..5ead6ec99ca 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -13810,6 +13810,18 @@ void Assembler::vcmpps(XMMRegister dst, XMMRegister nds, XMMRegister src, int co emit_int24((unsigned char)0xC2, (0xC0 | encode), (unsigned char)comparison); } +void Assembler::evcmpph(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegister src, + ComparisonPredicateFP comparison, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + attributes.reset_is_clear_context(); + int encode = vex_prefix_and_encode(kdst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); + emit_int24((unsigned char)0xC2, (0xC0 | encode), comparison); +} + void Assembler::evcmpsh(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegister src, ComparisonPredicateFP comparison) { assert(VM_Version::supports_avx512_fp16(), ""); InstructionAttr attributes(Assembler::AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); @@ -13822,7 +13834,7 @@ void Assembler::evcmpsh(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegi void Assembler::evcmpps(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegister src, ComparisonPredicateFP comparison, int vector_len) { - assert(VM_Version::supports_evex(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); // Encoding: EVEX.NDS.XXX.0F.W0 C2 /r ib InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -13834,7 +13846,7 @@ void Assembler::evcmpps(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegi void Assembler::evcmppd(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegister src, ComparisonPredicateFP comparison, int vector_len) { - assert(VM_Version::supports_evex(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); // Encoding: EVEX.NDS.XXX.66.0F.W1 C2 /r ib InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -14155,7 +14167,7 @@ void Assembler::vpblendvb(XMMRegister dst, XMMRegister nds, XMMRegister src, XMM } void Assembler::evblendmpd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { - assert(VM_Version::supports_evex(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); // Encoding: EVEX.NDS.XXX.66.0F38.W1 65 /r InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -14168,7 +14180,7 @@ void Assembler::evblendmpd(XMMRegister dst, KRegister mask, XMMRegister nds, XMM } void Assembler::evblendmps(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { - assert(VM_Version::supports_evex(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); // Encoding: EVEX.NDS.XXX.66.0F38.W0 65 /r InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -14180,9 +14192,9 @@ void Assembler::evblendmps(XMMRegister dst, KRegister mask, XMMRegister nds, XMM emit_int16(0x65, (0xC0 | encode)); } -void Assembler::evpblendmb (XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { - assert(VM_Version::supports_evex(), ""); +void Assembler::evpblendmb(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { assert(VM_Version::supports_avx512bw(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); // Encoding: EVEX.NDS.512.66.0F38.W0 66 /r InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -14194,9 +14206,9 @@ void Assembler::evpblendmb (XMMRegister dst, KRegister mask, XMMRegister nds, XM emit_int16(0x66, (0xC0 | encode)); } -void Assembler::evpblendmw (XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { - assert(VM_Version::supports_evex(), ""); +void Assembler::evpblendmw(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { assert(VM_Version::supports_avx512bw(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); // Encoding: EVEX.NDS.512.66.0F38.W1 66 /r InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -14208,8 +14220,8 @@ void Assembler::evpblendmw (XMMRegister dst, KRegister mask, XMMRegister nds, XM emit_int16(0x66, (0xC0 | encode)); } -void Assembler::evpblendmd (XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { - assert(VM_Version::supports_evex(), ""); +void Assembler::evpblendmd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); //Encoding: EVEX.NDS.512.66.0F38.W0 64 /r InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -14221,8 +14233,8 @@ void Assembler::evpblendmd (XMMRegister dst, KRegister mask, XMMRegister nds, XM emit_int16(0x64, (0xC0 | encode)); } -void Assembler::evpblendmq (XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { - assert(VM_Version::supports_evex(), ""); +void Assembler::evpblendmq(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); //Encoding: EVEX.NDS.512.66.0F38.W1 64 /r InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); attributes.set_is_evex_instruction(); @@ -14420,6 +14432,7 @@ void Assembler::shrxq(Register dst, Address src1, Register src2) { void Assembler::evpmovq2m(KRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx512vldq(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -14428,6 +14441,7 @@ void Assembler::evpmovq2m(KRegister dst, XMMRegister src, int vector_len) { void Assembler::evpmovd2m(KRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx512vldq(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -14436,6 +14450,7 @@ void Assembler::evpmovd2m(KRegister dst, XMMRegister src, int vector_len) { void Assembler::evpmovw2m(KRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx512vlbw(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -14444,6 +14459,7 @@ void Assembler::evpmovw2m(KRegister dst, XMMRegister src, int vector_len) { void Assembler::evpmovb2m(KRegister dst, XMMRegister src, int vector_len) { assert(VM_Version::supports_avx512vlbw(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -14452,6 +14468,7 @@ void Assembler::evpmovb2m(KRegister dst, XMMRegister src, int vector_len) { void Assembler::evpmovm2q(XMMRegister dst, KRegister src, int vector_len) { assert(VM_Version::supports_avx512vldq(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -14460,6 +14477,7 @@ void Assembler::evpmovm2q(XMMRegister dst, KRegister src, int vector_len) { void Assembler::evpmovm2d(XMMRegister dst, KRegister src, int vector_len) { assert(VM_Version::supports_avx512vldq(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -14468,6 +14486,7 @@ void Assembler::evpmovm2d(XMMRegister dst, KRegister src, int vector_len) { void Assembler::evpmovm2w(XMMRegister dst, KRegister src, int vector_len) { assert(VM_Version::supports_avx512vlbw(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -14476,6 +14495,7 @@ void Assembler::evpmovm2w(XMMRegister dst, KRegister src, int vector_len) { void Assembler::evpmovm2b(XMMRegister dst, KRegister src, int vector_len) { assert(VM_Version::supports_avx512vlbw(), ""); + assert(VM_Version::supports_avx512vl() || vector_len == Assembler::AVX_512bit, ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); @@ -17161,3 +17181,171 @@ void Assembler::evpermt2q(XMMRegister dst, XMMRegister nds, XMMRegister src, int emit_int16(0x7E, (0xC0 | encode)); } +void Assembler::evaddph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x58, (0xC0 | encode)); +} + +void Assembler::evaddph(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x58); + emit_operand(dst, src, 0); +} + +void Assembler::evsubph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x5C, (0xC0 | encode)); +} + +void Assembler::evsubph(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x5C); + emit_operand(dst, src, 0); +} + +void Assembler::evmulph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x59, (0xC0 | encode)); +} + +void Assembler::evmulph(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x59); + emit_operand(dst, src, 0); +} + +void Assembler::evminph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x5D, (0xC0 | encode)); +} + +void Assembler::evminph(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x5D); + emit_operand(dst, src, 0); +} + +void Assembler::evmaxph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x5F, (0xC0 | encode)); +} + +void Assembler::evmaxph(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x5F); + emit_operand(dst, src, 0); +} + +void Assembler::evdivph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x5E, (0xC0 | encode)); +} + +void Assembler::evdivph(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), "requires AVX512-FP16"); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x5E); + emit_operand(dst, src, 0); +} + +void Assembler::evsqrtph(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), ""); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int16(0x51, (0xC0 | encode)); +} + +void Assembler::evsqrtph(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), ""); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes); + emit_int8(0x51); + emit_operand(dst, src, 0); +} + +void Assembler::evfmadd132ph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), ""); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP6, &attributes); + emit_int16(0x98, (0xC0 | encode)); +} + +void Assembler::evfmadd132ph(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { + assert(VM_Version::supports_avx512_fp16(), ""); + assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, nds->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP6, &attributes); + emit_int8(0x98); + emit_operand(dst, src, 0); +} + diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 15ea45edb91..3a4eba334ef 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -2888,6 +2888,24 @@ private: void evplzcntd(XMMRegister dst, KRegister mask, XMMRegister src, bool merge, int vector_len); void evplzcntq(XMMRegister dst, KRegister mask, XMMRegister src, bool merge, int vector_len); + // Float16 Vector instructions. + void evaddph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evaddph(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void evsubph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evsubph(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void evdivph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evdivph(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void evmulph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evmulph(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void evminph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evminph(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void evmaxph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evmaxph(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void evfmadd132ph(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evfmadd132ph(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void evsqrtph(XMMRegister dst, XMMRegister src1, int vector_len); + void evsqrtph(XMMRegister dst, Address src1, int vector_len); + // Sub packed integers void psubb(XMMRegister dst, XMMRegister src); void psubw(XMMRegister dst, XMMRegister src); @@ -3195,6 +3213,9 @@ private: void evcmpps(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegister src, ComparisonPredicateFP comparison, int vector_len); + void evcmpph(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegister src, + ComparisonPredicateFP comparison, int vector_len); + void evcmpsh(KRegister kdst, KRegister mask, XMMRegister nds, XMMRegister src, ComparisonPredicateFP comparison); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 9ca46333668..5da3b8c09f9 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -6987,9 +6987,34 @@ void C2_MacroAssembler::vector_saturating_op(int ideal_opc, BasicType elem_bt, X } } +void C2_MacroAssembler::evfp16ph(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, int vlen_enc) { + switch(opcode) { + case Op_AddVHF: evaddph(dst, src1, src2, vlen_enc); break; + case Op_SubVHF: evsubph(dst, src1, src2, vlen_enc); break; + case Op_MulVHF: evmulph(dst, src1, src2, vlen_enc); break; + case Op_DivVHF: evdivph(dst, src1, src2, vlen_enc); break; + default: assert(false, "%s", NodeClassNames[opcode]); break; + } +} + +void C2_MacroAssembler::evfp16ph(int opcode, XMMRegister dst, XMMRegister src1, Address src2, int vlen_enc) { + switch(opcode) { + case Op_AddVHF: evaddph(dst, src1, src2, vlen_enc); break; + case Op_SubVHF: evsubph(dst, src1, src2, vlen_enc); break; + case Op_MulVHF: evmulph(dst, src1, src2, vlen_enc); break; + case Op_DivVHF: evdivph(dst, src1, src2, vlen_enc); break; + default: assert(false, "%s", NodeClassNames[opcode]); break; + } +} + void C2_MacroAssembler::scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, - KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc) { - if (opcode == Op_MaxHF) { + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2) { + vector_max_min_fp16(opcode, dst, src1, src2, ktmp, xtmp1, xtmp2, Assembler::AVX_128bit); +} + +void C2_MacroAssembler::vector_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc) { + if (opcode == Op_MaxVHF || opcode == Op_MaxHF) { // Move sign bits of src2 to mask register. evpmovw2m(ktmp, src2, vlen_enc); // xtmp1 = src2 < 0 ? src2 : src1 @@ -7001,15 +7026,15 @@ void C2_MacroAssembler::scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegi // the second source operand is returned. If only one value is a NaN (SNaN or QNaN) for this instruction, // the second source operand, either a NaN or a valid floating-point value, is returned // dst = max(xtmp1, xtmp2) - vmaxsh(dst, xtmp1, xtmp2); + evmaxph(dst, xtmp1, xtmp2, vlen_enc); // isNaN = is_unordered_quiet(xtmp1) - evcmpsh(ktmp, k0, xtmp1, xtmp1, Assembler::UNORD_Q); + evcmpph(ktmp, k0, xtmp1, xtmp1, Assembler::UNORD_Q, vlen_enc); // Final result is same as first source if its a NaN value, // in case second operand holds a NaN value then as per above semantics // result is same as second operand. Assembler::evmovdquw(dst, ktmp, xtmp1, true, vlen_enc); } else { - assert(opcode == Op_MinHF, ""); + assert(opcode == Op_MinVHF || opcode == Op_MinHF, ""); // Move sign bits of src1 to mask register. evpmovw2m(ktmp, src1, vlen_enc); // xtmp1 = src1 < 0 ? src2 : src1 @@ -7022,9 +7047,9 @@ void C2_MacroAssembler::scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegi // If only one value is a NaN (SNaN or QNaN) for this instruction, the second source operand, either a NaN // or a valid floating-point value, is written to the result. // dst = min(xtmp1, xtmp2) - vminsh(dst, xtmp1, xtmp2); + evminph(dst, xtmp1, xtmp2, vlen_enc); // isNaN = is_unordered_quiet(xtmp1) - evcmpsh(ktmp, k0, xtmp1, xtmp1, Assembler::UNORD_Q); + evcmpph(ktmp, k0, xtmp1, xtmp1, Assembler::UNORD_Q, vlen_enc); // Final result is same as first source if its a NaN value, // in case second operand holds a NaN value then as per above semantics // result is same as second operand. diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 2c5fb4b516a..dd2880d88c3 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -565,6 +565,13 @@ public: void select_from_two_vectors_evex(BasicType elem_bt, XMMRegister dst, XMMRegister src1, XMMRegister src2, int vlen_enc); + void evfp16ph(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, int vlen_enc); + + void evfp16ph(int opcode, XMMRegister dst, XMMRegister src1, Address src2, int vlen_enc); + + void vector_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc); + void scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2, - KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2, int vlen_enc); + KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2); #endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 7bde4ced2ba..e2880a22fa9 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1631,6 +1631,24 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { // * 128bit vroundpd instruction is present only in AVX1 int size_in_bits = vlen * type2aelembytes(bt) * BitsPerByte; switch (opcode) { + case Op_MaxVHF: + case Op_MinVHF: + if (!VM_Version::supports_avx512bw()) { + return false; + } + case Op_AddVHF: + case Op_DivVHF: + case Op_FmaVHF: + case Op_MulVHF: + case Op_SubVHF: + case Op_SqrtVHF: + if (size_in_bits < 512 && !VM_Version::supports_avx512vl()) { + return false; + } + if (!VM_Version::supports_avx512_fp16()) { + return false; + } + break; case Op_AbsVF: case Op_NegVF: if ((vlen == 16) && (VM_Version::supports_avx512dq() == false)) { @@ -10644,6 +10662,16 @@ instruct reinterpretS2HF(regF dst, rRegI src) ins_pipe(pipe_slow); %} +instruct reinterpretHF2S(rRegI dst, regF src) +%{ + match(Set dst (ReinterpretHF2S src)); + format %{ "vmovw $dst, $src" %} + ins_encode %{ + __ vmovw($dst$$Register, $src$$XMMRegister); + %} + ins_pipe(pipe_slow); +%} + instruct convF2HFAndS2HF(regF dst, regF src) %{ match(Set dst (ReinterpretS2HF (ConvF2HF src))); @@ -10664,16 +10692,6 @@ instruct convHF2SAndHF2F(regF dst, regF src) ins_pipe(pipe_slow); %} -instruct reinterpretHF2S(rRegI dst, regF src) -%{ - match(Set dst (ReinterpretHF2S src)); - format %{ "vmovw $dst, $src" %} - ins_encode %{ - __ vmovw($dst$$Register, $src$$XMMRegister); - %} - ins_pipe(pipe_slow); -%} - instruct scalar_sqrt_HF_reg(regF dst, regF src) %{ match(Set dst (SqrtHF src)); @@ -10707,7 +10725,7 @@ instruct scalar_minmax_HF_reg(regF dst, regF src1, regF src2, kReg ktmp, regF xt ins_encode %{ int opcode = this->ideal_Opcode(); __ scalar_max_min_fp16(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $ktmp$$KRegister, - $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, Assembler::AVX_128bit); + $xtmp1$$XMMRegister, $xtmp2$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -10722,3 +10740,94 @@ instruct scalar_fma_HF_reg(regF dst, regF src1, regF src2) %} ins_pipe( pipe_slow ); %} + + +instruct vector_sqrt_HF_reg(vec dst, vec src) +%{ + match(Set dst (SqrtVHF src)); + format %{ "vector_sqrt_fp16 $dst, $src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ evsqrtph($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + %} + ins_pipe(pipe_slow); +%} + +instruct vector_sqrt_HF_mem(vec dst, memory src) +%{ + match(Set dst (SqrtVHF (VectorReinterpret (LoadVector src)))); + format %{ "vector_sqrt_fp16_mem $dst, $src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ evsqrtph($dst$$XMMRegister, $src$$Address, vlen_enc); + %} + ins_pipe(pipe_slow); +%} + +instruct vector_binOps_HF_reg(vec dst, vec src1, vec src2) +%{ + match(Set dst (AddVHF src1 src2)); + match(Set dst (DivVHF src1 src2)); + match(Set dst (MulVHF src1 src2)); + match(Set dst (SubVHF src1 src2)); + format %{ "vector_binop_fp16 $dst, $src1, $src2" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + int opcode = this->ideal_Opcode(); + __ evfp16ph(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vlen_enc); + %} + ins_pipe(pipe_slow); +%} + + +instruct vector_binOps_HF_mem(vec dst, vec src1, memory src2) +%{ + match(Set dst (AddVHF src1 (VectorReinterpret (LoadVector src2)))); + match(Set dst (DivVHF src1 (VectorReinterpret (LoadVector src2)))); + match(Set dst (MulVHF src1 (VectorReinterpret (LoadVector src2)))); + match(Set dst (SubVHF src1 (VectorReinterpret (LoadVector src2)))); + format %{ "vector_binop_fp16_mem $dst, $src1, $src2" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + int opcode = this->ideal_Opcode(); + __ evfp16ph(opcode, $dst$$XMMRegister, $src1$$XMMRegister, $src2$$Address, vlen_enc); + %} + ins_pipe(pipe_slow); +%} + +instruct vector_fma_HF_reg(vec dst, vec src1, vec src2) +%{ + match(Set dst (FmaVHF src2 (Binary dst src1))); + format %{ "vector_fma_fp16 $dst, $src1, $src2\t# $dst = $dst * $src1 + $src2 fma packedH" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ evfmadd132ph($dst$$XMMRegister, $src2$$XMMRegister, $src1$$XMMRegister, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vector_fma_HF_mem(vec dst, memory src1, vec src2) +%{ + match(Set dst (FmaVHF src2 (Binary dst (VectorReinterpret (LoadVector src1))))); + format %{ "vector_fma_fp16_mem $dst, $src1, $src2\t# $dst = $dst * $src1 + $src2 fma packedH" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ evfmadd132ph($dst$$XMMRegister, $src2$$XMMRegister, $src1$$Address, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vector_minmax_HF_reg(vec dst, vec src1, vec src2, kReg ktmp, vec xtmp1, vec xtmp2) +%{ + match(Set dst (MinVHF src1 src2)); + match(Set dst (MaxVHF src1 src2)); + effect(TEMP_DEF dst, TEMP ktmp, TEMP xtmp1, TEMP xtmp2); + format %{ "vector_min_max_fp16 $dst, $src1, $src2\t using $ktmp, $xtmp1 and $xtmp2 as TEMP" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + int opcode = this->ideal_Opcode(); + __ vector_max_min_fp16(opcode, $dst$$XMMRegister, $src2$$XMMRegister, $src1$$XMMRegister, $ktmp$$KRegister, + $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 7239031c898..b938d5b7560 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -3965,10 +3965,10 @@ void MatchNode::count_commutative_op(int& count) { }; static const char *commut_vector_op_list[] = { - "AddVB", "AddVS", "AddVI", "AddVL", "AddVF", "AddVD", - "MulVB", "MulVS", "MulVI", "MulVL", "MulVF", "MulVD", + "AddVB", "AddVS", "AddVI", "AddVL", "AddVHF", "AddVF", "AddVD", + "MulVB", "MulVS", "MulVI", "MulVL", "MulVHF", "MulVF", "MulVD", "AndV", "OrV", "XorV", - "MaxV", "MinV", "UMax","UMin" + "MaxVHF", "MinVHF", "MaxV", "MinV", "UMax","UMin" }; if (_lChild && _rChild && (_lChild->_lChild || _rChild->_lChild)) { @@ -4335,15 +4335,15 @@ Form::DataType MatchRule::is_ideal_load() const { bool MatchRule::is_vector() const { static const char *vector_list[] = { - "AddVB","AddVS","AddVI","AddVL","AddVF","AddVD", - "SubVB","SubVS","SubVI","SubVL","SubVF","SubVD", - "MulVB","MulVS","MulVI","MulVL","MulVF","MulVD", - "DivVF","DivVD", + "AddVB","AddVS","AddVI","AddVL","AddVHF","AddVF","AddVD", + "SubVB","SubVS","SubVI","SubVL","SubVHF","SubVF","SubVD", + "MulVB","MulVS","MulVI","MulVL","MulVHF","MulVF","MulVD", + "DivVHF","DivVF","DivVD", "AbsVB","AbsVS","AbsVI","AbsVL","AbsVF","AbsVD", "NegVF","NegVD","NegVI","NegVL", - "SqrtVD","SqrtVF", + "SqrtVD","SqrtVF","SqrtVHF", "AndV" ,"XorV" ,"OrV", - "MaxV", "MinV", "UMinV", "UMaxV", + "MaxV", "MinV", "MinVHF", "MaxVHF", "UMinV", "UMaxV", "CompressV", "ExpandV", "CompressM", "CompressBitsV", "ExpandBitsV", "AddReductionVI", "AddReductionVL", "AddReductionVF", "AddReductionVD", @@ -4365,7 +4365,7 @@ bool MatchRule::is_vector() const { "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", "VectorCastF2HF", "VectorCastHF2F", "VectorUCastB2X", "VectorUCastS2X", "VectorUCastI2X", "VectorMaskWrapper","VectorMaskCmp","VectorReinterpret","LoadVectorMasked","StoreVectorMasked", - "FmaVD","FmaVF","PopCountVI","PopCountVL","PopulateIndex","VectorLongToMask", + "FmaVD", "FmaVF", "FmaVHF", "PopCountVI", "PopCountVL", "PopulateIndex", "VectorLongToMask", "CountLeadingZerosV", "CountTrailingZerosV", "SignumVF", "SignumVD", "SaturatingAddV", "SaturatingSubV", // Next are vector mask ops. "MaskAll", "AndVMask", "OrVMask", "XorVMask", "VectorMaskCast", diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index a8d1a29250a..bc259eed2d1 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -389,6 +389,7 @@ macro(AddReductionVI) macro(AddVL) macro(AddReductionVL) macro(AddVF) +macro(AddVHF) macro(AddReductionVF) macro(AddVD) macro(AddReductionVD) @@ -397,6 +398,7 @@ macro(SubVS) macro(SubVI) macro(SubVL) macro(SubVF) +macro(SubVHF) macro(SubVD) macro(MulVB) macro(MulVS) @@ -408,9 +410,12 @@ macro(MulVF) macro(MulReductionVF) macro(MulVD) macro(MulReductionVD) +macro(MulVHF) macro(MulAddVS2VI) macro(FmaVD) macro(FmaVF) +macro(FmaVHF) +macro(DivVHF) macro(DivVF) macro(DivVD) macro(AbsVB) @@ -425,6 +430,7 @@ macro(NegVF) macro(NegVD) macro(SqrtVD) macro(SqrtVF) +macro(SqrtVHF) macro(LShiftCntV) macro(RShiftCntV) macro(LShiftVB) @@ -447,6 +453,8 @@ macro(XorV) macro(XorReductionV) macro(MinV) macro(MaxV) +macro(MinVHF) +macro(MaxVHF) macro(UMinV) macro(UMaxV) macro(MinReductionV) diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index fd89a6e5431..e34a43cc1e2 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -2307,6 +2307,7 @@ bool Matcher::find_shared_visit(MStack& mstack, Node* n, uint opcode, bool& mem_ case Op_FmaHF: case Op_FmaVD: case Op_FmaVF: + case Op_FmaVHF: case Op_MacroLogicV: case Op_VectorCmpMasked: case Op_CompressV: @@ -2479,7 +2480,8 @@ void Matcher::find_shared_post_visit(Node* n, uint opcode) { case Op_FmaF: case Op_FmaHF: case Op_FmaVD: - case Op_FmaVF: { + case Op_FmaVF: + case Op_FmaVHF: { // Restructure into a binary tree for Matching. Node* pair = new BinaryNode(n->in(1), n->in(2)); n->set_req(2, pair); diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 092fa07e184..0746715f065 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2591,6 +2591,7 @@ void VLoopTypes::compute_vector_element_type() { // Smallest type containing range of values const Type* VLoopTypes::container_type(Node* n) const { + int opc = n->Opcode(); if (n->is_Mem()) { BasicType bt = n->as_Mem()->memory_type(); if (n->is_Store() && (bt == T_CHAR)) { @@ -2598,7 +2599,7 @@ const Type* VLoopTypes::container_type(Node* n) const { // preceding arithmetic operation extends values to signed Int. bt = T_SHORT; } - if (n->Opcode() == Op_LoadUB) { + if (opc == Op_LoadUB) { // Adjust type for unsigned byte loads, it is important for right shifts. // T_BOOLEAN is used because there is no basic type representing type // TypeInt::UBYTE. Use of T_BOOLEAN for vectors is fine because only @@ -2612,7 +2613,7 @@ const Type* VLoopTypes::container_type(Node* n) const { // Float to half float conversion may be succeeded by a conversion from // half float to float, in such a case back propagation of narrow type (SHORT) // may not be possible. - if (n->Opcode() == Op_ConvF2HF || n->Opcode() == Op_ReinterpretHF2S) { + if (opc == Op_ConvF2HF || opc == Op_ReinterpretHF2S) { return TypeInt::SHORT; } // A narrow type of arithmetic operations will be determined by diff --git a/src/hotspot/share/opto/superwordVTransformBuilder.cpp b/src/hotspot/share/opto/superwordVTransformBuilder.cpp index aee6add2a98..d356fcd5109 100644 --- a/src/hotspot/share/opto/superwordVTransformBuilder.cpp +++ b/src/hotspot/share/opto/superwordVTransformBuilder.cpp @@ -161,9 +161,11 @@ VTransformVectorNode* SuperWordVTransformBuilder::make_vector_vtnode_for_pack(co p0->is_CMove() || VectorNode::is_scalar_op_that_returns_int_but_vector_op_returns_long(opc) || VectorNode::is_convert_opcode(opc) || + VectorNode::is_reinterpret_opcode(opc) || VectorNode::is_scalar_unary_op_with_equal_input_and_output_types(opc) || - opc == Op_FmaD || - opc == Op_FmaF || + opc == Op_FmaD || + opc == Op_FmaF || + opc == Op_FmaHF || opc == Op_SignumF || opc == Op_SignumD, "pack type must be in this list"); diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 622766ecfd5..084b70a6906 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -46,6 +46,7 @@ int VectorNode::opcode(int sopc, BasicType bt) { default: return 0; } case Op_AddL: return (bt == T_LONG ? Op_AddVL : 0); + case Op_AddHF: return (bt == T_SHORT ? Op_AddVHF : 0); case Op_AddF: return (bt == T_FLOAT ? Op_AddVF : 0); case Op_AddD: return (bt == T_DOUBLE ? Op_AddVD : 0); @@ -59,6 +60,7 @@ int VectorNode::opcode(int sopc, BasicType bt) { default: return 0; } case Op_SubL: return (bt == T_LONG ? Op_SubVL : 0); + case Op_SubHF: return (bt == T_SHORT ? Op_SubVHF : 0); case Op_SubF: return (bt == T_FLOAT ? Op_SubVF : 0); case Op_SubD: return (bt == T_DOUBLE ? Op_SubVD : 0); @@ -72,6 +74,8 @@ int VectorNode::opcode(int sopc, BasicType bt) { default: return 0; } case Op_MulL: return (bt == T_LONG ? Op_MulVL : 0); + case Op_MulHF: + return (bt == T_SHORT ? Op_MulVHF : 0); case Op_MulF: return (bt == T_FLOAT ? Op_MulVF : 0); case Op_MulD: @@ -80,12 +84,16 @@ int VectorNode::opcode(int sopc, BasicType bt) { return (bt == T_DOUBLE ? Op_FmaVD : 0); case Op_FmaF: return (bt == T_FLOAT ? Op_FmaVF : 0); + case Op_FmaHF: + return (bt == T_SHORT ? Op_FmaVHF : 0); case Op_CMoveF: return (bt == T_FLOAT ? Op_VectorBlend : 0); case Op_CMoveD: return (bt == T_DOUBLE ? Op_VectorBlend : 0); case Op_Bool: return Op_VectorMaskCmp; + case Op_DivHF: + return (bt == T_SHORT ? Op_DivVHF : 0); case Op_DivF: return (bt == T_FLOAT ? Op_DivVF : 0); case Op_DivD: @@ -112,6 +120,8 @@ int VectorNode::opcode(int sopc, BasicType bt) { } case Op_MinL: return (bt == T_LONG ? Op_MinV : 0); + case Op_MinHF: + return (bt == T_SHORT ? Op_MinVHF : 0); case Op_MinF: return (bt == T_FLOAT ? Op_MinV : 0); case Op_MinD: @@ -127,6 +137,8 @@ int VectorNode::opcode(int sopc, BasicType bt) { } case Op_MaxL: return (bt == T_LONG ? Op_MaxV : 0); + case Op_MaxHF: + return (bt == T_SHORT ? Op_MaxVHF : 0); case Op_MaxF: return (bt == T_FLOAT ? Op_MaxV : 0); case Op_MaxD: @@ -154,6 +166,8 @@ int VectorNode::opcode(int sopc, BasicType bt) { return (is_integral_type(bt) ? Op_RotateLeftV : 0); case Op_RotateRight: return (is_integral_type(bt) ? Op_RotateRightV : 0); + case Op_SqrtHF: + return (bt == T_SHORT ? Op_SqrtVHF : 0); case Op_SqrtF: return (bt == T_FLOAT ? Op_SqrtVF : 0); case Op_SqrtD: @@ -266,6 +280,9 @@ int VectorNode::opcode(int sopc, BasicType bt) { return Op_SignumVF; case Op_SignumD: return Op_SignumVD; + case Op_ReinterpretS2HF: + case Op_ReinterpretHF2S: + return Op_VectorReinterpret; default: assert(!VectorNode::is_convert_opcode(sopc), @@ -378,6 +395,10 @@ int VectorNode::scalar_opcode(int sopc, BasicType bt) { assert(false, "basic type not handled"); return 0; } + case Op_MinVHF: + return Op_MinHF; + case Op_MaxVHF: + return Op_MaxHF; default: assert(false, "Vector node %s is not handled in VectorNode::scalar_opcode", @@ -618,10 +639,10 @@ void VectorNode::vector_operands(Node* n, uint* start, uint* end) { *start = 1; *end = (n->is_Con() && Matcher::supports_vector_constant_rotates(n->get_int())) ? 2 : 3; break; - case Op_AddI: case Op_AddL: case Op_AddF: case Op_AddD: - case Op_SubI: case Op_SubL: case Op_SubF: case Op_SubD: - case Op_MulI: case Op_MulL: case Op_MulF: case Op_MulD: - case Op_DivF: case Op_DivD: + case Op_AddI: case Op_AddL: case Op_AddHF: case Op_AddF: case Op_AddD: + case Op_SubI: case Op_SubL: case Op_SubHF: case Op_SubF: case Op_SubD: + case Op_MulI: case Op_MulL: case Op_MulHF: case Op_MulF: case Op_MulD: + case Op_DivHF: case Op_DivF: case Op_DivD: case Op_AndI: case Op_AndL: case Op_OrI: case Op_OrL: case Op_XorI: case Op_XorL: @@ -631,6 +652,7 @@ void VectorNode::vector_operands(Node* n, uint* start, uint* end) { break; case Op_FmaD: case Op_FmaF: + case Op_FmaHF: *start = 1; *end = 4; // 3 vector operands break; @@ -675,32 +697,38 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, const TypeVect* vt, b } switch (vopc) { - case Op_AddVB: return new AddVBNode(n1, n2, vt); - case Op_AddVS: return new AddVSNode(n1, n2, vt); - case Op_AddVI: return new AddVINode(n1, n2, vt); - case Op_AddVL: return new AddVLNode(n1, n2, vt); - case Op_AddVF: return new AddVFNode(n1, n2, vt); - case Op_AddVD: return new AddVDNode(n1, n2, vt); + case Op_AddVB: return new AddVBNode(n1, n2, vt); + case Op_AddVHF: return new AddVHFNode(n1, n2, vt); + case Op_AddVS: return new AddVSNode(n1, n2, vt); + case Op_AddVI: return new AddVINode(n1, n2, vt); + case Op_AddVL: return new AddVLNode(n1, n2, vt); + case Op_AddVF: return new AddVFNode(n1, n2, vt); + case Op_AddVD: return new AddVDNode(n1, n2, vt); - case Op_SubVB: return new SubVBNode(n1, n2, vt); - case Op_SubVS: return new SubVSNode(n1, n2, vt); - case Op_SubVI: return new SubVINode(n1, n2, vt); - case Op_SubVL: return new SubVLNode(n1, n2, vt); - case Op_SubVF: return new SubVFNode(n1, n2, vt); - case Op_SubVD: return new SubVDNode(n1, n2, vt); + case Op_SubVB: return new SubVBNode(n1, n2, vt); + case Op_SubVS: return new SubVSNode(n1, n2, vt); + case Op_SubVI: return new SubVINode(n1, n2, vt); + case Op_SubVL: return new SubVLNode(n1, n2, vt); + case Op_SubVHF: return new SubVHFNode(n1, n2, vt); + case Op_SubVF: return new SubVFNode(n1, n2, vt); + case Op_SubVD: return new SubVDNode(n1, n2, vt); - case Op_MulVB: return new MulVBNode(n1, n2, vt); - case Op_MulVS: return new MulVSNode(n1, n2, vt); - case Op_MulVI: return new MulVINode(n1, n2, vt); - case Op_MulVL: return new MulVLNode(n1, n2, vt); - case Op_MulVF: return new MulVFNode(n1, n2, vt); - case Op_MulVD: return new MulVDNode(n1, n2, vt); + case Op_MulVB: return new MulVBNode(n1, n2, vt); + case Op_MulVS: return new MulVSNode(n1, n2, vt); + case Op_MulVI: return new MulVINode(n1, n2, vt); + case Op_MulVL: return new MulVLNode(n1, n2, vt); + case Op_MulVHF: return new MulVHFNode(n1, n2, vt); + case Op_MulVF: return new MulVFNode(n1, n2, vt); + case Op_MulVD: return new MulVDNode(n1, n2, vt); - case Op_DivVF: return new DivVFNode(n1, n2, vt); - case Op_DivVD: return new DivVDNode(n1, n2, vt); + case Op_DivVHF: return new DivVHFNode(n1, n2, vt); + case Op_DivVF: return new DivVFNode(n1, n2, vt); + case Op_DivVD: return new DivVDNode(n1, n2, vt); case Op_MinV: return new MinVNode(n1, n2, vt); case Op_MaxV: return new MaxVNode(n1, n2, vt); + case Op_MinVHF: return new MinVHFNode(n1, n2, vt); + case Op_MaxVHF: return new MaxVHFNode(n1, n2, vt); case Op_AbsVF: return new AbsVFNode(n1, vt); case Op_AbsVD: return new AbsVDNode(n1, vt); @@ -717,8 +745,9 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, const TypeVect* vt, b case Op_ReverseV: return new ReverseVNode(n1, vt); case Op_ReverseBytesV: return new ReverseBytesVNode(n1, vt); - case Op_SqrtVF: return new SqrtVFNode(n1, vt); - case Op_SqrtVD: return new SqrtVDNode(n1, vt); + case Op_SqrtVHF : return new SqrtVHFNode(n1, vt); + case Op_SqrtVF : return new SqrtVFNode(n1, vt); + case Op_SqrtVD : return new SqrtVDNode(n1, vt); case Op_RoundVF: return new RoundVFNode(n1, vt); case Op_RoundVD: return new RoundVDNode(n1, vt); @@ -802,6 +831,7 @@ VectorNode* VectorNode::make(int vopc, Node* n1, Node* n2, Node* n3, const TypeV switch (vopc) { case Op_FmaVD: return new FmaVDNode(n1, n2, n3, vt); case Op_FmaVF: return new FmaVFNode(n1, n2, n3, vt); + case Op_FmaVHF: return new FmaVHFNode(n1, n2, n3, vt); case Op_SelectFromTwoVector: return new SelectFromTwoVectorNode(n1, n2, n3, vt); case Op_SignumVD: return new SignumVDNode(n1, n2, n3, vt); case Op_SignumVF: return new SignumVFNode(n1, n2, n3, vt); @@ -949,8 +979,20 @@ bool VectorNode::is_vector_bitwise_not_pattern(Node* n) { return false; } + +bool VectorNode::is_reinterpret_opcode(int opc) { + switch (opc) { + case Op_ReinterpretHF2S: + case Op_ReinterpretS2HF: + return true; + default: + return false; + } +} + bool VectorNode::is_scalar_unary_op_with_equal_input_and_output_types(int opc) { switch (opc) { + case Op_SqrtHF: case Op_SqrtF: case Op_SqrtD: case Op_AbsF: @@ -976,6 +1018,7 @@ bool VectorNode::is_scalar_unary_op_with_equal_input_and_output_types(int opc) { } } + // Java API for Long.bitCount/numberOfLeadingZeros/numberOfTrailingZeros // returns int type, but Vector API for them returns long type. To unify // the implementation in backend, AutoVectorization splits the vector diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 50220c9362b..36706a7b7a1 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -136,6 +136,8 @@ class VectorNode : public TypeNode { static bool is_scalar_unary_op_with_equal_input_and_output_types(int opc); static bool is_scalar_op_that_returns_int_but_vector_op_returns_long(int opc); + static bool is_reinterpret_opcode(int opc); + static void trace_new_vector(Node* n, const char* context) { #ifdef ASSERT @@ -207,6 +209,14 @@ public: virtual int Opcode() const; }; +//------------------------------AddVHFNode-------------------------------------- +// Vector add float +class AddVHFNode : public VectorNode { +public: + AddVHFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + //------------------------------AddVFNode-------------------------------------- // Vector add float class AddVFNode : public VectorNode { @@ -401,6 +411,15 @@ class SaturatingSubVNode : public SaturatingVectorNode { virtual int Opcode() const; }; +//------------------------------SubVHFNode-------------------------------------- +// Vector subtract half float +class SubVHFNode : public VectorNode { +public: + SubVHFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + + //------------------------------SubVFNode-------------------------------------- // Vector subtract float class SubVFNode : public VectorNode { @@ -453,6 +472,14 @@ public: bool has_uint_inputs() const; }; +//------------------------------MulVFNode-------------------------------------- +// Vector multiply half float +class MulVHFNode : public VectorNode { +public: + MulVHFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + //------------------------------MulVFNode-------------------------------------- // Vector multiply float class MulVFNode : public VectorNode { @@ -503,6 +530,14 @@ public: virtual int Opcode() const; }; +//------------------------------FmaVHFNode------------------------------------- +// Vector fused-multiply-add half-precision float +class FmaVHFNode : public FmaVNode { +public: + FmaVHFNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : FmaVNode(in1, in2, in3, vt) {} + virtual int Opcode() const; +}; + //------------------------------MulReductionVINode-------------------------------------- // Vector multiply byte, short and int as a reduction class MulReductionVINode : public ReductionNode { @@ -571,6 +606,14 @@ public: virtual uint size_of() const { return sizeof(*this); } }; +//------------------------------DivVHFNode------------------------------------- +// Vector divide half float +class DivVHFNode : public VectorNode { +public: + DivVHFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + //------------------------------DivVFNode-------------------------------------- // Vector divide float class DivVFNode : public VectorNode { @@ -611,6 +654,22 @@ public: virtual int Opcode() const; }; +//------------------------------MinVHFNode------------------------------------ +// Vector Min for half floats +class MinVHFNode : public VectorNode { +public: + MinVHFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + +//------------------------------MaxVHFNode------------------------------------ +// Vector Max for half floats +class MaxVHFNode : public VectorNode { +public: + MaxVHFNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + class UMinVNode : public VectorNode { public: UMinVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2 ,vt) { @@ -731,6 +790,14 @@ class PopCountVLNode : public VectorNode { virtual int Opcode() const; }; +//------------------------------SqrtVHFNode------------------------------------- +// Vector Sqrt half-precision float +class SqrtVHFNode : public VectorNode { +public: + SqrtVHFNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} + virtual int Opcode() const; +}; + //------------------------------SqrtVFNode-------------------------------------- // Vector Sqrt float class SqrtVFNode : public VectorNode { diff --git a/src/hotspot/share/opto/vtransform.cpp b/src/hotspot/share/opto/vtransform.cpp index 18b5c09acb8..c620b4d8aa6 100644 --- a/src/hotspot/share/opto/vtransform.cpp +++ b/src/hotspot/share/opto/vtransform.cpp @@ -576,6 +576,10 @@ VTransformApplyResult VTransformElementWiseVectorNode::apply(const VLoopAnalyzer assert(first->req() == 2 && req() == 2, "only one input expected"); int vopc = VectorCastNode::opcode(opc, in1->bottom_type()->is_vect()->element_basic_type()); vn = VectorCastNode::make(vopc, in1, bt, vlen); + } else if (VectorNode::is_reinterpret_opcode(opc)) { + assert(first->req() == 2 && req() == 2, "only one input expected"); + const TypeVect* vt = TypeVect::make(bt, vlen); + vn = new VectorReinterpretNode(in1, vt, in1->bottom_type()->is_vect()); } else if (VectorNode::can_use_RShiftI_instead_of_URShiftI(first, bt)) { opc = Op_RShiftI; vn = VectorNode::make(opc, in1, in2, vlen, bt); @@ -592,8 +596,9 @@ VTransformApplyResult VTransformElementWiseVectorNode::apply(const VLoopAnalyzer vn = VectorNode::make(opc, in1, in2, vlen, bt); // unary and binary } else { assert(req() == 4, "three inputs expected"); - assert(opc == Op_FmaD || - opc == Op_FmaF || + assert(opc == Op_FmaD || + opc == Op_FmaF || + opc == Op_FmaHF || opc == Op_SignumF || opc == Op_SignumD, "element wise operation must be from this list"); diff --git a/test/hotspot/jtreg/compiler/lib/generators/AnyBitsFloat16Generator.java b/test/hotspot/jtreg/compiler/lib/generators/AnyBitsFloat16Generator.java new file mode 100644 index 00000000000..f11e8353760 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/generators/AnyBitsFloat16Generator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.lib.generators; + +/** + * Provides an any-bits float16 distribution random generator, i.e. the bits are uniformly sampled, + * thus creating any possible float16 value, including the multiple different NaN representations. + */ +final class AnyBitsFloat16Generator extends BoundGenerator { + + /** + * Creates a new {@link AnyBitsFloat16Generator}. + */ + public AnyBitsFloat16Generator(Generators g) { + super(g); + } + + @Override + public Short next() { + return (short)g.random.nextInt(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/generators/Generators.java b/test/hotspot/jtreg/compiler/lib/generators/Generators.java index 231b9822990..ac4062f19d5 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/Generators.java +++ b/test/hotspot/jtreg/compiler/lib/generators/Generators.java @@ -26,6 +26,7 @@ package compiler.lib.generators; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; import java.util.*; +import static java.lang.Float.floatToFloat16; import jdk.test.lib.Utils; @@ -165,6 +166,20 @@ public final class Generators { return new AnyBitsDoubleGenerator(this); } + /** + * Generates uniform float16s in the range of [lo, hi) (inclusive of lo, exclusive of hi). + */ + public RestrictableGenerator uniformFloat16s(short lo, short hi) { + return new UniformFloat16Generator(this, lo, hi); + } + + /** + * Generates uniform float16s in the range of [0, 1) (inclusive of 0, exclusive of 1). + */ + public RestrictableGenerator uniformFloat16s() { + return uniformFloat16s(floatToFloat16(0.0f), floatToFloat16(1.0f)); + } + /** * Generates uniform doubles in the range of [lo, hi) (inclusive of lo, exclusive of hi). */ @@ -172,6 +187,14 @@ public final class Generators { return new UniformFloatGenerator(this, lo, hi); } + /** + * Provides an any-bits float16 distribution random generator, i.e. the bits are uniformly sampled, + * thus creating any possible float16 value, including the multiple different NaN representations. + */ + public Generator anyBitsFloat16s() { + return new AnyBitsFloat16Generator(this); + } + /** * Generates uniform floats in the range of [0, 1) (inclusive of 0, exclusive of 1). */ @@ -344,6 +367,25 @@ public final class Generators { return mixed(uniformLongs(), powerOfTwoLongs(rangeSpecial), weightUniform, weightSpecial); } + /** + * Randomly pick a float16 generator. + * + * @return Random float16 generator. + */ + public Generator float16s() { + switch(random.nextInt(0, 5)) { + case 0 -> { return uniformFloat16s(floatToFloat16(-1.0f), floatToFloat16(1.0f)); } + // Well-balanced, so that multiplication reduction never explodes or collapses to zero: + case 1 -> { return uniformFloat16s(floatToFloat16(0.999f), floatToFloat16(1.001f)); } + case 2 -> { return anyBitsFloat16s(); } + // A tame distribution, mixed in with the occasional special float value: + case 3 -> { return mixedWithSpecialFloat16s(uniformFloat16s(floatToFloat16(0.999f), floatToFloat16(1.001f)), 10, 1000); } + // Generating any bits, but special values are more frequent. + case 4 -> { return mixedWithSpecialFloat16s(anyBitsFloat16s(), 100, 200); } + default -> { throw new RuntimeException("impossible"); } + } + } + /** * Randomly pick a float generator. * @@ -388,6 +430,7 @@ public final class Generators { */ public final RestrictableGenerator SPECIAL_DOUBLES = orderedRandomElement(List.of( 0d, + -0d, 1d, -1d, Double.POSITIVE_INFINITY, @@ -415,11 +458,12 @@ public final class Generators { } /** - * Generates interesting double values, which often are corner cases such as, 0, 1, -1, NaN, +/- Infinity, Min, + * Generates interesting float values, which often are corner cases such as, 0, 1, -1, NaN, +/- Infinity, Min, * Max. */ public final RestrictableGenerator SPECIAL_FLOATS = orderedRandomElement(List.of( 0f, + -0f, 1f, -1f, Float.POSITIVE_INFINITY, @@ -430,6 +474,29 @@ public final class Generators { Float.MIN_VALUE )); + /** + * Generates interesting float16 values, which often are corner cases such as, +/- 0, NaN, +/- Infinity, Min, + * Max. + */ + public final RestrictableGenerator SPECIAL_FLOAT16S = orderedRandomElement(List.of( + floatToFloat16(0.0f), + floatToFloat16(-0.0f), + floatToFloat16(Float.POSITIVE_INFINITY), + floatToFloat16(Float.NEGATIVE_INFINITY), + floatToFloat16(Float.NaN), + floatToFloat16(0x1.ffcP+15f), // MAX_VALUE + floatToFloat16(0x1.0P-14f), // MIN_NORMAL + floatToFloat16(0x1.0P-24f) // MIN_VALUE + )); + + /** + * Returns a mixed generator that mixes the provided background generator and {@link #SPECIAL_FLOAT16S} with the provided + * weights. + */ + public Generator mixedWithSpecialFloat16s(Generator background, int weightNormal, int weightSpecial) { + return mixed(background, SPECIAL_FLOAT16S, weightNormal, weightSpecial); + } + /** * Returns a mixed generator that mixes the provided background generator and {@link #SPECIAL_FLOATS} with the provided * weights. diff --git a/test/hotspot/jtreg/compiler/lib/generators/RandomnessSource.java b/test/hotspot/jtreg/compiler/lib/generators/RandomnessSource.java index 2b09b92cf3d..f2771458975 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/RandomnessSource.java +++ b/test/hotspot/jtreg/compiler/lib/generators/RandomnessSource.java @@ -42,4 +42,6 @@ public interface RandomnessSource { double nextDouble(double lo, double hi); /** Samples the next float value in the half-open interval [lo, hi) uniformly at random. */ float nextFloat(float lo, float hi); + /** Samples the next float16 value in the half-open interval [lo, hi) uniformly at random. */ + short nextFloat16(short lo, short hi); } diff --git a/test/hotspot/jtreg/compiler/lib/generators/RandomnessSourceAdapter.java b/test/hotspot/jtreg/compiler/lib/generators/RandomnessSourceAdapter.java index a8e62031cf6..599091f3a1c 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/RandomnessSourceAdapter.java +++ b/test/hotspot/jtreg/compiler/lib/generators/RandomnessSourceAdapter.java @@ -24,6 +24,8 @@ package compiler.lib.generators; import java.util.random.RandomGenerator; +import static java.lang.Float.floatToFloat16; +import static java.lang.Float.float16ToFloat; /** * An adapter for using a {@link RandomGenerator} as a {@link RandomnessSource}. @@ -65,4 +67,9 @@ public class RandomnessSourceAdapter implements RandomnessSource { public float nextFloat(float lo, float hi) { return rand.nextFloat(lo, hi); } + + @Override + public short nextFloat16(short lo, short hi) { + return floatToFloat16(rand.nextFloat(float16ToFloat(lo), float16ToFloat(hi))); + } } diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformFloat16Generator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformFloat16Generator.java new file mode 100644 index 00000000000..b2ff252ef05 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/generators/UniformFloat16Generator.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.lib.generators; + +import static java.lang.Float.*; + +/** + * Provides a uniform float16 distribution random generator, in the provided range [lo, hi). + */ +final class UniformFloat16Generator extends UniformIntersectionRestrictableGenerator { + /** + * Creates a new {@link UniformFloat16Generator}. + * + * @param lo Lower bound of the range (inclusive). + * @param hi Higher bound of the range (exclusive). + */ + public UniformFloat16Generator(Generators g, Short lo, Short hi) { + super(g, lo, hi); + } + + @Override + public Short next() { + return g.random.nextFloat16(lo(), hi()); + } + + @Override + protected RestrictableGenerator doRestrictionFromIntersection(Short lo, Short hi) { + return new UniformFloat16Generator(g, lo, hi); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 46bd48eefb2..57e4d413fea 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -244,6 +244,11 @@ public class IRNode { vectorNode(ADD_VI, "AddVI", TYPE_INT); } + public static final String ADD_VHF = VECTOR_PREFIX + "ADD_VHF" + POSTFIX; + static { + vectorNode(ADD_VHF, "AddVHF", TYPE_SHORT); + } + public static final String ADD_VF = VECTOR_PREFIX + "ADD_VF" + POSTFIX; static { vectorNode(ADD_VF, "AddVF", TYPE_FLOAT); @@ -679,6 +684,11 @@ public class IRNode { beforeMatchingNameRegex(DIV_MOD_L, "DivModL"); } + public static final String DIV_VHF = VECTOR_PREFIX + "DIV_VHF" + POSTFIX; + static { + vectorNode(DIV_VHF, "DivVHF", TYPE_SHORT); + } + public static final String DIV_VF = VECTOR_PREFIX + "DIV_VF" + POSTFIX; static { vectorNode(DIV_VF, "DivVF", TYPE_FLOAT); @@ -716,6 +726,11 @@ public class IRNode { optoOnly(FIELD_ACCESS, regex); } + public static final String FMA_VHF = VECTOR_PREFIX + "FMA_VHF" + POSTFIX; + static { + vectorNode(FMA_VHF, "FmaVHF", TYPE_SHORT); + } + public static final String FMA_VF = VECTOR_PREFIX + "FMA_VF" + POSTFIX; static { vectorNode(FMA_VF, "FmaVF", TYPE_FLOAT); @@ -1148,6 +1163,11 @@ public class IRNode { vectorNode(MAX_VI, "MaxV", TYPE_INT); } + public static final String MAX_VHF = VECTOR_PREFIX + "MAX_VHF" + POSTFIX; + static { + vectorNode(MAX_VHF, "MaxVHF", TYPE_SHORT); + } + public static final String MAX_VF = VECTOR_PREFIX + "MAX_VF" + POSTFIX; static { vectorNode(MAX_VF, "MaxV", TYPE_FLOAT); @@ -1248,6 +1268,11 @@ public class IRNode { vectorNode(MIN_VI, "MinV", TYPE_INT); } + public static final String MIN_VHF = VECTOR_PREFIX + "MIN_VHF" + POSTFIX; + static { + vectorNode(MIN_VHF, "MinVHF", TYPE_SHORT); + } + public static final String MIN_VF = VECTOR_PREFIX + "MIN_VF" + POSTFIX; static { vectorNode(MIN_VF, "MinV", TYPE_FLOAT); @@ -1349,6 +1374,11 @@ public class IRNode { vectorNode(MUL_VI, "MulVI", TYPE_INT); } + public static final String MUL_VHF = VECTOR_PREFIX + "MUL_VHF" + POSTFIX; + static { + vectorNode(MUL_VHF, "MulVHF", TYPE_SHORT); + } + public static final String MUL_VF = VECTOR_PREFIX + "MUL_VF" + POSTFIX; static { vectorNode(MUL_VF, "MulVF", TYPE_FLOAT); @@ -1760,6 +1790,11 @@ public class IRNode { vectorNode(SIGNUM_VF, "SignumVF", TYPE_FLOAT); } + public static final String SQRT_VHF = VECTOR_PREFIX + "SQRT_VHF" + POSTFIX; + static { + vectorNode(SQRT_VHF, "SqrtVHF", TYPE_SHORT); + } + public static final String SQRT_HF = PREFIX + "SQRT_HF" + POSTFIX; static { beforeMatchingNameRegex(SQRT_HF, "SqrtHF"); @@ -1946,6 +1981,11 @@ public class IRNode { vectorNode(SUB_VL, "SubVL", TYPE_LONG); } + public static final String SUB_VHF = VECTOR_PREFIX + "SUB_VHF" + POSTFIX; + static { + vectorNode(SUB_VHF, "SubVHF", TYPE_SHORT); + } + public static final String SUB_VF = VECTOR_PREFIX + "SUB_VF" + POSTFIX; static { vectorNode(SUB_VF, "SubVF", TYPE_FLOAT); diff --git a/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java b/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java new file mode 100644 index 00000000000..d295c3618b9 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 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 + * 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 8346236 +* @summary Auto-vectorization support for various Float16 operations +* @modules jdk.incubator.vector +* @library /test/lib / +* @compile TestFloat16VectorOperations.java +* @run driver compiler.vectorization.TestFloat16VectorOperations +*/ + +package compiler.vectorization; +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.Float16; +import static jdk.incubator.vector.Float16.*; +import static java.lang.Float.*; +import jdk.test.lib.*; +import compiler.lib.generators.Generator; +import static compiler.lib.generators.Generators.G; + +public class TestFloat16VectorOperations { + private short[] input1; + private short[] input2; + private short[] input3; + private short[] output; + private static short SCALAR_FP16 = (short)0x7777; + private static final int LEN = 2048; + + public static void main(String args[]) { + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + } + + public static boolean assertResults(short expected, short actual) { + Float16 expected_fp16 = shortBitsToFloat16(expected); + Float16 actual_fp16 = shortBitsToFloat16(actual); + return !expected_fp16.equals(actual_fp16); + } + + public TestFloat16VectorOperations() { + input1 = new short[LEN]; + input2 = new short[LEN]; + input3 = new short[LEN]; + output = new short[LEN]; + + short min_value = float16ToRawShortBits(Float16.MIN_VALUE); + short max_value = float16ToRawShortBits(Float16.MAX_VALUE); + Generator gen = G.float16s(); + for (int i = 0; i < LEN; ++i) { + input1[i] = gen.next(); + input2[i] = gen.next(); + input3[i] = gen.next(); + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.ADD_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorAddFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(add(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorAddFloat16") + public void checkResultAdd() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) + float16ToFloat(input2[i])); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.SUB_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorSubFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(subtract(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorSubFloat16") + public void checkResultSub() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) - float16ToFloat(input2[i])); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.MUL_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMulFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(multiply(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMulFloat16") + public void checkResultMul() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) * float16ToFloat(input2[i])); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.DIV_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorDivFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(divide(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorDivFloat16") + public void checkResultDiv() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) / float16ToFloat(input2[i])); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.MIN_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMinFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(min(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMinFloat16") + public void checkResultMin() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.min(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.MAX_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMaxFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(max(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMaxFloat16") + public void checkResultMax() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.max(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.SQRT_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorSqrtFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(sqrt(shortBitsToFloat16(input1[i]))); + } + } + + @Check(test="vectorSqrtFloat16") + public void checkResultSqrt() { + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(sqrt(shortBitsToFloat16(input1[i]))); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input = " + input1[i] + + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorFmaFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), + shortBitsToFloat16(input3[i]))); + } + } + + @Check(test="vectorFmaFloat16") + public void checkResultFma() { + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), + shortBitsToFloat16(input3[i]))); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + "input3 = " + input3[i] + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.FMA_VHF, " >= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorFmaFloat16ScalarMixedConstants() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(SCALAR_FP16), + shortBitsToFloat16(floatToFloat16(3.0f)))); + } + } + + @Check(test="vectorFmaFloat16ScalarMixedConstants") + public void checkResultFmaScalarMixedConstants() { + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(SCALAR_FP16), + shortBitsToFloat16(floatToFloat16(3.0f)))); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + SCALAR_FP16 + + "input3 = 3.0 " + "output = " + output[i] + " expected = " + expected); + } + } + } + + + @Test + @Warmup(10000) + @IR(counts = {IRNode.FMA_VHF, " >= 1"}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorFmaFloat16MixedConstants() { + short input3 = floatToFloat16(3.0f); + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), shortBitsToFloat16(input3))); + } + } + + @Check(test="vectorFmaFloat16MixedConstants") + public void checkResultFmaMixedConstants() { + short input3 = floatToFloat16(3.0f); + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), shortBitsToFloat16(input3))); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + + "input3 = " + input3 + " output = " + output[i] + " expected = " + expected); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = {IRNode.FMA_VHF, " 0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorFmaFloat16AllConstants() { + short input1 = floatToFloat16(1.0f); + short input2 = floatToFloat16(2.0f); + short input3 = floatToFloat16(3.0f); + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1), shortBitsToFloat16(input2), shortBitsToFloat16(input3))); + } + } + + @Check(test="vectorFmaFloat16AllConstants") + public void checkResultFmaAllConstants() { + short input1 = floatToFloat16(1.0f); + short input2 = floatToFloat16(2.0f); + short input3 = floatToFloat16(3.0f); + for (int i = 0; i < LEN; ++i) { + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1), shortBitsToFloat16(input2), shortBitsToFloat16(input3))); + if (assertResults(expected, output[i])) { + throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1 + " input2 = " + input2 + + "input3 = " + input3 + " output = " + output[i] + " expected = " + expected); + } + } + } +} diff --git a/test/hotspot/jtreg/testlibrary_tests/generators/tests/MockRandomnessSource.java b/test/hotspot/jtreg/testlibrary_tests/generators/tests/MockRandomnessSource.java index c8d5f325706..21c7a8d250c 100644 --- a/test/hotspot/jtreg/testlibrary_tests/generators/tests/MockRandomnessSource.java +++ b/test/hotspot/jtreg/testlibrary_tests/generators/tests/MockRandomnessSource.java @@ -48,6 +48,7 @@ class MockRandomnessSource implements RandomnessSource { private final Queue> boundedIntegerQueue = new ArrayDeque<>(); private final Queue> boundedDoubleQueue = new ArrayDeque<>(); private final Queue> boundedFloatQueue = new ArrayDeque<>(); + private final Queue> boundedFloat16Queue = new ArrayDeque<>(); private T dequeueBounded(Queue> queue, T lo, T hi) { Bounded bounded = queue.remove(); @@ -91,6 +92,11 @@ class MockRandomnessSource implements RandomnessSource { return this; } + public MockRandomnessSource enqueueFloat16(short lo, short hi, short value) { + boundedFloat16Queue.add(new Bounded<>(lo, hi, value)); + return this; + } + public MockRandomnessSource checkEmpty() { checkQueueEmpty(unboundedLongQueue, "unbounded longs"); checkQueueEmpty(unboundedIntegerQueue, "unbounded integers"); @@ -98,6 +104,7 @@ class MockRandomnessSource implements RandomnessSource { checkQueueEmpty(boundedIntegerQueue, "bounded integers"); checkQueueEmpty(boundedDoubleQueue, "bounded doubles"); checkQueueEmpty(boundedFloatQueue, "bounded floats"); + checkQueueEmpty(boundedFloat16Queue, "bounded float16s"); return this; } @@ -130,4 +137,9 @@ class MockRandomnessSource implements RandomnessSource { public float nextFloat(float lo, float hi) { return dequeueBounded(boundedFloatQueue, lo, hi); } + + @Override + public short nextFloat16(short lo, short hi) { + return dequeueBounded(boundedFloat16Queue, lo, hi); + } } diff --git a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java index 203256ad7b8..8ad0c17ba98 100644 --- a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java +++ b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java @@ -57,6 +57,7 @@ public class TestGenerators { testUniformLongs(); testAnyBits(); testUniformFloat(); + testUniformFloat16(); testUniformDouble(); testSingle(); testMixed(); @@ -64,6 +65,7 @@ public class TestGenerators { specialInt(); specialLong(); testSpecialFloat(); + testSpecialFloat16(); testSpecialDouble(); testSafeRestrict(); testFill(); @@ -157,7 +159,7 @@ public class TestGenerators { .enqueueInteger(0, 10, 3) .enqueueDouble(0, 1, 3.4d) .enqueueInteger(0, 10, 6) - .enqueueInteger(0, 9, 1); + .enqueueInteger(0, 10, 1); var g = mockGS.mixedWithSpecialDoubles(mockGS.uniformDoubles(), 5, 5); Asserts.assertEQ(g.next(), 3.4d); Asserts.assertEQ(g.next(), -1d); @@ -169,12 +171,34 @@ public class TestGenerators { .enqueueInteger(0, 10, 3) .enqueueFloat(0, 1, 3.4f) .enqueueInteger(0, 10, 6) - .enqueueInteger(0, 9, 1); + .enqueueInteger(0, 10, 1); var g = mockGS.mixedWithSpecialFloats(mockGS.uniformFloats(), 5, 5); Asserts.assertEQ(g.next(), 3.4f); Asserts.assertEQ(g.next(), -1f); } + static void testSpecialFloat16() { + mockSource + .checkEmpty() + .enqueueInteger(0, 8, 2) + .enqueueFloat16((short)0, (short)15360, (short)17010) + .enqueueInteger(0, 8, 6) + .enqueueInteger(0, 8, 5) + .enqueueInteger(0, 8, 7) + .enqueueInteger(0, 8, 4); + var g = mockGS.mixedWithSpecialFloat16s(mockGS.uniformFloat16s(), 4, 4); + Asserts.assertEQ(g.next(), (short)17010); + Asserts.assertEQ(g.next(), (short)31743); + Asserts.assertEQ(g.next(), (short)1024); + } + + static void testUniformFloat16() { + mockSource.checkEmpty().enqueueFloat16((short)0, (short)10, (short)17664); + Asserts.assertEQ(mockGS.uniformFloat16s((short)0, (short)10).next(), (short)17664); + mockSource.checkEmpty().enqueueFloat16((short)0, (short)5, (short)31744); + Asserts.assertEQ(mockGS.uniformFloat16s((short)0, (short)5).next(), (short)31744); + } + static void testUniformFloat() { mockSource.checkEmpty().enqueueFloat(-1, 10, 3.14159f); Asserts.assertEQ(mockGS.uniformFloats(-1, 10).next(), 3.14159f); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java index a0a462ad6b1..ebbfbb01cc6 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java @@ -41,6 +41,8 @@ public class Float16OperationsBenchmark { short [] vector1; short [] vector2; short [] vector3; + short [] vector4; + short [] vector5; boolean [] vectorPredicate; static final short f16_one = Float.floatToFloat16(1.0f); @@ -53,12 +55,19 @@ public class Float16OperationsBenchmark { vector1 = new short[vectorDim]; vector2 = new short[vectorDim]; vector3 = new short[vectorDim]; + vector4 = new short[vectorDim]; + vector5 = new short[vectorDim]; vectorPredicate = new boolean[vectorDim]; IntStream.range(0, vectorDim).forEach(i -> {vector1[i] = Float.floatToFloat16((float)i);}); IntStream.range(0, vectorDim).forEach(i -> {vector2[i] = Float.floatToFloat16((float)i);}); IntStream.range(0, vectorDim).forEach(i -> {vector3[i] = Float.floatToFloat16((float)i);}); - + IntStream.range(0, vectorDim).forEach(i -> {vector4[i] = ((i & 0x1) == 0) ? + float16ToRawShortBits(Float16.POSITIVE_INFINITY) : + Float.floatToFloat16((float)i);}); + IntStream.range(0, vectorDim).forEach(i -> {vector5[i] = ((i & 0x1) == 0) ? + float16ToRawShortBits(Float16.NaN) : + Float.floatToFloat16((float)i);}); // Special Values Float16 [] specialValues = {Float16.NaN, Float16.NEGATIVE_INFINITY, Float16.valueOf(0.0), Float16.valueOf(-0.0), Float16.POSITIVE_INFINITY}; IntStream.range(0, vectorDim).forEach( @@ -140,7 +149,7 @@ public class Float16OperationsBenchmark { @Benchmark public void isNaNStoreBenchmark() { for (int i = 0; i < vectorDim; i++) { - vectorPredicate[i] = Float16.isNaN(shortBitsToFloat16(vector1[i])); + vectorPredicate[i] = isNaN(shortBitsToFloat16(vector1[i])); } } @@ -148,7 +157,7 @@ public class Float16OperationsBenchmark { @Benchmark public void isNaNCMovBenchmark() { for (int i = 0; i < vectorDim; i++) { - vectorRes[i] = Float16.isNaN(shortBitsToFloat16(vector1[i])) ? f16_one : f16_two; + vectorRes[i] = isNaN(shortBitsToFloat16(vector5[i])) ? vector1[i] : vector2[i]; } } @@ -156,7 +165,7 @@ public class Float16OperationsBenchmark { @Benchmark public void isInfiniteStoreBenchmark() { for (int i = 0; i < vectorDim; i++) { - vectorPredicate[i] = Float16.isInfinite(shortBitsToFloat16(vector1[i])); + vectorPredicate[i] = isInfinite(shortBitsToFloat16(vector1[i])); } } @@ -164,7 +173,7 @@ public class Float16OperationsBenchmark { @Benchmark public void isInfiniteCMovBenchmark() { for (int i = 0; i < vectorDim; i++) { - vectorRes[i] = Float16.isInfinite(shortBitsToFloat16(vector1[i])) ? f16_one : f16_two; + vectorRes[i] = isInfinite(shortBitsToFloat16(vector4[i])) ? vector1[i] : vector2[i]; } } @@ -172,7 +181,7 @@ public class Float16OperationsBenchmark { @Benchmark public void isFiniteStoreBenchmark() { for (int i = 0; i < vectorDim; i++) { - vectorPredicate[i] = Float16.isFinite(shortBitsToFloat16(vector1[i])); + vectorPredicate[i] = isFinite(shortBitsToFloat16(vector1[i])); } } @@ -180,7 +189,7 @@ public class Float16OperationsBenchmark { @Benchmark public void isFiniteCMovBenchmark() { for (int i = 0; i < vectorDim; i++) { - vectorRes[i] = Float16.isFinite(shortBitsToFloat16(vector1[i])) ? f16_one : f16_two; + vectorRes[i] = isFinite(shortBitsToFloat16(vector4[i])) ? vector1[i] : vector2[i]; } } @@ -293,4 +302,16 @@ public class Float16OperationsBenchmark { } return float16ToRawShortBits(sqrt(shortBitsToFloat16(floatToFloat16(distRes)))); } + + @Benchmark + public short dotProductFP16() { + short distRes = floatToFloat16(0.0f); + for (int i = 0; i < vectorDim; i++) { + vectorRes[i] = float16ToRawShortBits(multiply(shortBitsToFloat16(vector1[i]), shortBitsToFloat16(vector2[i]))); + } + for (int i = 0; i < vectorDim; i++) { + distRes = float16ToRawShortBits(add(shortBitsToFloat16(vectorRes[i]), shortBitsToFloat16(distRes))); + } + return distRes; + } } From 51b3d6bba29b256616cf00c0be7a7fe0f97621ab Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Thu, 10 Apr 2025 10:18:46 +0000 Subject: [PATCH 110/843] 8352431: java/net/httpclient/EmptyAuthenticate.java uses "localhost" Reviewed-by: dfuchs, jpai --- .../net/httpclient/EmptyAuthenticate.java | 143 +++++++++++++----- 1 file changed, 104 insertions(+), 39 deletions(-) diff --git a/test/jdk/java/net/httpclient/EmptyAuthenticate.java b/test/jdk/java/net/httpclient/EmptyAuthenticate.java index 2e80e1bdc81..ca5c41594e8 100644 --- a/test/jdk/java/net/httpclient/EmptyAuthenticate.java +++ b/test/jdk/java/net/httpclient/EmptyAuthenticate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,55 +24,120 @@ /* * @test * @bug 8263899 - * @summary HttpClient throws NPE in AuthenticationFilter when parsing www-authenticate head - * - * @run main/othervm EmptyAuthenticate + * @summary Verifies that empty `WWW-Authenticate` header is correctly parsed + * @library /test/jdk/java/net/httpclient/lib + * /test/lib + * @build jdk.httpclient.test.lib.common.HttpServerAdapters + * jdk.test.lib.net.SimpleSSLContext + * @run junit EmptyAuthenticate */ -import com.sun.net.httpserver.HttpServer; + +import jdk.httpclient.test.lib.common.HttpServerAdapters; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; +import jdk.test.lib.net.SimpleSSLContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.net.ssl.SSLContext; import java.io.IOException; -import java.io.OutputStream; -import java.net.InetSocketAddress; import java.net.URI; -import java.net.URISyntaxException; import java.net.http.HttpClient; +import java.net.http.HttpClient.Version; +import java.net.http.HttpHeaders; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.stream.Stream; -public class EmptyAuthenticate { +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static org.junit.jupiter.api.Assertions.assertEquals; - public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException { - int port = 0; +class EmptyAuthenticate { - //start server: - HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); - port = server.getAddress().getPort(); - server.createContext("/", exchange -> { - String response = "test body"; - //this empty header will make the HttpClient throw NPE - exchange.getResponseHeaders().add("www-authenticate", ""); - exchange.sendResponseHeaders(401, response.length()); - OutputStream os = exchange.getResponseBody(); - os.write(response.getBytes()); - os.close(); - }); - server.start(); + private static final SSLContext SSL_CONTEXT = createSslContext(); - HttpResponse response = null; - //run client: + private static final String WWW_AUTH_HEADER_NAME = "WWW-Authenticate"; + + private static SSLContext createSslContext() { try { - HttpClient httpClient = HttpClient.newHttpClient(); - HttpRequest request = HttpRequest.newBuilder(new URI("http://localhost:" + port + "/")).GET().build(); - //this line will throw NPE (wrapped by IOException) when parsing empty www-authenticate response header in AuthenticationFilter: - response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - boolean ok = !response.headers().firstValue("WWW-Authenticate").isEmpty(); - if (!ok) { - throw new RuntimeException("WWW-Authenicate missing"); - } - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("Test failed"); - } finally { - server.stop(0); + return new SimpleSSLContext().get(); + } catch (IOException exception) { + throw new RuntimeException(exception); } } + + @ParameterizedTest + @MethodSource("args") + void test(Version version, boolean secure) throws Exception { + String handlerPath = "/%s/%s/".formatted(EmptyAuthenticate.class.getSimpleName(), version); + String uriPath = handlerPath + (secure ? 's' : 'c'); + HttpTestServer server = createServer(version, secure, handlerPath); + try (HttpClient client = createClient(version, secure)) { + HttpRequest request = createRequest(server, secure, uriPath); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.discarding()); + HttpHeaders responseHeaders = response.headers(); + assertEquals( + "", + responseHeaders.firstValue(WWW_AUTH_HEADER_NAME).orElse(null), + () -> "was expecting empty `%s` header in: %s".formatted( + WWW_AUTH_HEADER_NAME, responseHeaders.map())); + } finally { + server.stop(); + } + } + + static Stream args() { + return Stream + .of(Version.HTTP_1_1, Version.HTTP_2) + .flatMap(version -> Stream + .of(true, false) + .map(secure -> Arguments.of(version, secure))); + } + + private static HttpTestServer createServer(Version version, boolean secure, String uriPath) + throws IOException { + HttpTestServer server = secure + ? HttpTestServer.create(version, SSL_CONTEXT) + : HttpTestServer.create(version); + HttpTestHandler handler = new ServerHandlerRespondingWithEmptyWwwAuthHeader(); + server.addHandler(handler, uriPath); + server.start(); + return server; + } + + private static final class ServerHandlerRespondingWithEmptyWwwAuthHeader implements HttpTestHandler { + + private int responseIndex = 0; + + @Override + public synchronized void handle(HttpServerAdapters.HttpTestExchange exchange) throws IOException { + try (exchange) { + exchange.getResponseHeaders().addHeader(WWW_AUTH_HEADER_NAME, ""); + byte[] responseBodyBytes = "test body %d" + .formatted(responseIndex) + .getBytes(StandardCharsets.US_ASCII); + exchange.sendResponseHeaders(401, responseBodyBytes.length); + exchange.getResponseBody().write(responseBodyBytes); + } finally { + responseIndex++; + } + } + + } + + private static HttpClient createClient(Version version, boolean secure) { + HttpClient.Builder clientBuilder = HttpClient.newBuilder().version(version).proxy(NO_PROXY); + if (secure) { + clientBuilder.sslContext(SSL_CONTEXT); + } + return clientBuilder.build(); + } + + private static HttpRequest createRequest(HttpTestServer server, boolean secure, String uriPath) { + URI uri = URI.create("%s://%s%s".formatted(secure ? "https" : "http", server.serverAuthority(), uriPath)); + return HttpRequest.newBuilder(uri).version(server.getVersion()).GET().build(); + } + } From 6c2667018a49ac78c3a01dc4d52ff6cdf39b7647 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Thu, 10 Apr 2025 10:21:32 +0000 Subject: [PATCH 111/843] 8324686: Remove redefinition of NULL for MSVC Reviewed-by: shade, dholmes --- .../utilities/globalDefinitions_visCPP.hpp | 19 ------------------- test/hotspot/jtreg/sources/TestNoNULL.java | 3 +-- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp index 83d07557287..4b4a0f4d838 100644 --- a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp @@ -54,25 +54,6 @@ #error unsupported platform #endif -// 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures -// When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in -// system header files. On 32-bit architectures, there is no problem. -// On 64-bit architectures, defining NULL as a 32-bit constant can cause -// problems with varargs functions: C++ integral promotion rules say for -// varargs, we pass the argument 0 as an int. So, if NULL was passed to a -// varargs function it will remain 32-bits. Depending on the calling -// convention of the machine, if the argument is passed on the stack then -// only 32-bits of the "NULL" pointer may be initialized to zero. The -// other 32-bits will be garbage. If the varargs function is expecting a -// pointer when it extracts the argument, then we may have a problem. -// -// Solution: For 64-bit architectures, redefine NULL as 64-bit constant 0. -#undef NULL -// 64-bit Windows uses a P64 data model (not LP64, although we define _LP64) -// Since longs are 32-bit we cannot use 0L here. Use the Visual C++ specific -// 64-bit integer-suffix (LL) instead. -#define NULL 0LL - typedef int64_t ssize_t; // Non-standard stdlib-like stuff: diff --git a/test/hotspot/jtreg/sources/TestNoNULL.java b/test/hotspot/jtreg/sources/TestNoNULL.java index 73a415466fe..12fe46a609e 100644 --- a/test/hotspot/jtreg/sources/TestNoNULL.java +++ b/test/hotspot/jtreg/sources/TestNoNULL.java @@ -74,8 +74,7 @@ public class TestNoNULL { private static void initializeExcludedPaths(Path rootDir) { List sourceExclusions = List.of( "src/hotspot/share/prims/jvmti.xml", - "src/hotspot/share/prims/jvmti.xsl", - "src/hotspot/share/utilities/globalDefinitions_visCPP.hpp" + "src/hotspot/share/prims/jvmti.xsl" ); List testExclusions = List.of( From 7e69b98e0548803b85b04b518929c073f8ffaf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Thu, 10 Apr 2025 11:37:20 +0000 Subject: [PATCH 112/843] 8350441: ZGC: Overhaul Page Allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Axel Boldt-Christmas Co-authored-by: Erik Österlund Co-authored-by: Stefan Karlsson Co-authored-by: Stefan Johansson Reviewed-by: stefank, aboldtch, eosterlund --- .../cpu/aarch64/gc/z/zAddress_aarch64.cpp | 2 +- src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp | 2 +- src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp | 2 +- src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp | 2 +- src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp | 15 +- .../bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp | 17 +- .../bsd/gc/z/zPhysicalMemoryBacking_bsd.hpp | 10 +- src/hotspot/os/linux/gc/z/zNUMA_linux.cpp | 15 +- .../gc/z/zPhysicalMemoryBacking_linux.cpp | 75 +- .../gc/z/zPhysicalMemoryBacking_linux.hpp | 32 +- ...ix.cpp => zVirtualMemoryManager_posix.cpp} | 13 +- .../os/windows/gc/z/zInitialize_windows.cpp | 3 + src/hotspot/os/windows/gc/z/zNUMA_windows.cpp | 14 +- .../gc/z/zPhysicalMemoryBacking_windows.cpp | 52 +- .../gc/z/zPhysicalMemoryBacking_windows.hpp | 8 +- ....cpp => zVirtualMemoryManager_windows.cpp} | 59 +- src/hotspot/share/gc/z/vmStructs_z.hpp | 22 +- src/hotspot/share/gc/z/zAddress.cpp | 12 + src/hotspot/share/gc/z/zAddress.hpp | 29 +- src/hotspot/share/gc/z/zAddress.inline.hpp | 259 +- src/hotspot/share/gc/z/zAddressSpaceLimit.cpp | 12 + src/hotspot/share/gc/z/zAddressSpaceLimit.hpp | 4 +- src/hotspot/share/gc/z/zAllocationFlags.hpp | 31 +- src/hotspot/share/gc/z/zArguments.cpp | 2 +- src/hotspot/share/gc/z/zArray.hpp | 44 +- src/hotspot/share/gc/z/zArray.inline.hpp | 89 +- src/hotspot/share/gc/z/zCollectedHeap.cpp | 7 +- src/hotspot/share/gc/z/zGeneration.cpp | 34 +- src/hotspot/share/gc/z/zGranuleMap.hpp | 5 +- src/hotspot/share/gc/z/zGranuleMap.inline.hpp | 13 +- src/hotspot/share/gc/z/zHeap.cpp | 46 +- src/hotspot/share/gc/z/zHeap.hpp | 5 +- src/hotspot/share/gc/z/zInitialize.cpp | 2 +- src/hotspot/share/gc/z/zIntrusiveRBTree.hpp | 293 ++ .../share/gc/z/zIntrusiveRBTree.inline.hpp | 1351 +++++++++ src/hotspot/share/gc/z/zList.hpp | 14 +- src/hotspot/share/gc/z/zList.inline.hpp | 29 +- src/hotspot/share/gc/z/zLiveMap.cpp | 41 +- src/hotspot/share/gc/z/zLiveMap.hpp | 15 +- src/hotspot/share/gc/z/zLiveMap.inline.hpp | 8 +- src/hotspot/share/gc/z/zMappedCache.cpp | 629 ++++ src/hotspot/share/gc/z/zMappedCache.hpp | 112 + src/hotspot/share/gc/z/zMemory.cpp | 284 -- src/hotspot/share/gc/z/zMemory.hpp | 104 - src/hotspot/share/gc/z/zMemory.inline.hpp | 80 - src/hotspot/share/gc/z/zNMT.cpp | 7 +- src/hotspot/share/gc/z/zNMT.hpp | 11 +- src/hotspot/share/gc/z/zNUMA.cpp | 13 +- src/hotspot/share/gc/z/zNUMA.hpp | 9 + src/hotspot/share/gc/z/zNUMA.inline.hpp | 24 + src/hotspot/share/gc/z/zObjectAllocator.cpp | 8 +- src/hotspot/share/gc/z/zPage.cpp | 114 +- src/hotspot/share/gc/z/zPage.hpp | 62 +- src/hotspot/share/gc/z/zPage.inline.hpp | 38 +- src/hotspot/share/gc/z/zPageAllocator.cpp | 2641 +++++++++++++---- src/hotspot/share/gc/z/zPageAllocator.hpp | 295 +- src/hotspot/share/gc/z/zPageCache.cpp | 332 --- src/hotspot/share/gc/z/zPageCache.hpp | 66 - src/hotspot/share/gc/z/zPageTable.cpp | 4 - src/hotspot/share/gc/z/zPageTable.inline.hpp | 4 +- src/hotspot/share/gc/z/zPhysicalMemory.cpp | 386 --- src/hotspot/share/gc/z/zPhysicalMemory.hpp | 105 - .../share/gc/z/zPhysicalMemory.inline.hpp | 74 - .../share/gc/z/zPhysicalMemoryManager.cpp | 376 +++ .../share/gc/z/zPhysicalMemoryManager.hpp | 79 + src/hotspot/share/gc/z/zRange.hpp | 76 + src/hotspot/share/gc/z/zRange.inline.hpp | 144 + src/hotspot/share/gc/z/zRangeRegistry.hpp | 150 + .../share/gc/z/zRangeRegistry.inline.hpp | 469 +++ src/hotspot/share/gc/z/zRelocate.cpp | 20 +- src/hotspot/share/gc/z/zRemembered.cpp | 2 - src/hotspot/share/gc/z/zRememberedSet.cpp | 6 - src/hotspot/share/gc/z/zRememberedSet.hpp | 3 +- src/hotspot/share/gc/z/zUncommitter.cpp | 27 +- src/hotspot/share/gc/z/zUncommitter.hpp | 9 +- src/hotspot/share/gc/z/zUnmapper.cpp | 129 - src/hotspot/share/gc/z/zUtils.hpp | 12 +- src/hotspot/share/gc/z/zUtils.inline.hpp | 33 +- src/hotspot/share/gc/z/zValue.hpp | 19 +- src/hotspot/share/gc/z/zValue.inline.hpp | 35 +- src/hotspot/share/gc/z/zVirtualMemory.cpp | 257 -- src/hotspot/share/gc/z/zVirtualMemory.hpp | 63 +- .../share/gc/z/zVirtualMemory.inline.hpp | 51 +- .../share/gc/z/zVirtualMemoryManager.cpp | 357 +++ .../share/gc/z/zVirtualMemoryManager.hpp | 109 + .../gc/z/zVirtualMemoryManager.inline.hpp | 52 + src/hotspot/share/gc/z/z_globals.hpp | 14 +- src/hotspot/share/jfr/metadata/metadata.xml | 20 +- src/hotspot/share/utilities/vmError.cpp | 6 + src/hotspot/share/utilities/vmError.hpp | 10 +- .../classes/sun/jvm/hotspot/gc/z/ZNUMA.java} | 51 +- .../sun/jvm/hotspot/gc/z/ZPageAllocator.java | 28 +- .../sun/jvm/hotspot/gc/z/ZPartition.java | 63 + .../jvm/hotspot/gc/z/ZPerNUMAZPartition.java | 61 + src/jdk.jfr/share/conf/jfr/default.jfc | 5 - src/jdk.jfr/share/conf/jfr/profile.jfc | 5 - test/hotspot/gtest/gc/z/test_zArray.cpp | 117 +- test/hotspot/gtest/gc/z/test_zForwarding.cpp | 6 +- .../gtest/gc/z/test_zIntrusiveRBTree.cpp | 379 +++ .../gtest/gc/z/test_zMapper_windows.cpp | 49 +- test/hotspot/gtest/gc/z/test_zMemory.cpp | 86 - test/hotspot/gtest/gc/z/test_zNUMA.cpp | 115 + .../gtest/gc/z/test_zPhysicalMemory.cpp | 218 -- .../gtest/gc/z/test_zVirtualMemory.cpp | 136 +- .../gtest/gc/z/test_zVirtualMemoryManager.cpp | 173 +- test/hotspot/gtest/gc/z/zunittest.hpp | 23 +- test/hotspot/jtreg/ProblemList-zgc.txt | 6 +- .../jtreg/gc/z/TestMappedCacheHarvest.java | 97 + .../jtreg/gc/z/TestPageCacheFlush.java | 82 - test/hotspot/jtreg/gc/z/TestUncommit.java | 6 +- ...stZForceDiscontiguousHeapReservations.java | 4 +- test/hotspot/jtreg/gc/z/TestZNMT.java | 4 +- .../jtreg/serviceability/sa/TestUniverse.java | 5 +- .../event/gc/detailed/TestZUnmapEvent.java | 70 - test/lib/jdk/test/lib/jfr/EventNames.java | 3 +- 115 files changed, 8564 insertions(+), 3846 deletions(-) rename src/hotspot/os/posix/gc/z/{zVirtualMemory_posix.cpp => zVirtualMemoryManager_posix.cpp} (81%) rename src/hotspot/os/windows/gc/z/{zVirtualMemory_windows.cpp => zVirtualMemoryManager_windows.cpp} (81%) create mode 100644 src/hotspot/share/gc/z/zIntrusiveRBTree.hpp create mode 100644 src/hotspot/share/gc/z/zIntrusiveRBTree.inline.hpp create mode 100644 src/hotspot/share/gc/z/zMappedCache.cpp create mode 100644 src/hotspot/share/gc/z/zMappedCache.hpp delete mode 100644 src/hotspot/share/gc/z/zMemory.cpp delete mode 100644 src/hotspot/share/gc/z/zMemory.hpp delete mode 100644 src/hotspot/share/gc/z/zMemory.inline.hpp delete mode 100644 src/hotspot/share/gc/z/zPageCache.cpp delete mode 100644 src/hotspot/share/gc/z/zPageCache.hpp delete mode 100644 src/hotspot/share/gc/z/zPhysicalMemory.cpp delete mode 100644 src/hotspot/share/gc/z/zPhysicalMemory.hpp delete mode 100644 src/hotspot/share/gc/z/zPhysicalMemory.inline.hpp create mode 100644 src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp create mode 100644 src/hotspot/share/gc/z/zPhysicalMemoryManager.hpp create mode 100644 src/hotspot/share/gc/z/zRange.hpp create mode 100644 src/hotspot/share/gc/z/zRange.inline.hpp create mode 100644 src/hotspot/share/gc/z/zRangeRegistry.hpp create mode 100644 src/hotspot/share/gc/z/zRangeRegistry.inline.hpp delete mode 100644 src/hotspot/share/gc/z/zUnmapper.cpp delete mode 100644 src/hotspot/share/gc/z/zVirtualMemory.cpp create mode 100644 src/hotspot/share/gc/z/zVirtualMemoryManager.cpp create mode 100644 src/hotspot/share/gc/z/zVirtualMemoryManager.hpp create mode 100644 src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp rename src/{hotspot/share/gc/z/zUnmapper.hpp => jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZNUMA.java} (52%) create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPartition.java create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZPerNUMAZPartition.java create mode 100644 test/hotspot/gtest/gc/z/test_zIntrusiveRBTree.cpp delete mode 100644 test/hotspot/gtest/gc/z/test_zMemory.cpp create mode 100644 test/hotspot/gtest/gc/z/test_zNUMA.cpp delete mode 100644 test/hotspot/gtest/gc/z/test_zPhysicalMemory.cpp create mode 100644 test/hotspot/jtreg/gc/z/TestMappedCacheHarvest.java delete mode 100644 test/hotspot/jtreg/gc/z/TestPageCacheFlush.java delete mode 100644 test/jdk/jdk/jfr/event/gc/detailed/TestZUnmapEvent.java diff --git a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp index a58c91a6a41..20e37528c04 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp @@ -95,7 +95,7 @@ size_t ZPlatformAddressOffsetBits() { static const size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1; const size_t max_address_offset_bits = valid_max_address_offset_bits - 3; const size_t min_address_offset_bits = max_address_offset_bits - 2; - const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); + const size_t address_offset = ZGlobalsPointers::min_address_offset_request(); const size_t address_offset_bits = log2i_exact(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); } diff --git a/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp b/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp index 28a57b2dc29..2e3eed8ec60 100644 --- a/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp @@ -92,7 +92,7 @@ size_t ZPlatformAddressOffsetBits() { static const size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1; const size_t max_address_offset_bits = valid_max_address_offset_bits - 3; const size_t min_address_offset_bits = max_address_offset_bits - 2; - const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); + const size_t address_offset = ZGlobalsPointers::min_address_offset_request(); const size_t address_offset_bits = log2i_exact(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); } diff --git a/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp index 683d892915f..1f2f0146f04 100644 --- a/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp @@ -94,7 +94,7 @@ size_t ZPlatformAddressOffsetBits() { static const size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1; const size_t max_address_offset_bits = valid_max_address_offset_bits - 3; const size_t min_address_offset_bits = max_address_offset_bits - 2; - const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); + const size_t address_offset = ZGlobalsPointers::min_address_offset_request(); const size_t address_offset_bits = log2i_exact(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); } diff --git a/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp b/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp index 3667a52050c..6b5b64d3036 100644 --- a/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zAddress_x86.cpp @@ -32,7 +32,7 @@ size_t ZPointerLoadShift; size_t ZPlatformAddressOffsetBits() { const size_t min_address_offset_bits = 42; // 4TB const size_t max_address_offset_bits = 44; // 16TB - const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); + const size_t address_offset = ZGlobalsPointers::min_address_offset_request(); const size_t address_offset_bits = log2i_exact(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); } diff --git a/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp b/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp index ac723483637..d0c06e2ebf1 100644 --- a/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp @@ -21,15 +21,24 @@ * questions. */ -#include "gc/z/zNUMA.hpp" -#include "utilities/globalDefinitions.hpp" +#include "gc/shared/gc_globals.hpp" +#include "gc/z/zCPU.inline.hpp" +#include "gc/z/zNUMA.inline.hpp" +#include "runtime/globals_extension.hpp" void ZNUMA::pd_initialize() { _enabled = false; - _count = 1; + _count = !FLAG_IS_DEFAULT(ZFakeNUMA) + ? ZFakeNUMA + : 1; } uint32_t ZNUMA::id() { + if (is_faked()) { + // ZFakeNUMA testing, ignores _enabled + return ZCPU::id() % ZFakeNUMA; + } + return 0; } diff --git a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp index 37c855c2e2b..86549e878cb 100644 --- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp @@ -26,7 +26,6 @@ #include "gc/z/zGlobals.hpp" #include "gc/z/zInitialize.hpp" #include "gc/z/zLargePages.inline.hpp" -#include "gc/z/zPhysicalMemory.inline.hpp" #include "gc/z/zPhysicalMemoryBacking_bsd.hpp" #include "logging/log.hpp" #include "runtime/globals.hpp" @@ -97,12 +96,12 @@ void ZPhysicalMemoryBacking::warn_commit_limits(size_t max_capacity) const { // Does nothing } -bool ZPhysicalMemoryBacking::commit_inner(zoffset offset, size_t length) const { +bool ZPhysicalMemoryBacking::commit_inner(zbacking_offset offset, size_t length) const { assert(is_aligned(untype(offset), os::vm_page_size()), "Invalid offset"); assert(is_aligned(length, os::vm_page_size()), "Invalid length"); log_trace(gc, heap)("Committing memory: %zuM-%zuM (%zuM)", - untype(offset) / M, untype(to_zoffset_end(offset, length)) / M, length / M); + untype(offset) / M, untype(to_zbacking_offset_end(offset, length)) / M, length / M); const uintptr_t addr = _base + untype(offset); const void* const res = mmap((void*)addr, length, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); @@ -116,7 +115,7 @@ bool ZPhysicalMemoryBacking::commit_inner(zoffset offset, size_t length) const { return true; } -size_t ZPhysicalMemoryBacking::commit(zoffset offset, size_t length) const { +size_t ZPhysicalMemoryBacking::commit(zbacking_offset offset, size_t length, uint32_t /* numa_id - ignored */) const { // Try to commit the whole region if (commit_inner(offset, length)) { // Success @@ -124,8 +123,8 @@ size_t ZPhysicalMemoryBacking::commit(zoffset offset, size_t length) const { } // Failed, try to commit as much as possible - zoffset start = offset; - zoffset end = offset + length; + zbacking_offset start = offset; + zbacking_offset end = offset + length; for (;;) { length = align_down((end - start) / 2, ZGranuleSize); @@ -144,12 +143,12 @@ size_t ZPhysicalMemoryBacking::commit(zoffset offset, size_t length) const { } } -size_t ZPhysicalMemoryBacking::uncommit(zoffset offset, size_t length) const { +size_t ZPhysicalMemoryBacking::uncommit(zbacking_offset offset, size_t length) const { assert(is_aligned(untype(offset), os::vm_page_size()), "Invalid offset"); assert(is_aligned(length, os::vm_page_size()), "Invalid length"); log_trace(gc, heap)("Uncommitting memory: %zuM-%zuM (%zuM)", - untype(offset) / M, untype(to_zoffset_end(offset, length)) / M, length / M); + untype(offset) / M, untype(to_zbacking_offset_end(offset, length)) / M, length / M); const uintptr_t start = _base + untype(offset); const void* const res = mmap((void*)start, length, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0); @@ -162,7 +161,7 @@ size_t ZPhysicalMemoryBacking::uncommit(zoffset offset, size_t length) const { return length; } -void ZPhysicalMemoryBacking::map(zaddress_unsafe addr, size_t size, zoffset offset) const { +void ZPhysicalMemoryBacking::map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const { const ZErrno err = mremap(_base + untype(offset), untype(addr), size); if (err) { fatal("Failed to remap memory (%s)", err.to_string()); diff --git a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.hpp b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.hpp index d74de5375ee..9fa64fb51bd 100644 --- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.hpp +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ private: uintptr_t _base; bool _initialized; - bool commit_inner(zoffset offset, size_t length) const; + bool commit_inner(zbacking_offset offset, size_t length) const; public: ZPhysicalMemoryBacking(size_t max_capacity); @@ -40,10 +40,10 @@ public: void warn_commit_limits(size_t max_capacity) const; - size_t commit(zoffset offset, size_t length) const; - size_t uncommit(zoffset offset, size_t length) const; + size_t commit(zbacking_offset offset, size_t length, uint32_t numa_id) const; + size_t uncommit(zbacking_offset offset, size_t length) const; - void map(zaddress_unsafe addr, size_t size, zoffset offset) const; + void map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const; void unmap(zaddress_unsafe addr, size_t size) const; }; diff --git a/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp index 5a5db428548..74e69655940 100644 --- a/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp @@ -21,23 +21,34 @@ * questions. */ +#include "gc/shared/gc_globals.hpp" #include "gc/z/zCPU.inline.hpp" #include "gc/z/zErrno.hpp" -#include "gc/z/zNUMA.hpp" +#include "gc/z/zNUMA.inline.hpp" #include "gc/z/zSyscall_linux.hpp" #include "os_linux.hpp" #include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" void ZNUMA::pd_initialize() { _enabled = UseNUMA; + + // UseNUMA and is_faked() are mutually excluded in zArguments.cpp. _count = UseNUMA ? os::Linux::numa_max_node() + 1 - : 1; + : !FLAG_IS_DEFAULT(ZFakeNUMA) + ? ZFakeNUMA + : 1; // No NUMA nodes } uint32_t ZNUMA::id() { + if (is_faked()) { + // ZFakeNUMA testing, ignores _enabled + return ZCPU::id() % ZFakeNUMA; + } + if (!_enabled) { // NUMA support not enabled return 0; diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp index 1ae4e18fcf1..c33e49b57f9 100644 --- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp @@ -388,7 +388,7 @@ bool ZPhysicalMemoryBacking::tmpfs_supports_transparent_huge_pages() const { return access(ZFILENAME_SHMEM_ENABLED, R_OK) == 0; } -ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs(zoffset offset, size_t length, bool touch) const { +ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_hugetlbfs(zbacking_offset offset, size_t length, bool touch) const { // On hugetlbfs, mapping a file segment will fail immediately, without // the need to touch the mapped pages first, if there aren't enough huge // pages available to back the mapping. @@ -439,7 +439,7 @@ static bool safe_touch_mapping(void* addr, size_t length, size_t page_size) { return true; } -ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_tmpfs(zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_tmpfs(zbacking_offset offset, size_t length) const { // On tmpfs, we need to touch the mapped pages to figure out // if there are enough pages available to back the mapping. void* const addr = mmap(nullptr, length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, untype(offset)); @@ -468,11 +468,11 @@ ZErrno ZPhysicalMemoryBacking::fallocate_compat_mmap_tmpfs(zoffset offset, size_ return backed ? 0 : ENOMEM; } -ZErrno ZPhysicalMemoryBacking::fallocate_compat_pwrite(zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::fallocate_compat_pwrite(zbacking_offset offset, size_t length) const { uint8_t data = 0; // Allocate backing memory by writing to each block - for (zoffset pos = offset; pos < offset + length; pos += _block_size) { + for (zbacking_offset pos = offset; pos < offset + length; pos += _block_size) { if (pwrite(_fd, &data, sizeof(data), untype(pos)) == -1) { // Failed return errno; @@ -483,7 +483,7 @@ ZErrno ZPhysicalMemoryBacking::fallocate_compat_pwrite(zoffset offset, size_t le return 0; } -ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_compat(zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_compat(zbacking_offset offset, size_t length) const { // fallocate(2) is only supported by tmpfs since Linux 3.5, and by hugetlbfs // since Linux 4.3. When fallocate(2) is not supported we emulate it using // mmap/munmap (for hugetlbfs and tmpfs with transparent huge pages) or pwrite @@ -497,7 +497,7 @@ ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_compat(zoffset offset, size_t } } -ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(zbacking_offset offset, size_t length) const { const int mode = 0; // Allocate const int res = ZSyscall::fallocate(_fd, mode, untype(offset), length); if (res == -1) { @@ -509,7 +509,7 @@ ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole_syscall(zoffset offset, size_ return 0; } -ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole(zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole(zbacking_offset offset, size_t length) const { // Using compat mode is more efficient when allocating space on hugetlbfs. // Note that allocating huge pages this way will only reserve them, and not // associate them with segments of the file. We must guarantee that we at @@ -536,7 +536,7 @@ ZErrno ZPhysicalMemoryBacking::fallocate_fill_hole(zoffset offset, size_t length return fallocate_fill_hole_compat(offset, length); } -ZErrno ZPhysicalMemoryBacking::fallocate_punch_hole(zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::fallocate_punch_hole(zbacking_offset offset, size_t length) const { if (ZLargePages::is_explicit()) { // We can only punch hole in pages that have been touched. Non-touched // pages are only reserved, and not associated with any specific file @@ -559,9 +559,9 @@ ZErrno ZPhysicalMemoryBacking::fallocate_punch_hole(zoffset offset, size_t lengt return 0; } -ZErrno ZPhysicalMemoryBacking::split_and_fallocate(bool punch_hole, zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::split_and_fallocate(bool punch_hole, zbacking_offset offset, size_t length) const { // Try first half - const zoffset offset0 = offset; + const zbacking_offset offset0 = offset; const size_t length0 = align_up(length / 2, _block_size); const ZErrno err0 = fallocate(punch_hole, offset0, length0); if (err0) { @@ -569,7 +569,7 @@ ZErrno ZPhysicalMemoryBacking::split_and_fallocate(bool punch_hole, zoffset offs } // Try second half - const zoffset offset1 = offset0 + length0; + const zbacking_offset offset1 = offset0 + length0; const size_t length1 = length - length0; const ZErrno err1 = fallocate(punch_hole, offset1, length1); if (err1) { @@ -580,7 +580,7 @@ ZErrno ZPhysicalMemoryBacking::split_and_fallocate(bool punch_hole, zoffset offs return 0; } -ZErrno ZPhysicalMemoryBacking::fallocate(bool punch_hole, zoffset offset, size_t length) const { +ZErrno ZPhysicalMemoryBacking::fallocate(bool punch_hole, zbacking_offset offset, size_t length) const { assert(is_aligned(untype(offset), _block_size), "Invalid offset"); assert(is_aligned(length, _block_size), "Invalid length"); @@ -596,9 +596,9 @@ ZErrno ZPhysicalMemoryBacking::fallocate(bool punch_hole, zoffset offset, size_t return err; } -bool ZPhysicalMemoryBacking::commit_inner(zoffset offset, size_t length) const { +bool ZPhysicalMemoryBacking::commit_inner(zbacking_offset offset, size_t length) const { log_trace(gc, heap)("Committing memory: %zuM-%zuM (%zuM)", - untype(offset) / M, untype(to_zoffset_end(offset, length)) / M, length / M); + untype(offset) / M, untype(to_zbacking_offset_end(offset, length)) / M, length / M); retry: const ZErrno err = fallocate(false /* punch_hole */, offset, length); @@ -627,30 +627,11 @@ retry: return true; } -static int offset_to_node(zoffset offset) { - const GrowableArray* mapping = os::Linux::numa_nindex_to_node(); - const size_t nindex = (untype(offset) >> ZGranuleSizeShift) % mapping->length(); - return mapping->at((int)nindex); -} +size_t ZPhysicalMemoryBacking::commit_numa_preferred(zbacking_offset offset, size_t length, uint32_t numa_id) const { + // Setup NUMA policy to allocate memory from a preferred node + os::Linux::numa_set_preferred((int)numa_id); -size_t ZPhysicalMemoryBacking::commit_numa_interleaved(zoffset offset, size_t length) const { - size_t committed = 0; - - // Commit one granule at a time, so that each granule - // can be allocated from a different preferred node. - while (committed < length) { - const zoffset granule_offset = offset + committed; - - // Setup NUMA policy to allocate memory from a preferred node - os::Linux::numa_set_preferred(offset_to_node(granule_offset)); - - if (!commit_inner(granule_offset, ZGranuleSize)) { - // Failed - break; - } - - committed += ZGranuleSize; - } + const size_t committed = commit_default(offset, length); // Restore NUMA policy os::Linux::numa_set_preferred(-1); @@ -658,7 +639,7 @@ size_t ZPhysicalMemoryBacking::commit_numa_interleaved(zoffset offset, size_t le return committed; } -size_t ZPhysicalMemoryBacking::commit_default(zoffset offset, size_t length) const { +size_t ZPhysicalMemoryBacking::commit_default(zbacking_offset offset, size_t length) const { // Try to commit the whole region if (commit_inner(offset, length)) { // Success @@ -666,8 +647,8 @@ size_t ZPhysicalMemoryBacking::commit_default(zoffset offset, size_t length) con } // Failed, try to commit as much as possible - zoffset start = offset; - zoffset end = offset + length; + zbacking_offset start = offset; + zbacking_offset_end end = to_zbacking_offset_end(offset, length); for (;;) { length = align_down((end - start) / 2, ZGranuleSize); @@ -686,19 +667,19 @@ size_t ZPhysicalMemoryBacking::commit_default(zoffset offset, size_t length) con } } -size_t ZPhysicalMemoryBacking::commit(zoffset offset, size_t length) const { +size_t ZPhysicalMemoryBacking::commit(zbacking_offset offset, size_t length, uint32_t numa_id) const { if (ZNUMA::is_enabled() && !ZLargePages::is_explicit()) { - // To get granule-level NUMA interleaving when using non-large pages, - // we must explicitly interleave the memory at commit/fallocate time. - return commit_numa_interleaved(offset, length); + // The memory is required to be preferred at the time it is paged in. As a + // consequence we must prefer the memory when committing non-large pages. + return commit_numa_preferred(offset, length, numa_id); } return commit_default(offset, length); } -size_t ZPhysicalMemoryBacking::uncommit(zoffset offset, size_t length) const { +size_t ZPhysicalMemoryBacking::uncommit(zbacking_offset offset, size_t length) const { log_trace(gc, heap)("Uncommitting memory: %zuM-%zuM (%zuM)", - untype(offset) / M, untype(to_zoffset_end(offset, length)) / M, length / M); + untype(offset) / M, untype(to_zbacking_offset_end(offset, length)) / M, length / M); const ZErrno err = fallocate(true /* punch_hole */, offset, length); if (err) { @@ -709,7 +690,7 @@ size_t ZPhysicalMemoryBacking::uncommit(zoffset offset, size_t length) const { return length; } -void ZPhysicalMemoryBacking::map(zaddress_unsafe addr, size_t size, zoffset offset) const { +void ZPhysicalMemoryBacking::map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const { const void* const res = mmap((void*)untype(addr), size, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, _fd, untype(offset)); if (res == MAP_FAILED) { ZErrno err; diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp index 59c00ad01bf..4b083d1c79c 100644 --- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,19 +48,19 @@ private: bool is_hugetlbfs() const; bool tmpfs_supports_transparent_huge_pages() const; - ZErrno fallocate_compat_mmap_hugetlbfs(zoffset offset, size_t length, bool touch) const; - ZErrno fallocate_compat_mmap_tmpfs(zoffset offset, size_t length) const; - ZErrno fallocate_compat_pwrite(zoffset offset, size_t length) const; - ZErrno fallocate_fill_hole_compat(zoffset offset, size_t length) const; - ZErrno fallocate_fill_hole_syscall(zoffset offset, size_t length) const; - ZErrno fallocate_fill_hole(zoffset offset, size_t length) const; - ZErrno fallocate_punch_hole(zoffset offset, size_t length) const; - ZErrno split_and_fallocate(bool punch_hole, zoffset offset, size_t length) const; - ZErrno fallocate(bool punch_hole, zoffset offset, size_t length) const; + ZErrno fallocate_compat_mmap_hugetlbfs(zbacking_offset offset, size_t length, bool touch) const; + ZErrno fallocate_compat_mmap_tmpfs(zbacking_offset offset, size_t length) const; + ZErrno fallocate_compat_pwrite(zbacking_offset offset, size_t length) const; + ZErrno fallocate_fill_hole_compat(zbacking_offset offset, size_t length) const; + ZErrno fallocate_fill_hole_syscall(zbacking_offset offset, size_t length) const; + ZErrno fallocate_fill_hole(zbacking_offset offset, size_t length) const; + ZErrno fallocate_punch_hole(zbacking_offset offset, size_t length) const; + ZErrno split_and_fallocate(bool punch_hole, zbacking_offset offset, size_t length) const; + ZErrno fallocate(bool punch_hole, zbacking_offset offset, size_t length) const; - bool commit_inner(zoffset offset, size_t length) const; - size_t commit_numa_interleaved(zoffset offset, size_t length) const; - size_t commit_default(zoffset offset, size_t length) const; + bool commit_inner(zbacking_offset offset, size_t length) const; + size_t commit_numa_preferred(zbacking_offset offset, size_t length, uint32_t numa_id) const; + size_t commit_default(zbacking_offset offset, size_t length) const; public: ZPhysicalMemoryBacking(size_t max_capacity); @@ -69,10 +69,10 @@ public: void warn_commit_limits(size_t max_capacity) const; - size_t commit(zoffset offset, size_t length) const; - size_t uncommit(zoffset offset, size_t length) const; + size_t commit(zbacking_offset offset, size_t length, uint32_t numa_id) const; + size_t uncommit(zbacking_offset offset, size_t length) const; - void map(zaddress_unsafe addr, size_t size, zoffset offset) const; + void map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const; void unmap(zaddress_unsafe addr, size_t size) const; }; diff --git a/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp b/src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp similarity index 81% rename from src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp rename to src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp index a103f764c98..4eea35c8a2e 100644 --- a/src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp +++ b/src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp @@ -22,21 +22,16 @@ */ #include "gc/z/zAddress.inline.hpp" -#include "gc/z/zVirtualMemory.hpp" +#include "gc/z/zVirtualMemoryManager.hpp" #include "logging/log.hpp" #include -#include -void ZVirtualMemoryManager::pd_initialize_before_reserve() { +void ZVirtualMemoryReserver::pd_register_callbacks(ZVirtualMemoryRegistry* registry) { // Does nothing } -void ZVirtualMemoryManager::pd_register_callbacks(ZMemoryManager* manager) { - // Does nothing -} - -bool ZVirtualMemoryManager::pd_reserve(zaddress_unsafe addr, size_t size) { +bool ZVirtualMemoryReserver::pd_reserve(zaddress_unsafe addr, size_t size) { void* const res = mmap((void*)untype(addr), size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); if (res == MAP_FAILED) { // Failed to reserve memory @@ -53,7 +48,7 @@ bool ZVirtualMemoryManager::pd_reserve(zaddress_unsafe addr, size_t size) { return true; } -void ZVirtualMemoryManager::pd_unreserve(zaddress_unsafe addr, size_t size) { +void ZVirtualMemoryReserver::pd_unreserve(zaddress_unsafe addr, size_t size) { const int res = munmap((void*)untype(addr), size); assert(res == 0, "Failed to unmap memory"); } diff --git a/src/hotspot/os/windows/gc/z/zInitialize_windows.cpp b/src/hotspot/os/windows/gc/z/zInitialize_windows.cpp index a4751617ce7..e0e0b3be82c 100644 --- a/src/hotspot/os/windows/gc/z/zInitialize_windows.cpp +++ b/src/hotspot/os/windows/gc/z/zInitialize_windows.cpp @@ -24,6 +24,9 @@ #include "gc/z/zInitialize.hpp" #include "gc/z/zSyscall_windows.hpp" +void ZVirtualMemoryReserverImpl_initialize(); + void ZInitialize::pd_initialize() { ZSyscall::initialize(); + ZVirtualMemoryReserverImpl_initialize(); } diff --git a/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp b/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp index afe8f18c392..dc7521dde56 100644 --- a/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp +++ b/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp @@ -21,14 +21,24 @@ * questions. */ -#include "gc/z/zNUMA.hpp" +#include "gc/shared/gc_globals.hpp" +#include "gc/z/zCPU.inline.hpp" +#include "gc/z/zNUMA.inline.hpp" +#include "runtime/globals_extension.hpp" void ZNUMA::pd_initialize() { _enabled = false; - _count = 1; + _count = !FLAG_IS_DEFAULT(ZFakeNUMA) + ? ZFakeNUMA + : 1; } uint32_t ZNUMA::id() { + if (is_faked()) { + // ZFakeNUMA testing + return ZCPU::id() % ZFakeNUMA; + } + return 0; } diff --git a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp index 2764f51c13b..b18abd7e979 100644 --- a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp +++ b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp @@ -33,9 +33,9 @@ class ZPhysicalMemoryBackingImpl : public CHeapObj { public: - virtual size_t commit(zoffset offset, size_t size) = 0; - virtual size_t uncommit(zoffset offset, size_t size) = 0; - virtual void map(zaddress_unsafe addr, size_t size, zoffset offset) const = 0; + virtual size_t commit(zbacking_offset offset, size_t size) = 0; + virtual size_t uncommit(zbacking_offset offset, size_t size) = 0; + virtual void map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const = 0; virtual void unmap(zaddress_unsafe addr, size_t size) const = 0; }; @@ -50,21 +50,29 @@ class ZPhysicalMemoryBackingSmallPages : public ZPhysicalMemoryBackingImpl { private: ZGranuleMap _handles; - HANDLE get_handle(zoffset offset) const { - HANDLE const handle = _handles.get(offset); + static zoffset to_zoffset(zbacking_offset offset) { + // A zbacking_offset is always a valid zoffset + return zoffset(untype(offset)); + } + + HANDLE get_handle(zbacking_offset offset) const { + const zoffset z_offset = to_zoffset(offset); + HANDLE const handle = _handles.get(z_offset); assert(handle != 0, "Should be set"); return handle; } - void put_handle(zoffset offset, HANDLE handle) { + void put_handle(zbacking_offset offset, HANDLE handle) { + const zoffset z_offset = to_zoffset(offset); assert(handle != INVALID_HANDLE_VALUE, "Invalid handle"); - assert(_handles.get(offset) == 0, "Should be cleared"); - _handles.put(offset, handle); + assert(_handles.get(z_offset) == 0, "Should be cleared"); + _handles.put(z_offset, handle); } - void clear_handle(zoffset offset) { - assert(_handles.get(offset) != 0, "Should be set"); - _handles.put(offset, 0); + void clear_handle(zbacking_offset offset) { + const zoffset z_offset = to_zoffset(offset); + assert(_handles.get(z_offset) != 0, "Should be set"); + _handles.put(z_offset, 0); } public: @@ -72,7 +80,7 @@ public: : ZPhysicalMemoryBackingImpl(), _handles(max_capacity) {} - size_t commit(zoffset offset, size_t size) { + size_t commit(zbacking_offset offset, size_t size) { for (size_t i = 0; i < size; i += ZGranuleSize) { HANDLE const handle = ZMapper::create_and_commit_paging_file_mapping(ZGranuleSize); if (handle == 0) { @@ -85,7 +93,7 @@ public: return size; } - size_t uncommit(zoffset offset, size_t size) { + size_t uncommit(zbacking_offset offset, size_t size) { for (size_t i = 0; i < size; i += ZGranuleSize) { HANDLE const handle = get_handle(offset + i); clear_handle(offset + i); @@ -95,7 +103,7 @@ public: return size; } - void map(zaddress_unsafe addr, size_t size, zoffset offset) const { + void map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const { assert(is_aligned(untype(offset), ZGranuleSize), "Misaligned"); assert(is_aligned(untype(addr), ZGranuleSize), "Misaligned"); assert(is_aligned(size, ZGranuleSize), "Misaligned"); @@ -149,7 +157,7 @@ public: : ZPhysicalMemoryBackingImpl(), _page_array(alloc_page_array(max_capacity)) {} - size_t commit(zoffset offset, size_t size) { + size_t commit(zbacking_offset offset, size_t size) { const size_t index = untype(offset) >> ZGranuleSizeShift; const size_t npages = size >> ZGranuleSizeShift; @@ -167,7 +175,7 @@ public: return npages_res << ZGranuleSizeShift; } - size_t uncommit(zoffset offset, size_t size) { + size_t uncommit(zbacking_offset offset, size_t size) { const size_t index = untype(offset) >> ZGranuleSizeShift; const size_t npages = size >> ZGranuleSizeShift; @@ -181,7 +189,7 @@ public: return npages_res << ZGranuleSizeShift; } - void map(zaddress_unsafe addr, size_t size, zoffset offset) const { + void map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const { const size_t npages = size >> ZGranuleSizeShift; const size_t index = untype(offset) >> ZGranuleSizeShift; @@ -222,21 +230,21 @@ void ZPhysicalMemoryBacking::warn_commit_limits(size_t max_capacity) const { // Does nothing } -size_t ZPhysicalMemoryBacking::commit(zoffset offset, size_t length) { +size_t ZPhysicalMemoryBacking::commit(zbacking_offset offset, size_t length, uint32_t /* numa_id - ignored */) { log_trace(gc, heap)("Committing memory: %zuM-%zuM (%zuM)", - untype(offset) / M, untype(to_zoffset_end(offset, length)) / M, length / M); + untype(offset) / M, untype(to_zbacking_offset_end(offset, length)) / M, length / M); return _impl->commit(offset, length); } -size_t ZPhysicalMemoryBacking::uncommit(zoffset offset, size_t length) { +size_t ZPhysicalMemoryBacking::uncommit(zbacking_offset offset, size_t length) { log_trace(gc, heap)("Uncommitting memory: %zuM-%zuM (%zuM)", - untype(offset) / M, untype(to_zoffset_end(offset, length)) / M, length / M); + untype(offset) / M, untype(to_zbacking_offset_end(offset, length)) / M, length / M); return _impl->uncommit(offset, length); } -void ZPhysicalMemoryBacking::map(zaddress_unsafe addr, size_t size, zoffset offset) const { +void ZPhysicalMemoryBacking::map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const { assert(is_aligned(untype(offset), ZGranuleSize), "Misaligned: " PTR_FORMAT, untype(offset)); assert(is_aligned(untype(addr), ZGranuleSize), "Misaligned: " PTR_FORMAT, addr); assert(is_aligned(size, ZGranuleSize), "Misaligned: " PTR_FORMAT, size); diff --git a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp index b8b73519ab5..91d59f49609 100644 --- a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp +++ b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,10 +42,10 @@ public: void warn_commit_limits(size_t max_capacity) const; - size_t commit(zoffset offset, size_t length); - size_t uncommit(zoffset offset, size_t length); + size_t commit(zbacking_offset offset, size_t length, uint32_t numa_id); + size_t uncommit(zbacking_offset offset, size_t length); - void map(zaddress_unsafe addr, size_t size, zoffset offset) const; + void map(zaddress_unsafe addr, size_t size, zbacking_offset offset) const; void unmap(zaddress_unsafe addr, size_t size) const; }; diff --git a/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp b/src/hotspot/os/windows/gc/z/zVirtualMemoryManager_windows.cpp similarity index 81% rename from src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp rename to src/hotspot/os/windows/gc/z/zVirtualMemoryManager_windows.cpp index ac5be56a0c0..48a32157f59 100644 --- a/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp +++ b/src/hotspot/os/windows/gc/z/zVirtualMemoryManager_windows.cpp @@ -26,25 +26,26 @@ #include "gc/z/zLargePages.inline.hpp" #include "gc/z/zMapper_windows.hpp" #include "gc/z/zSyscall_windows.hpp" +#include "gc/z/zValue.inline.hpp" #include "gc/z/zVirtualMemory.inline.hpp" +#include "gc/z/zVirtualMemoryManager.inline.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" -class ZVirtualMemoryManagerImpl : public CHeapObj { +class ZVirtualMemoryReserverImpl : public CHeapObj { public: - virtual void initialize_before_reserve() {} - virtual void register_callbacks(ZMemoryManager* manager) {} + virtual void register_callbacks(ZVirtualMemoryRegistry* registry) {} virtual bool reserve(zaddress_unsafe addr, size_t size) = 0; virtual void unreserve(zaddress_unsafe addr, size_t size) = 0; }; // Implements small pages (paged) support using placeholder reservation. // -// When a memory area is free (kept by the virtual memory manager) a +// When a memory area is available (kept by the virtual memory manager) a // single placeholder is covering that memory area. When memory is -// allocated from the manager the placeholder is split into granule +// removed from the registry the placeholder is split into granule // sized placeholders to allow mapping operations on that granularity. -class ZVirtualMemoryManagerSmallPages : public ZVirtualMemoryManagerImpl { +class ZVirtualMemoryReserverSmallPages : public ZVirtualMemoryReserverImpl { private: class PlaceholderCallbacks : public AllStatic { private: @@ -84,7 +85,7 @@ private: // Called when a memory area is going to be handed out to be used. // // Splits the memory area into granule-sized placeholders. - static void prepare_for_hand_out_callback(const ZMemory& area) { + static void prepare_for_hand_out_callback(const ZVirtualMemory& area) { assert(is_aligned(area.size(), ZGranuleSize), "Must be granule aligned"); split_into_granule_sized_placeholders(area.start(), area.size()); @@ -93,7 +94,7 @@ private: // Called when a memory area is handed back to the memory manager. // // Combines the granule-sized placeholders into one placeholder. - static void prepare_for_hand_back_callback(const ZMemory& area) { + static void prepare_for_hand_back_callback(const ZVirtualMemory& area) { assert(is_aligned(area.size(), ZGranuleSize), "Must be granule aligned"); coalesce_into_one_placeholder(area.start(), area.size()); @@ -103,7 +104,7 @@ private: // existing, adjacent memory area. // // Coalesces the underlying placeholders into one. - static void grow_callback(const ZMemory& from, const ZMemory& to) { + static void grow_callback(const ZVirtualMemory& from, const ZVirtualMemory& to) { assert(is_aligned(from.size(), ZGranuleSize), "Must be granule aligned"); assert(is_aligned(to.size(), ZGranuleSize), "Must be granule aligned"); assert(from != to, "Must have grown"); @@ -116,7 +117,7 @@ private: // memory area. // // Splits the memory into two placeholders. - static void shrink_callback(const ZMemory& from, const ZMemory& to) { + static void shrink_callback(const ZVirtualMemory& from, const ZVirtualMemory& to) { assert(is_aligned(from.size(), ZGranuleSize), "Must be granule aligned"); assert(is_aligned(to.size(), ZGranuleSize), "Must be granule aligned"); assert(from != to, "Must have shrunk"); @@ -129,7 +130,7 @@ private: } public: - static ZMemoryManager::Callbacks callbacks() { + static ZVirtualMemoryRegistry::Callbacks callbacks() { // Each reserved virtual memory address area registered in _manager is // exactly covered by a single placeholder. Callbacks are installed so // that whenever a memory area changes, the corresponding placeholder @@ -153,7 +154,7 @@ private: // See comment in zMapper_windows.cpp explaining why placeholders are // split into ZGranuleSize sized placeholders. - ZMemoryManager::Callbacks callbacks; + ZVirtualMemoryRegistry::Callbacks callbacks; callbacks._prepare_for_hand_out = &prepare_for_hand_out_callback; callbacks._prepare_for_hand_back = &prepare_for_hand_back_callback; @@ -164,8 +165,8 @@ private: } }; - virtual void register_callbacks(ZMemoryManager* manager) { - manager->register_callbacks(PlaceholderCallbacks::callbacks()); + virtual void register_callbacks(ZVirtualMemoryRegistry* registry) { + registry->register_callbacks(PlaceholderCallbacks::callbacks()); } virtual bool reserve(zaddress_unsafe addr, size_t size) { @@ -185,12 +186,8 @@ private: // ZPhysicalMemory layer needs access to the section HANDLE ZAWESection; -class ZVirtualMemoryManagerLargePages : public ZVirtualMemoryManagerImpl { +class ZVirtualMemoryReserverLargePages : public ZVirtualMemoryReserverImpl { private: - virtual void initialize_before_reserve() { - ZAWESection = ZMapper::create_shared_awe_section(); - } - virtual bool reserve(zaddress_unsafe addr, size_t size) { const zaddress_unsafe res = ZMapper::reserve_for_shared_awe(ZAWESection, addr, size); @@ -201,27 +198,33 @@ private: virtual void unreserve(zaddress_unsafe addr, size_t size) { ZMapper::unreserve_for_shared_awe(addr, size); } + +public: + ZVirtualMemoryReserverLargePages() { + ZAWESection = ZMapper::create_shared_awe_section(); + } }; -static ZVirtualMemoryManagerImpl* _impl = nullptr; +static ZVirtualMemoryReserverImpl* _impl = nullptr; + +void ZVirtualMemoryReserverImpl_initialize() { + assert(_impl == nullptr, "Should only initialize once"); -void ZVirtualMemoryManager::pd_initialize_before_reserve() { if (ZLargePages::is_enabled()) { - _impl = new ZVirtualMemoryManagerLargePages(); + _impl = new ZVirtualMemoryReserverLargePages(); } else { - _impl = new ZVirtualMemoryManagerSmallPages(); + _impl = new ZVirtualMemoryReserverSmallPages(); } - _impl->initialize_before_reserve(); } -void ZVirtualMemoryManager::pd_register_callbacks(ZMemoryManager* manager) { - _impl->register_callbacks(manager); +void ZVirtualMemoryReserver::pd_register_callbacks(ZVirtualMemoryRegistry* registry) { + _impl->register_callbacks(registry); } -bool ZVirtualMemoryManager::pd_reserve(zaddress_unsafe addr, size_t size) { +bool ZVirtualMemoryReserver::pd_reserve(zaddress_unsafe addr, size_t size) { return _impl->reserve(addr, size); } -void ZVirtualMemoryManager::pd_unreserve(zaddress_unsafe addr, size_t size) { +void ZVirtualMemoryReserver::pd_unreserve(zaddress_unsafe addr, size_t size) { _impl->unreserve(addr, size); } diff --git a/src/hotspot/share/gc/z/vmStructs_z.hpp b/src/hotspot/share/gc/z/vmStructs_z.hpp index 47fa6ac3021..e1eb2a661f5 100644 --- a/src/hotspot/share/gc/z/vmStructs_z.hpp +++ b/src/hotspot/share/gc/z/vmStructs_z.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,11 @@ #include "gc/z/zForwarding.hpp" #include "gc/z/zGranuleMap.hpp" #include "gc/z/zHeap.hpp" +#include "gc/z/zNUMA.hpp" #include "gc/z/zPageAllocator.hpp" #include "gc/z/zPageType.hpp" +#include "gc/z/zValue.hpp" +#include "gc/z/zVirtualMemory.hpp" #include "utilities/macros.hpp" // Expose some ZGC globals to the SA agent. @@ -61,6 +64,7 @@ public: typedef ZGranuleMap ZGranuleMapForPageTable; typedef ZGranuleMap ZGranuleMapForForwarding; typedef ZAttachedArray ZAttachedArrayForForwarding; +typedef ZValue ZPerNUMAZPartition; #define VM_STRUCTS_Z(nonstatic_field, volatile_nonstatic_field, static_field) \ static_field(ZGlobalsForVMStructs, _instance_p, ZGlobalsForVMStructs*) \ @@ -87,8 +91,13 @@ typedef ZAttachedArray ZAttachedArrayForForwardin volatile_nonstatic_field(ZPage, _top, zoffset_end) \ \ nonstatic_field(ZPageAllocator, _max_capacity, const size_t) \ - volatile_nonstatic_field(ZPageAllocator, _capacity, size_t) \ - volatile_nonstatic_field(ZPageAllocator, _used, size_t) \ + nonstatic_field(ZPageAllocator, _partitions, ZPerNUMAZPartition) \ + \ + static_field(ZNUMA, _count, uint32_t) \ + nonstatic_field(ZPerNUMAZPartition, _addr, const uintptr_t) \ + \ + volatile_nonstatic_field(ZPartition, _capacity, size_t) \ + nonstatic_field(ZPartition, _used, size_t) \ \ nonstatic_field(ZPageTable, _map, ZGranuleMapForPageTable) \ \ @@ -97,8 +106,8 @@ typedef ZAttachedArray ZAttachedArrayForForwardin \ nonstatic_field(ZForwardingTable, _map, ZGranuleMapForForwarding) \ \ - nonstatic_field(ZVirtualMemory, _start, const zoffset) \ - nonstatic_field(ZVirtualMemory, _end, const zoffset_end) \ + nonstatic_field(ZVirtualMemory, _start, const zoffset_end) \ + nonstatic_field(ZVirtualMemory, _size, const size_t) \ \ nonstatic_field(ZForwarding, _virtual, const ZVirtualMemory) \ nonstatic_field(ZForwarding, _object_alignment_shift, const size_t) \ @@ -134,6 +143,9 @@ typedef ZAttachedArray ZAttachedArrayForForwardin declare_toplevel_type(ZPageType) \ declare_toplevel_type(ZPageAllocator) \ declare_toplevel_type(ZPageTable) \ + declare_toplevel_type(ZPartition) \ + declare_toplevel_type(ZNUMA) \ + declare_toplevel_type(ZPerNUMAZPartition) \ declare_toplevel_type(ZAttachedArrayForForwarding) \ declare_toplevel_type(ZGranuleMapForPageTable) \ declare_toplevel_type(ZGranuleMapForForwarding) \ diff --git a/src/hotspot/share/gc/z/zAddress.cpp b/src/hotspot/share/gc/z/zAddress.cpp index 59489f62372..98779419219 100644 --- a/src/hotspot/share/gc/z/zAddress.cpp +++ b/src/hotspot/share/gc/z/zAddress.cpp @@ -24,6 +24,7 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/gc_globals.hpp" #include "gc/z/zAddress.inline.hpp" +#include "gc/z/zNUMA.inline.hpp" #include "gc/z/zVerify.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/java.hpp" @@ -36,6 +37,10 @@ size_t ZAddressOffsetBits; uintptr_t ZAddressOffsetMask; size_t ZAddressOffsetMax; +size_t ZBackingOffsetMax; + +uint32_t ZBackingIndexMax; + uintptr_t ZPointerRemapped; uintptr_t ZPointerRemappedYoungMask; uintptr_t ZPointerRemappedOldMask; @@ -145,3 +150,10 @@ void ZGlobalsPointers::flip_old_relocate_start() { ZPointerRemappedOldMask ^= ZPointerRemappedMask; set_good_masks(); } + +size_t ZGlobalsPointers::min_address_offset_request() { + // See ZVirtualMemoryReserver for logic around setting up the heap for NUMA + const size_t desired_for_heap = MaxHeapSize * ZVirtualToPhysicalRatio; + const size_t desired_for_numa_multiplier = ZNUMA::count() > 1 ? 2 : 1; + return round_up_power_of_2(desired_for_heap * desired_for_numa_multiplier); +} diff --git a/src/hotspot/share/gc/z/zAddress.hpp b/src/hotspot/share/gc/z/zAddress.hpp index 6b3c887062e..de97c17d089 100644 --- a/src/hotspot/share/gc/z/zAddress.hpp +++ b/src/hotspot/share/gc/z/zAddress.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,12 @@ const size_t ZAddressOffsetShift = 0; extern uintptr_t ZAddressOffsetMask; extern size_t ZAddressOffsetMax; +// Describes the maximal offset inside the backing storage. +extern size_t ZBackingOffsetMax; + +// Describes the maximal granule index inside the backing storage. +extern uint32_t ZBackingIndexMax; + // Layout of metadata bits in colored pointer / zpointer. // // A zpointer is a combination of the address bits (heap base bit + offset) @@ -223,16 +229,25 @@ const int ZPointerStoreGoodMaskLowOrderBitsOffset = LITTLE_ENDIAN_ONLY(0 // Offsets // - Virtual address range offsets -// - Physical memory offsets -enum class zoffset : uintptr_t {}; +enum class zoffset : uintptr_t { invalid = UINTPTR_MAX }; // Offsets including end of offset range -enum class zoffset_end : uintptr_t {}; +enum class zoffset_end : uintptr_t { invalid = UINTPTR_MAX }; + +// - Physical memory segment offsets +enum class zbacking_offset : uintptr_t {}; +// Offsets including end of offset range +enum class zbacking_offset_end : uintptr_t {}; + +// - Physical memory segment indicies +enum class zbacking_index : uint32_t { zero = 0, invalid = UINT32_MAX }; +// Offsets including end of indicies range +enum class zbacking_index_end : uint32_t { zero = 0, invalid = UINT32_MAX }; // Colored oop -enum class zpointer : uintptr_t { null = 0 }; +enum class zpointer : uintptr_t { null = 0 }; // Uncolored oop - safe to dereference -enum class zaddress : uintptr_t { null = 0 }; +enum class zaddress : uintptr_t { null = 0 }; // Uncolored oop - not safe to dereference, could point uncommitted memory enum class zaddress_unsafe : uintptr_t { null = 0 }; @@ -307,6 +322,8 @@ public: static void flip_young_relocate_start(); static void flip_old_mark_start(); static void flip_old_relocate_start(); + + static size_t min_address_offset_request(); }; #endif // SHARE_GC_Z_ZADDRESS_HPP diff --git a/src/hotspot/share/gc/z/zAddress.inline.hpp b/src/hotspot/share/gc/z/zAddress.inline.hpp index bbc92a7e2aa..98f6900cbf0 100644 --- a/src/hotspot/share/gc/z/zAddress.inline.hpp +++ b/src/hotspot/share/gc/z/zAddress.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,124 @@ #include "gc/z/zAddress.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/z/zGlobals.hpp" #include "oops/oop.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/atomic.hpp" +#include "utilities/align.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" #include "utilities/powerOfTwo.hpp" #include CPU_HEADER_INLINE(gc/z/zAddress) +#include + +// Offset Operator Macro +// Creates operators for the offset, offset_end style types + +#define CREATE_ZOFFSET_OPERATORS(offset_type) \ + \ + /* Arithmetic operators for offset_type */ \ + \ +inline offset_type operator+(offset_type offset, size_t size) { \ + const auto size_value = checked_cast>(size); \ + return to_##offset_type(untype(offset) + size_value); \ +} \ + \ +inline offset_type& operator+=(offset_type& offset, size_t size) { \ + const auto size_value = checked_cast>(size); \ + offset = to_##offset_type(untype(offset) + size_value); \ + return offset; \ +} \ + \ +inline offset_type operator-(offset_type offset, size_t size) { \ + const auto size_value = checked_cast>(size); \ + return to_##offset_type(untype(offset) - size_value); \ +} \ + \ +inline size_t operator-(offset_type first, offset_type second) { \ + return untype(first - untype(second)); \ +} \ + \ +inline offset_type& operator-=(offset_type& offset, size_t size) { \ + const auto size_value = checked_cast>(size); \ + offset = to_##offset_type(untype(offset) - size_value); \ + return offset; \ +} \ + \ + /* Arithmetic operators for offset_type##_end */ \ + \ +inline offset_type##_end operator+(offset_type##_end offset, size_t size) { \ + const auto size_value = checked_cast>(size); \ + return to_##offset_type##_end(untype(offset) + size_value); \ +} \ + \ +inline offset_type##_end& operator+=(offset_type##_end& offset, size_t size) { \ + const auto size_value = checked_cast>(size); \ + offset = to_##offset_type##_end(untype(offset) + size_value); \ + return offset; \ +} \ + \ +inline offset_type##_end operator-(offset_type##_end first, size_t size) { \ + const auto size_value = checked_cast>(size); \ + return to_##offset_type##_end(untype(first) - size_value); \ +} \ + \ +inline size_t operator-(offset_type##_end first, offset_type##_end second) { \ + return untype(first - untype(second)); \ +} \ + \ +inline offset_type##_end& operator-=(offset_type##_end& offset, size_t size) { \ + const auto size_value = checked_cast>(size); \ + offset = to_##offset_type##_end(untype(offset) - size_value); \ + return offset; \ +} \ + \ + /* Arithmetic operators for offset_type cross offset_type##_end */ \ + \ +inline size_t operator-(offset_type##_end first, offset_type second) { \ + return untype(first - untype(second)); \ +} \ + \ + /* Logical operators for offset_type cross offset_type##_end */ \ + \ +inline bool operator!=(offset_type first, offset_type##_end second) { \ + return untype(first) != untype(second); \ +} \ + \ +inline bool operator!=(offset_type##_end first, offset_type second) { \ + return untype(first) != untype(second); \ +} \ + \ +inline bool operator==(offset_type first, offset_type##_end second) { \ + return untype(first) == untype(second); \ +} \ + \ +inline bool operator==(offset_type##_end first, offset_type second) { \ + return untype(first) == untype(second); \ +} \ + \ +inline bool operator<(offset_type##_end first, offset_type second) { \ + return untype(first) < untype(second); \ +} \ + \ +inline bool operator<(offset_type first, offset_type##_end second) { \ + return untype(first) < untype(second); \ +} \ + \ +inline bool operator<=(offset_type##_end first, offset_type second) { \ + return untype(first) <= untype(second); \ +} \ + \ +inline bool operator>(offset_type first, offset_type##_end second) { \ + return untype(first) > untype(second); \ +} \ + \ +inline bool operator>=(offset_type first, offset_type##_end second) { \ + return untype(first) >= untype(second); \ +} \ + // zoffset functions inline uintptr_t untype(zoffset offset) { @@ -59,31 +169,6 @@ inline zoffset to_zoffset(zoffset_end offset) { return to_zoffset(value); } -inline zoffset operator+(zoffset offset, size_t size) { - return to_zoffset(untype(offset) + size); -} - -inline zoffset& operator+=(zoffset& offset, size_t size) { - offset = to_zoffset(untype(offset) + size); - return offset; -} - -inline zoffset operator-(zoffset offset, size_t size) { - const uintptr_t value = untype(offset) - size; - return to_zoffset(value); -} - -inline size_t operator-(zoffset left, zoffset right) { - const size_t diff = untype(left) - untype(right); - assert(diff < ZAddressOffsetMax, "Underflow"); - return diff; -} - -inline zoffset& operator-=(zoffset& offset, size_t size) { - offset = to_zoffset(untype(offset) - size); - return offset; -} - inline bool to_zoffset_end(zoffset_end* result, zoffset_end start, size_t size) { const uintptr_t value = untype(start) + size; if (value <= ZAddressOffsetMax) { @@ -109,62 +194,124 @@ inline zoffset_end to_zoffset_end(zoffset offset) { return zoffset_end(untype(offset)); } -inline bool operator!=(zoffset first, zoffset_end second) { - return untype(first) != untype(second); +CREATE_ZOFFSET_OPERATORS(zoffset) + +// zbacking_offset functions + +inline uintptr_t untype(zbacking_offset offset) { + const uintptr_t value = static_cast(offset); + assert(value < ZBackingOffsetMax, "must have no other bits"); + return value; } -inline bool operator!=(zoffset_end first, zoffset second) { - return untype(first) != untype(second); +inline uintptr_t untype(zbacking_offset_end offset) { + const uintptr_t value = static_cast(offset); + assert(value <= ZBackingOffsetMax, "must have no other bits"); + return value; } -inline bool operator==(zoffset first, zoffset_end second) { - return untype(first) == untype(second); +inline zbacking_offset to_zbacking_offset(uintptr_t value) { + assert(value < ZBackingOffsetMax, "must have no other bits"); + return zbacking_offset(value); } -inline bool operator==(zoffset_end first, zoffset second) { - return untype(first) == untype(second); +inline zbacking_offset to_zbacking_offset(zbacking_offset_end offset) { + const uintptr_t value = untype(offset); + return to_zbacking_offset(value); } -inline bool operator<(zoffset_end first, zoffset second) { - return untype(first) < untype(second); +inline zbacking_offset_end to_zbacking_offset_end(zbacking_offset start, size_t size) { + const uintptr_t value = untype(start) + size; + assert(value <= ZBackingOffsetMax, "Overflow start: " PTR_FORMAT " size: " PTR_FORMAT " value: " PTR_FORMAT, + untype(start), size, value); + return zbacking_offset_end(value); } -inline bool operator<(zoffset first, zoffset_end second) { - return untype(first) < untype(second); +inline zbacking_offset_end to_zbacking_offset_end(uintptr_t value) { + assert(value <= ZBackingOffsetMax, "must have no other bits"); + return zbacking_offset_end(value); } -inline bool operator<=(zoffset_end first, zoffset second) { - return untype(first) <= untype(second); +inline zbacking_offset_end to_zbacking_offset_end(zbacking_offset offset) { + return zbacking_offset_end(untype(offset)); } -inline bool operator>(zoffset first, zoffset_end second) { - return untype(first) > untype(second); +CREATE_ZOFFSET_OPERATORS(zbacking_offset) + +// zbacking_index functions + +inline uint32_t untype(zbacking_index index) { + const uint32_t value = static_cast(index); + assert(value < ZBackingIndexMax, "must have no other bits"); + return value; } -inline bool operator>=(zoffset first, zoffset_end second) { - return untype(first) >= untype(second); +inline uint32_t untype(zbacking_index_end index) { + const uint32_t value = static_cast(index); + assert(value <= ZBackingIndexMax, "must have no other bits"); + return value; } -inline size_t operator-(zoffset_end first, zoffset second) { - return untype(first) - untype(second); +inline zbacking_index to_zbacking_index(uint32_t value) { + assert(value < ZBackingIndexMax, "must have no other bits"); + return zbacking_index(value); } -inline zoffset_end operator-(zoffset_end first, size_t second) { - return to_zoffset_end(untype(first) - second); +inline zbacking_index to_zbacking_index(zbacking_index_end index) { + const uint32_t value = untype(index); + return to_zbacking_index(value); } -inline size_t operator-(zoffset_end first, zoffset_end second) { - return untype(first) - untype(second); +inline zbacking_index_end to_zbacking_index_end(zbacking_index start, size_t size) { + const uint32_t start_value = untype(start); + const uint32_t value = start_value + checked_cast(size); + assert(value <= ZBackingIndexMax && start_value <= value, + "Overflow start: %x size: %zu value: %x", start_value, size, value); + return zbacking_index_end(value); } -inline zoffset_end& operator-=(zoffset_end& offset, size_t size) { - offset = to_zoffset_end(untype(offset) - size); - return offset; +inline zbacking_index_end to_zbacking_index_end(uint32_t value) { + assert(value <= ZBackingIndexMax, "must have no other bits"); + return zbacking_index_end(value); } -inline zoffset_end& operator+=(zoffset_end& offset, size_t size) { - offset = to_zoffset_end(untype(offset) + size); - return offset; +inline zbacking_index_end to_zbacking_index_end(zbacking_index index) { + return zbacking_index_end(untype(index)); +} + +CREATE_ZOFFSET_OPERATORS(zbacking_index) + +#undef CREATE_ZOFFSET_OPERATORS + +// zbacking_offset <-> zbacking_index conversion functions + +inline zbacking_index to_zbacking_index(zbacking_offset offset) { + const uintptr_t value = untype(offset); + assert(is_aligned(value, ZGranuleSize), "must be granule aligned"); + return to_zbacking_index((uint32_t)(value >> ZGranuleSizeShift)); +} + +inline zbacking_offset to_zbacking_offset(zbacking_index index) { + const uintptr_t value = untype(index); + return to_zbacking_offset(value << ZGranuleSizeShift); +} + +// ZRange helper functions + +inline zoffset to_start_type(zoffset_end offset) { + return to_zoffset(offset); +} + +inline zbacking_index to_start_type(zbacking_index_end offset) { + return to_zbacking_index(offset); +} + +inline zoffset_end to_end_type(zoffset start, size_t size) { + return to_zoffset_end(start, size); +} + +inline zbacking_index_end to_end_type(zbacking_index start, size_t size) { + return to_zbacking_index_end(start, size); } // zpointer functions diff --git a/src/hotspot/share/gc/z/zAddressSpaceLimit.cpp b/src/hotspot/share/gc/z/zAddressSpaceLimit.cpp index fc42d9f3db1..9a6fb12779a 100644 --- a/src/hotspot/share/gc/z/zAddressSpaceLimit.cpp +++ b/src/hotspot/share/gc/z/zAddressSpaceLimit.cpp @@ -22,11 +22,13 @@ */ #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "gc/z/zAddressSpaceLimit.hpp" #include "gc/z/zGlobals.hpp" #include "runtime/globals.hpp" #include "runtime/os.hpp" #include "utilities/align.hpp" +#include "utilities/ostream.hpp" static size_t address_space_limit() { size_t limit = 0; @@ -44,3 +46,13 @@ size_t ZAddressSpaceLimit::heap() { const size_t limit = address_space_limit() / MaxVirtMemFraction; return align_up(limit, ZGranuleSize); } + +void ZAddressSpaceLimit::print_limits() { + const size_t limit = address_space_limit(); + + if (limit == SIZE_MAX) { + log_info_p(gc, init)("Address Space Size: unlimited"); + } else { + log_info_p(gc, init)("Address Space Size: limited (" EXACTFMT ")", EXACTFMTARGS(limit)); + } +} diff --git a/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp b/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp index 66e01f0ebb0..1c9c65c3255 100644 --- a/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp +++ b/src/hotspot/share/gc/z/zAddressSpaceLimit.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ class ZAddressSpaceLimit : public AllStatic { public: static size_t heap(); + + static void print_limits(); }; #endif // SHARE_GC_Z_ZADDRESSSPACELIMIT_HPP diff --git a/src/hotspot/share/gc/z/zAllocationFlags.hpp b/src/hotspot/share/gc/z/zAllocationFlags.hpp index c6998bac6c1..d94badae929 100644 --- a/src/hotspot/share/gc/z/zAllocationFlags.hpp +++ b/src/hotspot/share/gc/z/zAllocationFlags.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,25 +31,22 @@ // Allocation flags layout // ----------------------- // -// 7 2 1 0 -// +-----+-+-+-+ -// |00000|1|1|1| -// +-----+-+-+-+ -// | | | | -// | | | * 0-0 Non-Blocking Flag (1-bit) -// | | | -// | | * 1-1 GC Relocation Flag (1-bit) -// | | -// | * 2-2 Low Address Flag (1-bit) +// 7 1 0 +// +------+-+-+ +// |000000|1|1| +// +------+-+-+ +// | | | +// | | * 0-0 Non-Blocking Flag (1-bit) +// | | +// | * 1-1 GC Relocation Flag (1-bit) // | -// * 7-3 Unused (5-bits) +// * 7-2 Unused (6-bits) // class ZAllocationFlags { private: typedef ZBitField field_non_blocking; typedef ZBitField field_gc_relocation; - typedef ZBitField field_low_address; uint8_t _flags; @@ -65,10 +62,6 @@ public: _flags |= field_gc_relocation::encode(true); } - void set_low_address() { - _flags |= field_low_address::encode(true); - } - bool non_blocking() const { return field_non_blocking::decode(_flags); } @@ -76,10 +69,6 @@ public: bool gc_relocation() const { return field_gc_relocation::decode(_flags); } - - bool low_address() const { - return field_low_address::decode(_flags); - } }; #endif // SHARE_GC_Z_ZALLOCATIONFLAGS_HPP diff --git a/src/hotspot/share/gc/z/zArguments.cpp b/src/hotspot/share/gc/z/zArguments.cpp index f972e0718b4..67b9f6f0bb9 100644 --- a/src/hotspot/share/gc/z/zArguments.cpp +++ b/src/hotspot/share/gc/z/zArguments.cpp @@ -122,7 +122,7 @@ void ZArguments::initialize() { GCArguments::initialize(); // Enable NUMA by default - if (FLAG_IS_DEFAULT(UseNUMA)) { + if (FLAG_IS_DEFAULT(UseNUMA) && FLAG_IS_DEFAULT(ZFakeNUMA)) { FLAG_SET_DEFAULT(UseNUMA, true); } diff --git a/src/hotspot/share/gc/z/zArray.hpp b/src/hotspot/share/gc/z/zArray.hpp index 7bcd4f59eeb..1b7e99b3ace 100644 --- a/src/hotspot/share/gc/z/zArray.hpp +++ b/src/hotspot/share/gc/z/zArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,49 @@ #include +template class ZArray; class ZLock; -template using ZArray = GrowableArrayCHeap; +template +class ZArraySlice : public GrowableArrayView { + friend class ZArray; + friend class ZArray>; + friend class ZArraySlice>; + friend class ZArraySlice; + +private: + ZArraySlice(T* data, int len); + +public: + ZArraySlice slice_front(int end); + ZArraySlice slice_front(int end) const; + + ZArraySlice slice_back(int start); + ZArraySlice slice_back(int start) const; + + ZArraySlice slice(int start, int end); + ZArraySlice slice(int start, int end) const; + + operator ZArraySlice() const; +}; + +template +class ZArray : public GrowableArrayCHeap { +public: + using GrowableArrayCHeap::GrowableArrayCHeap; + + ZArraySlice slice_front(int end); + ZArraySlice slice_front(int end) const; + + ZArraySlice slice_back(int start); + ZArraySlice slice_back(int start) const; + + ZArraySlice slice(int start, int end); + ZArraySlice slice(int start, int end) const; + + operator ZArraySlice(); + operator ZArraySlice() const; +}; template class ZArrayIteratorImpl : public StackObj { diff --git a/src/hotspot/share/gc/z/zArray.inline.hpp b/src/hotspot/share/gc/z/zArray.inline.hpp index ec7feda8d63..547a73ffc0d 100644 --- a/src/hotspot/share/gc/z/zArray.inline.hpp +++ b/src/hotspot/share/gc/z/zArray.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,93 @@ #include "gc/z/zLock.inline.hpp" #include "runtime/atomic.hpp" +template +ZArraySlice::ZArraySlice(T* data, int len) + : GrowableArrayView(data, len, len) {} + +template +ZArraySlice ZArraySlice::slice_front(int end) { + return slice(0, end); +} + +template +ZArraySlice ZArraySlice::slice_front(int end) const { + return slice(0, end); +} + +template +ZArraySlice ZArraySlice::slice_back(int start) { + return slice(start, this->_len); +} + +template +ZArraySlice ZArraySlice::slice_back(int start) const { + return slice(start, this->_len); +} + +template +ZArraySlice ZArraySlice::slice(int start, int end) { + assert(0 <= start && start <= end && end <= this->_len, + "slice called with invalid range (%d, %d) for length %d", start, end, this->_len); + return ZArraySlice(this->_data + start, end - start); +} + +template +ZArraySlice ZArraySlice::slice(int start, int end) const { + assert(0 <= start && start <= end && end <= this->_len, + "slice called with invalid range (%d, %d) for length %d", start, end, this->_len); + return ZArraySlice(this->_data + start, end - start); +} + +template +ZArraySlice::operator ZArraySlice() const { + return slice(0, this->_len); +} + +template +ZArraySlice ZArray::slice_front(int end) { + return slice(0, end); +} + +template +ZArraySlice ZArray::slice_front(int end) const { + return slice(0, end); +} + +template +ZArraySlice ZArray::slice_back(int start) { + return slice(start, this->_len); +} + +template +ZArraySlice ZArray::slice_back(int start) const { + return slice(start, this->_len); +} + +template +ZArraySlice ZArray::slice(int start, int end) { + assert(0 <= start && start <= end && end <= this->_len, + "slice called with invalid range (%d, %d) for length %d", start, end, this->_len); + return ZArraySlice(this->_data + start, end - start); +} + +template +ZArraySlice ZArray::slice(int start, int end) const { + assert(0 <= start && start <= end && end <= this->_len, + "slice called with invalid range (%d, %d) for length %d", start, end, this->_len); + return ZArraySlice(this->_data + start, end - start); +} + +template +ZArray::operator ZArraySlice() { + return slice(0, this->_len); +} + +template +ZArray::operator ZArraySlice() const { + return slice(0, this->_len); +} + template inline bool ZArrayIteratorImpl::next_serial(size_t* index) { if (_next == _end) { diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index 828e3c9d033..642ad42a1d7 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -53,6 +53,7 @@ #include "runtime/stackWatermarkSet.hpp" #include "services/memoryUsage.hpp" #include "utilities/align.hpp" +#include "utilities/ostream.hpp" ZCollectedHeap* ZCollectedHeap::heap() { return named_heap(CollectedHeap::Z); @@ -245,7 +246,7 @@ size_t ZCollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const { } MemoryUsage ZCollectedHeap::memory_usage() { - const size_t initial_size = ZHeap::heap()->initial_capacity(); + const size_t initial_size = InitialHeapSize; const size_t committed = ZHeap::heap()->capacity(); const size_t used = MIN2(ZHeap::heap()->used(), committed); const size_t max_size = ZHeap::heap()->max_capacity(); @@ -355,10 +356,14 @@ void ZCollectedHeap::prepare_for_verify() { } void ZCollectedHeap::print_on(outputStream* st) const { + StreamAutoIndentor auto_indentor(st); + _heap.print_on(st); } void ZCollectedHeap::print_on_error(outputStream* st) const { + StreamAutoIndentor auto_indentor(st); + _heap.print_on_error(st); } diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index f8475256733..f3cd3393fc5 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -160,7 +160,7 @@ void ZGeneration::free_empty_pages(ZRelocationSetSelector* selector, int bulk) { // the page allocator lock, and trying to satisfy stalled allocations // too frequently. if (selector->should_free_empty_pages(bulk)) { - const size_t freed = ZHeap::heap()->free_empty_pages(selector->empty_pages()); + const size_t freed = ZHeap::heap()->free_empty_pages(_id, selector->empty_pages()); increase_freed(freed); selector->clear_empty_pages(); } @@ -190,17 +190,6 @@ void ZGeneration::select_relocation_set(bool promote_all) { for (ZPage* page; pt_iter.next(&page);) { if (!page->is_relocatable()) { // Not relocatable, don't register - // Note that the seqnum can change under our feet here as the page - // can be concurrently freed and recycled by a concurrent generation - // collection. However this property is stable across such transitions. - // If it was not relocatable before recycling, then it won't be - // relocatable after it gets recycled either, as the seqnum atomically - // becomes allocating for the given generation. The opposite property - // also holds: if the page is relocatable, then it can't have been - // concurrently freed; if it was re-allocated it would not be - // relocatable, and if it was not re-allocated we know that it was - // allocated earlier than mark start of the current generation - // collection. continue; } @@ -213,15 +202,14 @@ void ZGeneration::select_relocation_set(bool promote_all) { // Reclaim empty pages in bulk - // An active iterator blocks immediate recycle and delete of pages. - // The intent it to allow the code that iterates over the pages to - // safely read the properties of the pages without them being changed - // by another thread. However, this function both iterates over the - // pages AND frees/recycles them. We "yield" the iterator, so that we - // can perform immediate recycling (as long as no other thread is - // iterating over the pages). The contract is that the pages that are - // about to be freed are "owned" by this thread, and no other thread - // will change their states. + // An active iterator blocks immediate deletion of pages. The intent is + // to allow the code that iterates over pages to safely read properties + // of the pages without them being freed/deleted. However, this + // function both iterates over the pages AND frees them. We "yield" the + // iterator, so that we can perform immediate deletion (as long as no + // other thread is iterating over the pages). The contract is that the + // pages that are about to be freed are "owned" by this thread, and no + // other thread will change their states. pt_iter.yield([&]() { free_empty_pages(&selector, 64 /* bulk */); }); @@ -934,7 +922,7 @@ void ZGenerationYoung::flip_promote(ZPage* from_page, ZPage* to_page) { _page_table->replace(from_page, to_page); // Update statistics - _page_allocator->promote_used(from_page->size()); + _page_allocator->promote_used(from_page, to_page); increase_freed(from_page->size()); increase_promoted(from_page->live_bytes()); } @@ -943,7 +931,7 @@ void ZGenerationYoung::in_place_relocate_promote(ZPage* from_page, ZPage* to_pag _page_table->replace(from_page, to_page); // Update statistics - _page_allocator->promote_used(from_page->size()); + _page_allocator->promote_used(from_page, to_page); } void ZGenerationYoung::register_flip_promoted(const ZArray& pages) { diff --git a/src/hotspot/share/gc/z/zGranuleMap.hpp b/src/hotspot/share/gc/z/zGranuleMap.hpp index 58c95e331b6..4cde26847be 100644 --- a/src/hotspot/share/gc/z/zGranuleMap.hpp +++ b/src/hotspot/share/gc/z/zGranuleMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,9 @@ public: T get_acquire(zoffset offset) const; void release_put(zoffset offset, T value); void release_put(zoffset offset, size_t size, T value); + + const T* addr(zoffset offset) const; + T* addr(zoffset offset); }; template diff --git a/src/hotspot/share/gc/z/zGranuleMap.inline.hpp b/src/hotspot/share/gc/z/zGranuleMap.inline.hpp index 6cdc31f8270..21be6a3d80a 100644 --- a/src/hotspot/share/gc/z/zGranuleMap.inline.hpp +++ b/src/hotspot/share/gc/z/zGranuleMap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,6 +101,17 @@ inline void ZGranuleMap::release_put(zoffset offset, size_t size, T value) { put(offset, size, value); } +template +inline const T* ZGranuleMap::addr(zoffset offset) const { + const size_t index = index_for_offset(offset); + return _map + index; +} + +template +inline T* ZGranuleMap::addr(zoffset offset) { + return const_cast(const_cast*>(this)->addr(offset)); +} + template inline ZGranuleMapIterator::ZGranuleMapIterator(const ZGranuleMap* granule_map) : ZArrayIteratorImpl(granule_map->_map, granule_map->_size) {} diff --git a/src/hotspot/share/gc/z/zHeap.cpp b/src/hotspot/share/gc/z/zHeap.cpp index e0f4cb65303..90f8a867135 100644 --- a/src/hotspot/share/gc/z/zHeap.cpp +++ b/src/hotspot/share/gc/z/zHeap.cpp @@ -59,7 +59,7 @@ ZHeap::ZHeap() _page_table(), _allocator_eden(), _allocator_relocation(), - _serviceability(initial_capacity(), min_capacity(), max_capacity()), + _serviceability(InitialHeapSize, min_capacity(), max_capacity()), _old(&_page_table, &_page_allocator), _young(&_page_table, _old.forwarding_table(), &_page_allocator), _initialized(false) { @@ -94,10 +94,6 @@ bool ZHeap::is_initialized() const { return _initialized; } -size_t ZHeap::initial_capacity() const { - return _page_allocator.initial_capacity(); -} - size_t ZHeap::min_capacity() const { return _page_allocator.min_capacity(); } @@ -240,18 +236,18 @@ void ZHeap::undo_alloc_page(ZPage* page) { log_trace(gc)("Undo page allocation, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT ", size: %zu", p2i(Thread::current()), ZUtils::thread_name(), p2i(page), page->size()); - free_page(page, false /* allow_defragment */); + free_page(page); } -void ZHeap::free_page(ZPage* page, bool allow_defragment) { +void ZHeap::free_page(ZPage* page) { // Remove page table entry _page_table.remove(page); // Free page - _page_allocator.free_page(page, allow_defragment); + _page_allocator.free_page(page); } -size_t ZHeap::free_empty_pages(const ZArray* pages) { +size_t ZHeap::free_empty_pages(ZGenerationId id, const ZArray* pages) { size_t freed = 0; // Remove page table entries ZArrayIterator iter(pages); @@ -261,7 +257,7 @@ size_t ZHeap::free_empty_pages(const ZArray* pages) { } // Free pages - _page_allocator.free_pages(pages); + _page_allocator.free_pages(id, pages); return freed; } @@ -319,21 +315,32 @@ ZServiceabilityCounters* ZHeap::serviceability_counters() { } void ZHeap::print_on(outputStream* st) const { - st->print_cr(" ZHeap used %zuM, capacity %zuM, max capacity %zuM", - used() / M, - capacity() / M, - max_capacity() / M); + streamIndentor indentor(st, 1); + _page_allocator.print_on(st); + + // Metaspace printing prepends spaces instead of using outputStream indentation + streamIndentor indentor_back(st, -1); MetaspaceUtils::print_on(st); } void ZHeap::print_on_error(outputStream* st) const { - print_on(st); + { + streamIndentor indentor(st, 1); + _page_allocator.print_on_error(st); + + // Metaspace printing prepends spaces instead of using outputStream indentation + streamIndentor indentor_back(st, -1); + MetaspaceUtils::print_on(st); + } st->cr(); print_globals_on(st); st->cr(); print_page_table_on(st); + st->cr(); + + _page_allocator.print_extended_on_error(st); } void ZHeap::print_globals_on(outputStream* st) const { @@ -366,9 +373,12 @@ void ZHeap::print_page_table_on(outputStream* st) const { // Print all pages st->print_cr("ZGC Page Table:"); - ZPageTableIterator iter(&_page_table); - for (ZPage* page; iter.next(&page);) { - page->print_on(st); + { + streamIndentor indentor(st, 1); + ZPageTableIterator iter(&_page_table); + for (ZPage* page; iter.next(&page);) { + page->print_on(st); + } } // Allow pages to be deleted diff --git a/src/hotspot/share/gc/z/zHeap.hpp b/src/hotspot/share/gc/z/zHeap.hpp index 25cd2209003..823fc009b2c 100644 --- a/src/hotspot/share/gc/z/zHeap.hpp +++ b/src/hotspot/share/gc/z/zHeap.hpp @@ -67,7 +67,6 @@ public: void out_of_memory(); // Heap metrics - size_t initial_capacity() const; size_t min_capacity() const; size_t max_capacity() const; size_t soft_max_capacity() const; @@ -104,8 +103,8 @@ public: // Page allocation ZPage* alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age); void undo_alloc_page(ZPage* page); - void free_page(ZPage* page, bool allow_defragment); - size_t free_empty_pages(const ZArray* pages); + void free_page(ZPage* page); + size_t free_empty_pages(ZGenerationId id, const ZArray* pages); // Object allocation bool is_alloc_stalling() const; diff --git a/src/hotspot/share/gc/z/zInitialize.cpp b/src/hotspot/share/gc/z/zInitialize.cpp index 125231355ac..b8efa8bcd69 100644 --- a/src/hotspot/share/gc/z/zInitialize.cpp +++ b/src/hotspot/share/gc/z/zInitialize.cpp @@ -57,8 +57,8 @@ void ZInitialize::initialize(ZBarrierSet* barrier_set) { // Early initialization ZNMT::initialize(); - ZGlobalsPointers::initialize(); ZNUMA::initialize(); + ZGlobalsPointers::initialize(); ZCPU::initialize(); ZStatValue::initialize(); ZThreadLocalAllocBuffer::initialize(); diff --git a/src/hotspot/share/gc/z/zIntrusiveRBTree.hpp b/src/hotspot/share/gc/z/zIntrusiveRBTree.hpp new file mode 100644 index 00000000000..ff204d86462 --- /dev/null +++ b/src/hotspot/share/gc/z/zIntrusiveRBTree.hpp @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZINTRUSIVERBTREE_HPP +#define SHARE_GC_Z_ZINTRUSIVERBTREE_HPP + +#include "metaprogramming/enableIf.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +enum class ZIntrusiveRBTreeDirection { LEFT, RIGHT }; + +class ZIntrusiveRBTreeNode { + template + friend class ZIntrusiveRBTree; + +public: + enum Color { RED = 0b0, BLACK = 0b1 }; + +private: + class ColoredNodePtr { + private: + static constexpr uintptr_t COLOR_MASK = 0b1; + static constexpr uintptr_t NODE_MASK = ~COLOR_MASK; + + uintptr_t _value; + + public: + ColoredNodePtr(ZIntrusiveRBTreeNode* node = nullptr, Color color = RED); + + constexpr Color color() const; + constexpr bool is_black() const; + constexpr bool is_red() const; + + ZIntrusiveRBTreeNode* node() const; + ZIntrusiveRBTreeNode* red_node() const; + ZIntrusiveRBTreeNode* black_node() const; + }; + +private: + ColoredNodePtr _colored_parent; + ZIntrusiveRBTreeNode* _left; + ZIntrusiveRBTreeNode* _right; + + template + const ZIntrusiveRBTreeNode* find_next_node() const; + + template + const ZIntrusiveRBTreeNode* child() const; + template + ZIntrusiveRBTreeNode* child(); + + template + ZIntrusiveRBTreeNode* const* child_addr() const; + + template + bool has_child() const; + + template + void update_child(ZIntrusiveRBTreeNode* new_child); + + void link_node(ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode** insert_location); + + void copy_parent_and_color(ZIntrusiveRBTreeNode* other); + void update_parent_and_color(ZIntrusiveRBTreeNode* parent, Color color); + + void update_parent(ZIntrusiveRBTreeNode* parent); + void update_color(Color color); + + void update_left_child(ZIntrusiveRBTreeNode* new_child); + void update_right_child(ZIntrusiveRBTreeNode* new_child); + + const ZIntrusiveRBTreeNode* parent() const; + ZIntrusiveRBTreeNode* parent(); + const ZIntrusiveRBTreeNode* red_parent() const; + ZIntrusiveRBTreeNode* red_parent(); + const ZIntrusiveRBTreeNode* black_parent() const; + ZIntrusiveRBTreeNode* black_parent(); + + bool has_parent() const; + + Color color() const; + bool is_black() const; + bool is_red() const; + static bool is_black(ZIntrusiveRBTreeNode* node); + + ZIntrusiveRBTreeNode* const* left_child_addr() const; + ZIntrusiveRBTreeNode* const* right_child_addr() const; + + const ZIntrusiveRBTreeNode* left_child() const; + ZIntrusiveRBTreeNode* left_child(); + const ZIntrusiveRBTreeNode* right_child() const; + ZIntrusiveRBTreeNode* right_child(); + + bool has_left_child() const; + bool has_right_child() const; + +public: + ZIntrusiveRBTreeNode(); + + const ZIntrusiveRBTreeNode* prev() const; + ZIntrusiveRBTreeNode* prev(); + const ZIntrusiveRBTreeNode* next() const; + ZIntrusiveRBTreeNode* next(); +}; + +template +class ZIntrusiveRBTree { +public: + class FindCursor { + friend class ZIntrusiveRBTree; + + private: + ZIntrusiveRBTreeNode** _insert_location; + ZIntrusiveRBTreeNode* _parent; + bool _left_most; + bool _right_most; + DEBUG_ONLY(uintptr_t _sequence_number;) + + FindCursor(ZIntrusiveRBTreeNode** insert_location, ZIntrusiveRBTreeNode* parent, bool left_most, bool right_most DEBUG_ONLY(COMMA uintptr_t sequence_number)); + FindCursor(); + +#ifdef ASSERT + bool is_valid(uintptr_t sequence_number) const; +#endif + + public: + FindCursor(const FindCursor&) = default; + FindCursor& operator=(const FindCursor&) = default; + + bool is_valid() const; + bool found() const; + ZIntrusiveRBTreeNode* node() const; + bool is_left_most() const; + bool is_right_most() const; + ZIntrusiveRBTreeNode* parent() const; + ZIntrusiveRBTreeNode** insert_location() const; + }; + +private: + ZIntrusiveRBTreeNode* _root_node; + ZIntrusiveRBTreeNode* _left_most; + ZIntrusiveRBTreeNode* _right_most; + DEBUG_ONLY(uintptr_t _sequence_number;) + + NONCOPYABLE(ZIntrusiveRBTree); + +#ifdef ASSERT + template + bool verify_node(ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode* left_child, ZIntrusiveRBTreeNode* right_child); + template + bool verify_node(ZIntrusiveRBTreeNode* parent); + template + bool verify_node(ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode* left_child); + struct any_t {}; + template + bool verify_node(ZIntrusiveRBTreeNode* parent, any_t, ZIntrusiveRBTreeNode* right_child); +#endif // ASSERT + + ZIntrusiveRBTreeNode* const* root_node_addr() const; + + void update_child_or_root(ZIntrusiveRBTreeNode* old_node, ZIntrusiveRBTreeNode* new_node, ZIntrusiveRBTreeNode* parent); + void rotate_and_update_child_or_root(ZIntrusiveRBTreeNode* old_node, ZIntrusiveRBTreeNode* new_node, ZIntrusiveRBTreeNode::Color color); + + template + void rebalance_insert_with_sibling(ZIntrusiveRBTreeNode* node, ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode* grand_parent); + template + bool rebalance_insert_with_parent_sibling(ZIntrusiveRBTreeNode** node_addr, ZIntrusiveRBTreeNode** parent_addr, ZIntrusiveRBTreeNode* grand_parent); + void rebalance_insert(ZIntrusiveRBTreeNode* new_node); + + template + bool rebalance_remove_with_sibling(ZIntrusiveRBTreeNode** node_addr, ZIntrusiveRBTreeNode** parent_addr); + void rebalance_remove(ZIntrusiveRBTreeNode* rebalance_from); + + FindCursor make_cursor(ZIntrusiveRBTreeNode* const* insert_location, ZIntrusiveRBTreeNode* parent, bool left_most, bool right_most) const; + template + FindCursor find_next(const FindCursor& cursor) const; + +public: + ZIntrusiveRBTree(); + + ZIntrusiveRBTreeNode* first() const; + ZIntrusiveRBTreeNode* last() const; + + FindCursor root_cursor() const; + FindCursor get_cursor(const ZIntrusiveRBTreeNode* node) const; + FindCursor prev_cursor(const ZIntrusiveRBTreeNode* node) const; + FindCursor next_cursor(const ZIntrusiveRBTreeNode* node) const; + FindCursor prev(const FindCursor& cursor) const; + FindCursor next(const FindCursor& cursor) const; + FindCursor find(const Key& key) const; + + void insert(ZIntrusiveRBTreeNode* new_node, const FindCursor& find_cursor); + void replace(ZIntrusiveRBTreeNode* new_node, const FindCursor& find_cursor); + void remove(const FindCursor& find_cursor); + + void verify_tree(); + +public: + template + class IteratorImplementation; + + using Iterator = IteratorImplementation; + using ConstIterator = IteratorImplementation; + using ReverseIterator = IteratorImplementation; + using ConstReverseIterator = IteratorImplementation; + + // remove and replace invalidate the iterators + // however the iterators provide a remove and replace + // function which does not invalidate that iterator nor + // any end iterator + Iterator begin(); + Iterator end(); + ConstIterator begin() const; + ConstIterator end() const; + ConstIterator cbegin() const; + ConstIterator cend() const; + ReverseIterator rbegin(); + ReverseIterator rend(); + ConstReverseIterator rbegin() const; + ConstReverseIterator rend() const; + ConstReverseIterator crbegin() const; + ConstReverseIterator crend() const; +}; + +template +template +class ZIntrusiveRBTree::IteratorImplementation { + friend IteratorImplementation; + +public: + using difference_type = std::ptrdiff_t; + using value_type = const ZIntrusiveRBTreeNode; + using pointer = value_type*; + using reference = value_type&; + +private: + ZIntrusiveRBTree* _tree; + const ZIntrusiveRBTreeNode* _node; + bool _removed; + + bool at_end() const; + +public: + IteratorImplementation(ZIntrusiveRBTree& tree, pointer node); + IteratorImplementation(const IteratorImplementation&) = default; + template + IteratorImplementation(const IteratorImplementation& other); + + reference operator*() const; + pointer operator->(); + IteratorImplementation& operator--(); + IteratorImplementation operator--(int); + IteratorImplementation& operator++(); + IteratorImplementation operator++(int); + + template + void replace(ZIntrusiveRBTreeNode * new_node); + template + void remove(); + + // Note: friend operator overloads defined inside class declaration because of problems with ADL + friend bool operator==(const IteratorImplementation& a, const IteratorImplementation& b) { + precond(a._tree == b._tree); + return a._node == b._node; + } + friend bool operator!=(const IteratorImplementation& a, const IteratorImplementation& b) { + precond(a._tree == b._tree); + return a._node != b._node; + } +}; + +#endif // SHARE_GC_Z_ZINTRUSIVERBTREE_HPP diff --git a/src/hotspot/share/gc/z/zIntrusiveRBTree.inline.hpp b/src/hotspot/share/gc/z/zIntrusiveRBTree.inline.hpp new file mode 100644 index 00000000000..b62db5166dd --- /dev/null +++ b/src/hotspot/share/gc/z/zIntrusiveRBTree.inline.hpp @@ -0,0 +1,1351 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZINTRUSIVERBTREE_INLINE_HPP +#define SHARE_GC_Z_ZINTRUSIVERBTREE_INLINE_HPP + +#include "gc/z/zIntrusiveRBTree.hpp" + +#include "metaprogramming/enableIf.hpp" +#include "utilities/debug.hpp" + +static constexpr ZIntrusiveRBTreeDirection other(const ZIntrusiveRBTreeDirection& direction) { + return direction == ZIntrusiveRBTreeDirection::LEFT ? ZIntrusiveRBTreeDirection::RIGHT : ZIntrusiveRBTreeDirection::LEFT; +} + +inline ZIntrusiveRBTreeNode::ColoredNodePtr::ColoredNodePtr(ZIntrusiveRBTreeNode* node, Color color) + : _value(reinterpret_cast(node) | color) {} + +inline constexpr ZIntrusiveRBTreeNode::Color ZIntrusiveRBTreeNode::ColoredNodePtr::color() const { + return static_cast(_value & COLOR_MASK); +} + +inline constexpr bool ZIntrusiveRBTreeNode::ColoredNodePtr::is_black() const { + return color() == BLACK; +} + +inline constexpr bool ZIntrusiveRBTreeNode::ColoredNodePtr::is_red() const { + return color() == RED; +} + +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::ColoredNodePtr::node() const { + return reinterpret_cast(_value & NODE_MASK); +} + +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::ColoredNodePtr::red_node() const { + precond(is_red()); + return reinterpret_cast(_value); +} +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::ColoredNodePtr::black_node() const { + precond(is_black()); + return reinterpret_cast(_value ^ BLACK); +} + +template +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::find_next_node() const { + constexpr ZIntrusiveRBTreeDirection OTHER_DIRECTION = other(DIRECTION); + const ZIntrusiveRBTreeNode* node = this; + + // Down the tree + if (node->has_child()) { + node = node->child(); + while (node->has_child()) { + node = node->child(); + } + return node; + } + + // Up the tree + const ZIntrusiveRBTreeNode* parent = node->parent(); + while (parent != nullptr && node == parent->child()) { + node = parent; + parent = node->parent(); + } + return parent; +} + +template +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::child() const { + if (DIRECTION == ZIntrusiveRBTreeDirection::LEFT) { + return _left; + } + assert(DIRECTION == ZIntrusiveRBTreeDirection::RIGHT, "must be"); + return _right; +} + +template +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::child() { + return const_cast(const_cast(this)->template child()); +} + +template +inline ZIntrusiveRBTreeNode* const* ZIntrusiveRBTreeNode::child_addr() const { + if (DIRECTION == ZIntrusiveRBTreeDirection::LEFT) { + return &_left; + } + assert(DIRECTION == ZIntrusiveRBTreeDirection::RIGHT, "must be"); + return &_right; +} + +template +inline bool ZIntrusiveRBTreeNode::has_child() const { + if (DIRECTION == ZIntrusiveRBTreeDirection::LEFT) { + return _left != nullptr; + } + assert(DIRECTION == ZIntrusiveRBTreeDirection::RIGHT, "must be"); + return _right != nullptr; +} + +template +inline void ZIntrusiveRBTreeNode::update_child(ZIntrusiveRBTreeNode* new_child) { + if (DIRECTION == ZIntrusiveRBTreeDirection::LEFT) { + _left = new_child; + return; + } + assert(DIRECTION == ZIntrusiveRBTreeDirection::RIGHT, "must be"); + _right = new_child; +} + +inline void ZIntrusiveRBTreeNode::link_node(ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode** insert_location) { + // Newly linked node is always red + _colored_parent = ColoredNodePtr(parent, RED); + _left = nullptr; + _right = nullptr; + + // Link into location + *insert_location = this; +} + +inline void ZIntrusiveRBTreeNode::copy_parent_and_color(ZIntrusiveRBTreeNode* other) { + _colored_parent = other->_colored_parent; +} + +inline void ZIntrusiveRBTreeNode::update_parent_and_color(ZIntrusiveRBTreeNode* parent, Color color) { + _colored_parent = ColoredNodePtr(parent, color); +} + +inline void ZIntrusiveRBTreeNode::update_parent(ZIntrusiveRBTreeNode* parent) { + _colored_parent = ColoredNodePtr(parent, color()); +} + +inline void ZIntrusiveRBTreeNode::update_color(Color color) { + _colored_parent = ColoredNodePtr(parent(), color); +} + +inline void ZIntrusiveRBTreeNode::update_left_child(ZIntrusiveRBTreeNode* new_child) { + update_child(new_child); +} + +inline void ZIntrusiveRBTreeNode::update_right_child(ZIntrusiveRBTreeNode* new_child) { + update_child(new_child); +} + +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::parent() const { + return _colored_parent.node(); +} + +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::parent() { + return const_cast(const_cast(this)->parent()); +} + +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::red_parent() const { + return _colored_parent.red_node(); +} +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::red_parent() { + return const_cast(const_cast(this)->red_parent()); +} + +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::black_parent() const { + return _colored_parent.black_node(); +} +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::black_parent() { + return const_cast(const_cast(this)->black_parent()); +} + +inline bool ZIntrusiveRBTreeNode::has_parent() const { + return _colored_parent.node() != nullptr; +} + +inline ZIntrusiveRBTreeNode::Color ZIntrusiveRBTreeNode::color() const { + return _colored_parent.color(); +} + +inline bool ZIntrusiveRBTreeNode::is_black() const { + return _colored_parent.is_black(); +} + +inline bool ZIntrusiveRBTreeNode::is_red() const { + return _colored_parent.is_red(); +} + +inline bool ZIntrusiveRBTreeNode::is_black(ZIntrusiveRBTreeNode* node) { + return node == nullptr || node->is_black(); +} + +inline ZIntrusiveRBTreeNode* const* ZIntrusiveRBTreeNode::left_child_addr() const { + return child_addr(); +} + +inline ZIntrusiveRBTreeNode* const* ZIntrusiveRBTreeNode::right_child_addr() const { + return child_addr(); +} + +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::left_child() const { + return child(); +} + +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::left_child() { + return const_cast(const_cast(this)->left_child()); +} + +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::right_child() const { + return child(); +} + +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::right_child() { + return const_cast(const_cast(this)->right_child()); +} + +inline bool ZIntrusiveRBTreeNode::has_left_child() const { + return has_child(); +} + +inline bool ZIntrusiveRBTreeNode::has_right_child() const { + return has_child(); +} + +inline ZIntrusiveRBTreeNode::ZIntrusiveRBTreeNode() {} + +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::prev() const { + return find_next_node(); +} + +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::prev() { + return const_cast(const_cast(this)->prev()); +} + +inline const ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::next() const { + return find_next_node(); +} + +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTreeNode::next() { + return const_cast(const_cast(this)->next()); +} + +#ifdef ASSERT +template +template +inline bool ZIntrusiveRBTree::verify_node(ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode* left_child, ZIntrusiveRBTreeNode* right_child) { + if (swap_left_right) { + ::swap(left_child, right_child); + } + assert(parent->left_child() == left_child, swap_left_right ? "Bad child Swapped" : "Bad child"); + assert(parent->right_child() == right_child, swap_left_right ? "Bad child Swapped" : "Bad child"); + if (left_child != nullptr) { + assert(left_child->parent() == parent, swap_left_right ? "Bad parent Swapped" : "Bad parent"); + } + if (right_child != nullptr) { + assert(right_child->parent() == parent, swap_left_right ? "Bad parent Swapped" : "Bad parent"); + } + return true; +} + +template +template +inline bool ZIntrusiveRBTree::verify_node(ZIntrusiveRBTreeNode* parent) { + if (parent == nullptr) { + return true; + } + if (swap_left_right) { + return verify_node(parent, parent->right_child()); + } + return verify_node(parent, parent->left_child()); +} + +template +template +inline bool ZIntrusiveRBTree::verify_node(ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode* left_child) { + if (swap_left_right) { + return verify_node(parent, left_child, parent->left_child()); + } + return verify_node(parent, left_child, parent->right_child()); +} + +template +template +inline bool ZIntrusiveRBTree::verify_node(ZIntrusiveRBTreeNode* parent, any_t, ZIntrusiveRBTreeNode* right_child) { + if (swap_left_right) { + return verify_node(parent, parent->right_child(), right_child); + } + return verify_node(parent, parent->left_child(), right_child); +} +#endif // ASSERT + +template +inline ZIntrusiveRBTreeNode* const* ZIntrusiveRBTree::root_node_addr() const { + return &_root_node; +} + +template +void ZIntrusiveRBTree::update_child_or_root(ZIntrusiveRBTreeNode* old_node, ZIntrusiveRBTreeNode* new_node, ZIntrusiveRBTreeNode* parent) { + if (parent == nullptr) { + // Update root + _root_node = new_node; + return; + } + if (old_node == parent->left_child()) { + parent->update_left_child(new_node); + return; + } + assert(old_node == parent->right_child(), "must be"); + parent->update_right_child(new_node); +} + +template +inline void ZIntrusiveRBTree::rotate_and_update_child_or_root(ZIntrusiveRBTreeNode* old_node, ZIntrusiveRBTreeNode* new_node, ZIntrusiveRBTreeNode::Color color) { + ZIntrusiveRBTreeNode* const parent = old_node->parent(); + new_node->copy_parent_and_color(old_node); + old_node->update_parent_and_color(new_node, color); + update_child_or_root(old_node, new_node, parent); +} + +template +template +inline void ZIntrusiveRBTree::rebalance_insert_with_sibling(ZIntrusiveRBTreeNode* node, ZIntrusiveRBTreeNode* parent, ZIntrusiveRBTreeNode* grand_parent) { + DEBUG_ONLY(const bool swap_left_right = PARENT_SIBLING_DIRECTION == ZIntrusiveRBTreeDirection::LEFT;) + constexpr ZIntrusiveRBTreeDirection OTHER_DIRECTION = other(PARENT_SIBLING_DIRECTION); + ZIntrusiveRBTreeNode* sibling = parent->template child(); + DEBUG_ONLY(bool rotated_parent = false;) + if (node == sibling) { + DEBUG_ONLY(rotated_parent = true;) + // Rotate up node through parent + ZIntrusiveRBTreeNode* child = node->template child(); + + //// PRE + // + // G G + // / \ + // p or p + // \ / + // n n + // / \ + // (c) (c) + // + //// + precond(grand_parent->is_black()); + precond(parent->is_red()); + precond(node->is_red()); + precond(verify_node(grand_parent, parent)); + precond(verify_node(parent, any_t{}, node)); + precond(verify_node(node, child)); + precond(verify_node(child)); + + // Fix children + parent->template update_child(child); + node->template update_child(parent); + + // Fix parents and colors + if (child != nullptr) { + child->update_parent_and_color(parent, ZIntrusiveRBTreeNode::BLACK); + } + parent->update_parent_and_color(node, ZIntrusiveRBTreeNode::RED); + + //// POST + // + // G G + // / \ + // n or n + // / \ + // p p + // \ / + // (C) (C) + // + //// + postcond(grand_parent->is_black()); + postcond(parent->is_red()); + postcond(node->is_red()); + postcond(ZIntrusiveRBTreeNode::is_black(child)); + // The grand_parent is updated in the next rotation + // postcond(verify_node(grand_parent, node)); + postcond(verify_node(node, parent)); + postcond(verify_node(parent, any_t{}, child)); + postcond(verify_node(child)); + + parent = node; + sibling = parent->template child(); + DEBUG_ONLY(node = parent->template child();) + } + + //// PRE + // + // G G + // / \ + // p or p + // / \ / \ + // n (s) (s) n + // + //// + precond(grand_parent->is_black()); + precond(parent->is_red()); + precond(node->is_red()); + precond(rotated_parent || verify_node(grand_parent, parent)); + precond(verify_node(parent, node, sibling)); + precond(verify_node(node)); + precond(verify_node(sibling)); + + // Rotate up parent through grand-parent + + // Fix children + grand_parent->template update_child(sibling); + parent->template update_child(grand_parent); + + // Fix parents and colors + if (sibling != nullptr) { + sibling->update_parent_and_color(grand_parent, ZIntrusiveRBTreeNode::BLACK); + } + rotate_and_update_child_or_root(grand_parent, parent, ZIntrusiveRBTreeNode::RED); + + //// POST + // + // P P + // / \ / \ + // n g or g n + // / \ + // (S) (S) + // + //// + postcond(parent->is_black()); + postcond(grand_parent->is_red()); + postcond(node->is_red()); + postcond(ZIntrusiveRBTreeNode::is_black(sibling)); + postcond(verify_node(parent, node, grand_parent)); + postcond(verify_node(node)); + postcond(verify_node(grand_parent, sibling)); + postcond(verify_node(sibling)); +} + +template +template +inline bool ZIntrusiveRBTree::rebalance_insert_with_parent_sibling(ZIntrusiveRBTreeNode** node_addr, ZIntrusiveRBTreeNode** parent_addr, ZIntrusiveRBTreeNode* grand_parent) { + DEBUG_ONLY(const bool swap_left_right = PARENT_SIBLING_DIRECTION == ZIntrusiveRBTreeDirection::LEFT;) + constexpr ZIntrusiveRBTreeDirection OTHER_DIRECTION = other(PARENT_SIBLING_DIRECTION); + ZIntrusiveRBTreeNode* const parent_sibling = grand_parent->template child(); + ZIntrusiveRBTreeNode*& node = *node_addr; + ZIntrusiveRBTreeNode*& parent = *parent_addr; + if (parent_sibling != nullptr && parent_sibling->is_red()) { + //// PRE + // + // G G + // / \ / \ + // p u or u p + // / \ / \ + // n | n n | n + // + //// + precond(grand_parent->is_black()); + precond(parent_sibling->is_red()); + precond(parent->is_red()); + precond(node->is_red()); + precond(verify_node(grand_parent, parent, parent_sibling)); + precond(parent->left_child() == node || parent->right_child() == node); + precond(verify_node(parent)); + precond(verify_node(parent_sibling)); + precond(verify_node(node)); + + // Flip colors of parent, parent sibling and grand parent + parent_sibling->update_parent_and_color(grand_parent, ZIntrusiveRBTreeNode::BLACK); + parent->update_parent_and_color(grand_parent, ZIntrusiveRBTreeNode::BLACK); + ZIntrusiveRBTreeNode* grand_grand_parent = grand_parent->black_parent(); + grand_parent->update_parent_and_color(grand_grand_parent, ZIntrusiveRBTreeNode::RED); + + //// POST + // + // g g + // / \ / \ + // P U or U P + // / \ / \ + // n | n n | n + // + //// + postcond(grand_parent->is_red()); + postcond(parent_sibling->is_black()); + postcond(parent->is_black()); + postcond(node->is_red()); + postcond(verify_node(grand_parent, parent, parent_sibling)); + postcond(parent->left_child() == node || parent->right_child() == node); + postcond(verify_node(parent)); + postcond(verify_node(parent_sibling)); + postcond(verify_node(node)); + + // Recurse up the tree + node = grand_parent; + parent = grand_grand_parent; + return false; // Not finished + } + + rebalance_insert_with_sibling(node, parent, grand_parent); + return true; // Finished +} + +template +inline void ZIntrusiveRBTree::rebalance_insert(ZIntrusiveRBTreeNode* new_node) { + ZIntrusiveRBTreeNode* node = new_node; + ZIntrusiveRBTreeNode* parent = node->red_parent(); + for (;;) { + precond(node->is_red()); + if (parent == nullptr) { + // Recursive (or root) case + node->update_parent_and_color(parent, ZIntrusiveRBTreeNode::BLACK); + break; + } + if (parent->is_black()) { + // Tree is balanced + break; + } + ZIntrusiveRBTreeNode* grand_parent = parent->red_parent(); + if (parent == grand_parent->left_child() ? rebalance_insert_with_parent_sibling(&node, &parent, grand_parent) + : rebalance_insert_with_parent_sibling(&node, &parent, grand_parent)) { + break; + } + } +} + +template +template +inline bool ZIntrusiveRBTree::rebalance_remove_with_sibling(ZIntrusiveRBTreeNode** node_addr, ZIntrusiveRBTreeNode** parent_addr) { + DEBUG_ONLY(const bool swap_left_right = SIBLING_DIRECTION == ZIntrusiveRBTreeDirection::LEFT;) + constexpr ZIntrusiveRBTreeDirection OTHER_DIRECTION = other(SIBLING_DIRECTION); + ZIntrusiveRBTreeNode*& node = *node_addr; + ZIntrusiveRBTreeNode*& parent = *parent_addr; + ZIntrusiveRBTreeNode* sibling = parent->template child(); + if (sibling->is_red()) { + ZIntrusiveRBTreeNode* sibling_child = sibling->template child(); + //// PRE + // + // P P + // / \ / \ + // N s or s N + // / \ + // SC SC + // + //// + precond(parent->is_black()); + precond(ZIntrusiveRBTreeNode::is_black(node)); + precond(sibling->is_red()); + precond(ZIntrusiveRBTreeNode::is_black(sibling_child)); + precond(verify_node(parent, node, sibling)); + precond(verify_node(node)); + precond(verify_node(sibling, sibling_child)); + precond(verify_node(sibling_child)); + + // Rotate sibling up through parent + + // Fix children + parent->template update_child(sibling_child); + sibling->template update_child(parent); + + // Fix parents and colors + sibling_child->update_parent_and_color(parent, ZIntrusiveRBTreeNode::BLACK); + rotate_and_update_child_or_root(parent, sibling, ZIntrusiveRBTreeNode::RED); + + //// POST + // + // S S + // / \ + // p p + // / \ / \ + // N SC SC N + // + //// + postcond(sibling->is_black()); + postcond(parent->is_red()); + postcond(ZIntrusiveRBTreeNode::is_black(node)); + postcond(ZIntrusiveRBTreeNode::is_black(sibling_child)); + postcond(verify_node(sibling, parent)); + postcond(verify_node(parent, node, sibling_child)); + postcond(verify_node(node)); + postcond(verify_node(sibling_child)); + + // node has a new sibling + sibling = sibling_child; + } + + ZIntrusiveRBTreeNode* sibling_child = sibling->template child(); + DEBUG_ONLY(bool rotated_parent = false;) + if (ZIntrusiveRBTreeNode::is_black(sibling_child)) { + DEBUG_ONLY(rotated_parent = true;) + ZIntrusiveRBTreeNode* sibling_other_child = sibling->template child(); + if (ZIntrusiveRBTreeNode::is_black(sibling_other_child)) { + //// PRE + // + // (p) (p) + // / \ / \ + // N S or S N + // + //// + precond(ZIntrusiveRBTreeNode::is_black(node)); + precond(sibling->is_black()); + precond(verify_node(parent, node, sibling)); + + // Flip sibling color to RED + sibling->update_parent_and_color(parent, ZIntrusiveRBTreeNode::RED); + + //// POST + // + // (p) (p) + // / \ / \ + // N s or s N + // + //// + postcond(ZIntrusiveRBTreeNode::is_black(node)); + postcond(sibling->is_red()); + postcond(verify_node(parent, node, sibling)); + + if (parent->is_black()) { + // We did not introduce a RED-RED edge, if parent is + // the root we are done, else recurse up the tree + if (parent->parent() != nullptr) { + node = parent; + parent = node->parent(); + return false; + } + return true; + } + // Change RED-RED edge to BLACK-RED edge + parent->update_color(ZIntrusiveRBTreeNode::BLACK); + return true; + } + + ZIntrusiveRBTreeNode* sibling_grand_child = sibling_other_child->template child(); + //// PRE + // + // (p) (p) + // / \ / \ + // N S S N + // / or \ + // soc soc + // \ / + // (sgc) (sgc) + // + //// + precond(ZIntrusiveRBTreeNode::is_black(node)); + precond(sibling->is_black()); + precond(sibling_other_child->is_red()); + precond(verify_node(parent, node, sibling)); + precond(verify_node(node)); + precond(verify_node(sibling, sibling_other_child, sibling_child)); + precond(verify_node(sibling_other_child, any_t{}, sibling_grand_child)); + precond(verify_node(sibling_grand_child)); + + // Rotate sibling other child through the sibling + + // Fix children + sibling->template update_child(sibling_grand_child); + sibling_other_child->template update_child(sibling); + parent->template update_child(sibling_other_child); + + // Fix parents and colors + if (sibling_grand_child != nullptr) { + sibling_grand_child->update_parent_and_color(sibling, ZIntrusiveRBTreeNode::BLACK); + } + // Defer updating the sibling and sibling other child parents until + // after we rotate below. This will also fix the any potential RED-RED + // edge between parent and sibling_other_child + + //// POST + // + // (p) (p) + // / \ / \ + // N soc or soc N + // / \ / \ + // SGC S S SGC + // + //// + postcond(ZIntrusiveRBTreeNode::is_black(node)); + postcond(sibling->is_black()); + postcond(sibling_other_child->is_red()); + postcond(ZIntrusiveRBTreeNode::is_black(sibling_grand_child)); + // Deferred + // postcond(verify_node(parent, node, sibling_other_child)); + postcond(verify_node(node)); + // postcond(verify_node(sibling_other_child, sibling_grand_child, sibling)); + postcond(verify_node(sibling_grand_child)); + postcond(verify_node(sibling)); + + // node has a new sibling + sibling_child = sibling; + sibling = sibling_other_child; + } + + ZIntrusiveRBTreeNode* sibling_other_child = sibling->template child(); + //// PRE + // + // (p) (p) + // / \ / \ + // N S or S N + // / \ / \ + // (soc)(sc) (sc)(soc) + // + //// + DEBUG_ONLY(ZIntrusiveRBTreeNode::Color parent_color = parent->color();) + precond(ZIntrusiveRBTreeNode::is_black(node)); + precond(rotated_parent || sibling->is_black()); + DEBUG_ONLY(bool sibling_other_child_is_black = ZIntrusiveRBTreeNode::is_black(sibling_other_child);) + precond(rotated_parent || verify_node(parent, node, sibling)); + precond(verify_node(node)); + precond(rotated_parent || verify_node(sibling, sibling_other_child, sibling_child)); + postcond(verify_node(sibling_other_child)); + postcond(verify_node(sibling_child)); + + // Rotate sibling through parent and fix colors + + // Fix children + parent->template update_child(sibling_other_child); + sibling->template update_child(parent); + + // Fix parents and colors + sibling_child->update_parent_and_color(sibling, ZIntrusiveRBTreeNode::BLACK); + if (sibling_other_child != nullptr) { + sibling_other_child->update_parent(parent); + } + rotate_and_update_child_or_root(parent, sibling, ZIntrusiveRBTreeNode::BLACK); + + //// POST + // + // (s) (s) + // / \ / \ + // P SC or SC P + // / \ / \ + // N (soc) (soc) N + // + //// + postcond(sibling->color() == parent_color); + postcond(parent->is_black()); + postcond(sibling_child->is_black()); + postcond(ZIntrusiveRBTreeNode::is_black(node)); + postcond(sibling_other_child_is_black == ZIntrusiveRBTreeNode::is_black(sibling_other_child)); + postcond(verify_node(sibling, parent, sibling_child)); + postcond(verify_node(parent, node, sibling_other_child)); + postcond(verify_node(sibling_child)); + postcond(verify_node(node)); + postcond(verify_node(sibling_other_child)); + return true; +} + +template +inline void ZIntrusiveRBTree::rebalance_remove(ZIntrusiveRBTreeNode* rebalance_from) { + ZIntrusiveRBTreeNode* node = nullptr; + ZIntrusiveRBTreeNode* parent = rebalance_from; + + for (;;) { + precond(ZIntrusiveRBTreeNode::is_black(node)); + precond(parent != nullptr); + if (node == parent->left_child() ? rebalance_remove_with_sibling(&node, &parent) + : rebalance_remove_with_sibling(&node, &parent)) { + break; + } + } +} + +template +inline ZIntrusiveRBTree::FindCursor::FindCursor(ZIntrusiveRBTreeNode** insert_location, ZIntrusiveRBTreeNode* parent, bool left_most, bool right_most DEBUG_ONLY(COMMA uintptr_t sequence_number)) + : _insert_location(insert_location), + _parent(parent), + _left_most(left_most), + _right_most(right_most) + DEBUG_ONLY(COMMA _sequence_number(sequence_number)) {} + +template +inline ZIntrusiveRBTree::FindCursor::FindCursor() + : _insert_location(nullptr), + _parent(nullptr), + _left_most(), + _right_most() + DEBUG_ONLY(COMMA _sequence_number()) {} + +#ifdef ASSERT +template +inline bool ZIntrusiveRBTree::FindCursor::is_valid(uintptr_t sequence_number) const { + return is_valid() && _sequence_number == sequence_number; +} +#endif // ASSERT + +template +inline bool ZIntrusiveRBTree::FindCursor::is_valid() const { + return insert_location() != nullptr; +} + +template +inline bool ZIntrusiveRBTree::FindCursor::found() const { + return node() != nullptr; +} + +template +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTree::FindCursor::node() const { + precond(is_valid()); + return *_insert_location == nullptr ? nullptr : *_insert_location; +} + +template +inline bool ZIntrusiveRBTree::FindCursor::is_left_most() const { + precond(is_valid()); + return _left_most; +} + +template +inline bool ZIntrusiveRBTree::FindCursor::is_right_most() const { + precond(is_valid()); + return _right_most; +} + +template +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTree::FindCursor::parent() const { + precond(is_valid()); + return _parent; +} + +template +inline ZIntrusiveRBTreeNode** ZIntrusiveRBTree::FindCursor::insert_location() const { + return _insert_location; +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::make_cursor(ZIntrusiveRBTreeNode* const* insert_location, ZIntrusiveRBTreeNode* parent, bool left_most, bool right_most) const { + return FindCursor(const_cast(insert_location), parent, left_most, right_most DEBUG_ONLY(COMMA _sequence_number)); +} + +template +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::find_next(const FindCursor& cursor) const { + constexpr ZIntrusiveRBTreeDirection OTHER_DIRECTION = other(DIRECTION); + if (cursor.found()) { + ZIntrusiveRBTreeNode* const node = cursor.node(); + const ZIntrusiveRBTreeNode* const next_node = node->template find_next_node(); + if (next_node != nullptr) { + return get_cursor(next_node); + } + const bool is_right_most = DIRECTION == ZIntrusiveRBTreeDirection::RIGHT && node == _right_most; + const bool is_left_most = DIRECTION == ZIntrusiveRBTreeDirection::LEFT && node == _left_most; + return make_cursor(node->template child_addr(), node, is_left_most, is_right_most); + } + ZIntrusiveRBTreeNode* const parent = cursor.parent(); + if (parent == nullptr) { + assert(&_root_node == cursor.insert_location(), "must be"); + // tree is empty + return FindCursor(); + } + if (parent->template child_addr() == cursor.insert_location()) { + // Cursor at leaf in other direction, parent is next in direction + return get_cursor(parent); + } + assert(parent->template child_addr() == cursor.insert_location(), "must be"); + // Cursor at leaf in direction, parent->next in direction is also cursors next in direction + return get_cursor(parent->template find_next_node()); +} + +template +inline ZIntrusiveRBTree::ZIntrusiveRBTree() + : _root_node(nullptr), + _left_most(nullptr), + _right_most(nullptr) + DEBUG_ONLY(COMMA _sequence_number()) {} + +template +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTree::first() const { + return _left_most; +} + +template +inline ZIntrusiveRBTreeNode* ZIntrusiveRBTree::last() const { + return _right_most; +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::root_cursor() const { + const bool is_left_most = _root_node == _left_most; + const bool is_right_most = _root_node == _right_most; + return make_cursor(&_root_node, nullptr, is_left_most, is_right_most); +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::get_cursor(const ZIntrusiveRBTreeNode* node) const { + if (node == nullptr) { + // Return a invalid cursor + return FindCursor(); + } + const bool is_left_most = node == _left_most; + const bool is_right_most = node == _right_most; + if (node->has_parent()) { + const ZIntrusiveRBTreeNode* const parent = node->parent(); + if (parent->left_child() == node) { + return make_cursor(parent->left_child_addr(), nullptr, is_left_most, is_right_most); + } + assert(parent->right_child() == node, "must be"); + return make_cursor(parent->right_child_addr(), nullptr, is_left_most, is_right_most); + } + // No parent, root node + return make_cursor(&_root_node, nullptr, is_left_most, is_right_most); +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::prev_cursor(const ZIntrusiveRBTreeNode* node) const { + return prev(get_cursor(node)); +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::next_cursor(const ZIntrusiveRBTreeNode* node) const { + return next(get_cursor(node)); +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::prev(const FindCursor& cursor) const { + return find_next(cursor); +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::next(const FindCursor& cursor) const { + return find_next(cursor); +} + +template +inline typename ZIntrusiveRBTree::FindCursor ZIntrusiveRBTree::find(const Key& key) const { + Compare compare_fn; + ZIntrusiveRBTreeNode* const* insert_location = root_node_addr(); + ZIntrusiveRBTreeNode* parent = nullptr; + bool left_most = true; + bool right_most = true; + while (*insert_location != nullptr) { + int result = compare_fn(key, *insert_location); + if (result == 0) { + assert(*insert_location != _left_most || left_most, "must be"); + assert(*insert_location != _right_most || right_most, "must be"); + return make_cursor(insert_location, parent, *insert_location == _left_most, *insert_location == _right_most); + } + parent = *insert_location; + if (result < 0) { + insert_location = parent->left_child_addr(); + // We took one step to the left, cannot be right_most. + right_most = false; + } else { + insert_location = parent->right_child_addr(); + // We took one step to the right, cannot be left_most. + left_most = false; + } + } + return make_cursor(insert_location, parent, left_most, right_most); +} + +template +inline void ZIntrusiveRBTree::insert(ZIntrusiveRBTreeNode* new_node, const FindCursor& find_cursor) { + precond(find_cursor.is_valid(_sequence_number)); + precond(!find_cursor.found()); + DEBUG_ONLY(_sequence_number++;) + + // Link in the new node + new_node->link_node(find_cursor.parent(), find_cursor.insert_location()); + + // Keep track of first and last node(s) + if (find_cursor.is_left_most()) { + _left_most = new_node; + } + if (find_cursor.is_right_most()) { + _right_most = new_node; + } + + rebalance_insert(new_node); +} + +template +inline void ZIntrusiveRBTree::replace(ZIntrusiveRBTreeNode* new_node, const FindCursor& find_cursor) { + precond(find_cursor.is_valid(_sequence_number)); + precond(find_cursor.found()); + DEBUG_ONLY(_sequence_number++;) + + const ZIntrusiveRBTreeNode* const node = find_cursor.node(); + + if (new_node != node) { + // Node has changed + + // Copy the node to new location + *new_node = *node; + + // Update insert location + *find_cursor.insert_location() = new_node; + + // Update children's parent + if (new_node->has_left_child()) { + new_node->left_child()->update_parent(new_node); + } + if (new_node->has_right_child()) { + new_node->right_child()->update_parent(new_node); + } + + // Keep track of first and last node(s) + if (find_cursor.is_left_most()) { + assert(_left_most == node, "must be"); + _left_most = new_node; + } + if (find_cursor.is_right_most()) { + assert(_right_most == node, "must be"); + _right_most = new_node; + } + } +} + +template +inline void ZIntrusiveRBTree::remove(const FindCursor& find_cursor) { + precond(find_cursor.is_valid(_sequence_number)); + precond(find_cursor.found()); + DEBUG_ONLY(_sequence_number++;) + + ZIntrusiveRBTreeNode* const node = find_cursor.node(); + ZIntrusiveRBTreeNode* const parent = node->parent(); + + // Keep track of first and last node(s) + if (find_cursor.is_left_most()) { + assert(_left_most == node, "must be"); + _left_most = _left_most->next(); + } + if (find_cursor.is_right_most()) { + assert(_right_most == node, "must be"); + _right_most = _right_most->prev(); + } + + ZIntrusiveRBTreeNode* rebalance_from = nullptr; + + if (!node->has_left_child() && !node->has_right_child()) { + // No children + + // Remove node + update_child_or_root(node, nullptr, parent); + if (node->is_black()) { + // We unbalanced the tree + rebalance_from = parent; + } + } else if (!node->has_left_child() || !node->has_right_child()) { + assert(node->has_right_child() || node->has_left_child(), "must be"); + // Only one child + ZIntrusiveRBTreeNode* child = node->has_left_child() ? node->left_child() : node->right_child(); + + // Let child take nodes places + update_child_or_root(node, child, parent); + + // And update parent and color + child->copy_parent_and_color(node); + } else { + assert(node->has_left_child() && node->has_right_child(), "must be"); + // Find next node and let it take the nodes place + // This asymmetry always swap next instead of prev, + // I wonder how this behaves w.r.t. our mapped cache + // strategy of mostly removing from the left side of + // the tree + + // This will never walk up the tree, hope the compiler sees this. + ZIntrusiveRBTreeNode* next_node = node->next(); + + ZIntrusiveRBTreeNode* next_node_parent = next_node->parent(); + ZIntrusiveRBTreeNode* next_node_child = next_node->right_child(); + if (next_node_parent != node) { + // Not the direct descendant, adopt node's child + ZIntrusiveRBTreeNode* node_child = node->right_child(); + next_node->update_right_child(node_child); + node_child->update_parent(next_node); + + // And let parent adopt their grand child + next_node_parent->update_left_child(next_node_child); + } else { + next_node_parent = next_node; + } + // Adopt node's other child + ZIntrusiveRBTreeNode* node_child = node->left_child(); + next_node->update_left_child(node_child); + node_child->update_parent(next_node); + + update_child_or_root(node, next_node, parent); + + // Update parent(s) and colors + if (next_node_child != nullptr) { + next_node_child->update_parent_and_color(next_node_parent, ZIntrusiveRBTreeNode::BLACK); + } else if (next_node->is_black()) { + rebalance_from = next_node_parent; + } + next_node->copy_parent_and_color(node); + } + + if (rebalance_from == nullptr) { + // Removal did not unbalance the tree + return; + } + + rebalance_remove(rebalance_from); +} + +template +inline void ZIntrusiveRBTree::verify_tree() { + // Properties: + // (a) Node's are either BLACK or RED + // (b) All nullptr children are counted as BLACK + // (c) Compare::operator(Node*, Node*) <=> 0 is transitive + // Invariants: + // (1) Root node is BLACK + // (2) All RED nodes only have BLACK children + // (3) Every simple path from the root to a leaf + // contains the same amount of BLACK nodes + // (4) A node's children must have that node as + // its parent + // (5) Each node N in the sub-tree formed from a + // node A's child must: + // if left child: Compare::operator(A, N) < 0 + // if right child: Compare::operator(A, N) > 0 + // + // Note: 1-4 may not hold during a call to insert + // and remove. + + // Helpers + const auto is_leaf = [](ZIntrusiveRBTreeNode* node) { + return node == nullptr; + }; + const auto is_black = [&](ZIntrusiveRBTreeNode* node) { + return is_leaf(node) || node->is_black(); + }; + const auto is_red = [&](ZIntrusiveRBTreeNode* node) { + return !is_black(node); + }; + + // Verify (1) + ZIntrusiveRBTreeNode* const root_node = _root_node; + guarantee(is_black(root_node), "Invariant (1)"); + + // Verify (2) + const auto verify_2 = [&](ZIntrusiveRBTreeNode* node) { + guarantee(!is_red(node) || is_black(node->left_child()), "Invariant (2)"); + guarantee(!is_red(node) || is_black(node->right_child()), "Invariant (2)"); + }; + + // Verify (3) + size_t first_simple_path_black_nodes_traversed = 0; + const auto verify_3 = [&](ZIntrusiveRBTreeNode* node, size_t black_nodes_traversed) { + if (!is_leaf(node)) { return; } + if (first_simple_path_black_nodes_traversed == 0) { + first_simple_path_black_nodes_traversed = black_nodes_traversed; + } + guarantee(first_simple_path_black_nodes_traversed == black_nodes_traversed, "Invariant (3)"); + }; + + // Verify (4) + const auto verify_4 = [&](ZIntrusiveRBTreeNode* node) { + if (is_leaf(node)) { return; } + guarantee(!node->has_left_child() || node->left_child()->parent() == node, "Invariant (4)"); + guarantee(!node->has_right_child() || node->right_child()->parent() == node, "Invariant (4)"); + }; + guarantee(root_node == nullptr || root_node->parent() == nullptr, "Invariant (4)"); + + // Verify (5) + const auto verify_5 = [&](ZIntrusiveRBTreeNode* node) { + // Because of the transitive property of Compare (c) we simply check + // this that (5) hold for each parent child pair. + if (is_leaf(node)) { return; } + Compare compare_fn; + guarantee(!node->has_left_child() || compare_fn(node->left_child(), node) < 0, "Invariant (5)"); + guarantee(!node->has_right_child() || compare_fn(node->right_child(), node) > 0, "Invariant (5)"); + }; + + // Walk every simple path by recursively descending the tree from the root + const auto recursive_walk = [&](auto&& recurse, ZIntrusiveRBTreeNode* node, size_t black_nodes_traversed) { + if (is_black(node)) { black_nodes_traversed++; } + verify_2(node); + verify_3(node, black_nodes_traversed); + verify_4(node); + verify_5(node); + if (is_leaf(node)) { return; } + recurse(recurse, node->left_child(), black_nodes_traversed); + recurse(recurse, node->right_child(), black_nodes_traversed); + }; + recursive_walk(recursive_walk, root_node, 0); +} + +template +inline typename ZIntrusiveRBTree::Iterator ZIntrusiveRBTree::begin() { + return Iterator(*this, first()); +} + +template +inline typename ZIntrusiveRBTree::Iterator ZIntrusiveRBTree::end() { + return Iterator(*this, nullptr); +} + +template +inline typename ZIntrusiveRBTree::ConstIterator ZIntrusiveRBTree::begin() const { + return cbegin(); +} + +template +inline typename ZIntrusiveRBTree::ConstIterator ZIntrusiveRBTree::end() const { + return cend(); +} + +template +inline typename ZIntrusiveRBTree::ConstIterator ZIntrusiveRBTree::cbegin() const { + return const_cast*>(this)->begin(); +} + +template +inline typename ZIntrusiveRBTree::ConstIterator ZIntrusiveRBTree::cend() const { + return const_cast*>(this)->end(); +} + +template +inline typename ZIntrusiveRBTree::ReverseIterator ZIntrusiveRBTree::rbegin() { + return ReverseIterator(*this, last()); +} + +template +inline typename ZIntrusiveRBTree::ReverseIterator ZIntrusiveRBTree::rend() { + return ReverseIterator(*this, nullptr); +} + +template +inline typename ZIntrusiveRBTree::ConstReverseIterator ZIntrusiveRBTree::rbegin() const { + return crbegin(); +} + +template +inline typename ZIntrusiveRBTree::ConstReverseIterator ZIntrusiveRBTree::rend() const { + return crend(); +} + +template +inline typename ZIntrusiveRBTree::ConstReverseIterator ZIntrusiveRBTree::crbegin() const { + return const_cast*>(this)->rbegin(); +} + +template +inline typename ZIntrusiveRBTree::ConstReverseIterator ZIntrusiveRBTree::crend() const { + return const_cast*>(this)->rend(); +} + +template +template +inline bool ZIntrusiveRBTree::IteratorImplementation::at_end() const { + return _node == nullptr; +} + +template +template +inline ZIntrusiveRBTree::IteratorImplementation::IteratorImplementation(ZIntrusiveRBTree& tree, pointer node) +: _tree(&tree), + _node(node), + _removed(false) {} + +template +template +template +inline ZIntrusiveRBTree::IteratorImplementation::IteratorImplementation(const IteratorImplementation& other) +: _tree(other._tree), + _node(other._node), + _removed(false) {} + +template +template +inline typename ZIntrusiveRBTree::template IteratorImplementation::reference ZIntrusiveRBTree::IteratorImplementation::operator*() const { + precond(!_removed); + return *_node; +} + +template +template +inline typename ZIntrusiveRBTree::template IteratorImplementation::pointer ZIntrusiveRBTree::IteratorImplementation::operator->() { + precond(!_removed); + return _node; +} + +template +template +inline typename ZIntrusiveRBTree::template IteratorImplementation& ZIntrusiveRBTree::IteratorImplementation::operator--() { + if (_removed) { + _removed = false; + } else if (Reverse) { + precond(_node != _tree->last()); + _node = at_end() ? _tree->first() : _node->next(); + } else { + precond(_node != _tree->first()); + _node = at_end() ? _tree->last() : _node->prev(); + } + return *this; +} + +template +template +inline typename ZIntrusiveRBTree::template IteratorImplementation ZIntrusiveRBTree::IteratorImplementation::operator--(int) { + IteratorImplementation tmp = *this; + --(*this); + return tmp; +} + +template +template +inline typename ZIntrusiveRBTree::template IteratorImplementation& ZIntrusiveRBTree::IteratorImplementation::operator++() { + if (_removed) { + _removed = false; + } else if (Reverse) { + precond(!at_end()); + _node = _node->prev(); + } else { + precond(!at_end()); + _node = _node->next(); + } + return *this; +} + +template +template +inline typename ZIntrusiveRBTree::template IteratorImplementation ZIntrusiveRBTree::IteratorImplementation::operator++(int) { + IteratorImplementation tmp = *this; + ++(*this); + return tmp; +} + +template +template +template +void ZIntrusiveRBTree::IteratorImplementation::replace(ZIntrusiveRBTreeNode* new_node) { + precond(!_removed); + precond(!at_end()); + FindCursor cursor = _tree->get_cursor(_node); + _node = new_node; + _tree->replace(new_node, cursor); +} + +template +template +template +void ZIntrusiveRBTree::IteratorImplementation::remove() { + precond(!_removed); + precond(!at_end()); + FindCursor cursor = _tree->get_cursor(_node); + ++(*this); + _removed = true; + _tree->remove(cursor); +} + +#endif // SHARE_GC_Z_ZINTRUSIVERBTREE_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zList.hpp b/src/hotspot/share/gc/z/zList.hpp index 0da2f823864..36cefbbeef7 100644 --- a/src/hotspot/share/gc/z/zList.hpp +++ b/src/hotspot/share/gc/z/zList.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #define SHARE_GC_Z_ZLIST_HPP #include "memory/allocation.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" template class ZList; @@ -46,7 +47,12 @@ private: public: ZListNode(); - ~ZListNode(); + ~ZListNode() { + // Implementation placed here to make it easier easier to embed ZListNode + // instances without having to include zListNode.inline.hpp. + assert(_next == this, "Should not be in a list"); + assert(_prev == this, "Should not be in a list"); + } }; // Doubly linked list @@ -59,6 +65,7 @@ private: NONCOPYABLE(ZList); void verify_head() const; + void verify_head_error_reporter_safe() const; void insert(ZListNode* before, ZListNode* node); @@ -68,6 +75,9 @@ private: public: ZList(); + size_t size_error_reporter_safe() const; + bool is_empty_error_reporter_safe() const; + size_t size() const; bool is_empty() const; diff --git a/src/hotspot/share/gc/z/zList.inline.hpp b/src/hotspot/share/gc/z/zList.inline.hpp index 9c4f2b8fbf2..20edfaa620b 100644 --- a/src/hotspot/share/gc/z/zList.inline.hpp +++ b/src/hotspot/share/gc/z/zList.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,17 +27,13 @@ #include "gc/z/zList.hpp" #include "utilities/debug.hpp" +#include "utilities/vmError.hpp" template inline ZListNode::ZListNode() : _next(this), _prev(this) {} -template -inline ZListNode::~ZListNode() { - verify_links_unlinked(); -} - template inline void ZListNode::verify_links() const { assert(_next->_prev == this, "Corrupt list node"); @@ -62,6 +58,16 @@ inline void ZList::verify_head() const { _head.verify_links(); } +template +inline void ZList::verify_head_error_reporter_safe() const { + if (VMError::is_error_reported() && VMError::is_error_reported_in_current_thread()) { + // Do not verify if this thread is in the process of reporting an error. + return; + } + + verify_head(); +} + template inline void ZList::insert(ZListNode* before, ZListNode* node) { verify_head(); @@ -97,6 +103,17 @@ inline ZList::ZList() verify_head(); } +template +inline size_t ZList::size_error_reporter_safe() const { + verify_head_error_reporter_safe(); + return _size; +} + +template +inline bool ZList::is_empty_error_reporter_safe() const { + return size_error_reporter_safe() == 0; +} + template inline size_t ZList::size() const { verify_head(); diff --git a/src/hotspot/share/gc/z/zLiveMap.cpp b/src/hotspot/share/gc/z/zLiveMap.cpp index ef125af9c2e..5b9e0a932c3 100644 --- a/src/hotspot/share/gc/z/zLiveMap.cpp +++ b/src/hotspot/share/gc/z/zLiveMap.cpp @@ -34,24 +34,19 @@ static const ZStatCounter ZCounterMarkSeqNumResetContention("Contention", "Mark SeqNum Reset Contention", ZStatUnitOpsPerSecond); static const ZStatCounter ZCounterMarkSegmentResetContention("Contention", "Mark Segment Reset Contention", ZStatUnitOpsPerSecond); -static size_t bitmap_size(uint32_t size, size_t NumSegments) { - // We need at least one bit per segment - return MAX2(size, NumSegments) * 2; -} - -ZLiveMap::ZLiveMap(uint32_t size) - : _seqnum(0), +ZLiveMap::ZLiveMap(uint32_t object_max_count) + : _segment_size((object_max_count == 1 ? 1u : (object_max_count / NumSegments)) * BitsPerObject), + _segment_shift(log2i_exact(_segment_size)), + _seqnum(0), _live_objects(0), _live_bytes(0), _segment_live_bits(0), _segment_claim_bits(0), - _bitmap_size(bitmap_size(size, NumSegments)), - _bitmap(0), - _segment_shift(log2i_exact(segment_size())) {} + _bitmap(0) {} -void ZLiveMap::allocate_bitmap() { - if (_bitmap.size() != _bitmap_size) { - _bitmap.initialize(_bitmap_size, false /* clear */); +void ZLiveMap::initialize_bitmap() { + if (_bitmap.size() == 0) { + _bitmap.initialize(size_t(_segment_size) * size_t(NumSegments), false /* clear */); } } @@ -71,14 +66,14 @@ void ZLiveMap::reset(ZGenerationId id) { _live_bytes = 0; _live_objects = 0; - // We lazily initialize the bitmap the first time the page is - // marked, i.e. a bit is about to be set for the first time. - allocate_bitmap(); - // Clear segment claimed/live bits segment_live_bits().clear(); segment_claim_bits().clear(); + // We lazily initialize the bitmap the first time the page is marked, i.e. + // a bit is about to be set for the first time. + initialize_bitmap(); + assert(_seqnum == seqnum_initializing, "Invalid"); // Make sure the newly reset marking information is ordered @@ -125,7 +120,7 @@ void ZLiveMap::reset_segment(BitMap::idx_t segment) { // Segment claimed, clear it const BitMap::idx_t start_index = segment_start(segment); const BitMap::idx_t end_index = segment_end(segment); - if (segment_size() / BitsPerWord >= 32) { + if (_segment_size / BitsPerWord >= 32) { _bitmap.clear_large_range(start_index, end_index); } else { _bitmap.clear_range(start_index, end_index); @@ -135,13 +130,3 @@ void ZLiveMap::reset_segment(BitMap::idx_t segment) { const bool success = set_segment_live(segment); assert(success, "Should never fail"); } - -void ZLiveMap::resize(uint32_t size) { - const size_t new_bitmap_size = bitmap_size(size, NumSegments); - _bitmap_size = new_bitmap_size; - _segment_shift = log2i_exact(segment_size()); - - if (_bitmap.size() != 0 && _bitmap.size() != new_bitmap_size) { - _bitmap.reinitialize(new_bitmap_size, false /* clear */); - } -} diff --git a/src/hotspot/share/gc/z/zLiveMap.hpp b/src/hotspot/share/gc/z/zLiveMap.hpp index 9f6514b574f..71457d05a41 100644 --- a/src/hotspot/share/gc/z/zLiveMap.hpp +++ b/src/hotspot/share/gc/z/zLiveMap.hpp @@ -35,16 +35,18 @@ class ZLiveMap { friend class ZLiveMapTest; private: - static const size_t NumSegments = 64; + static const uint32_t NumSegments = 64; + static const uint32_t BitsPerObject = 2; + + const uint32_t _segment_size; + const int _segment_shift; volatile uint32_t _seqnum; volatile uint32_t _live_objects; volatile size_t _live_bytes; BitMap::bm_word_t _segment_live_bits; BitMap::bm_word_t _segment_claim_bits; - size_t _bitmap_size; ZBitMap _bitmap; - int _segment_shift; const BitMapView segment_live_bits() const; const BitMapView segment_claim_bits() const; @@ -52,8 +54,6 @@ private: BitMapView segment_live_bits(); BitMapView segment_claim_bits(); - BitMap::idx_t segment_size() const; - BitMap::idx_t segment_start(BitMap::idx_t segment) const; BitMap::idx_t segment_end(BitMap::idx_t segment) const; @@ -66,7 +66,7 @@ private: bool claim_segment(BitMap::idx_t segment); - void allocate_bitmap(); + void initialize_bitmap(); void reset(ZGenerationId id); void reset_segment(BitMap::idx_t segment); @@ -77,11 +77,10 @@ private: void iterate_segment(BitMap::idx_t segment, Function function); public: - ZLiveMap(uint32_t size); + ZLiveMap(uint32_t object_max_count); ZLiveMap(const ZLiveMap& other) = delete; void reset(); - void resize(uint32_t size); bool is_marked(ZGenerationId id) const; diff --git a/src/hotspot/share/gc/z/zLiveMap.inline.hpp b/src/hotspot/share/gc/z/zLiveMap.inline.hpp index fdbbdfaba0e..a7f836a8559 100644 --- a/src/hotspot/share/gc/z/zLiveMap.inline.hpp +++ b/src/hotspot/share/gc/z/zLiveMap.inline.hpp @@ -87,10 +87,6 @@ inline BitMap::idx_t ZLiveMap::next_live_segment(BitMap::idx_t segment) const { return segment_live_bits().find_first_set_bit(segment + 1, NumSegments); } -inline BitMap::idx_t ZLiveMap::segment_size() const { - return _bitmap_size / NumSegments; -} - inline BitMap::idx_t ZLiveMap::index_to_segment(BitMap::idx_t index) const { return index >> _segment_shift; } @@ -125,11 +121,11 @@ inline void ZLiveMap::inc_live(uint32_t objects, size_t bytes) { } inline BitMap::idx_t ZLiveMap::segment_start(BitMap::idx_t segment) const { - return segment_size() * segment; + return segment * _segment_size; } inline BitMap::idx_t ZLiveMap::segment_end(BitMap::idx_t segment) const { - return segment_start(segment) + segment_size(); + return segment_start(segment) + _segment_size; } inline size_t ZLiveMap::do_object(ObjectClosure* cl, zaddress addr) const { diff --git a/src/hotspot/share/gc/z/zMappedCache.cpp b/src/hotspot/share/gc/z/zMappedCache.cpp new file mode 100644 index 00000000000..c1c6e9edee9 --- /dev/null +++ b/src/hotspot/share/gc/z/zMappedCache.cpp @@ -0,0 +1,629 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zIntrusiveRBTree.inline.hpp" +#include "gc/z/zList.inline.hpp" +#include "gc/z/zMappedCache.hpp" +#include "gc/z/zVirtualMemory.inline.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" + +class ZMappedCacheEntry { +private: + ZVirtualMemory _vmem; + ZMappedCache::TreeNode _tree_node; + ZMappedCache::SizeClassListNode _size_class_list_node; + +public: + ZMappedCacheEntry(ZVirtualMemory vmem) + : _vmem(vmem), + _tree_node(), + _size_class_list_node() {} + + static ZMappedCacheEntry* cast_to_entry(ZMappedCache::TreeNode* tree_node); + static const ZMappedCacheEntry* cast_to_entry(const ZMappedCache::TreeNode* tree_node); + static ZMappedCacheEntry* cast_to_entry(ZMappedCache::SizeClassListNode* list_node); + + zoffset start() const { + return _vmem.start(); + } + + zoffset_end end() const { + return _vmem.end(); + } + + ZVirtualMemory vmem() const { + return _vmem; + } + + ZMappedCache::TreeNode* node_addr() { + return &_tree_node; + } + + void update_start(ZVirtualMemory vmem) { + precond(vmem.end() == end()); + + _vmem = vmem; + } + + ZMappedCache::ZSizeClassListNode* size_class_node() { + return &_size_class_list_node; + } +}; + +ZMappedCacheEntry* ZMappedCacheEntry::cast_to_entry(ZMappedCache::TreeNode* tree_node) { + return const_cast(ZMappedCacheEntry::cast_to_entry(const_cast(tree_node))); +} + +const ZMappedCacheEntry* ZMappedCacheEntry::cast_to_entry(const ZMappedCache::TreeNode* tree_node) { + return (const ZMappedCacheEntry*)((uintptr_t)tree_node - offset_of(ZMappedCacheEntry, _tree_node)); +} + +ZMappedCacheEntry* ZMappedCacheEntry::cast_to_entry(ZMappedCache::SizeClassListNode* list_node) { + const size_t offset = offset_of(ZMappedCacheEntry, _size_class_list_node); + return (ZMappedCacheEntry*)((uintptr_t)list_node - offset); +} + +static void* entry_address_for_zoffset_end(zoffset_end offset) { + STATIC_ASSERT(is_aligned(ZCacheLineSize, alignof(ZMappedCacheEntry)));; + + // This spreads out the location of the entries in an effort to combat hyper alignment. + // Verify if this is an efficient and worthwhile optimization. + + constexpr size_t aligned_entry_size = align_up(sizeof(ZMappedCacheEntry), ZCacheLineSize); + + // Do not use the last location + constexpr size_t number_of_locations = ZGranuleSize / aligned_entry_size - 1; + const size_t granule_index = untype(offset) >> ZGranuleSizeShift; + const size_t index = granule_index % number_of_locations; + const uintptr_t end_addr = untype(offset) + ZAddressHeapBase; + + return reinterpret_cast(end_addr - aligned_entry_size * (index + 1)); +} + +static ZMappedCacheEntry* create_entry(const ZVirtualMemory& vmem) { + precond(vmem.size() >= ZGranuleSize); + + void* placement_addr = entry_address_for_zoffset_end(vmem.end()); + ZMappedCacheEntry* entry = new (placement_addr) ZMappedCacheEntry(vmem); + + postcond(entry->start() == vmem.start()); + postcond(entry->end() == vmem.end()); + + return entry; +} + +int ZMappedCache::EntryCompare::operator()(ZMappedCache::TreeNode* a, ZMappedCache::TreeNode* b) { + const ZVirtualMemory vmem_a = ZMappedCacheEntry::cast_to_entry(a)->vmem(); + const ZVirtualMemory vmem_b = ZMappedCacheEntry::cast_to_entry(b)->vmem(); + + if (vmem_a.end() < vmem_b.start()) { return -1; } + if (vmem_b.end() < vmem_a.start()) { return 1; } + + return 0; // Overlapping +} + +int ZMappedCache::EntryCompare::operator()(zoffset key, ZMappedCache::TreeNode* node) { + const ZVirtualMemory vmem = ZMappedCacheEntry::cast_to_entry(node)->vmem(); + + if (key < vmem.start()) { return -1; } + if (key > vmem.end()) { return 1; } + + return 0; // Containing +} + +int ZMappedCache::size_class_index(size_t size) { + // Returns the size class index of for size, or -1 if smaller than the smallest size class. + const int size_class_power = log2i_graceful(size) - (int)ZGranuleSizeShift; + + if (size_class_power < MinSizeClassShift) { + // Allocation is smaller than the smallest size class minimum size. + return -1; + } + + return MIN2(size_class_power, MaxSizeClassShift) - MinSizeClassShift; +} + +int ZMappedCache::guaranteed_size_class_index(size_t size) { + // Returns the size class index of the smallest size class which can always + // accommodate a size allocation, or -1 otherwise. + const int size_class_power = log2i_ceil(size) - (int)ZGranuleSizeShift; + + if (size_class_power > MaxSizeClassShift) { + // Allocation is larger than the largest size class minimum size. + return -1; + } + + return MAX2(size_class_power, MinSizeClassShift) - MinSizeClassShift; +} + +void ZMappedCache::tree_insert(const Tree::FindCursor& cursor, const ZVirtualMemory& vmem) { + ZMappedCacheEntry* const entry = create_entry(vmem); + + // Insert creates a new entry + _entry_count += 1; + + // Insert in tree + _tree.insert(entry->node_addr(), cursor); + + // Insert in size-class lists + const size_t size = vmem.size(); + const int index = size_class_index(size); + if (index != -1) { + _size_class_lists[index].insert_first(entry->size_class_node()); + } +} + +void ZMappedCache::tree_remove(const Tree::FindCursor& cursor, const ZVirtualMemory& vmem) { + ZMappedCacheEntry* entry = ZMappedCacheEntry::cast_to_entry(cursor.node()); + + // Remove destroys an old entry + _entry_count -= 1; + + // Remove from tree + _tree.remove(cursor); + + // Insert in size-class lists + const size_t size = vmem.size(); + const int index = size_class_index(size); + if (index != -1) { + _size_class_lists[index].remove(entry->size_class_node()); + } + + // Destroy entry + entry->~ZMappedCacheEntry(); +} + +void ZMappedCache::tree_replace(const Tree::FindCursor& cursor, const ZVirtualMemory& vmem) { + ZMappedCacheEntry* const entry = create_entry(vmem); + + ZMappedCache::TreeNode* const node = cursor.node(); + ZMappedCacheEntry* const old_entry = ZMappedCacheEntry::cast_to_entry(node); + assert(old_entry->end() != vmem.end(), "should not replace, use update"); + + // Replace in tree + _tree.replace(entry->node_addr(), cursor); + + // Replace in size-class lists + + // Remove old + const size_t old_size = old_entry->vmem().size(); + const int old_index = size_class_index(old_size); + if (old_index != -1) { + _size_class_lists[old_index].remove(old_entry->size_class_node()); + } + + // Insert new + const size_t new_size = vmem.size(); + const int new_index = size_class_index(new_size); + if (new_index != -1) { + _size_class_lists[new_index].insert_first(entry->size_class_node()); + } + + // Destroy old entry + old_entry->~ZMappedCacheEntry(); +} + +void ZMappedCache::tree_update(ZMappedCacheEntry* entry, const ZVirtualMemory& vmem) { + assert(entry->end() == vmem.end(), "must be"); + + // Remove or add to size-class lists if required + + const size_t old_size = entry->vmem().size(); + const size_t new_size = vmem.size(); + const int old_index = size_class_index(old_size); + const int new_index = size_class_index(new_size); + + if (old_index != new_index) { + // Size class changed + + // Remove old + if (old_index != -1) { + _size_class_lists[old_index].remove(entry->size_class_node()); + } + + // Insert new + if (new_index != -1) { + _size_class_lists[new_index].insert_first(entry->size_class_node()); + } + } + + // And update entry + entry->update_start(vmem); +} + +template +ZVirtualMemory ZMappedCache::remove_vmem(ZMappedCacheEntry* const entry, size_t min_size, SelectFunction select) { + ZVirtualMemory vmem = entry->vmem(); + const size_t size = vmem.size(); + + if (size < min_size) { + // Do not select this, smaller than min_size + return ZVirtualMemory(); + } + + // Query how much to remove + const size_t to_remove = select(size); + assert(to_remove <= size, "must not remove more than size"); + + if (to_remove == 0) { + // Nothing to remove + return ZVirtualMemory(); + } + + if (to_remove != size) { + // Partial removal + if (strategy == RemovalStrategy::LowestAddress) { + const size_t unused_size = size - to_remove; + const ZVirtualMemory unused_vmem = vmem.shrink_from_back(unused_size); + tree_update(entry, unused_vmem); + + } else { + assert(strategy == RemovalStrategy::HighestAddress, "must be LowestAddress or HighestAddress"); + + const size_t unused_size = size - to_remove; + const ZVirtualMemory unused_vmem = vmem.shrink_from_front(unused_size); + + auto cursor = _tree.get_cursor(entry->node_addr()); + assert(cursor.is_valid(), "must be"); + tree_replace(cursor, unused_vmem); + } + + } else { + // Whole removal + auto cursor = _tree.get_cursor(entry->node_addr()); + assert(cursor.is_valid(), "must be"); + tree_remove(cursor, vmem); + } + + // Update statistics + _size -= to_remove; + _min = MIN2(_size, _min); + + postcond(to_remove == vmem.size()); + return vmem; +} + +template +bool ZMappedCache::try_remove_vmem_size_class(size_t min_size, SelectFunction select, ConsumeFunction consume) { +new_max_size: + // Query the max select size possible given the size of the cache + const size_t max_size = select(_size); + + if (max_size < min_size) { + // Never select less than min_size + return false; + } + + // Start scanning from max_size guaranteed size class to the largest size class + const int guaranteed_index = guaranteed_size_class_index(max_size); + for (int index = guaranteed_index; index != -1 && index < NumSizeClasses; ++index) { + ZList& list = _size_class_lists[index]; + if (!list.is_empty()) { + ZMappedCacheEntry* const entry = ZMappedCacheEntry::cast_to_entry(list.first()); + + // Because this is guaranteed, select should always succeed + const ZVirtualMemory vmem = remove_vmem(entry, min_size, select); + assert(!vmem.is_null(), "select must succeed"); + + if (consume(vmem)) { + // consume is satisfied + return true; + } + + // Continue with a new max_size + goto new_max_size; + } + } + + // Consume the rest starting at max_size's size class to min_size's size class + const int max_size_index = size_class_index(max_size); + const int min_size_index = size_class_index(min_size); + const int lowest_index = MAX2(min_size_index, 0); + + for (int index = max_size_index; index >= lowest_index; --index) { + ZListIterator iter(&_size_class_lists[index]); + for (ZSizeClassListNode* list_node; iter.next(&list_node);) { + ZMappedCacheEntry* const entry = ZMappedCacheEntry::cast_to_entry(list_node); + + // Try remove + const ZVirtualMemory vmem = remove_vmem(entry, min_size, select); + + if (!vmem.is_null() && consume(vmem)) { + // Found a vmem and consume is satisfied + return true; + } + } + } + + // consume was not satisfied + return false; +} + +template +void ZMappedCache::scan_remove_vmem(size_t min_size, SelectFunction select, ConsumeFunction consume) { + if (strategy == RemovalStrategy::SizeClasses) { + if (try_remove_vmem_size_class(min_size, select, consume)) { + // Satisfied using size classes + return; + } + + if (size_class_index(min_size) != -1) { + // There exists a size class for our min size. All possibilities must have + // been exhausted, do not scan the tree. + return; + } + + // Fallthrough to tree scan + } + + if (strategy == RemovalStrategy::HighestAddress) { + // Scan whole tree starting at the highest address + for (ZMappedCache::TreeNode* node = _tree.last(); node != nullptr; node = node->prev()) { + ZMappedCacheEntry* const entry = ZMappedCacheEntry::cast_to_entry(node); + + const ZVirtualMemory vmem = remove_vmem(entry, min_size, select); + + if (!vmem.is_null() && consume(vmem)) { + // Found a vmem and consume is satisfied. + return; + } + } + + } else { + assert(strategy == RemovalStrategy::SizeClasses || strategy == RemovalStrategy::LowestAddress, "unknown strategy"); + + // Scan whole tree starting at the lowest address + for (ZMappedCache::TreeNode* node = _tree.first(); node != nullptr; node = node->next()) { + ZMappedCacheEntry* const entry = ZMappedCacheEntry::cast_to_entry(node); + + const ZVirtualMemory vmem = remove_vmem(entry, min_size, select); + + if (!vmem.is_null() && consume(vmem)) { + // Found a vmem and consume is satisfied. + return; + } + } + } +} + +template +void ZMappedCache::scan_remove_vmem(SelectFunction select, ConsumeFunction consume) { + // Scan without a min_size + scan_remove_vmem(0, select, consume); +} + +template +size_t ZMappedCache::remove_discontiguous_with_strategy(size_t size, ZArray* out) { + precond(size > 0); + precond(is_aligned(size, ZGranuleSize)); + + size_t remaining = size; + + const auto select_size_fn = [&](size_t vmem_size) { + // Select at most remaining + return MIN2(remaining, vmem_size); + }; + + const auto consume_vmem_fn = [&](ZVirtualMemory vmem) { + const size_t vmem_size = vmem.size(); + out->append(vmem); + + assert(vmem_size <= remaining, "consumed to much"); + + // Track remaining, and stop when it reaches zero + remaining -= vmem_size; + + return remaining == 0; + }; + + scan_remove_vmem(select_size_fn, consume_vmem_fn); + + return size - remaining; +} + +ZMappedCache::ZMappedCache() + : _tree(), + _entry_count(0), + _size_class_lists{}, + _size(0), + _min(_size) {} + +void ZMappedCache::insert(const ZVirtualMemory& vmem) { + _size += vmem.size(); + + Tree::FindCursor current_cursor = _tree.find(vmem.start()); + Tree::FindCursor next_cursor = _tree.next(current_cursor); + + const bool extends_left = current_cursor.found(); + const bool extends_right = next_cursor.is_valid() && next_cursor.found() && + ZMappedCacheEntry::cast_to_entry(next_cursor.node())->start() == vmem.end(); + + if (extends_left && extends_right) { + ZMappedCacheEntry* next_entry = ZMappedCacheEntry::cast_to_entry(next_cursor.node()); + + const ZVirtualMemory left_vmem = ZMappedCacheEntry::cast_to_entry(current_cursor.node())->vmem(); + const ZVirtualMemory right_vmem = next_entry->vmem(); + assert(left_vmem.adjacent_to(vmem), "must be"); + assert(vmem.adjacent_to(right_vmem), "must be"); + + ZVirtualMemory new_vmem = left_vmem; + new_vmem.grow_from_back(vmem.size()); + new_vmem.grow_from_back(right_vmem.size()); + + // Remove current (left vmem) + tree_remove(current_cursor, left_vmem); + + // And update next's start + tree_update(next_entry, new_vmem); + + return; + } + + if (extends_left) { + const ZVirtualMemory left_vmem = ZMappedCacheEntry::cast_to_entry(current_cursor.node())->vmem(); + assert(left_vmem.adjacent_to(vmem), "must be"); + + ZVirtualMemory new_vmem = left_vmem; + new_vmem.grow_from_back(vmem.size()); + + tree_replace(current_cursor, new_vmem); + + return; + } + + if (extends_right) { + ZMappedCacheEntry* next_entry = ZMappedCacheEntry::cast_to_entry(next_cursor.node()); + + const ZVirtualMemory right_vmem = next_entry->vmem(); + assert(vmem.adjacent_to(right_vmem), "must be"); + + ZVirtualMemory new_vmem = vmem; + new_vmem.grow_from_back(right_vmem.size()); + + // Update next's start + tree_update(next_entry, new_vmem); + + return; + } + + tree_insert(current_cursor, vmem); +} + +ZVirtualMemory ZMappedCache::remove_contiguous(size_t size) { + precond(size > 0); + precond(is_aligned(size, ZGranuleSize)); + + ZVirtualMemory result; + + const auto select_size_fn = [&](size_t) { + // We always select the size + return size; + }; + + const auto consume_vmem_fn = [&](ZVirtualMemory vmem) { + assert(result.is_null(), "only consume once"); + assert(vmem.size() == size, "wrong size consumed"); + + result = vmem; + + // Only require one vmem + return true; + }; + + if (size == ZPageSizeSmall) { + // Small page allocations allocate at the lowest possible address + scan_remove_vmem(size, select_size_fn, consume_vmem_fn); + } else { + // Other sizes uses approximate best fit size classes first + scan_remove_vmem(size, select_size_fn, consume_vmem_fn); + } + + return result; +} + +size_t ZMappedCache::remove_discontiguous(size_t size, ZArray* out) { + return remove_discontiguous_with_strategy(size, out); +} + +size_t ZMappedCache::reset_min() { + const size_t old_min = _min; + + _min = _size; + + return old_min; +} + +size_t ZMappedCache::remove_from_min(size_t max_size, ZArray* out) { + const size_t size = MIN2(_min, max_size); + + if (size == 0) { + return 0; + } + + return remove_discontiguous_with_strategy(size, out); +} + +void ZMappedCache::print_on(outputStream* st) const { + // This may be called from error printing where we may not hold the lock, so + // values may be inconsistent. As such we read the _entry_count only once. And + // use is_empty_error_reporter_safe and size_error_reporter_safe on the size + // class lists. + const size_t entry_count = Atomic::load(&_entry_count); + + st->print("Cache"); + st->fill_to(17); + st->print_cr("%zuM (%zu)", _size / M, entry_count); + + if (entry_count == 0) { + // Empty cache, skip printing size classes + return; + } + + // Aggregate the number of size class entries + size_t size_class_entry_count = 0; + for (int index = 0; index < NumSizeClasses; ++index) { + size_class_entry_count += _size_class_lists[index].size_error_reporter_safe(); + } + + // Print information on size classes + streamIndentor indentor(st, 1); + + st->print("size classes"); + st->fill_to(17); + + // Print the number of entries smaller than the min size class's size + const size_t small_entry_size_count = entry_count - size_class_entry_count; + bool first = true; + if (small_entry_size_count != 0) { + st->print(EXACTFMT " (%zu)", EXACTFMTARGS(ZGranuleSize), small_entry_size_count); + first = false; + } + + for (int index = 0; index < NumSizeClasses; ++index) { + const ZList& list = _size_class_lists[index]; + if (!list.is_empty_error_reporter_safe()) { + const int shift = index + MinSizeClassShift + (int)ZGranuleSizeShift; + const size_t size = (size_t)1 << shift; + + st->print("%s" EXACTFMT " (%zu)", first ? "" : ", ", EXACTFMTARGS(size), list.size_error_reporter_safe()); + first = false; + } + } + + st->cr(); +} + +void ZMappedCache::print_extended_on(outputStream* st) const { + // Print the ranges and size of all nodes in the tree + for (ZMappedCache::TreeNode* node = _tree.first(); node != nullptr; node = node->next()) { + const ZVirtualMemory vmem = ZMappedCacheEntry::cast_to_entry(node)->vmem(); + + st->print_cr(PTR_FORMAT " " PTR_FORMAT " " EXACTFMT, + untype(vmem.start()), untype(vmem.end()), EXACTFMTARGS(vmem.size())); + } +} diff --git a/src/hotspot/share/gc/z/zMappedCache.hpp b/src/hotspot/share/gc/z/zMappedCache.hpp new file mode 100644 index 00000000000..8d1c90fd003 --- /dev/null +++ b/src/hotspot/share/gc/z/zMappedCache.hpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZMAPPEDCACHE_HPP +#define SHARE_GC_Z_ZMAPPEDCACHE_HPP + +#include "gc/z/zAddress.hpp" +#include "gc/z/zArray.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zIntrusiveRBTree.hpp" +#include "gc/z/zList.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + +class ZMappedCacheEntry; +class ZVirtualMemory; + +class ZMappedCache { + friend class ZMappedCacheEntry; + +private: + struct EntryCompare { + int operator()(ZIntrusiveRBTreeNode* a, ZIntrusiveRBTreeNode* b); + int operator()(zoffset key, ZIntrusiveRBTreeNode* node); + }; + + struct ZSizeClassListNode { + ZListNode _node; + }; + + using Tree = ZIntrusiveRBTree; + using TreeNode = ZIntrusiveRBTreeNode; + using SizeClassList = ZList; + using SizeClassListNode = ZSizeClassListNode; + + // Maintain size class lists from 4MB to 16GB + static constexpr int MaxLongArraySizeClassShift = 3 /* 8 byte */ + 31 /* max length */; + static constexpr int MinSizeClassShift = 1; + static constexpr int MaxSizeClassShift = MaxLongArraySizeClassShift - ZGranuleSizeShift; + static constexpr int NumSizeClasses = MaxSizeClassShift - MinSizeClassShift + 1; + + Tree _tree; + size_t _entry_count; + SizeClassList _size_class_lists[NumSizeClasses]; + size_t _size; + size_t _min; + + static int size_class_index(size_t size); + static int guaranteed_size_class_index(size_t size); + + void tree_insert(const Tree::FindCursor& cursor, const ZVirtualMemory& vmem); + void tree_remove(const Tree::FindCursor& cursor, const ZVirtualMemory& vmem); + void tree_replace(const Tree::FindCursor& cursor, const ZVirtualMemory& vmem); + void tree_update(ZMappedCacheEntry* entry, const ZVirtualMemory& vmem); + + enum class RemovalStrategy { + LowestAddress, + HighestAddress, + SizeClasses, + }; + + template + ZVirtualMemory remove_vmem(ZMappedCacheEntry* const entry, size_t min_size, SelectFunction select); + + template + bool try_remove_vmem_size_class(size_t min_size, SelectFunction select, ConsumeFunction consume); + + template + void scan_remove_vmem(size_t min_size, SelectFunction select, ConsumeFunction consume); + + template + void scan_remove_vmem(SelectFunction select, ConsumeFunction consume); + + template + size_t remove_discontiguous_with_strategy(size_t size, ZArray* out); + +public: + ZMappedCache(); + + void insert(const ZVirtualMemory& vmem); + + ZVirtualMemory remove_contiguous(size_t size); + size_t remove_discontiguous(size_t size, ZArray* out); + + size_t reset_min(); + size_t remove_from_min(size_t max_size, ZArray* out); + + void print_on(outputStream* st) const; + void print_extended_on(outputStream* st) const; +}; + +#endif // SHARE_GC_Z_ZMAPPEDCACHE_HPP diff --git a/src/hotspot/share/gc/z/zMemory.cpp b/src/hotspot/share/gc/z/zMemory.cpp deleted file mode 100644 index 35e95888d4d..00000000000 --- a/src/hotspot/share/gc/z/zMemory.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "gc/z/zList.inline.hpp" -#include "gc/z/zLock.inline.hpp" -#include "gc/z/zMemory.inline.hpp" - -void ZMemoryManager::shrink_from_front(ZMemory* area, size_t size) { - if (_callbacks._shrink != nullptr) { - const ZMemory* from = area; - const ZMemory to(area->start() + size, area->size() - size); - _callbacks._shrink(*from, to); - } - area->shrink_from_front(size); -} - -void ZMemoryManager::shrink_from_back(ZMemory* area, size_t size) { - if (_callbacks._shrink != nullptr) { - const ZMemory* from = area; - const ZMemory to(area->start(), area->size() - size); - _callbacks._shrink(*from, to); - } - area->shrink_from_back(size); -} - -void ZMemoryManager::grow_from_front(ZMemory* area, size_t size) { - if (_callbacks._grow != nullptr) { - const ZMemory* from = area; - const ZMemory to(area->start() - size, area->size() + size); - _callbacks._grow(*from, to); - } - area->grow_from_front(size); -} - -void ZMemoryManager::grow_from_back(ZMemory* area, size_t size) { - if (_callbacks._grow != nullptr) { - const ZMemory* from = area; - const ZMemory to(area->start(), area->size() + size); - _callbacks._grow(*from, to); - } - area->grow_from_back(size); -} - -ZMemoryManager::Callbacks::Callbacks() - : _prepare_for_hand_out(nullptr), - _prepare_for_hand_back(nullptr), - _grow(nullptr), - _shrink(nullptr) {} - -ZMemoryManager::ZMemoryManager() - : _freelist(), - _callbacks() {} - -bool ZMemoryManager::free_is_contiguous() const { - return _freelist.size() == 1; -} - -void ZMemoryManager::register_callbacks(const Callbacks& callbacks) { - _callbacks = callbacks; -} - -zoffset ZMemoryManager::peek_low_address() const { - ZLocker locker(&_lock); - - const ZMemory* const area = _freelist.first(); - if (area != nullptr) { - return area->start(); - } - - // Out of memory - return zoffset(UINTPTR_MAX); -} - -zoffset_end ZMemoryManager::peak_high_address_end() const { - ZLocker locker(&_lock); - - const ZMemory* const area = _freelist.last(); - if (area != nullptr) { - return area->end(); - } - - // Out of memory - return zoffset_end(UINTPTR_MAX); -} - -zoffset ZMemoryManager::alloc_low_address(size_t size) { - ZLocker locker(&_lock); - - ZListIterator iter(&_freelist); - for (ZMemory* area; iter.next(&area);) { - if (area->size() >= size) { - zoffset start; - - if (area->size() == size) { - // Exact match, remove area - start = area->start(); - _freelist.remove(area); - delete area; - } else { - // Larger than requested, shrink area - start = area->start(); - shrink_from_front(area, size); - } - - if (_callbacks._prepare_for_hand_out != nullptr) { - _callbacks._prepare_for_hand_out(ZMemory(start, size)); - } - - return start; - } - } - - // Out of memory - return zoffset(UINTPTR_MAX); -} - -zoffset ZMemoryManager::alloc_low_address_at_most(size_t size, size_t* allocated) { - ZLocker locker(&_lock); - - ZMemory* const area = _freelist.first(); - if (area != nullptr) { - const zoffset start = area->start(); - - if (area->size() <= size) { - // Smaller than or equal to requested, remove area - _freelist.remove(area); - *allocated = area->size(); - delete area; - } else { - // Larger than requested, shrink area - shrink_from_front(area, size); - *allocated = size; - } - - if (_callbacks._prepare_for_hand_out != nullptr) { - _callbacks._prepare_for_hand_out(ZMemory(start, *allocated)); - } - - return start; - } - - // Out of memory - *allocated = 0; - return zoffset(UINTPTR_MAX); -} - -zoffset ZMemoryManager::alloc_high_address(size_t size) { - ZLocker locker(&_lock); - - ZListReverseIterator iter(&_freelist); - for (ZMemory* area; iter.next(&area);) { - if (area->size() >= size) { - zoffset start; - - if (area->size() == size) { - // Exact match, remove area - start = area->start(); - _freelist.remove(area); - delete area; - } else { - // Larger than requested, shrink area - shrink_from_back(area, size); - start = to_zoffset(area->end()); - } - - if (_callbacks._prepare_for_hand_out != nullptr) { - _callbacks._prepare_for_hand_out(ZMemory(start, size)); - } - - return start; - } - } - - // Out of memory - return zoffset(UINTPTR_MAX); -} - -void ZMemoryManager::move_into(zoffset start, size_t size) { - assert(start != zoffset(UINTPTR_MAX), "Invalid address"); - const zoffset_end end = to_zoffset_end(start, size); - - ZListIterator iter(&_freelist); - for (ZMemory* area; iter.next(&area);) { - if (start < area->start()) { - ZMemory* const prev = _freelist.prev(area); - if (prev != nullptr && start == prev->end()) { - if (end == area->start()) { - // Merge with prev and current area - grow_from_back(prev, size + area->size()); - _freelist.remove(area); - delete area; - } else { - // Merge with prev area - grow_from_back(prev, size); - } - } else if (end == area->start()) { - // Merge with current area - grow_from_front(area, size); - } else { - // Insert new area before current area - assert(end < area->start(), "Areas must not overlap"); - ZMemory* const new_area = new ZMemory(start, size); - _freelist.insert_before(area, new_area); - } - - // Done - return; - } - } - - // Insert last - ZMemory* const last = _freelist.last(); - if (last != nullptr && start == last->end()) { - // Merge with last area - grow_from_back(last, size); - } else { - // Insert new area last - ZMemory* const new_area = new ZMemory(start, size); - _freelist.insert_last(new_area); - } -} - -void ZMemoryManager::free(zoffset start, size_t size) { - ZLocker locker(&_lock); - - if (_callbacks._prepare_for_hand_back != nullptr) { - _callbacks._prepare_for_hand_back(ZMemory(start, size)); - } - - move_into(start, size); -} - -void ZMemoryManager::register_range(zoffset start, size_t size) { - // Note that there's no need to call the _prepare_for_hand_back when memory - // is added the first time. We don't have to undo the effects of a previous - // _prepare_for_hand_out callback. - - // No need to lock during initialization. - - move_into(start, size); -} - -bool ZMemoryManager::unregister_first(zoffset* start_out, size_t* size_out) { - // Note that this doesn't hand out memory to be used, so we don't call the - // _prepare_for_hand_out callback. - - ZLocker locker(&_lock); - - if (_freelist.is_empty()) { - return false; - } - - // Don't invoke the _prepare_for_hand_out callback - - ZMemory* const area = _freelist.remove_first(); - - // Return the range - *start_out = area->start(); - *size_out = area->size(); - - delete area; - - return true; -} diff --git a/src/hotspot/share/gc/z/zMemory.hpp b/src/hotspot/share/gc/z/zMemory.hpp deleted file mode 100644 index da37596c1c7..00000000000 --- a/src/hotspot/share/gc/z/zMemory.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 - * 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_GC_Z_ZMEMORY_HPP -#define SHARE_GC_Z_ZMEMORY_HPP - -#include "gc/z/zAddress.hpp" -#include "gc/z/zList.hpp" -#include "gc/z/zLock.hpp" -#include "memory/allocation.hpp" - -class ZMemory : public CHeapObj { - friend class ZList; - -private: - zoffset _start; - zoffset_end _end; - ZListNode _node; - -public: - ZMemory(zoffset start, size_t size); - - zoffset start() const; - zoffset_end end() const; - size_t size() const; - - bool operator==(const ZMemory& other) const; - bool operator!=(const ZMemory& other) const; - - bool contains(const ZMemory& other) const; - - void shrink_from_front(size_t size); - void shrink_from_back(size_t size); - void grow_from_front(size_t size); - void grow_from_back(size_t size); -}; - -class ZMemoryManager { - friend class ZVirtualMemoryManagerTest; - -public: - typedef void (*CallbackPrepare)(const ZMemory& area); - typedef void (*CallbackResize)(const ZMemory& from, const ZMemory& to); - - struct Callbacks { - CallbackPrepare _prepare_for_hand_out; - CallbackPrepare _prepare_for_hand_back; - CallbackResize _grow; - CallbackResize _shrink; - - Callbacks(); - }; - -private: - mutable ZLock _lock; - ZList _freelist; - Callbacks _callbacks; - - void shrink_from_front(ZMemory* area, size_t size); - void shrink_from_back(ZMemory* area, size_t size); - void grow_from_front(ZMemory* area, size_t size); - void grow_from_back(ZMemory* area, size_t size); - - void move_into(zoffset start, size_t size); - -public: - ZMemoryManager(); - - bool free_is_contiguous() const; - - void register_callbacks(const Callbacks& callbacks); - - zoffset peek_low_address() const; - zoffset_end peak_high_address_end() const; - zoffset alloc_low_address(size_t size); - zoffset alloc_low_address_at_most(size_t size, size_t* allocated); - zoffset alloc_high_address(size_t size); - - void free(zoffset start, size_t size); - void register_range(zoffset start, size_t size); - bool unregister_first(zoffset* start_out, size_t* size_out); -}; - -#endif // SHARE_GC_Z_ZMEMORY_HPP diff --git a/src/hotspot/share/gc/z/zMemory.inline.hpp b/src/hotspot/share/gc/z/zMemory.inline.hpp deleted file mode 100644 index 39e5b26d856..00000000000 --- a/src/hotspot/share/gc/z/zMemory.inline.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 - * 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_GC_Z_ZMEMORY_INLINE_HPP -#define SHARE_GC_Z_ZMEMORY_INLINE_HPP - -#include "gc/z/zMemory.hpp" - -#include "gc/z/zAddress.inline.hpp" -#include "gc/z/zList.inline.hpp" -#include "utilities/debug.hpp" - -inline ZMemory::ZMemory(zoffset start, size_t size) - : _start(start), - _end(to_zoffset_end(start, size)) {} - -inline zoffset ZMemory::start() const { - return _start; -} - -inline zoffset_end ZMemory::end() const { - return _end; -} - -inline size_t ZMemory::size() const { - return end() - start(); -} - -inline bool ZMemory::operator==(const ZMemory& other) const { - return _start == other._start && _end == other._end; -} - -inline bool ZMemory::operator!=(const ZMemory& other) const { - return !operator==(other); -} - -inline bool ZMemory::contains(const ZMemory& other) const { - return _start <= other._start && other.end() <= end(); -} - -inline void ZMemory::shrink_from_front(size_t size) { - assert(this->size() > size, "Too small"); - _start += size; -} - -inline void ZMemory::shrink_from_back(size_t size) { - assert(this->size() > size, "Too small"); - _end -= size; -} - -inline void ZMemory::grow_from_front(size_t size) { - assert(size_t(start()) >= size, "Too big"); - _start -= size; -} - -inline void ZMemory::grow_from_back(size_t size) { - _end += size; -} - -#endif // SHARE_GC_Z_ZMEMORY_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zNMT.cpp b/src/hotspot/share/gc/z/zNMT.cpp index 4e1efbf9caf..76e164308dd 100644 --- a/src/hotspot/share/gc/z/zNMT.cpp +++ b/src/hotspot/share/gc/z/zNMT.cpp @@ -24,7 +24,6 @@ #include "gc/z/zAddress.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zNMT.hpp" -#include "gc/z/zVirtualMemory.hpp" #include "nmt/memTag.hpp" #include "nmt/memTracker.hpp" #include "nmt/memoryFileTracker.hpp" @@ -60,15 +59,15 @@ void ZNMT::unreserve(zaddress_unsafe start, size_t size) { } } -void ZNMT::commit(zoffset offset, size_t size) { +void ZNMT::commit(zbacking_offset offset, size_t size) { MemTracker::allocate_memory_in(ZNMT::_device, untype(offset), size, CALLER_PC, mtJavaHeap); } -void ZNMT::uncommit(zoffset offset, size_t size) { +void ZNMT::uncommit(zbacking_offset offset, size_t size) { MemTracker::free_memory_in(ZNMT::_device, untype(offset), size); } -void ZNMT::map(zaddress_unsafe addr, size_t size, zoffset offset) { +void ZNMT::map(zaddress_unsafe addr, size_t size, zbacking_offset offset) { // NMT doesn't track mappings at the moment. } diff --git a/src/hotspot/share/gc/z/zNMT.hpp b/src/hotspot/share/gc/z/zNMT.hpp index bea6a6b62ac..b5b1aa07870 100644 --- a/src/hotspot/share/gc/z/zNMT.hpp +++ b/src/hotspot/share/gc/z/zNMT.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,10 @@ #include "gc/z/zAddress.hpp" #include "gc/z/zGlobals.hpp" -#include "gc/z/zMemory.hpp" -#include "gc/z/zVirtualMemory.hpp" #include "memory/allStatic.hpp" #include "nmt/memTracker.hpp" #include "nmt/memoryFileTracker.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/nativeCallStack.hpp" class ZNMT : public AllStatic { private: @@ -44,10 +41,10 @@ public: static void reserve(zaddress_unsafe start, size_t size); static void unreserve(zaddress_unsafe start, size_t size); - static void commit(zoffset offset, size_t size); - static void uncommit(zoffset offset, size_t size); + static void commit(zbacking_offset offset, size_t size); + static void uncommit(zbacking_offset offset, size_t size); - static void map(zaddress_unsafe addr, size_t size, zoffset offset); + static void map(zaddress_unsafe addr, size_t size, zbacking_offset offset); static void unmap(zaddress_unsafe addr, size_t size); }; diff --git a/src/hotspot/share/gc/z/zNUMA.cpp b/src/hotspot/share/gc/z/zNUMA.cpp index a302a1843bb..cf2d88a90e5 100644 --- a/src/hotspot/share/gc/z/zNUMA.cpp +++ b/src/hotspot/share/gc/z/zNUMA.cpp @@ -21,8 +21,10 @@ * questions. */ +#include "gc/shared/gc_globals.hpp" #include "gc/shared/gcLogPrecious.hpp" -#include "gc/z/zNUMA.hpp" +#include "gc/z/zNUMA.inline.hpp" +#include "utilities/macros.hpp" bool ZNUMA::_enabled; uint32_t ZNUMA::_count; @@ -31,11 +33,20 @@ void ZNUMA::initialize() { pd_initialize(); log_info_p(gc, init)("NUMA Support: %s", to_string()); + if (_enabled) { + assert(!is_faked(), "Currently not supported"); log_info_p(gc, init)("NUMA Nodes: %u", _count); + + } else if (is_faked()) { + log_info_p(gc, init)("Fake NUMA Nodes: %u", count()); } } const char* ZNUMA::to_string() { + if (is_faked()) { + return "Faked"; + } + return _enabled ? "Enabled" : "Disabled"; } diff --git a/src/hotspot/share/gc/z/zNUMA.hpp b/src/hotspot/share/gc/z/zNUMA.hpp index ac614247522..de74086b10a 100644 --- a/src/hotspot/share/gc/z/zNUMA.hpp +++ b/src/hotspot/share/gc/z/zNUMA.hpp @@ -24,10 +24,15 @@ #ifndef SHARE_GC_Z_ZNUMA_HPP #define SHARE_GC_Z_ZNUMA_HPP +#include "gc/z/zGlobals.hpp" #include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" class ZNUMA : public AllStatic { + friend class VMStructs; + friend class ZNUMATest; + friend class ZTest; + private: static bool _enabled; static uint32_t _count; @@ -36,13 +41,17 @@ private: public: static void initialize(); + static bool is_enabled(); + static bool is_faked(); static uint32_t count(); static uint32_t id(); static uint32_t memory_id(uintptr_t addr); + static size_t calculate_share(uint32_t numa_id, size_t total, size_t granule = ZGranuleSize, uint32_t ignore_count = 0); + static const char* to_string(); }; diff --git a/src/hotspot/share/gc/z/zNUMA.inline.hpp b/src/hotspot/share/gc/z/zNUMA.inline.hpp index 4596c8f090b..d90b44e905a 100644 --- a/src/hotspot/share/gc/z/zNUMA.inline.hpp +++ b/src/hotspot/share/gc/z/zNUMA.inline.hpp @@ -26,12 +26,36 @@ #include "gc/z/zNUMA.hpp" +#include "gc/shared/gc_globals.hpp" +#include "gc/z/zGlobals.hpp" +#include "utilities/align.hpp" + inline bool ZNUMA::is_enabled() { return _enabled; } +inline bool ZNUMA::is_faked() { + return ZFakeNUMA > 1; +} + inline uint32_t ZNUMA::count() { return _count; } +inline size_t ZNUMA::calculate_share(uint32_t numa_id, size_t total, size_t granule, uint32_t ignore_count) { + assert(total % granule == 0, "total must be divisible by granule"); + assert(ignore_count < count(), "must not ignore all nodes"); + assert(numa_id < count() - ignore_count, "numa_id must be in bounds"); + + const uint32_t num_nodes = count() - ignore_count; + const size_t base_share = ((total / num_nodes) / granule) * granule; + + const size_t extra_share_nodes = (total - base_share * num_nodes) / granule; + if (numa_id < extra_share_nodes) { + return base_share + granule; + } + + return base_share; +} + #endif // SHARE_GC_Z_ZNUMA_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zObjectAllocator.cpp b/src/hotspot/share/gc/z/zObjectAllocator.cpp index 81a92aa6cc6..54724c1b48e 100644 --- a/src/hotspot/share/gc/z/zObjectAllocator.cpp +++ b/src/hotspot/share/gc/z/zObjectAllocator.cpp @@ -138,10 +138,10 @@ zaddress ZObjectAllocator::alloc_object_in_medium_page(size_t size, } if (is_null(addr)) { - // When a new medium page is required, we synchronize the allocation - // of the new page using a lock. This is to avoid having multiple - // threads requesting a medium page from the page cache when we know - // only one of the will succeed in installing the page at this layer. + // When a new medium page is required, we synchronize the allocation of the + // new page using a lock. This is to avoid having multiple threads allocate + // medium pages when we know only one of them will succeed in installing + // the page at this layer. ZLocker locker(&_medium_page_alloc_lock); // When holding the lock we can't allow the page allocator to stall, diff --git a/src/hotspot/share/gc/z/zPage.cpp b/src/hotspot/share/gc/z/zPage.cpp index 5264076c8a9..f4cc7542052 100644 --- a/src/hotspot/share/gc/z/zPage.cpp +++ b/src/hotspot/share/gc/z/zPage.cpp @@ -23,42 +23,47 @@ #include "gc/shared/gc_globals.hpp" #include "gc/z/zGeneration.inline.hpp" -#include "gc/z/zList.inline.hpp" #include "gc/z/zPage.inline.hpp" -#include "gc/z/zPhysicalMemory.inline.hpp" +#include "gc/z/zPageAge.hpp" #include "gc/z/zRememberedSet.inline.hpp" -#include "gc/z/zVirtualMemory.inline.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" -#include "utilities/growableArray.hpp" -ZPage::ZPage(ZPageType type, const ZVirtualMemory& vmem, const ZPhysicalMemory& pmem) +ZPage::ZPage(ZPageType type, ZPageAge age, const ZVirtualMemory& vmem, ZMultiPartitionTracker* multi_partition_tracker, uint32_t partition_id) : _type(type), - _generation_id(ZGenerationId::young), - _age(ZPageAge::eden), - _numa_id((uint8_t)-1), - _seqnum(0), - _seqnum_other(0), + _generation_id(/* set in reset */), + _age(/* set in reset */), + _seqnum(/* set in reset */), + _seqnum_other(/* set in reset */), + _single_partition_id(partition_id), _virtual(vmem), _top(to_zoffset_end(start())), _livemap(object_max_count()), _remembered_set(), - _last_used(0), - _physical(pmem), - _node() { + _multi_partition_tracker(multi_partition_tracker) { assert(!_virtual.is_null(), "Should not be null"); - assert(!_physical.is_null(), "Should not be null"); - assert(_virtual.size() == _physical.size(), "Virtual/Physical size mismatch"); assert((_type == ZPageType::small && size() == ZPageSizeSmall) || (_type == ZPageType::medium && size() == ZPageSizeMedium) || (_type == ZPageType::large && is_aligned(size(), ZGranuleSize)), "Page type/size mismatch"); + reset(age); + + if (is_old()) { + remset_alloc(); + } } -ZPage* ZPage::clone_limited() const { +ZPage::ZPage(ZPageType type, ZPageAge age, const ZVirtualMemory& vmem, uint32_t partition_id) + : ZPage(type, age, vmem, nullptr /* multi_partition_tracker */, partition_id) {} + +ZPage::ZPage(ZPageType type, ZPageAge age, const ZVirtualMemory& vmem, ZMultiPartitionTracker* multi_partition_tracker) + : ZPage(type, age, vmem, multi_partition_tracker, -1u /* partition_id */) {} + +ZPage* ZPage::clone_for_promotion() const { + assert(_age != ZPageAge::old, "must be used for promotion"); // Only copy type and memory layouts, and also update _top. Let the rest be // lazily reconstructed when needed. - ZPage* const page = new ZPage(_type, _virtual, _physical); + ZPage* const page = new ZPage(_type, ZPageAge::old, _virtual, _multi_partition_tracker, _single_partition_id); page->_top = _top; return page; @@ -85,19 +90,16 @@ void ZPage::remset_alloc() { _remembered_set.initialize(size()); } -void ZPage::remset_delete() { - _remembered_set.delete_all(); -} - -void ZPage::reset(ZPageAge age) { +ZPage* ZPage::reset(ZPageAge age) { _age = age; - _last_used = 0; _generation_id = age == ZPageAge::old ? ZGenerationId::old : ZGenerationId::young; reset_seqnum(); + + return this; } void ZPage::reset_livemap() { @@ -108,59 +110,6 @@ void ZPage::reset_top_for_allocation() { _top = to_zoffset_end(start()); } -void ZPage::reset_type_and_size(ZPageType type) { - _type = type; - _livemap.resize(object_max_count()); -} - -ZPage* ZPage::retype(ZPageType type) { - assert(_type != type, "Invalid retype"); - reset_type_and_size(type); - return this; -} - -ZPage* ZPage::split(size_t split_of_size) { - return split(type_from_size(split_of_size), split_of_size); -} - -ZPage* ZPage::split_with_pmem(ZPageType type, const ZPhysicalMemory& pmem) { - // Resize this page - const ZVirtualMemory vmem = _virtual.split(pmem.size()); - assert(vmem.end() == _virtual.start(), "Should be consecutive"); - - reset_type_and_size(type_from_size(_virtual.size())); - - log_trace(gc, page)("Split page [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT "]", - untype(vmem.start()), - untype(vmem.end()), - untype(_virtual.end())); - - // Create new page - return new ZPage(type, vmem, pmem); -} - -ZPage* ZPage::split(ZPageType type, size_t split_of_size) { - assert(_virtual.size() > split_of_size, "Invalid split"); - - const ZPhysicalMemory pmem = _physical.split(split_of_size); - - return split_with_pmem(type, pmem); -} - -ZPage* ZPage::split_committed() { - // Split any committed part of this page into a separate page, - // leaving this page with only uncommitted physical memory. - const ZPhysicalMemory pmem = _physical.split_committed(); - if (pmem.is_null()) { - // Nothing committed - return nullptr; - } - - assert(!_physical.is_null(), "Should not be null"); - - return split_with_pmem(type_from_size(pmem.size()), pmem); -} - class ZFindBaseOopClosure : public ObjectClosure { private: volatile zpointer* _p; @@ -215,18 +164,19 @@ void* ZPage::remset_current() { return _remembered_set.current(); } -void ZPage::print_on_msg(outputStream* out, const char* msg) const { - out->print_cr(" %-6s " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s/%-4u %s%s%s", +void ZPage::print_on_msg(outputStream* st, const char* msg) const { + st->print_cr("%-6s " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s/%-4u %s%s%s%s", type_to_string(), untype(start()), untype(top()), untype(end()), is_young() ? "Y" : "O", seqnum(), - is_allocating() ? " Allocating " : "", is_relocatable() ? " Relocatable" : "", - msg == nullptr ? "" : msg); + is_allocating() ? " Allocating" : "", + is_allocating() && msg != nullptr ? " " : "", + msg != nullptr ? msg : ""); } -void ZPage::print_on(outputStream* out) const { - print_on_msg(out, nullptr); +void ZPage::print_on(outputStream* st) const { + print_on_msg(st, nullptr); } void ZPage::print() const { diff --git a/src/hotspot/share/gc/z/zPage.hpp b/src/hotspot/share/gc/z/zPage.hpp index 9b6c155f77d..96900a37680 100644 --- a/src/hotspot/share/gc/z/zPage.hpp +++ b/src/hotspot/share/gc/z/zPage.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,38 +25,34 @@ #define SHARE_GC_Z_ZPAGE_HPP #include "gc/z/zGenerationId.hpp" -#include "gc/z/zList.hpp" #include "gc/z/zLiveMap.hpp" #include "gc/z/zPageAge.hpp" #include "gc/z/zPageType.hpp" -#include "gc/z/zPhysicalMemory.hpp" #include "gc/z/zRememberedSet.hpp" #include "gc/z/zVirtualMemory.hpp" #include "memory/allocation.hpp" +#include "oops/oopsHierarchy.hpp" class ZGeneration; +class ZMultiPartitionTracker; class ZPage : public CHeapObj { friend class VMStructs; - friend class ZList; friend class ZForwardingTest; private: - ZPageType _type; - ZGenerationId _generation_id; - ZPageAge _age; - uint8_t _numa_id; - uint32_t _seqnum; - uint32_t _seqnum_other; - ZVirtualMemory _virtual; - volatile zoffset_end _top; - ZLiveMap _livemap; - ZRememberedSet _remembered_set; - uint64_t _last_used; - ZPhysicalMemory _physical; - ZListNode _node; + const ZPageType _type; + ZGenerationId _generation_id; + ZPageAge _age; + uint32_t _seqnum; + uint32_t _seqnum_other; + const uint32_t _single_partition_id; + const ZVirtualMemory _virtual; + volatile zoffset_end _top; + ZLiveMap _livemap; + ZRememberedSet _remembered_set; + ZMultiPartitionTracker* const _multi_partition_tracker; - ZPageType type_from_size(size_t size) const; const char* type_to_string() const; BitMap::idx_t bit_index(zaddress addr) const; @@ -71,12 +67,13 @@ private: void reset_seqnum(); - ZPage* split_with_pmem(ZPageType type, const ZPhysicalMemory& pmem); + ZPage(ZPageType type, ZPageAge age, const ZVirtualMemory& vmem, ZMultiPartitionTracker* multi_partition_tracker, uint32_t partition_id); public: - ZPage(ZPageType type, const ZVirtualMemory& vmem, const ZPhysicalMemory& pmem); + ZPage(ZPageType type, ZPageAge age, const ZVirtualMemory& vmem, uint32_t partition_id); + ZPage(ZPageType type, ZPageAge age, const ZVirtualMemory& vmem, ZMultiPartitionTracker* multi_partition_tracker); - ZPage* clone_limited() const; + ZPage* clone_for_promotion() const; uint32_t object_max_count() const; size_t object_alignment_shift() const; @@ -99,28 +96,20 @@ public: size_t used() const; const ZVirtualMemory& virtual_memory() const; - const ZPhysicalMemory& physical_memory() const; - ZPhysicalMemory& physical_memory(); - uint8_t numa_id(); + uint32_t single_partition_id() const; + bool is_multi_partition() const; + ZMultiPartitionTracker* multi_partition_tracker() const; + ZPageAge age() const; uint32_t seqnum() const; bool is_allocating() const; bool is_relocatable() const; - uint64_t last_used() const; - void set_last_used(); - - void reset(ZPageAge age); + ZPage* reset(ZPageAge age); void reset_livemap(); void reset_top_for_allocation(); - void reset_type_and_size(ZPageType type); - - ZPage* retype(ZPageType type); - ZPage* split(size_t split_of_size); - ZPage* split(ZPageType type, size_t split_of_size); - ZPage* split_committed(); bool is_in(zoffset offset) const; bool is_in(zaddress addr) const; @@ -156,7 +145,6 @@ public: void swap_remset_bitmaps(); void remset_alloc(); - void remset_delete(); ZBitMap::ReverseIterator remset_reverse_iterator_previous(); BitMap::Iterator remset_iterator_limited_current(uintptr_t l_offset, size_t size); @@ -193,8 +181,8 @@ public: void log_msg(const char* msg_format, ...) const ATTRIBUTE_PRINTF(2, 3); - void print_on_msg(outputStream* out, const char* msg) const; - void print_on(outputStream* out) const; + void print_on_msg(outputStream* st, const char* msg) const; + void print_on(outputStream* st) const; void print() const; // Verification diff --git a/src/hotspot/share/gc/z/zPage.inline.hpp b/src/hotspot/share/gc/z/zPage.inline.hpp index 5d476f273d3..f6c2029ac06 100644 --- a/src/hotspot/share/gc/z/zPage.inline.hpp +++ b/src/hotspot/share/gc/z/zPage.inline.hpp @@ -30,28 +30,14 @@ #include "gc/z/zGeneration.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zLiveMap.inline.hpp" -#include "gc/z/zNUMA.hpp" -#include "gc/z/zPhysicalMemory.inline.hpp" #include "gc/z/zRememberedSet.inline.hpp" -#include "gc/z/zUtils.inline.hpp" #include "gc/z/zVirtualMemory.inline.hpp" #include "logging/logStream.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "utilities/align.hpp" -#include "utilities/checkedCast.hpp" #include "utilities/debug.hpp" -inline ZPageType ZPage::type_from_size(size_t size) const { - if (size == ZPageSizeSmall) { - return ZPageType::small; - } else if (size == ZPageSizeMedium) { - return ZPageType::medium; - } else { - return ZPageType::large; - } -} - inline const char* ZPage::type_to_string() const { switch (type()) { case ZPageType::small: @@ -170,20 +156,16 @@ inline const ZVirtualMemory& ZPage::virtual_memory() const { return _virtual; } -inline const ZPhysicalMemory& ZPage::physical_memory() const { - return _physical; +inline uint32_t ZPage::single_partition_id() const { + return _single_partition_id; } -inline ZPhysicalMemory& ZPage::physical_memory() { - return _physical; +inline bool ZPage::is_multi_partition() const { + return _multi_partition_tracker != nullptr; } -inline uint8_t ZPage::numa_id() { - if (_numa_id == (uint8_t)-1) { - _numa_id = checked_cast(ZNUMA::memory_id(untype(ZOffset::address(start())))); - } - - return _numa_id; +inline ZMultiPartitionTracker* ZPage::multi_partition_tracker() const { + return _multi_partition_tracker; } inline ZPageAge ZPage::age() const { @@ -202,14 +184,6 @@ inline bool ZPage::is_relocatable() const { return _seqnum < generation()->seqnum(); } -inline uint64_t ZPage::last_used() const { - return _last_used; -} - -inline void ZPage::set_last_used() { - _last_used = (uint64_t)ceil(os::elapsedTime()); -} - inline bool ZPage::is_in(zoffset offset) const { return offset >= start() && offset < top(); } diff --git a/src/hotspot/share/gc/z/zPageAllocator.cpp b/src/hotspot/share/gc/z/zPageAllocator.cpp index 7913aa68fbe..444f7a9b845 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.cpp +++ b/src/hotspot/share/gc/z/zPageAllocator.cpp @@ -23,6 +23,8 @@ #include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/z/zAddress.hpp" +#include "gc/z/zAllocationFlags.hpp" #include "gc/z/zArray.inline.hpp" #include "gc/z/zDriver.hpp" #include "gc/z/zFuture.inline.hpp" @@ -31,71 +33,361 @@ #include "gc/z/zGlobals.hpp" #include "gc/z/zLargePages.inline.hpp" #include "gc/z/zLock.inline.hpp" +#include "gc/z/zMappedCache.hpp" +#include "gc/z/zNUMA.inline.hpp" #include "gc/z/zPage.inline.hpp" #include "gc/z/zPageAge.hpp" #include "gc/z/zPageAllocator.inline.hpp" -#include "gc/z/zPageCache.hpp" +#include "gc/z/zPageType.hpp" +#include "gc/z/zPhysicalMemoryManager.hpp" #include "gc/z/zSafeDelete.inline.hpp" #include "gc/z/zStat.hpp" #include "gc/z/zTask.hpp" #include "gc/z/zUncommitter.hpp" -#include "gc/z/zUnmapper.hpp" +#include "gc/z/zValue.inline.hpp" +#include "gc/z/zVirtualMemory.inline.hpp" +#include "gc/z/zVirtualMemoryManager.inline.hpp" #include "gc/z/zWorkers.hpp" #include "jfr/jfrEvents.hpp" #include "logging/log.hpp" +#include "memory/allocation.hpp" +#include "nmt/memTag.hpp" #include "runtime/globals.hpp" #include "runtime/init.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" +#include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/ticks.hpp" +#include "utilities/vmError.hpp" + +#include + +class ZMemoryAllocation; static const ZStatCounter ZCounterMutatorAllocationRate("Memory", "Allocation Rate", ZStatUnitBytesPerSecond); -static const ZStatCounter ZCounterPageCacheFlush("Memory", "Page Cache Flush", ZStatUnitBytesPerSecond); +static const ZStatCounter ZCounterMappedCacheHarvest("Memory", "Mapped Cache Harvest", ZStatUnitBytesPerSecond); static const ZStatCounter ZCounterDefragment("Memory", "Defragment", ZStatUnitOpsPerSecond); static const ZStatCriticalPhase ZCriticalPhaseAllocationStall("Allocation Stall"); -ZSafePageRecycle::ZSafePageRecycle(ZPageAllocator* page_allocator) - : _page_allocator(page_allocator), - _unsafe_to_recycle() {} - -void ZSafePageRecycle::activate() { - _unsafe_to_recycle.activate(); +static void check_numa_mismatch(const ZVirtualMemory& vmem, uint32_t desired_id) { + if (ZNUMA::is_enabled()) { + // Check if memory ended up on desired NUMA node or not + const uint32_t actual_id = ZNUMA::memory_id(untype(ZOffset::address(vmem.start()))); + if (actual_id != desired_id) { + log_debug(gc, heap)("NUMA Mismatch: desired %d, actual %d", desired_id, actual_id); + } + } } -void ZSafePageRecycle::deactivate() { - auto delete_function = [&](ZPage* page) { - _page_allocator->safe_destroy_page(page); - }; +class ZMemoryAllocation : public CHeapObj { +private: + const size_t _size; + ZPartition* _partition; + ZVirtualMemory _satisfied_from_cache_vmem; + ZArray _partial_vmems; + int _num_harvested; + size_t _harvested; + size_t _increased_capacity; + size_t _committed_capacity; + bool _commit_failed; - _unsafe_to_recycle.deactivate_and_apply(delete_function); -} + explicit ZMemoryAllocation(const ZMemoryAllocation& other) + : ZMemoryAllocation(other._size) { + // Transfer the partition + set_partition(other._partition); -ZPage* ZSafePageRecycle::register_and_clone_if_activated(ZPage* page) { - if (!_unsafe_to_recycle.is_activated()) { - // The page has no concurrent readers. - // Recycle original page. - return page; + // Reserve space for the partial vmems + _partial_vmems.reserve(other._partial_vmems.length() + (other._satisfied_from_cache_vmem.is_null() ? 1 : 0)); + + // Transfer the claimed capacity + transfer_claimed_capacity(other); } - // The page could have concurrent readers. - // It would be unsafe to recycle this page at this point. + ZMemoryAllocation(const ZMemoryAllocation& a1, const ZMemoryAllocation& a2) + : ZMemoryAllocation(a1._size + a2._size) { + // Transfer the partition + assert(a1._partition == a2._partition, "only merge with same partition"); + set_partition(a1._partition); - // As soon as the page is added to _unsafe_to_recycle, it - // must not be used again. Hence, the extra double-checked - // locking to only clone the page if it is believed to be - // unsafe to recycle the page. - ZPage* const cloned_page = page->clone_limited(); - if (!_unsafe_to_recycle.add_if_activated(page)) { - // It became safe to recycle the page after the is_activated check - delete cloned_page; - return page; + // Reserve space for the partial vmems + const int num_vmems_a1 = a1._partial_vmems.length() + (a1._satisfied_from_cache_vmem.is_null() ? 1 : 0); + const int num_vmems_a2 = a2._partial_vmems.length() + (a2._satisfied_from_cache_vmem.is_null() ? 1 : 0); + _partial_vmems.reserve(num_vmems_a1 + num_vmems_a2); + + // Transfer the claimed capacity + transfer_claimed_capacity(a1); + transfer_claimed_capacity(a2); } - // The original page has been registered to be deleted by another thread. - // Recycle the cloned page. - return cloned_page; -} + void transfer_claimed_capacity(const ZMemoryAllocation& from) { + assert(from._committed_capacity == 0, "Unexpected value %zu", from._committed_capacity); + assert(!from._commit_failed, "Unexpected value"); + + // Transfer increased capacity + _increased_capacity += from._increased_capacity; + + // Transfer satisfying vmem or partial mappings + const ZVirtualMemory vmem = from._satisfied_from_cache_vmem; + if (!vmem.is_null()) { + assert(_partial_vmems.is_empty(), "Must either have result or partial vmems"); + _partial_vmems.push(vmem); + _num_harvested += 1; + _harvested += vmem.size(); + } else { + _partial_vmems.appendAll(&from._partial_vmems); + _num_harvested += from._num_harvested; + _harvested += from._harvested; + } + } + +public: + explicit ZMemoryAllocation(size_t size) + : _size(size), + _partition(nullptr), + _satisfied_from_cache_vmem(), + _partial_vmems(0), + _num_harvested(0), + _harvested(0), + _increased_capacity(0), + _committed_capacity(0), + _commit_failed(false) {} + + void reset_for_retry() { + assert(_satisfied_from_cache_vmem.is_null(), "Incompatible with reset"); + + _partition = nullptr; + _partial_vmems.clear(); + _num_harvested = 0; + _harvested = 0; + _increased_capacity = 0; + _committed_capacity = 0; + _commit_failed = false; + } + + size_t size() const { + return _size; + } + + ZPartition& partition() const { + assert(_partition != nullptr, "Should have been initialized"); + return *_partition; + } + + void set_partition(ZPartition* partition) { + assert(_partition == nullptr, "Should be initialized only once"); + _partition = partition; + } + + ZVirtualMemory satisfied_from_cache_vmem() const { + return _satisfied_from_cache_vmem; + } + + void set_satisfied_from_cache_vmem(ZVirtualMemory vmem) { + precond(_satisfied_from_cache_vmem.is_null()); + precond(vmem.size() == size()); + precond(_partial_vmems.is_empty()); + + _satisfied_from_cache_vmem = vmem; + } + + ZArray* partial_vmems() { + return &_partial_vmems; + } + + const ZArray* partial_vmems() const { + return &_partial_vmems; + } + + int num_harvested() const { + return _num_harvested; + } + + size_t harvested() const { + return _harvested; + } + + void set_harvested(int num_harvested, size_t harvested) { + _num_harvested = num_harvested; + _harvested = harvested; + } + + size_t increased_capacity() const { + return _increased_capacity; + } + + void set_increased_capacity(size_t increased_capacity) { + _increased_capacity = increased_capacity; + } + + size_t committed_capacity() const { + return _committed_capacity; + } + + void set_committed_capacity(size_t committed_capacity) { + assert(_committed_capacity == 0, "Should only commit once"); + _committed_capacity = committed_capacity; + _commit_failed = committed_capacity != _increased_capacity; + } + + bool commit_failed() const { + return _commit_failed; + } + + static void destroy(ZMemoryAllocation* allocation) { + delete allocation; + } + + static void merge(const ZMemoryAllocation& allocation, ZMemoryAllocation** merge_location) { + ZMemoryAllocation* const other_allocation = *merge_location; + if (other_allocation == nullptr) { + // First allocation, allocate new partition + *merge_location = new ZMemoryAllocation(allocation); + } else { + // Merge with other allocation + *merge_location = new ZMemoryAllocation(allocation, *other_allocation); + + // Delete old allocation + delete other_allocation; + } + } +}; + +class ZSinglePartitionAllocation { +private: + ZMemoryAllocation _allocation; + +public: + ZSinglePartitionAllocation(size_t size) + : _allocation(size) {} + + size_t size() const { + return _allocation.size(); + } + + ZMemoryAllocation* allocation() { + return &_allocation; + } + + const ZMemoryAllocation* allocation() const { + return &_allocation; + } + + void reset_for_retry() { + _allocation.reset_for_retry(); + } +}; + +class ZMultiPartitionAllocation : public StackObj { +private: + const size_t _size; + ZArray _allocations; + +public: + ZMultiPartitionAllocation(size_t size) + : _size(size), + _allocations(0) {} + + ~ZMultiPartitionAllocation() { + for (ZMemoryAllocation* allocation : _allocations) { + ZMemoryAllocation::destroy(allocation); + } + } + + void initialize() { + precond(_allocations.is_empty()); + + // The multi-partition allocation creates at most one allocation per partition. + const int length = (int)ZNUMA::count(); + + _allocations.reserve(length); + } + + void reset_for_retry() { + for (ZMemoryAllocation* allocation : _allocations) { + ZMemoryAllocation::destroy(allocation); + } + _allocations.clear(); + } + + size_t size() const { + return _size; + } + + ZArray* allocations() { + return &_allocations; + } + + const ZArray* allocations() const { + return &_allocations; + } + + void register_allocation(const ZMemoryAllocation& allocation) { + ZMemoryAllocation** const slot = allocation_slot(allocation.partition().numa_id()); + + ZMemoryAllocation::merge(allocation, slot); + } + + ZMemoryAllocation** allocation_slot(uint32_t numa_id) { + // Try to find an existing allocation for numa_id + for (int i = 0; i < _allocations.length(); ++i) { + ZMemoryAllocation** const slot_addr = _allocations.adr_at(i); + ZMemoryAllocation* const allocation = *slot_addr; + if (allocation->partition().numa_id() == numa_id) { + // Found an existing slot + return slot_addr; + } + } + + // Push an empty slot for the numa_id + _allocations.push(nullptr); + + // Return the address of the slot + return &_allocations.last(); + } + + int sum_num_harvested_vmems() const { + int total = 0; + + for (const ZMemoryAllocation* allocation : _allocations) { + total += allocation->num_harvested(); + } + + return total; + } + + size_t sum_harvested() const { + size_t total = 0; + + for (const ZMemoryAllocation* allocation : _allocations) { + total += allocation->harvested(); + } + + return total; + } + + size_t sum_committed_increased_capacity() const { + size_t total = 0; + + for (const ZMemoryAllocation* allocation : _allocations) { + total += allocation->committed_capacity(); + } + + return total; + } +}; + +struct ZPageAllocationStats { + int _num_harvested_vmems; + size_t _total_harvested; + size_t _total_committed_capacity; + + ZPageAllocationStats(int num_harvested_vmems, size_t total_harvested, size_t total_committed_capacity) + : _num_harvested_vmems(num_harvested_vmems), + _total_harvested(total_harvested), + _total_committed_capacity(total_committed_capacity) {} +}; class ZPageAllocation : public StackObj { friend class ZList; @@ -104,27 +396,39 @@ private: const ZPageType _type; const size_t _size; const ZAllocationFlags _flags; + const ZPageAge _age; + const Ticks _start_timestamp; const uint32_t _young_seqnum; const uint32_t _old_seqnum; - size_t _flushed; - size_t _committed; - ZList _pages; + const uint32_t _initiating_numa_id; + bool _is_multi_partition; + ZSinglePartitionAllocation _single_partition_allocation; + ZMultiPartitionAllocation _multi_partition_allocation; ZListNode _node; ZFuture _stall_result; public: - ZPageAllocation(ZPageType type, size_t size, ZAllocationFlags flags) + ZPageAllocation(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age) : _type(type), _size(size), _flags(flags), + _age(age), + _start_timestamp(Ticks::now()), _young_seqnum(ZGeneration::young()->seqnum()), _old_seqnum(ZGeneration::old()->seqnum()), - _flushed(0), - _committed(0), - _pages(), + _initiating_numa_id(ZNUMA::id()), + _is_multi_partition(false), + _single_partition_allocation(size), + _multi_partition_allocation(size), _node(), _stall_result() {} + void reset_for_retry() { + _is_multi_partition = false; + _single_partition_allocation.reset_for_retry(); + _multi_partition_allocation.reset_for_retry(); + } + ZPageType type() const { return _type; } @@ -137,6 +441,10 @@ public: return _flags; } + ZPageAge age() const { + return _age; + } + uint32_t young_seqnum() const { return _young_seqnum; } @@ -145,30 +453,56 @@ public: return _old_seqnum; } - size_t flushed() const { - return _flushed; + uint32_t initiating_numa_id() const { + return _initiating_numa_id; } - void set_flushed(size_t flushed) { - _flushed = flushed; + bool is_multi_partition() const { + return _is_multi_partition; } - size_t committed() const { - return _committed; + void initiate_multi_partition_allocation() { + assert(!_is_multi_partition, "Reinitialization?"); + _is_multi_partition = true; + _multi_partition_allocation.initialize(); } - void set_committed(size_t committed) { - _committed = committed; + ZMultiPartitionAllocation* multi_partition_allocation() { + assert(_is_multi_partition, "multi-partition allocation must be initiated"); + + return &_multi_partition_allocation; + } + + const ZMultiPartitionAllocation* multi_partition_allocation() const { + assert(_is_multi_partition, "multi-partition allocation must be initiated"); + + return &_multi_partition_allocation; + } + + ZSinglePartitionAllocation* single_partition_allocation() { + assert(!_is_multi_partition, "multi-partition allocation must not have been initiated"); + + return &_single_partition_allocation; + } + + const ZSinglePartitionAllocation* single_partition_allocation() const { + assert(!_is_multi_partition, "multi-partition allocation must not have been initiated"); + + return &_single_partition_allocation; + } + + ZVirtualMemory satisfied_from_cache_vmem() const { + precond(!_is_multi_partition); + + const ZMemoryAllocation* const allocation = _single_partition_allocation.allocation(); + + return allocation->satisfied_from_cache_vmem(); } bool wait() { return _stall_result.get(); } - ZList* pages() { - return &_pages; - } - void satisfy(bool result) { _stall_result.set(result); } @@ -176,6 +510,741 @@ public: bool gc_relocation() const { return _flags.gc_relocation(); } + + ZPageAllocationStats stats() const { + if (_is_multi_partition) { + return ZPageAllocationStats( + _multi_partition_allocation.sum_num_harvested_vmems(), + _multi_partition_allocation.sum_harvested(), + _multi_partition_allocation.sum_committed_increased_capacity()); + } else { + return ZPageAllocationStats( + _single_partition_allocation.allocation()->num_harvested(), + _single_partition_allocation.allocation()->harvested(), + _single_partition_allocation.allocation()->committed_capacity()); + } + } + + void send_event(bool successful) { + EventZPageAllocation event; + + Ticks end_timestamp = Ticks::now(); + const ZPageAllocationStats st = stats(); + + event.commit(_start_timestamp, + end_timestamp, + (u8)_type, + _size, + st._total_harvested, + st._total_committed_capacity, + (unsigned)st._num_harvested_vmems, + _is_multi_partition, + successful, + _flags.non_blocking()); + } +}; + +const ZVirtualMemoryManager& ZPartition::virtual_memory_manager() const { + return _page_allocator->_virtual; +} + +ZVirtualMemoryManager& ZPartition::virtual_memory_manager() { + return _page_allocator->_virtual; +} + +const ZPhysicalMemoryManager& ZPartition::physical_memory_manager() const { + return _page_allocator->_physical; +} + +ZPhysicalMemoryManager& ZPartition::physical_memory_manager() { + return _page_allocator->_physical; +} + +#ifdef ASSERT + +void ZPartition::verify_virtual_memory_multi_partition_association(const ZVirtualMemory& vmem) const { + const ZVirtualMemoryManager& manager = virtual_memory_manager(); + + assert(manager.is_in_multi_partition(vmem), + "Virtual memory must be associated with the extra space " + "actual: %u", virtual_memory_manager().lookup_partition_id(vmem)); +} + +void ZPartition::verify_virtual_memory_association(const ZVirtualMemory& vmem, bool check_multi_partition) const { + const ZVirtualMemoryManager& manager = virtual_memory_manager(); + + if (check_multi_partition && manager.is_in_multi_partition(vmem)) { + // We allow claim/free/commit physical operation in multi-partition allocations + // to use virtual memory associated with the extra space. + return; + } + + const uint32_t vmem_numa_id = virtual_memory_manager().lookup_partition_id(vmem); + assert(_numa_id == vmem_numa_id, + "Virtual memory must be associated with the current partition " + "expected: %u, actual: %u", _numa_id, vmem_numa_id); +} + +void ZPartition::verify_virtual_memory_association(const ZArray* vmems) const { + for (const ZVirtualMemory& vmem : *vmems) { + verify_virtual_memory_association(vmem); + } +} + +void ZPartition::verify_memory_allocation_association(const ZMemoryAllocation* allocation) const { + assert(this == &allocation->partition(), + "Memory allocation must be associated with the current partition " + "expected: %u, actual: %u", _numa_id, allocation->partition().numa_id()); +} + +#endif // ASSERT + +ZPartition::ZPartition(uint32_t numa_id, ZPageAllocator* page_allocator) + : _page_allocator(page_allocator), + _cache(), + _uncommitter(numa_id, this), + _min_capacity(ZNUMA::calculate_share(numa_id, page_allocator->min_capacity())), + _max_capacity(ZNUMA::calculate_share(numa_id, page_allocator->max_capacity())), + _current_max_capacity(_max_capacity), + _capacity(0), + _claimed(0), + _used(0), + _last_commit(0.0), + _last_uncommit(0.0), + _to_uncommit(0), + _numa_id(numa_id) {} + +uint32_t ZPartition::numa_id() const { + return _numa_id; +} + +size_t ZPartition::available() const { + return _current_max_capacity - _used - _claimed; +} + +size_t ZPartition::increase_capacity(size_t size) { + const size_t increased = MIN2(size, _current_max_capacity - _capacity); + + if (increased > 0) { + // Update atomically since we have concurrent readers + Atomic::add(&_capacity, increased); + + _last_commit = os::elapsedTime(); + _last_uncommit = 0; + _cache.reset_min(); + } + + return increased; +} + +void ZPartition::decrease_capacity(size_t size, bool set_max_capacity) { + // Update capacity atomically since we have concurrent readers + Atomic::sub(&_capacity, size); + + // Adjust current max capacity to avoid further attempts to increase capacity + if (set_max_capacity) { + const size_t current_max_capacity_before = _current_max_capacity; + Atomic::store(&_current_max_capacity, _capacity); + + log_debug_p(gc)("Forced to lower max partition (%u) capacity from " + "%zuM(%.0f%%) to %zuM(%.0f%%)", + _numa_id, + current_max_capacity_before / M, percent_of(current_max_capacity_before, _max_capacity), + _current_max_capacity / M, percent_of(_current_max_capacity, _max_capacity)); + } +} + +void ZPartition::increase_used(size_t size) { + // The partition usage tracking is only read and updated under the page + // allocator lock. Usage statistics for generations and GC cycles are + // collected on the ZPageAllocator level. + _used += size; +} + +void ZPartition::decrease_used(size_t size) { + // The partition usage tracking is only read and updated under the page + // allocator lock. Usage statistics for generations and GC cycles are + // collected on the ZPageAllocator level. + _used -= size; +} + +void ZPartition::free_memory(const ZVirtualMemory& vmem) { + const size_t size = vmem.size(); + + // Cache the vmem + _cache.insert(vmem); + + // Update accounting + decrease_used(size); +} + +void ZPartition::claim_from_cache_or_increase_capacity(ZMemoryAllocation* allocation) { + const size_t size = allocation->size(); + ZArray* const out = allocation->partial_vmems(); + + // We are guaranteed to succeed the claiming of capacity here + assert(available() >= size, "Must be"); + + // Associate the allocation with this partition. + allocation->set_partition(this); + + // Try to allocate one contiguous vmem + ZVirtualMemory vmem = _cache.remove_contiguous(size); + if (!vmem.is_null()) { + // Found a satisfying vmem in the cache + allocation->set_satisfied_from_cache_vmem(vmem); + + // Done + return; + } + + // Try increase capacity + const size_t increased_capacity = increase_capacity(size); + + allocation->set_increased_capacity(increased_capacity); + + if (increased_capacity == size) { + // Capacity increase covered the entire request, done. + return; + } + + // Could not increase capacity enough to satisfy the allocation completely. + // Try removing multiple vmems from the mapped cache. + const size_t remaining = size - increased_capacity; + const size_t harvested = _cache.remove_discontiguous(remaining, out); + const int num_harvested = out->length(); + + allocation->set_harvested(num_harvested, harvested); + + assert(harvested + increased_capacity == size, + "Mismatch harvested: %zu increased_capacity: %zu size: %zu", + harvested, increased_capacity, size); + + return; +} + +bool ZPartition::claim_capacity(ZMemoryAllocation* allocation) { + const size_t size = allocation->size(); + + if (available() < size) { + // Out of memory + return false; + } + + claim_from_cache_or_increase_capacity(allocation); + + // Updated used statistics + increase_used(size); + + // Success + return true; +} + +size_t ZPartition::uncommit(uint64_t* timeout) { + ZArray flushed_vmems; + size_t flushed = 0; + + { + // We need to join the suspendible thread set while manipulating capacity + // and used, to make sure GC safepoints will have a consistent view. + SuspendibleThreadSetJoiner sts_joiner; + ZLocker locker(&_page_allocator->_lock); + + const double now = os::elapsedTime(); + const double time_since_last_commit = std::floor(now - _last_commit); + const double time_since_last_uncommit = std::floor(now - _last_uncommit); + + if (time_since_last_commit < double(ZUncommitDelay)) { + // We have committed within the delay, stop uncommitting. + *timeout = uint64_t(double(ZUncommitDelay) - time_since_last_commit); + return 0; + } + + // We flush out and uncommit chunks at a time (~0.8% of the max capacity, + // but at least one granule and at most 256M), in case demand for memory + // increases while we are uncommitting. + const size_t limit_upper_bound = MAX2(ZGranuleSize, align_down(256 * M / ZNUMA::count(), ZGranuleSize)); + const size_t limit = MIN2(align_up(_current_max_capacity >> 7, ZGranuleSize), limit_upper_bound); + + if (limit == 0) { + // This may occur if the current max capacity for this partition is 0 + + // Set timeout to ZUncommitDelay + *timeout = ZUncommitDelay; + return 0; + } + + if (time_since_last_uncommit < double(ZUncommitDelay)) { + // We are in the uncommit phase + const size_t num_uncommits_left = _to_uncommit / limit; + const double time_left = double(ZUncommitDelay) - time_since_last_uncommit; + if (time_left < *timeout * num_uncommits_left) { + // Running out of time, speed up. + uint64_t new_timeout = uint64_t(std::floor(time_left / double(num_uncommits_left + 1))); + *timeout = new_timeout; + } + } else { + // We are about to start uncommitting + _to_uncommit = _cache.reset_min(); + _last_uncommit = now; + + const size_t split = _to_uncommit / limit + 1; + uint64_t new_timeout = ZUncommitDelay / split; + *timeout = new_timeout; + } + + // Never uncommit below min capacity. + const size_t retain = MAX2(_used, _min_capacity); + const size_t release = _capacity - retain; + const size_t flush = MIN3(release, limit, _to_uncommit); + + if (flush == 0) { + // Nothing to flush + return 0; + } + + // Flush memory from the mapped cache to uncommit + flushed = _cache.remove_from_min(flush, &flushed_vmems); + if (flushed == 0) { + // Nothing flushed + return 0; + } + + // Record flushed memory as claimed and how much we've flushed for this partition + Atomic::add(&_claimed, flushed); + _to_uncommit -= flushed; + } + + // Unmap and uncommit flushed memory + for (const ZVirtualMemory vmem : flushed_vmems) { + unmap_virtual(vmem); + uncommit_physical(vmem); + free_physical(vmem); + free_virtual(vmem); + } + + { + SuspendibleThreadSetJoiner sts_joiner; + ZLocker locker(&_page_allocator->_lock); + + // Adjust claimed and capacity to reflect the uncommit + Atomic::sub(&_claimed, flushed); + decrease_capacity(flushed, false /* set_max_capacity */); + } + + return flushed; +} + +void ZPartition::sort_segments_physical(const ZVirtualMemory& vmem) { + verify_virtual_memory_association(vmem, true /* check_multi_partition */); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Sort physical segments + manager.sort_segments_physical(vmem); +} + +void ZPartition::claim_physical(const ZVirtualMemory& vmem) { + verify_virtual_memory_association(vmem, true /* check_multi_partition */); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Alloc physical memory + manager.alloc(vmem, _numa_id); +} + +void ZPartition::free_physical(const ZVirtualMemory& vmem) { + verify_virtual_memory_association(vmem, true /* check_multi_partition */); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Free physical memory + manager.free(vmem, _numa_id); +} + +size_t ZPartition::commit_physical(const ZVirtualMemory& vmem) { + verify_virtual_memory_association(vmem, true /* check_multi_partition */); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Commit physical memory + return manager.commit(vmem, _numa_id); +} + +size_t ZPartition::uncommit_physical(const ZVirtualMemory& vmem) { + assert(ZUncommit, "should not uncommit when uncommit is disabled"); + verify_virtual_memory_association(vmem); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Uncommit physical memory + return manager.uncommit(vmem); +} + +void ZPartition::map_virtual(const ZVirtualMemory& vmem) { + verify_virtual_memory_association(vmem); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Map virtual memory to physical memory + manager.map(vmem, _numa_id); +} + +void ZPartition::unmap_virtual(const ZVirtualMemory& vmem) { + verify_virtual_memory_association(vmem); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Unmap virtual memory from physical memory + manager.unmap(vmem); +} + +void ZPartition::map_virtual_from_multi_partition(const ZVirtualMemory& vmem) { + verify_virtual_memory_multi_partition_association(vmem); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Sort physical segments + manager.sort_segments_physical(vmem); + + // Map virtual memory to physical memory + manager.map(vmem, _numa_id); +} + +void ZPartition::unmap_virtual_from_multi_partition(const ZVirtualMemory& vmem) { + verify_virtual_memory_multi_partition_association(vmem); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Unmap virtual memory from physical memory + manager.unmap(vmem); +} + +ZVirtualMemory ZPartition::claim_virtual(size_t size) { + ZVirtualMemoryManager& manager = virtual_memory_manager(); + + return manager.remove_from_low(size, _numa_id); +} + +size_t ZPartition::claim_virtual(size_t size, ZArray* vmems_out) { + ZVirtualMemoryManager& manager = virtual_memory_manager(); + + return manager.remove_from_low_many_at_most(size, _numa_id, vmems_out); +} + +void ZPartition::free_virtual(const ZVirtualMemory& vmem) { + verify_virtual_memory_association(vmem); + + ZVirtualMemoryManager& manager = virtual_memory_manager(); + + // Free virtual memory + manager.insert(vmem, _numa_id); +} + +void ZPartition::free_and_claim_virtual_from_low_many(const ZVirtualMemory& vmem, ZArray* vmems_out) { + verify_virtual_memory_association(vmem); + + ZVirtualMemoryManager& manager = virtual_memory_manager(); + + // Shuffle virtual memory + manager.insert_and_remove_from_low_many(vmem, _numa_id, vmems_out); +} + +ZVirtualMemory ZPartition::free_and_claim_virtual_from_low_exact_or_many(size_t size, ZArray* vmems_in_out) { + verify_virtual_memory_association(vmems_in_out); + + ZVirtualMemoryManager& manager = virtual_memory_manager(); + + // Shuffle virtual memory + return manager.insert_and_remove_from_low_exact_or_many(size, _numa_id, vmems_in_out); +} + +static void pretouch_memory(zoffset start, size_t size) { + // At this point we know that we have a valid zoffset / zaddress. + const zaddress zaddr = ZOffset::address(start); + const uintptr_t addr = untype(zaddr); + const size_t page_size = ZLargePages::is_explicit() ? ZGranuleSize : os::vm_page_size(); + os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); +} + +class ZPreTouchTask : public ZTask { +private: + volatile uintptr_t _current; + const uintptr_t _end; + +public: + ZPreTouchTask(zoffset start, zoffset_end end) + : ZTask("ZPreTouchTask"), + _current(untype(start)), + _end(untype(end)) {} + + virtual void work() { + const size_t size = ZGranuleSize; + + for (;;) { + // Claim an offset for this thread + const uintptr_t claimed = Atomic::fetch_then_add(&_current, size); + if (claimed >= _end) { + // Done + break; + } + + // At this point we know that we have a valid zoffset / zaddress. + const zoffset offset = to_zoffset(claimed); + + // Pre-touch the granule + pretouch_memory(offset, size); + } + } +}; + +bool ZPartition::prime(ZWorkers* workers, size_t size) { + if (size == 0) { + return true; + } + + // Claim virtual memory + const ZVirtualMemory vmem = claim_virtual(size); + + // Increase capacity + increase_capacity(size); + + // Claim the backing physical memory + claim_physical(vmem); + + // Commit the claimed physical memory + const size_t committed = commit_physical(vmem); + + if (committed != vmem.size()) { + // This is a failure state. We do not cleanup the maybe partially committed memory. + return false; + } + + map_virtual(vmem); + + check_numa_mismatch(vmem, _numa_id); + + if (AlwaysPreTouch) { + // Pre-touch memory + ZPreTouchTask task(vmem.start(), vmem.end()); + workers->run_all(&task); + } + + // We don't have to take a lock here as no other threads will access the cache + // until we're finished + _cache.insert(vmem); + + return true; +} + +ZVirtualMemory ZPartition::prepare_harvested_and_claim_virtual(ZMemoryAllocation* allocation) { + verify_memory_allocation_association(allocation); + + // Unmap virtual memory + for (const ZVirtualMemory vmem : *allocation->partial_vmems()) { + unmap_virtual(vmem); + } + + const size_t harvested = allocation->harvested(); + const int granule_count = (int)(harvested >> ZGranuleSizeShift); + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Stash segments + ZArray stash(granule_count); + manager.stash_segments(*allocation->partial_vmems(), &stash); + + // Shuffle virtual memory. We attempt to allocate enough memory to cover the + // entire allocation size, not just for the harvested memory. + const ZVirtualMemory result = free_and_claim_virtual_from_low_exact_or_many(allocation->size(), allocation->partial_vmems()); + + // Restore segments + if (!result.is_null()) { + // Got exact match. Restore stashed physical segments for the harvested part. + manager.restore_segments(result.first_part(harvested), stash); + } else { + // Got many partial vmems + manager.restore_segments(*allocation->partial_vmems(), stash); + } + + if (result.is_null()) { + // Before returning harvested memory to the cache it must be mapped. + for (const ZVirtualMemory vmem : *allocation->partial_vmems()) { + map_virtual(vmem); + } + } + + return result; +} + +void ZPartition::copy_physical_segments_to_partition(const ZVirtualMemory& at, const ZVirtualMemory& from) { + verify_virtual_memory_association(at); + verify_virtual_memory_association(from, true /* check_multi_partition */); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + // Copy segments + manager.copy_physical_segments(at, from); +} + +void ZPartition::copy_physical_segments_from_partition(const ZVirtualMemory& at, const ZVirtualMemory& to) { + verify_virtual_memory_association(at); + verify_virtual_memory_association(to, true /* check_multi_partition */); + + ZPhysicalMemoryManager& manager = physical_memory_manager(); + + + // Copy segments + manager.copy_physical_segments(to, at); +} + +void ZPartition::commit_increased_capacity(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem) { + assert(allocation->increased_capacity() > 0, "Nothing to commit"); + + const size_t already_committed = allocation->harvested(); + + const ZVirtualMemory already_committed_vmem = vmem.first_part(already_committed); + const ZVirtualMemory to_be_committed_vmem = vmem.last_part(already_committed); + + // Try to commit the uncommitted physical memory + const size_t committed = commit_physical(to_be_committed_vmem); + + // Keep track of the committed amount + allocation->set_committed_capacity(committed); +} + +void ZPartition::map_memory(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem) { + sort_segments_physical(vmem); + map_virtual(vmem); + + check_numa_mismatch(vmem, allocation->partition().numa_id()); +} + +void ZPartition::free_memory_alloc_failed(ZMemoryAllocation* allocation) { + verify_memory_allocation_association(allocation); + + // Only decrease the overall used and not the generation used, + // since the allocation failed and generation used wasn't bumped. + decrease_used(allocation->size()); + + size_t freed = 0; + + // Free mapped memory + for (const ZVirtualMemory vmem : *allocation->partial_vmems()) { + freed += vmem.size(); + _cache.insert(vmem); + } + assert(allocation->harvested() + allocation->committed_capacity() == freed, "must have freed all"); + + // Adjust capacity to reflect the failed capacity increase + const size_t remaining = allocation->size() - freed; + if (remaining > 0) { + const bool set_max_capacity = allocation->commit_failed(); + decrease_capacity(remaining, set_max_capacity); + } +} + +void ZPartition::threads_do(ThreadClosure* tc) const { + tc->do_thread(const_cast(&_uncommitter)); +} + +void ZPartition::print_on(outputStream* st) const { + st->print("Partition %u", _numa_id); + st->fill_to(17); + st->print_cr("used %zuM, capacity %zuM, max capacity %zuM", + _used / M, _capacity / M, _max_capacity / M); + + streamIndentor indentor(st, 1); + print_cache_on(st); +} + +void ZPartition::print_cache_on(outputStream* st) const { + _cache.print_on(st); +} + +void ZPartition::print_extended_on_error(outputStream* st) const { + st->print_cr("Partition %u", _numa_id); + + streamIndentor indentor(st, 1); + + _cache.print_extended_on(st); +} + +class ZMultiPartitionTracker : CHeapObj { +private: + struct Element { + ZVirtualMemory _vmem; + ZPartition* _partition; + }; + + ZArray _map; + + ZMultiPartitionTracker(int capacity) + : _map(capacity) {} + + const ZArray* map() const { + return &_map; + } + + ZArray* map() { + return &_map; + } + +public: + void prepare_memory_for_free(const ZVirtualMemory& vmem, ZArray* vmems_out) const { + // Remap memory back to original partition + for (const Element partial_allocation : *map()) { + ZVirtualMemory remaining_vmem = partial_allocation._vmem; + ZPartition& partition = *partial_allocation._partition; + + const size_t size = remaining_vmem.size(); + + // Allocate new virtual address ranges + const int start_index = vmems_out->length(); + const size_t claimed_virtual = partition.claim_virtual(remaining_vmem.size(), vmems_out); + + // We are holding memory associated with this partition, and we do not + // overcommit virtual memory claiming. So virtual memory must always + // be available. + assert(claimed_virtual == size, "must succeed"); + + // Remap to the newly allocated virtual address ranges + for (const ZVirtualMemory& to_vmem : vmems_out->slice_back(start_index)) { + const ZVirtualMemory from_vmem = remaining_vmem.shrink_from_front(to_vmem.size()); + + // Copy physical segments + partition.copy_physical_segments_to_partition(to_vmem, from_vmem); + + // Unmap from_vmem + partition.unmap_virtual_from_multi_partition(from_vmem); + + // Map to_vmem + partition.map_virtual(to_vmem); + } + assert(remaining_vmem.size() == 0, "must have mapped all claimed virtual memory"); + } + } + + static void destroy(const ZMultiPartitionTracker* tracker) { + delete tracker; + } + + static ZMultiPartitionTracker* create(const ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { + const ZArray* const partial_allocations = multi_partition_allocation->allocations(); + + ZMultiPartitionTracker* const tracker = new ZMultiPartitionTracker(partial_allocations->length()); + + ZVirtualMemory remaining = vmem; + + // Each partial allocation is mapped to the virtual memory in order + for (ZMemoryAllocation* partial_allocation : *partial_allocations) { + // Track each separate vmem's partition + const ZVirtualMemory partial_vmem = remaining.shrink_from_front(partial_allocation->size()); + ZPartition* const partition = &partial_allocation->partition(); + tracker->map()->push({partial_vmem, partition}); + } + + return tracker; + } }; ZPageAllocator::ZPageAllocator(size_t min_capacity, @@ -183,23 +1252,16 @@ ZPageAllocator::ZPageAllocator(size_t min_capacity, size_t soft_max_capacity, size_t max_capacity) : _lock(), - _cache(), _virtual(max_capacity), _physical(max_capacity), _min_capacity(min_capacity), - _initial_capacity(initial_capacity), _max_capacity(max_capacity), - _current_max_capacity(max_capacity), - _capacity(0), - _claimed(0), _used(0), - _used_generations{0, 0}, - _collection_stats{{0, 0}, {0, 0}}, + _used_generations{0,0}, + _collection_stats{{0, 0},{0, 0}}, + _partitions(ZValueIdTagType{}, this), _stalled(), - _unmapper(new ZUnmapper(this)), - _uncommitter(new ZUncommitter(this)), _safe_destroy(), - _safe_recycle(this), _initialized(false) { if (!_virtual.is_initialized() || !_physical.is_initialized()) { @@ -231,69 +1293,20 @@ bool ZPageAllocator::is_initialized() const { return _initialized; } -class ZPreTouchTask : public ZTask { -private: - volatile uintptr_t _current; - const uintptr_t _end; +bool ZPageAllocator::prime_cache(ZWorkers* workers, size_t size) { + ZPartitionIterator iter = partition_iterator(); + for (ZPartition* partition; iter.next(&partition);) { + const uint32_t numa_id = partition->numa_id(); + const size_t to_prime = ZNUMA::calculate_share(numa_id, size); - static void pretouch(zaddress zaddr, size_t size) { - const uintptr_t addr = untype(zaddr); - const size_t page_size = ZLargePages::is_explicit() ? ZGranuleSize : os::vm_page_size(); - os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); - } - -public: - ZPreTouchTask(zoffset start, zoffset_end end) - : ZTask("ZPreTouchTask"), - _current(untype(start)), - _end(untype(end)) {} - - virtual void work() { - const size_t size = ZGranuleSize; - - for (;;) { - // Claim an offset for this thread - const uintptr_t claimed = Atomic::fetch_then_add(&_current, size); - if (claimed >= _end) { - // Done - break; - } - - // At this point we know that we have a valid zoffset / zaddress. - const zoffset offset = to_zoffset(claimed); - const zaddress addr = ZOffset::address(offset); - - // Pre-touch the granule - pretouch(addr, size); + if (!partition->prime(workers, to_prime)) { + return false; } } -}; - -bool ZPageAllocator::prime_cache(ZWorkers* workers, size_t size) { - ZAllocationFlags flags; - flags.set_non_blocking(); - flags.set_low_address(); - - ZPage* const page = alloc_page(ZPageType::large, size, flags, ZPageAge::eden); - if (page == nullptr) { - return false; - } - - if (AlwaysPreTouch) { - // Pre-touch page - ZPreTouchTask task(page->start(), page->end()); - workers->run_all(&task); - } - - free_page(page, false /* allow_defragment */); return true; } -size_t ZPageAllocator::initial_capacity() const { - return _initial_capacity; -} - size_t ZPageAllocator::min_capacity() const { return _min_capacity; } @@ -303,14 +1316,31 @@ size_t ZPageAllocator::max_capacity() const { } size_t ZPageAllocator::soft_max_capacity() const { - // Note that SoftMaxHeapSize is a manageable flag - const size_t soft_max_capacity = Atomic::load(&SoftMaxHeapSize); - const size_t current_max_capacity = Atomic::load(&_current_max_capacity); - return MIN2(soft_max_capacity, current_max_capacity); + const size_t current_max_capacity = ZPageAllocator::current_max_capacity(); + const size_t soft_max_heapsize = Atomic::load(&SoftMaxHeapSize); + return MIN2(soft_max_heapsize, current_max_capacity); +} + +size_t ZPageAllocator::current_max_capacity() const { + size_t current_max_capacity = 0; + + ZPartitionConstIterator iter = partition_iterator(); + for (const ZPartition* partition; iter.next(&partition);) { + current_max_capacity += Atomic::load(&partition->_current_max_capacity); + } + + return current_max_capacity; } size_t ZPageAllocator::capacity() const { - return Atomic::load(&_capacity); + size_t capacity = 0; + + ZPartitionConstIterator iter = partition_iterator(); + for (const ZPartition* partition; iter.next(&partition);) { + capacity += Atomic::load(&partition->_capacity); + } + + return capacity; } size_t ZPageAllocator::used() const { @@ -322,19 +1352,27 @@ size_t ZPageAllocator::used_generation(ZGenerationId id) const { } size_t ZPageAllocator::unused() const { - const ssize_t capacity = (ssize_t)Atomic::load(&_capacity); - const ssize_t used = (ssize_t)Atomic::load(&_used); - const ssize_t claimed = (ssize_t)Atomic::load(&_claimed); + const ssize_t used = (ssize_t)ZPageAllocator::used(); + ssize_t capacity = 0; + ssize_t claimed = 0; + + ZPartitionConstIterator iter = partition_iterator(); + for (const ZPartition* partition; iter.next(&partition);) { + capacity += (ssize_t)Atomic::load(&partition->_capacity); + claimed += (ssize_t)Atomic::load(&partition->_claimed); + } + const ssize_t unused = capacity - used - claimed; return unused > 0 ? (size_t)unused : 0; } ZPageAllocatorStats ZPageAllocator::stats(ZGeneration* generation) const { ZLocker locker(&_lock); + return ZPageAllocatorStats(_min_capacity, _max_capacity, soft_max_capacity(), - _capacity, + capacity(), _used, _collection_stats[(int)generation->id()]._used_high, _collection_stats[(int)generation->id()]._used_low, @@ -347,211 +1385,47 @@ ZPageAllocatorStats ZPageAllocator::stats(ZGeneration* generation) const { void ZPageAllocator::reset_statistics(ZGenerationId id) { assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); - _collection_stats[(int)id]._used_high = _used; - _collection_stats[(int)id]._used_low = _used; -} +#ifdef ASSERT + { + // We may free without safepoint synchronization, take the lock to get + // consistent values. + ZLocker locker(&_lock); + size_t total_used = 0; -size_t ZPageAllocator::increase_capacity(size_t size) { - const size_t increased = MIN2(size, _current_max_capacity - _capacity); - - if (increased > 0) { - // Update atomically since we have concurrent readers - Atomic::add(&_capacity, increased); - - // Record time of last commit. When allocation, we prefer increasing - // the capacity over flushing the cache. That means there could be - // expired pages in the cache at this time. However, since we are - // increasing the capacity we are obviously in need of committed - // memory and should therefore not be uncommitting memory. - _cache.set_last_commit(); - } - - return increased; -} - -void ZPageAllocator::decrease_capacity(size_t size, bool set_max_capacity) { - // Update atomically since we have concurrent readers - Atomic::sub(&_capacity, size); - - if (set_max_capacity) { - // Adjust current max capacity to avoid further attempts to increase capacity - log_error_p(gc)("Forced to lower max Java heap size from " - "%zuM(%.0f%%) to %zuM(%.0f%%)", - _current_max_capacity / M, percent_of(_current_max_capacity, _max_capacity), - _capacity / M, percent_of(_capacity, _max_capacity)); - - // Update atomically since we have concurrent readers - Atomic::store(&_current_max_capacity, _capacity); - } -} - -void ZPageAllocator::increase_used(size_t size) { - // We don't track generation usage here because this page - // could be allocated by a thread that satisfies a stalling - // allocation. The stalled thread can wake up and potentially - // realize that the page alloc should be undone. If the alloc - // and the undo gets separated by a safepoint, the generation - // statistics could se a decreasing used value between mark - // start and mark end. - - // Update atomically since we have concurrent readers - const size_t used = Atomic::add(&_used, size); - - // Update used high - for (auto& stats : _collection_stats) { - if (used > stats._used_high) { - stats._used_high = used; + ZPartitionIterator iter(&_partitions); + for (ZPartition* partition; iter.next(&partition);) { + total_used += partition->_used; } - } -} -void ZPageAllocator::decrease_used(size_t size) { - // Update atomically since we have concurrent readers - const size_t used = Atomic::sub(&_used, size); - - // Update used low - for (auto& stats : _collection_stats) { - if (used < stats._used_low) { - stats._used_low = used; - } + assert(total_used == _used, "Must be consistent at safepoint %zu == %zu", total_used, _used); } +#endif + + // Read once, we may have concurrent writers. + const size_t used = Atomic::load(&_used); + + _collection_stats[(int)id]._used_high = used; + _collection_stats[(int)id]._used_low = used; } void ZPageAllocator::increase_used_generation(ZGenerationId id, size_t size) { - // Update atomically since we have concurrent readers + // Update atomically since we have concurrent readers and writers Atomic::add(&_used_generations[(int)id], size, memory_order_relaxed); } void ZPageAllocator::decrease_used_generation(ZGenerationId id, size_t size) { - // Update atomically since we have concurrent readers + // Update atomically since we have concurrent readers and writers Atomic::sub(&_used_generations[(int)id], size, memory_order_relaxed); } -void ZPageAllocator::promote_used(size_t size) { - decrease_used_generation(ZGenerationId::young, size); - increase_used_generation(ZGenerationId::old, size); -} +void ZPageAllocator::promote_used(const ZPage* from, const ZPage* to) { + assert(from->start() == to->start(), "pages start at same offset"); + assert(from->size() == to->size(), "pages are the same size"); + assert(from->age() != ZPageAge::old, "must be promotion"); + assert(to->age() == ZPageAge::old, "must be promotion"); -bool ZPageAllocator::commit_page(ZPage* page) { - // Commit physical memory - return _physical.commit(page->physical_memory()); -} - -void ZPageAllocator::uncommit_page(ZPage* page) { - if (!ZUncommit) { - return; - } - - // Uncommit physical memory - _physical.uncommit(page->physical_memory()); -} - -void ZPageAllocator::map_page(const ZPage* page) const { - // Map physical memory - _physical.map(page->start(), page->physical_memory()); -} - -void ZPageAllocator::unmap_page(const ZPage* page) const { - // Unmap physical memory - _physical.unmap(page->start(), page->size()); -} - -void ZPageAllocator::safe_destroy_page(ZPage* page) { - // Destroy page safely - _safe_destroy.schedule_delete(page); -} - -void ZPageAllocator::destroy_page(ZPage* page) { - // Free virtual memory - _virtual.free(page->virtual_memory()); - - // Free physical memory - _physical.free(page->physical_memory()); - - // Destroy page safely - safe_destroy_page(page); -} - -bool ZPageAllocator::should_defragment(const ZPage* page) const { - // A small page can end up at a high address (second half of the address space) - // if we've split a larger page or we have a constrained address space. To help - // fight address space fragmentation we remap such pages to a lower address, if - // a lower address is available. - return page->type() == ZPageType::small && - page->start() >= to_zoffset(_virtual.reserved() / 2) && - page->start() > _virtual.lowest_available_address(); -} - -ZPage* ZPageAllocator::defragment_page(ZPage* page) { - // Harvest the physical memory (which is committed) - ZPhysicalMemory pmem; - ZPhysicalMemory& old_pmem = page->physical_memory(); - pmem.add_segments(old_pmem); - old_pmem.remove_segments(); - - _unmapper->unmap_and_destroy_page(page); - - // Allocate new virtual memory at a low address - const ZVirtualMemory vmem = _virtual.alloc(pmem.size(), true /* force_low_address */); - - // Create the new page and map it - ZPage* new_page = new ZPage(ZPageType::small, vmem, pmem); - map_page(new_page); - - // Update statistics - ZStatInc(ZCounterDefragment); - - return new_page; -} - -bool ZPageAllocator::is_alloc_allowed(size_t size) const { - const size_t available = _current_max_capacity - _used - _claimed; - return available >= size; -} - -bool ZPageAllocator::alloc_page_common_inner(ZPageType type, size_t size, ZList* pages) { - if (!is_alloc_allowed(size)) { - // Out of memory - return false; - } - - // Try allocate from the page cache - ZPage* const page = _cache.alloc_page(type, size); - if (page != nullptr) { - // Success - pages->insert_last(page); - return true; - } - - // Try increase capacity - const size_t increased = increase_capacity(size); - if (increased < size) { - // Could not increase capacity enough to satisfy the allocation - // completely. Flush the page cache to satisfy the remainder. - const size_t remaining = size - increased; - _cache.flush_for_allocation(remaining, pages); - } - - // Success - return true; -} - -bool ZPageAllocator::alloc_page_common(ZPageAllocation* allocation) { - const ZPageType type = allocation->type(); - const size_t size = allocation->size(); - const ZAllocationFlags flags = allocation->flags(); - ZList* const pages = allocation->pages(); - - if (!alloc_page_common_inner(type, size, pages)) { - // Out of memory - return false; - } - - // Updated used statistics - increase_used(size); - - // Success - return true; + decrease_used_generation(ZGenerationId::young, to->size()); + increase_used_generation(ZGenerationId::old, to->size()); } static void check_out_of_memory_during_initialization() { @@ -560,6 +1434,42 @@ static void check_out_of_memory_during_initialization() { } } +ZPage* ZPageAllocator::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age) { + EventZPageAllocation event; + + ZPageAllocation allocation(type, size, flags, age); + + // Allocate the page + ZPage* const page = alloc_page_inner(&allocation); + if (page == nullptr) { + return nullptr; + } + + // Update allocation statistics. Exclude gc relocations to avoid + // artificial inflation of the allocation rate during relocation. + if (!flags.gc_relocation() && is_init_completed()) { + // Note that there are two allocation rate counters, which have + // different purposes and are sampled at different frequencies. + ZStatInc(ZCounterMutatorAllocationRate, size); + ZStatMutatorAllocRate::sample_allocation(size); + } + + const ZPageAllocationStats stats = allocation.stats(); + const int num_harvested_vmems = stats._num_harvested_vmems; + const size_t harvested = stats._total_harvested; + const size_t committed = stats._total_committed_capacity; + + if (harvested > 0) { + ZStatInc(ZCounterMappedCacheHarvest, harvested); + log_debug(gc, heap)("Mapped Cache Harvested: %zuM (%d)", harvested / M, num_harvested_vmems); + } + + // Send event for successful allocation + allocation.send_event(true /* successful */); + + return page; +} + bool ZPageAllocator::alloc_page_stall(ZPageAllocation* allocation) { ZStatTimer timer(ZCriticalPhaseAllocationStall); EventZAllocationStall event; @@ -591,16 +1501,70 @@ bool ZPageAllocator::alloc_page_stall(ZPageAllocation* allocation) { return result; } -bool ZPageAllocator::alloc_page_or_stall(ZPageAllocation* allocation) { +ZPage* ZPageAllocator::alloc_page_inner(ZPageAllocation* allocation) { +retry: + + // Claim the capacity needed for this allocation. + // + // The claimed capacity comes from memory already mapped in the cache, or + // from increasing the capacity. The increased capacity allows us to allocate + // physical memory from the physical memory manager later on. + // + // Note that this call might block in a safepoint if the non-blocking flag is + // not set. + if (!claim_capacity_or_stall(allocation)) { + // Out of memory + return nullptr; + } + + // If the entire claimed capacity came from claiming a single vmem from the + // mapped cache then the allocation has been satisfied and we are done. + const ZVirtualMemory cached_vmem = satisfied_from_cache_vmem(allocation); + if (!cached_vmem.is_null()) { + return create_page(allocation, cached_vmem); + } + + // We couldn't find a satisfying vmem in the cache, so we need to build one. + + // Claim virtual memory, either from remapping harvested vmems from the + // mapped cache or by claiming it straight from the virtual memory manager. + const ZVirtualMemory vmem = claim_virtual_memory(allocation); + if (vmem.is_null()) { + log_error(gc)("Out of address space"); + free_after_alloc_page_failed(allocation); + + // Crash in debug builds for more information + DEBUG_ONLY(fatal("Out of address space");) + + return nullptr; + } + + // Claim physical memory for the increased capacity. The previous claiming of + // capacity guarantees that this will succeed. + claim_physical_for_increased_capacity(allocation, vmem); + + // Commit memory for the increased capacity and map the entire vmem. + if (!commit_and_map(allocation, vmem)) { + free_after_alloc_page_failed(allocation); + goto retry; + } + + return create_page(allocation, vmem); +} + +bool ZPageAllocator::claim_capacity_or_stall(ZPageAllocation* allocation) { { ZLocker locker(&_lock); - if (alloc_page_common(allocation)) { - // Success + // Try to claim memory + if (claim_capacity(allocation)) { + // Keep track of usage + increase_used(allocation->size()); + return true; } - // Failed + // Failed to claim memory if (allocation->flags().non_blocking()) { // Don't stall return false; @@ -614,168 +1578,603 @@ bool ZPageAllocator::alloc_page_or_stall(ZPageAllocation* allocation) { return alloc_page_stall(allocation); } -ZPage* ZPageAllocator::alloc_page_create(ZPageAllocation* allocation) { - const size_t size = allocation->size(); +bool ZPageAllocator::claim_capacity(ZPageAllocation* allocation) { + const uint32_t start_numa_id = allocation->initiating_numa_id(); + const uint32_t start_partition = start_numa_id; + const uint32_t num_partitions = _partitions.count(); - // Allocate virtual memory. To make error handling a lot more straight - // forward, we allocate virtual memory before destroying flushed pages. - // Flushed pages are also unmapped and destroyed asynchronously, so we - // can't immediately reuse that part of the address space anyway. - const ZVirtualMemory vmem = _virtual.alloc(size, allocation->flags().low_address()); - if (vmem.is_null()) { - log_error(gc)("Out of address space"); - return nullptr; + // Round robin single-partition claiming + + for (uint32_t i = 0; i < num_partitions; ++i) { + const uint32_t partition_id = (start_partition + i) % num_partitions; + + if (claim_capacity_single_partition(allocation->single_partition_allocation(), partition_id)) { + return true; + } } - ZPhysicalMemory pmem; - size_t flushed = 0; - - // Harvest physical memory from flushed pages - ZListRemoveIterator iter(allocation->pages()); - for (ZPage* page; iter.next(&page);) { - flushed += page->size(); - - // Harvest flushed physical memory - ZPhysicalMemory& fmem = page->physical_memory(); - pmem.add_segments(fmem); - fmem.remove_segments(); - - // Unmap and destroy page - _unmapper->unmap_and_destroy_page(page); - } - - if (flushed > 0) { - allocation->set_flushed(flushed); - - // Update statistics - ZStatInc(ZCounterPageCacheFlush, flushed); - log_debug(gc, heap)("Page Cache Flushed: %zuM", flushed / M); - } - - // Allocate any remaining physical memory. Capacity and used has - // already been adjusted, we just need to fetch the memory, which - // is guaranteed to succeed. - if (flushed < size) { - const size_t remaining = size - flushed; - allocation->set_committed(remaining); - _physical.alloc(pmem, remaining); - } - - // Create new page - return new ZPage(allocation->type(), vmem, pmem); -} - -bool ZPageAllocator::is_alloc_satisfied(ZPageAllocation* allocation) const { - // The allocation is immediately satisfied if the list of pages contains - // exactly one page, with the type and size that was requested. However, - // even if the allocation is immediately satisfied we might still want to - // return false here to force the page to be remapped to fight address - // space fragmentation. - - if (allocation->pages()->size() != 1) { - // Not a single page + if (!is_multi_partition_enabled() || sum_available() < allocation->size()) { + // Multi-partition claiming is not possible return false; } - const ZPage* const page = allocation->pages()->first(); - if (page->type() != allocation->type() || - page->size() != allocation->size()) { - // Wrong type or size - return false; - } + // Multi-partition claiming + + // Flip allocation to multi-partition allocation + allocation->initiate_multi_partition_allocation(); + + ZMultiPartitionAllocation* const multi_partition_allocation = allocation->multi_partition_allocation(); + + claim_capacity_multi_partition(multi_partition_allocation, start_partition); - // Allocation immediately satisfied return true; } -ZPage* ZPageAllocator::alloc_page_finalize(ZPageAllocation* allocation) { - // Fast path - if (is_alloc_satisfied(allocation)) { - return allocation->pages()->remove_first(); - } +bool ZPageAllocator::claim_capacity_single_partition(ZSinglePartitionAllocation* single_partition_allocation, uint32_t partition_id) { + ZPartition& partition = _partitions.get(partition_id); - // Slow path - ZPage* const page = alloc_page_create(allocation); - if (page == nullptr) { - // Out of address space - return nullptr; - } - - // Commit page - if (commit_page(page)) { - // Success - map_page(page); - return page; - } - - // Failed or partially failed. Split of any successfully committed - // part of the page into a new page and insert it into list of pages, - // so that it will be re-inserted into the page cache. - ZPage* const committed_page = page->split_committed(); - destroy_page(page); - - if (committed_page != nullptr) { - map_page(committed_page); - allocation->pages()->insert_last(committed_page); - } - - return nullptr; + return partition.claim_capacity(single_partition_allocation->allocation()); } -ZPage* ZPageAllocator::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age) { - EventZPageAllocation event; +void ZPageAllocator::claim_capacity_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, uint32_t start_partition) { + const size_t size = multi_partition_allocation->size(); + const uint32_t num_partitions = _partitions.count(); + const size_t split_size = align_up(size / num_partitions, ZGranuleSize); -retry: - ZPageAllocation allocation(type, size, flags); + size_t remaining = size; - // Allocate one or more pages from the page cache. If the allocation - // succeeds but the returned pages don't cover the complete allocation, - // then finalize phase is allowed to allocate the remaining memory - // directly from the physical memory manager. Note that this call might - // block in a safepoint if the non-blocking flag is not set. - if (!alloc_page_or_stall(&allocation)) { - // Out of memory - return nullptr; + const auto do_claim_one_partition = [&](ZPartition& partition, bool claim_evenly) { + if (remaining == 0) { + // All memory claimed + return false; + } + + const size_t max_alloc_size = claim_evenly ? MIN2(split_size, remaining) : remaining; + + // This guarantees that claim_physical below will succeed + const size_t alloc_size = MIN2(max_alloc_size, partition.available()); + + // Skip over empty allocations + if (alloc_size == 0) { + // Continue + return true; + } + + ZMemoryAllocation partial_allocation(alloc_size); + + // Claim capacity for this allocation - this should succeed + const bool result = partition.claim_capacity(&partial_allocation); + assert(result, "Should have succeeded"); + + // Register allocation + multi_partition_allocation->register_allocation(partial_allocation); + + // Update remaining + remaining -= alloc_size; + + // Continue + return true; + }; + + // Loops over every partition and claims memory + const auto do_claim_each_partition = [&](bool claim_evenly) { + for (uint32_t i = 0; i < num_partitions; ++i) { + const uint32_t partition_id = (start_partition + i) % num_partitions; + ZPartition& partition = _partitions.get(partition_id); + + if (!do_claim_one_partition(partition, claim_evenly)) { + // All memory claimed + break; + } + } + }; + + // Try to claim from multiple partitions + + // Try to claim up to split_size on each partition + do_claim_each_partition(true /* claim_evenly */); + + // Try claim the remaining + do_claim_each_partition(false /* claim_evenly */); + + assert(remaining == 0, "Must have claimed capacity for the whole allocation"); +} + +ZVirtualMemory ZPageAllocator::satisfied_from_cache_vmem(const ZPageAllocation* allocation) const { + if (allocation->is_multi_partition()) { + // Multi-partition allocations are always harvested and/or committed, so + // there's never a satisfying vmem from the caches. + return {}; } - ZPage* const page = alloc_page_finalize(&allocation); - if (page == nullptr) { - // Failed to commit or map. Clean up and retry, in the hope that - // we can still allocate by flushing the page cache (more aggressively). - free_pages_alloc_failed(&allocation); - goto retry; + return allocation->satisfied_from_cache_vmem(); +} + +ZVirtualMemory ZPageAllocator::claim_virtual_memory(ZPageAllocation* allocation) { + // Note: that the single-partition performs "shuffling" of already harvested + // vmem(s), while the multi-partition searches for available virtual memory + // area without shuffling. + + if (allocation->is_multi_partition()) { + return claim_virtual_memory_multi_partition(allocation->multi_partition_allocation()); + } else { + return claim_virtual_memory_single_partition(allocation->single_partition_allocation()); + } +} + +ZVirtualMemory ZPageAllocator::claim_virtual_memory_single_partition(ZSinglePartitionAllocation* single_partition_allocation) { + ZMemoryAllocation* const allocation = single_partition_allocation->allocation(); + ZPartition& partition = allocation->partition(); + + if (allocation->harvested() > 0) { + // We claim virtual memory from the harvested vmems and perhaps also + // allocate more to match the allocation request. + return partition.prepare_harvested_and_claim_virtual(allocation); + } else { + // Just try to claim virtual memory + return partition.claim_virtual(allocation->size()); + } +} + +ZVirtualMemory ZPageAllocator::claim_virtual_memory_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation) { + const size_t size = multi_partition_allocation->size(); + + const ZVirtualMemory vmem = _virtual.remove_from_low_multi_partition(size); + if (!vmem.is_null()) { + // Copy claimed multi-partition vmems, we leave the old vmems mapped until + // after we have committed. In case committing fails we can simply + // reinsert the initial vmems. + copy_claimed_physical_multi_partition(multi_partition_allocation, vmem); } - // The generation's used is tracked here when the page is handed out - // to the allocating thread. The overall heap "used" is tracked in - // the lower-level allocation code. - const ZGenerationId id = age == ZPageAge::old ? ZGenerationId::old : ZGenerationId::young; - increase_used_generation(id, size); + return vmem; +} - // Reset page. This updates the page's sequence number and must - // be done after we potentially blocked in a safepoint (stalled) - // where the global sequence number was updated. - page->reset(age); - page->reset_top_for_allocation(); - page->reset_livemap(); - if (age == ZPageAge::old) { - page->remset_alloc(); +void ZPageAllocator::copy_claimed_physical_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { + // Start at the new dest offset + ZVirtualMemory remaining_dest_vmem = vmem; + + for (const ZMemoryAllocation* partial_allocation : *multi_partition_allocation->allocations()) { + // Split off the partial allocation's destination vmem + ZVirtualMemory partial_dest_vmem = remaining_dest_vmem.shrink_from_front(partial_allocation->size()); + + // Get the partial allocation's partition + ZPartition& partition = partial_allocation->partition(); + + // Copy all physical segments from the partition to the destination vmem + for (const ZVirtualMemory from_vmem : *partial_allocation->partial_vmems()) { + // Split off destination + const ZVirtualMemory to_vmem = partial_dest_vmem.shrink_from_front(from_vmem.size()); + + // Copy physical segments + partition.copy_physical_segments_from_partition(from_vmem, to_vmem); + } + } +} + +void ZPageAllocator::claim_physical_for_increased_capacity(ZPageAllocation* allocation, const ZVirtualMemory& vmem) { + assert(allocation->size() == vmem.size(), "vmem should be the final entry"); + + if (allocation->is_multi_partition()) { + claim_physical_for_increased_capacity_multi_partition(allocation->multi_partition_allocation(), vmem); + } else { + claim_physical_for_increased_capacity_single_partition(allocation->single_partition_allocation(), vmem); + } +} + +void ZPageAllocator::claim_physical_for_increased_capacity_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem) { + claim_physical_for_increased_capacity(single_partition_allocation->allocation(), vmem); +} + +void ZPageAllocator::claim_physical_for_increased_capacity_multi_partition(const ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { + ZVirtualMemory remaining = vmem; + + for (ZMemoryAllocation* allocation : *multi_partition_allocation->allocations()) { + const ZVirtualMemory partial = remaining.shrink_from_front(allocation->size()); + claim_physical_for_increased_capacity(allocation, partial); + } +} + +void ZPageAllocator::claim_physical_for_increased_capacity(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem) { + // The previously harvested memory is memory that has already been committed + // and mapped. The rest of the vmem gets physical memory assigned here and + // will be committed in a subsequent function. + + const size_t already_committed = allocation->harvested(); + const size_t non_committed = allocation->size() - already_committed; + const size_t increased_capacity = allocation->increased_capacity(); + + assert(non_committed == increased_capacity, + "Mismatch non_committed: " PTR_FORMAT " increased_capacity: " PTR_FORMAT, + non_committed, increased_capacity); + + if (non_committed > 0) { + ZPartition& partition = allocation->partition(); + ZVirtualMemory non_committed_vmem = vmem.last_part(already_committed); + partition.claim_physical(non_committed_vmem); + } +} + +bool ZPageAllocator::commit_and_map(ZPageAllocation* allocation, const ZVirtualMemory& vmem) { + assert(allocation->size() == vmem.size(), "vmem should be the final entry"); + + if (allocation->is_multi_partition()) { + return commit_and_map_multi_partition(allocation->multi_partition_allocation(), vmem); + } else { + return commit_and_map_single_partition(allocation->single_partition_allocation(), vmem); + } +} + +bool ZPageAllocator::commit_and_map_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem) { + const bool commit_successful = commit_single_partition(single_partition_allocation, vmem); + + // Map the vmem + map_committed_single_partition(single_partition_allocation, vmem); + + if (commit_successful) { + return true; } - // Update allocation statistics. Exclude gc relocations to avoid - // artificial inflation of the allocation rate during relocation. - if (!flags.gc_relocation() && is_init_completed()) { - // Note that there are two allocation rate counters, which have - // different purposes and are sampled at different frequencies. - ZStatInc(ZCounterMutatorAllocationRate, size); - ZStatMutatorAllocRate::sample_allocation(size); + // Commit failed + cleanup_failed_commit_single_partition(single_partition_allocation, vmem); + + return false; +} + +bool ZPageAllocator::commit_and_map_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { + if (commit_multi_partition(multi_partition_allocation, vmem)) { + // Commit successful + + // Unmap harvested vmems + unmap_harvested_multi_partition(multi_partition_allocation); + + // Map the vmem + map_committed_multi_partition(multi_partition_allocation, vmem); + + return true; } - // Send event - event.commit((u8)type, size, allocation.flushed(), allocation.committed(), - page->physical_memory().nsegments(), flags.non_blocking()); + // Commit failed + cleanup_failed_commit_multi_partition(multi_partition_allocation, vmem); - return page; + return false; +} + +void ZPageAllocator::commit(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem) { + ZPartition& partition = allocation->partition(); + + if (allocation->increased_capacity() > 0) { + // Commit memory + partition.commit_increased_capacity(allocation, vmem); + } +} + +bool ZPageAllocator::commit_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem) { + ZMemoryAllocation* const allocation = single_partition_allocation->allocation(); + + commit(allocation, vmem); + + return !allocation->commit_failed(); +} + +bool ZPageAllocator::commit_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { + bool commit_failed = false; + ZVirtualMemory remaining = vmem; + for (ZMemoryAllocation* const allocation : *multi_partition_allocation->allocations()) { + // Split off the partial allocation's memory range + const ZVirtualMemory partial_vmem = remaining.shrink_from_front(allocation->size()); + + commit(allocation, partial_vmem); + + // Keep track if any partial allocation failed to commit + commit_failed |= allocation->commit_failed(); + } + + assert(remaining.size() == 0, "all memory must be accounted for"); + + return !commit_failed; +} + +void ZPageAllocator::unmap_harvested_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation) { + for (ZMemoryAllocation* const allocation : *multi_partition_allocation->allocations()) { + ZPartition& partition = allocation->partition(); + ZArray* const partial_vmems = allocation->partial_vmems(); + + // Unmap harvested vmems + while (!partial_vmems->is_empty()) { + const ZVirtualMemory to_unmap = partial_vmems->pop(); + partition.unmap_virtual(to_unmap); + partition.free_virtual(to_unmap); + } + } +} + +void ZPageAllocator::map_committed_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem) { + ZMemoryAllocation* const allocation = single_partition_allocation->allocation(); + ZPartition& partition = allocation->partition(); + + const size_t total_committed = allocation->harvested() + allocation->committed_capacity(); + const ZVirtualMemory total_committed_vmem = vmem.first_part(total_committed); + + if (total_committed_vmem.size() > 0) { + // Map all the committed memory + partition.map_memory(allocation, total_committed_vmem); + } +} + +void ZPageAllocator::map_committed_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { + ZVirtualMemory remaining = vmem; + for (ZMemoryAllocation* const allocation : *multi_partition_allocation->allocations()) { + assert(!allocation->commit_failed(), "Sanity check"); + + ZPartition& partition = allocation->partition(); + + // Split off the partial allocation's memory range + const ZVirtualMemory to_vmem = remaining.shrink_from_front(allocation->size()); + + // Map the partial_allocation to partial_vmem + partition.map_virtual_from_multi_partition(to_vmem); + } + + assert(remaining.size() == 0, "all memory must be accounted for"); +} + +void ZPageAllocator::cleanup_failed_commit_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem) { + ZMemoryAllocation* const allocation = single_partition_allocation->allocation(); + + assert(allocation->commit_failed(), "Must have failed to commit"); + + const size_t committed = allocation->committed_capacity(); + const ZVirtualMemory non_harvested_vmem = vmem.last_part(allocation->harvested()); + const ZVirtualMemory committed_vmem = non_harvested_vmem.first_part(committed); + const ZVirtualMemory non_committed_vmem = non_harvested_vmem.last_part(committed); + + if (committed_vmem.size() > 0) { + // Register the committed and mapped memory. We insert the committed + // memory into partial_vmems so that it will be inserted into the cache + // in a subsequent step. + allocation->partial_vmems()->append(committed_vmem); + } + + // Free the virtual and physical memory we fetched to use but failed to commit + ZPartition& partition = allocation->partition(); + partition.free_physical(non_committed_vmem); + partition.free_virtual(non_committed_vmem); +} + +void ZPageAllocator::cleanup_failed_commit_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem) { + ZVirtualMemory remaining = vmem; + for (ZMemoryAllocation* const allocation : *multi_partition_allocation->allocations()) { + // Split off the partial allocation's memory range + const ZVirtualMemory partial_vmem = remaining.shrink_from_front(allocation->size()); + + if (allocation->harvested() == allocation->size()) { + // Everything is harvested, the mappings are already in the partial_vmems, + // nothing to cleanup. + continue; + } + + const size_t committed = allocation->committed_capacity(); + const ZVirtualMemory non_harvested_vmem = vmem.last_part(allocation->harvested()); + const ZVirtualMemory committed_vmem = non_harvested_vmem.first_part(committed); + const ZVirtualMemory non_committed_vmem = non_harvested_vmem.last_part(committed); + + ZPartition& partition = allocation->partition(); + + if (allocation->commit_failed()) { + // Free the physical memory we failed to commit. Virtual memory is later + // freed for the entire multi-partition allocation after all memory + // allocations have been visited. + partition.free_physical(non_committed_vmem); + } + + if (committed_vmem.size() == 0) { + // Nothing committed, nothing more to cleanup + continue; + } + + // Remove the harvested part + const ZVirtualMemory non_harvest_vmem = partial_vmem.last_part(allocation->harvested()); + + ZArray* const partial_vmems = allocation->partial_vmems(); + + // Keep track of the start index + const int start_index = partial_vmems->length(); + + // Claim virtual memory for the committed part + const size_t claimed_virtual = partition.claim_virtual(committed, partial_vmems); + + // We are holding memory associated with this partition, and we do not + // overcommit virtual memory claiming. So virtual memory must always be + // available. + assert(claimed_virtual == committed, "must succeed"); + + // Associate and map the physical memory with the partial vmems + + ZVirtualMemory remaining_committed_vmem = committed_vmem; + for (const ZVirtualMemory& to_vmem : partial_vmems->slice_back(start_index)) { + const ZVirtualMemory from_vmem = remaining_committed_vmem.shrink_from_front(to_vmem.size()); + + // Copy physical mappings + partition.copy_physical_segments_to_partition(to_vmem, from_vmem); + + // Map memory + partition.map_virtual(to_vmem); + } + + assert(remaining_committed_vmem.size() == 0, "all memory must be accounted for"); + } + + assert(remaining.size() == 0, "all memory must be accounted for"); + + // Free the unused virtual memory + _virtual.insert_multi_partition(vmem); +} + +void ZPageAllocator::free_after_alloc_page_failed(ZPageAllocation* allocation) { + // Send event for failed allocation + allocation->send_event(false /* successful */); + + ZLocker locker(&_lock); + + // Free memory + free_memory_alloc_failed(allocation); + + // Keep track of usage + decrease_used(allocation->size()); + + // Reset allocation for a potential retry + allocation->reset_for_retry(); + + // Try satisfy stalled allocations + satisfy_stalled(); +} + +void ZPageAllocator::free_memory_alloc_failed(ZPageAllocation* allocation) { + // The current max capacity may be decreased, store the value before freeing memory + const size_t current_max_capacity_before = current_max_capacity(); + + if (allocation->is_multi_partition()) { + free_memory_alloc_failed_multi_partition(allocation->multi_partition_allocation()); + } else { + free_memory_alloc_failed_single_partition(allocation->single_partition_allocation()); + } + + const size_t current_max_capacity_after = current_max_capacity(); + + if (current_max_capacity_before != current_max_capacity_after) { + log_error_p(gc)("Forced to lower max Java heap size from " + "%zuM(%.0f%%) to %zuM(%.0f%%)", + current_max_capacity_before / M, percent_of(current_max_capacity_before, _max_capacity), + current_max_capacity_after / M, percent_of(current_max_capacity_after, _max_capacity)); + } +} + +void ZPageAllocator::free_memory_alloc_failed_single_partition(ZSinglePartitionAllocation* single_partition_allocation) { + free_memory_alloc_failed(single_partition_allocation->allocation()); +} + +void ZPageAllocator::free_memory_alloc_failed_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation) { + for (ZMemoryAllocation* allocation : *multi_partition_allocation->allocations()) { + free_memory_alloc_failed(allocation); + } +} + +void ZPageAllocator::free_memory_alloc_failed(ZMemoryAllocation* allocation) { + ZPartition& partition = allocation->partition(); + + partition.free_memory_alloc_failed(allocation); +} + +ZPage* ZPageAllocator::create_page(ZPageAllocation* allocation, const ZVirtualMemory& vmem) { + // We don't track generation usage when claiming capacity, because this page + // could have been allocated by a thread that satisfies a stalling allocation. + // The stalled thread can wake up and potentially realize that the page alloc + // should be undone. If the alloc and the undo gets separated by a safepoint, + // the generation statistics could se a decreasing used value between mark + // start and mark end. At this point an allocation will be successful, so we + // update the generation usage. + const ZGenerationId id = allocation->age() == ZPageAge::old ? ZGenerationId::old : ZGenerationId::young; + increase_used_generation(id, allocation->size()); + + const ZPageType type = allocation->type(); + const ZPageAge age = allocation->age(); + + if (allocation->is_multi_partition()) { + const ZMultiPartitionAllocation* const multi_partition_allocation = allocation->multi_partition_allocation(); + ZMultiPartitionTracker* const tracker = ZMultiPartitionTracker::create(multi_partition_allocation, vmem); + + return new ZPage(type, age, vmem, tracker); + } + + const ZSinglePartitionAllocation* const single_partition_allocation = allocation->single_partition_allocation(); + const uint32_t partition_id = single_partition_allocation->allocation()->partition().numa_id(); + + return new ZPage(type, age, vmem, partition_id); +} + +void ZPageAllocator::prepare_memory_for_free(ZPage* page, ZArray* vmems) { + // Extract memory and destroy the page + const ZVirtualMemory vmem = page->virtual_memory(); + const ZPageType page_type = page->type(); + const ZMultiPartitionTracker* const tracker = page->multi_partition_tracker(); + + safe_destroy_page(page); + + // Multi-partition memory is always remapped + if (tracker != nullptr) { + tracker->prepare_memory_for_free(vmem, vmems); + + // Free the virtual memory + _virtual.insert_multi_partition(vmem); + + // Destroy the tracker + ZMultiPartitionTracker::destroy(tracker); + return; + } + + // Try to remap and defragment if page is large + if (page_type == ZPageType::large) { + remap_and_defragment(vmem, vmems); + return; + } + + // Leave the memory untouched + vmems->append(vmem); +} + +void ZPageAllocator::remap_and_defragment(const ZVirtualMemory& vmem, ZArray* vmems_out) { + ZPartition& partition = partition_from_vmem(vmem); + + // If no lower address can be found, don't remap/defrag + if (_virtual.lowest_available_address(partition.numa_id()) > vmem.start()) { + vmems_out->append(vmem); + return; + } + + ZStatInc(ZCounterDefragment); + + // Synchronously unmap the virtual memory + partition.unmap_virtual(vmem); + + // Stash segments + ZArray stash(vmem.granule_count()); + _physical.stash_segments(vmem, &stash); + + // Shuffle vmem - put new vmems in vmems_out + const int start_index = vmems_out->length(); + partition.free_and_claim_virtual_from_low_many(vmem, vmems_out); + + // The output array may contain results from other defragmentations as well, + // so we only operate on the result(s) we just got. + ZArraySlice defragmented_vmems = vmems_out->slice_back(start_index); + + // Restore segments + _physical.restore_segments(defragmented_vmems, stash); + + // Map and pre-touch + for (const ZVirtualMemory& claimed_vmem : defragmented_vmems) { + partition.map_virtual(claimed_vmem); + pretouch_memory(claimed_vmem.start(), claimed_vmem.size()); + } +} + +void ZPageAllocator::free_memory(ZArray* vmems) { + ZLocker locker(&_lock); + + // Free the vmems + for (const ZVirtualMemory vmem : *vmems) { + ZPartition& partition = partition_from_vmem(vmem); + + // Free the vmem + partition.free_memory(vmem); + + // Keep track of usage + decrease_used(vmem.size()); + } + + // Try satisfy stalled allocations + satisfy_stalled(); } void ZPageAllocator::satisfy_stalled() { @@ -786,11 +2185,14 @@ void ZPageAllocator::satisfy_stalled() { return; } - if (!alloc_page_common(allocation)) { + if (!claim_capacity(allocation)) { // Allocation could not be satisfied, give up return; } + // Keep track of usage + increase_used(allocation->size()); + // Allocation succeeded, dequeue and satisfy allocation request. // Note that we must dequeue the allocation request first, since // it will immediately be deallocated once it has been satisfied. @@ -799,164 +2201,94 @@ void ZPageAllocator::satisfy_stalled() { } } -ZPage* ZPageAllocator::prepare_to_recycle(ZPage* page, bool allow_defragment) { - // Make sure we have a page that is safe to recycle - ZPage* const to_recycle = _safe_recycle.register_and_clone_if_activated(page); +bool ZPageAllocator::is_multi_partition_enabled() const { + return _virtual.is_multi_partition_enabled(); +} - // Defragment the page before recycle if allowed and needed - if (allow_defragment && should_defragment(to_recycle)) { - return defragment_page(to_recycle); +const ZPartition& ZPageAllocator::partition_from_partition_id(uint32_t numa_id) const { + return _partitions.get(numa_id); +} + +ZPartition& ZPageAllocator::partition_from_partition_id(uint32_t numa_id) { + return _partitions.get(numa_id); +} + +ZPartition& ZPageAllocator::partition_from_vmem(const ZVirtualMemory& vmem) { + return partition_from_partition_id(_virtual.lookup_partition_id(vmem)); +} + +size_t ZPageAllocator::sum_available() const { + size_t total = 0; + + ZPartitionConstIterator iter = partition_iterator(); + for (const ZPartition* partition; iter.next(&partition);) { + total += partition->available(); } - // Remove the remset before recycling - if (to_recycle->is_old() && to_recycle == page) { - to_recycle->remset_delete(); - } - - return to_recycle; + return total; } -void ZPageAllocator::recycle_page(ZPage* page) { - // Set time when last used - page->set_last_used(); +void ZPageAllocator::increase_used(size_t size) { + // Update atomically since we have concurrent readers + const size_t used = Atomic::add(&_used, size); - // Cache page - _cache.free_page(page); -} - -void ZPageAllocator::free_page(ZPage* page, bool allow_defragment) { - const ZGenerationId generation_id = page->generation_id(); - - // Prepare page for recycling before taking the lock - ZPage* const to_recycle = prepare_to_recycle(page, allow_defragment); - - ZLocker locker(&_lock); - - // Update used statistics - const size_t size = to_recycle->size(); - decrease_used(size); - decrease_used_generation(generation_id, size); - - // Free page - recycle_page(to_recycle); - - // Try satisfy stalled allocations - satisfy_stalled(); -} - -void ZPageAllocator::free_pages(const ZArray* pages) { - ZArray to_recycle_pages; - - size_t young_size = 0; - size_t old_size = 0; - - // Prepare pages for recycling before taking the lock - ZArrayIterator pages_iter(pages); - for (ZPage* page; pages_iter.next(&page);) { - if (page->is_young()) { - young_size += page->size(); - } else { - old_size += page->size(); + // Update used high + for (auto& stats : _collection_stats) { + if (used > stats._used_high) { + stats._used_high = used; } - - // Prepare to recycle - ZPage* const to_recycle = prepare_to_recycle(page, true /* allow_defragment */); - - // Register for recycling - to_recycle_pages.push(to_recycle); } - - ZLocker locker(&_lock); - - // Update used statistics - decrease_used(young_size + old_size); - decrease_used_generation(ZGenerationId::young, young_size); - decrease_used_generation(ZGenerationId::old, old_size); - - // Free pages - ZArrayIterator iter(&to_recycle_pages); - for (ZPage* page; iter.next(&page);) { - recycle_page(page); - } - - // Try satisfy stalled allocations - satisfy_stalled(); } -void ZPageAllocator::free_pages_alloc_failed(ZPageAllocation* allocation) { - // The page(s) in the allocation are either taken from the cache or a newly - // created, mapped and commited ZPage. These page(s) have not been inserted in - // the page table, nor allocated a remset, so prepare_to_recycle is not required. - ZLocker locker(&_lock); +void ZPageAllocator::decrease_used(size_t size) { + // Update atomically since we have concurrent readers + const size_t used = Atomic::sub(&_used, size); - // Only decrease the overall used and not the generation used, - // since the allocation failed and generation used wasn't bumped. - decrease_used(allocation->size()); - - size_t freed = 0; - - // Free any allocated/flushed pages - ZListRemoveIterator iter(allocation->pages()); - for (ZPage* page; iter.next(&page);) { - freed += page->size(); - recycle_page(page); - } - - // Adjust capacity and used to reflect the failed capacity increase - const size_t remaining = allocation->size() - freed; - decrease_capacity(remaining, true /* set_max_capacity */); - - // Try satisfy stalled allocations - satisfy_stalled(); -} - -size_t ZPageAllocator::uncommit(uint64_t* timeout) { - // We need to join the suspendible thread set while manipulating capacity and - // used, to make sure GC safepoints will have a consistent view. - ZList pages; - size_t flushed; - - { - SuspendibleThreadSetJoiner sts_joiner; - ZLocker locker(&_lock); - - // Never uncommit below min capacity. We flush out and uncommit chunks at - // a time (~0.8% of the max capacity, but at least one granule and at most - // 256M), in case demand for memory increases while we are uncommitting. - const size_t retain = MAX2(_used, _min_capacity); - const size_t release = _capacity - retain; - const size_t limit = MIN2(align_up(_current_max_capacity >> 7, ZGranuleSize), 256 * M); - const size_t flush = MIN2(release, limit); - - // Flush pages to uncommit - flushed = _cache.flush_for_uncommit(flush, &pages, timeout); - if (flushed == 0) { - // Nothing flushed - return 0; + // Update used low + for (auto& stats : _collection_stats) { + if (used < stats._used_low) { + stats._used_low = used; } + } +} - // Record flushed pages as claimed - Atomic::add(&_claimed, flushed); +void ZPageAllocator::safe_destroy_page(ZPage* page) { + // Destroy page safely + _safe_destroy.schedule_delete(page); +} + +void ZPageAllocator::free_page(ZPage* page) { + // Extract the id from the page + const ZGenerationId id = page->generation_id(); + const size_t size = page->size(); + + // Extract vmems and destroy the page + ZArray vmems; + prepare_memory_for_free(page, &vmems); + + // Updated used statistics + decrease_used_generation(id, size); + + // Free the extracted vmems + free_memory(&vmems); +} + +void ZPageAllocator::free_pages(ZGenerationId id, const ZArray* pages) { + // Prepare memory from pages to be cached + ZArray vmems; + for (ZPage* page : *pages) { + assert(page->generation_id() == id, "All pages must be from the same generation"); + const size_t size = page->size(); + + // Extract vmems and destroy the page + prepare_memory_for_free(page, &vmems); + + // Updated used statistics + decrease_used_generation(id, size); } - // Unmap, uncommit, and destroy flushed pages - ZListRemoveIterator iter(&pages); - for (ZPage* page; iter.next(&page);) { - unmap_page(page); - uncommit_page(page); - destroy_page(page); - } - - { - SuspendibleThreadSetJoiner sts_joiner; - ZLocker locker(&_lock); - - // Adjust claimed and capacity to reflect the uncommit - Atomic::sub(&_claimed, flushed); - decrease_capacity(flushed, false /* set_max_capacity */); - } - - return flushed; + // Free the extracted vmems + free_memory(&vmems); } void ZPageAllocator::enable_safe_destroy() const { @@ -967,14 +2299,6 @@ void ZPageAllocator::disable_safe_destroy() const { _safe_destroy.disable_deferred_delete(); } -void ZPageAllocator::enable_safe_recycle() const { - _safe_recycle.activate(); -} - -void ZPageAllocator::disable_safe_recycle() const { - _safe_recycle.deactivate(); -} - static bool has_alloc_seen_young(const ZPageAllocation* allocation) { return allocation->young_seqnum() != ZGeneration::young()->seqnum(); } @@ -1045,7 +2369,94 @@ void ZPageAllocator::handle_alloc_stalling_for_old(bool cleared_all_soft_refs) { restart_gc(); } -void ZPageAllocator::threads_do(ThreadClosure* tc) const { - tc->do_thread(_unmapper); - tc->do_thread(_uncommitter); +ZPartitionConstIterator ZPageAllocator::partition_iterator() const { + return ZPartitionConstIterator(&_partitions); +} + +ZPartitionIterator ZPageAllocator::partition_iterator() { + return ZPartitionIterator(&_partitions); +} + +void ZPageAllocator::threads_do(ThreadClosure* tc) const { + ZPartitionConstIterator iter = partition_iterator(); + for (const ZPartition* partition; iter.next(&partition);) { + partition->threads_do(tc); + } +} + +void ZPageAllocator::print_on(outputStream* st) const { + ZLocker lock(&_lock); + print_on_inner(st); +} + +static bool try_lock_on_error(ZLock* lock) { + if (VMError::is_error_reported() && VMError::is_error_reported_in_current_thread()) { + return lock->try_lock(); + } + + lock->lock(); + + return true; +} + +void ZPageAllocator::print_extended_on_error(outputStream* st) const { + st->print_cr("ZMappedCache:"); + + streamIndentor indentor(st, 1); + + if (!try_lock_on_error(&_lock)) { + // We can't print without taking the lock since printing the contents of + // the cache requires iterating over the nodes in the cache's tree, which + // is not thread-safe. + st->print_cr(""); + + return; + } + + // Print each partition's cache content + ZPartitionConstIterator iter = partition_iterator(); + for (const ZPartition* partition; iter.next(&partition);) { + partition->print_extended_on_error(st); + } + + _lock.unlock(); +} + +void ZPageAllocator::print_on_error(outputStream* st) const { + const bool locked = try_lock_on_error(&_lock); + + if (!locked) { + st->print_cr(""); + } + + // Print information even though we have not successfully taken the lock. + // This is thread-safe, but may produce inconsistent results. + print_on_inner(st); + + if (locked) { + _lock.unlock(); + } +} + +void ZPageAllocator::print_on_inner(outputStream* st) const { + // Print total usage + st->print("ZHeap"); + st->fill_to(17); + st->print_cr("used %zuM, capacity %zuM, max capacity %zuM", + used() / M, capacity() / M, max_capacity() / M); + + // Print per-partition + + streamIndentor indentor(st, 1); + + if (_partitions.count() == 1) { + // The summary printing is redundant if we only have one partition + _partitions.get(0).print_cache_on(st); + return; + } + + ZPartitionConstIterator iter = partition_iterator(); + for (const ZPartition* partition; iter.next(&partition);) { + partition->print_on(st); + } } diff --git a/src/hotspot/share/gc/z/zPageAllocator.hpp b/src/hotspot/share/gc/z/zPageAllocator.hpp index e80169fe260..05b0d6774d9 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.hpp +++ b/src/hotspot/share/gc/z/zPageAllocator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,68 +24,72 @@ #ifndef SHARE_GC_Z_ZPAGEALLOCATOR_HPP #define SHARE_GC_Z_ZPAGEALLOCATOR_HPP +#include "gc/z/zAddress.hpp" #include "gc/z/zAllocationFlags.hpp" #include "gc/z/zArray.hpp" +#include "gc/z/zGenerationId.hpp" +#include "gc/z/zGranuleMap.hpp" #include "gc/z/zList.hpp" #include "gc/z/zLock.hpp" +#include "gc/z/zMappedCache.hpp" +#include "gc/z/zPage.hpp" #include "gc/z/zPageAge.hpp" -#include "gc/z/zPageCache.hpp" #include "gc/z/zPageType.hpp" -#include "gc/z/zPhysicalMemory.hpp" +#include "gc/z/zPhysicalMemoryManager.hpp" #include "gc/z/zSafeDelete.hpp" -#include "gc/z/zVirtualMemory.hpp" +#include "gc/z/zUncommitter.hpp" +#include "gc/z/zValue.hpp" +#include "gc/z/zVirtualMemoryManager.hpp" +#include "utilities/ostream.hpp" class ThreadClosure; class ZGeneration; +class ZMemoryAllocation; +class ZMultiPartitionAllocation; class ZPageAllocation; class ZPageAllocator; class ZPageAllocatorStats; +class ZSegmentStash; +class ZSinglePartitionAllocation; +class ZVirtualMemory; class ZWorkers; -class ZUncommitter; -class ZUnmapper; -class ZSafePageRecycle { +class ZPartition { + friend class VMStructs; + friend class ZPageAllocator; + private: - ZPageAllocator* _page_allocator; - ZActivatedArray _unsafe_to_recycle; + ZPageAllocator* const _page_allocator; + ZMappedCache _cache; + ZUncommitter _uncommitter; + const size_t _min_capacity; + const size_t _max_capacity; + volatile size_t _current_max_capacity; + volatile size_t _capacity; + volatile size_t _claimed; + size_t _used; + double _last_commit; + double _last_uncommit; + size_t _to_uncommit; + const uint32_t _numa_id; + + const ZVirtualMemoryManager& virtual_memory_manager() const; + ZVirtualMemoryManager& virtual_memory_manager(); + + const ZPhysicalMemoryManager& physical_memory_manager() const; + ZPhysicalMemoryManager& physical_memory_manager(); + + void verify_virtual_memory_multi_partition_association(const ZVirtualMemory& vmem) const NOT_DEBUG_RETURN; + void verify_virtual_memory_association(const ZVirtualMemory& vmem, bool check_multi_partition = false) const NOT_DEBUG_RETURN; + void verify_virtual_memory_association(const ZArray* vmems) const NOT_DEBUG_RETURN; + void verify_memory_allocation_association(const ZMemoryAllocation* allocation) const NOT_DEBUG_RETURN; public: - ZSafePageRecycle(ZPageAllocator* page_allocator); + ZPartition(uint32_t numa_id, ZPageAllocator* page_allocator); - void activate(); - void deactivate(); + uint32_t numa_id() const; - ZPage* register_and_clone_if_activated(ZPage* page); -}; - -class ZPageAllocator { - friend class VMStructs; - friend class ZUnmapper; - friend class ZUncommitter; - -private: - mutable ZLock _lock; - ZPageCache _cache; - ZVirtualMemoryManager _virtual; - ZPhysicalMemoryManager _physical; - const size_t _min_capacity; - const size_t _initial_capacity; - const size_t _max_capacity; - volatile size_t _current_max_capacity; - volatile size_t _capacity; - volatile size_t _claimed; - volatile size_t _used; - size_t _used_generations[2]; - struct { - size_t _used_high; - size_t _used_low; - } _collection_stats[2]; - ZList _stalled; - ZUnmapper* _unmapper; - ZUncommitter* _uncommitter; - mutable ZSafeDelete _safe_destroy; - mutable ZSafePageRecycle _safe_recycle; - bool _initialized; + size_t available() const; size_t increase_capacity(size_t size); void decrease_capacity(size_t size, bool set_max_capacity); @@ -93,38 +97,146 @@ private: void increase_used(size_t size); void decrease_used(size_t size); - void increase_used_generation(ZGenerationId id, size_t size); - void decrease_used_generation(ZGenerationId id, size_t size); + void free_memory(const ZVirtualMemory& vmem); - bool commit_page(ZPage* page); - void uncommit_page(ZPage* page); - - void map_page(const ZPage* page) const; - void unmap_page(const ZPage* page) const; - - void destroy_page(ZPage* page); - - bool should_defragment(const ZPage* page) const; - ZPage* defragment_page(ZPage* page); - - bool is_alloc_allowed(size_t size) const; - - bool alloc_page_common_inner(ZPageType type, size_t size, ZList* pages); - bool alloc_page_common(ZPageAllocation* allocation); - bool alloc_page_stall(ZPageAllocation* allocation); - bool alloc_page_or_stall(ZPageAllocation* allocation); - bool is_alloc_satisfied(ZPageAllocation* allocation) const; - ZPage* alloc_page_create(ZPageAllocation* allocation); - ZPage* alloc_page_finalize(ZPageAllocation* allocation); - void free_pages_alloc_failed(ZPageAllocation* allocation); - - void satisfy_stalled(); + void claim_from_cache_or_increase_capacity(ZMemoryAllocation* allocation); + bool claim_capacity(ZMemoryAllocation* allocation); size_t uncommit(uint64_t* timeout); + void sort_segments_physical(const ZVirtualMemory& vmem); + + void claim_physical(const ZVirtualMemory& vmem); + void free_physical(const ZVirtualMemory& vmem); + size_t commit_physical(const ZVirtualMemory& vmem); + size_t uncommit_physical(const ZVirtualMemory& vmem); + + void map_virtual(const ZVirtualMemory& vmem); + void unmap_virtual(const ZVirtualMemory& vmem); + + void map_virtual_from_multi_partition(const ZVirtualMemory& vmem); + void unmap_virtual_from_multi_partition(const ZVirtualMemory& vmem); + + ZVirtualMemory claim_virtual(size_t size); + size_t claim_virtual(size_t size, ZArray* vmems_out); + void free_virtual(const ZVirtualMemory& vmem); + + void free_and_claim_virtual_from_low_many(const ZVirtualMemory& vmem, ZArray* vmems_out); + ZVirtualMemory free_and_claim_virtual_from_low_exact_or_many(size_t size, ZArray* vmems_in_out); + + bool prime(ZWorkers* workers, size_t size); + + ZVirtualMemory prepare_harvested_and_claim_virtual(ZMemoryAllocation* allocation); + + void copy_physical_segments_to_partition(const ZVirtualMemory& at, const ZVirtualMemory& from); + void copy_physical_segments_from_partition(const ZVirtualMemory& at, const ZVirtualMemory& to); + + void commit_increased_capacity(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem); + void map_memory(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem); + + void free_memory_alloc_failed(ZMemoryAllocation* allocation); + + void threads_do(ThreadClosure* tc) const; + + void print_on(outputStream* st) const; + void print_cache_on(outputStream* st) const; + void print_extended_on_error(outputStream* st) const; +}; + +using ZPartitionIterator = ZPerNUMAIterator; +using ZPartitionConstIterator = ZPerNUMAConstIterator; + +class ZPageAllocator { + friend class VMStructs; + friend class ZMultiPartitionTracker; + friend class ZPartition; + friend class ZUncommitter; + +private: + mutable ZLock _lock; + ZVirtualMemoryManager _virtual; + ZPhysicalMemoryManager _physical; + const size_t _min_capacity; + const size_t _max_capacity; + volatile size_t _used; + volatile size_t _used_generations[2]; + struct { + size_t _used_high; + size_t _used_low; + } _collection_stats[2]; + ZPerNUMA _partitions; + ZList _stalled; + mutable ZSafeDelete _safe_destroy; + bool _initialized; + + bool alloc_page_stall(ZPageAllocation* allocation); + ZPage* alloc_page_inner(ZPageAllocation* allocation); + + bool claim_capacity_or_stall(ZPageAllocation* allocation); + bool claim_capacity(ZPageAllocation* allocation); + bool claim_capacity_single_partition(ZSinglePartitionAllocation* single_partition_allocation, uint32_t partition_id); + void claim_capacity_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, uint32_t start_partition); + + ZVirtualMemory satisfied_from_cache_vmem(const ZPageAllocation* allocation) const; + + ZVirtualMemory claim_virtual_memory(ZPageAllocation* allocation); + ZVirtualMemory claim_virtual_memory_single_partition(ZSinglePartitionAllocation* single_partition_allocation); + ZVirtualMemory claim_virtual_memory_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation); + + void copy_claimed_physical_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem); + + void claim_physical_for_increased_capacity(ZPageAllocation* allocation, const ZVirtualMemory& vmem); + void claim_physical_for_increased_capacity_single_partition(ZSinglePartitionAllocation* allocation, const ZVirtualMemory& vmem); + void claim_physical_for_increased_capacity_multi_partition(const ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem); + void claim_physical_for_increased_capacity(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem); + + bool commit_and_map(ZPageAllocation* allocation, const ZVirtualMemory& vmem); + bool commit_and_map_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem); + bool commit_and_map_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem); + + void commit(ZMemoryAllocation* allocation, const ZVirtualMemory& vmem); + bool commit_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem); + bool commit_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem); + + void unmap_harvested_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation); + + void map_committed_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem); + void map_committed_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem); + + void cleanup_failed_commit_single_partition(ZSinglePartitionAllocation* single_partition_allocation, const ZVirtualMemory& vmem); + void cleanup_failed_commit_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation, const ZVirtualMemory& vmem); + + void free_after_alloc_page_failed(ZPageAllocation* allocation); + + void free_memory_alloc_failed(ZPageAllocation* allocation); + void free_memory_alloc_failed_single_partition(ZSinglePartitionAllocation* single_partition_allocation); + void free_memory_alloc_failed_multi_partition(ZMultiPartitionAllocation* multi_partition_allocation); + void free_memory_alloc_failed(ZMemoryAllocation* allocation); + + ZPage* create_page(ZPageAllocation* allocation, const ZVirtualMemory& vmem); + + void prepare_memory_for_free(ZPage* page, ZArray* vmems); + void remap_and_defragment(const ZVirtualMemory& vmem, ZArray* vmems_out); + void free_memory(ZArray* vmems); + + void satisfy_stalled(); + + bool is_multi_partition_enabled() const; + + const ZPartition& partition_from_partition_id(uint32_t partition_id) const; + ZPartition& partition_from_partition_id(uint32_t partition_id); + ZPartition& partition_from_vmem(const ZVirtualMemory& vmem); + + size_t sum_available() const; + + void increase_used(size_t size); + void decrease_used(size_t size); + void notify_out_of_memory(); void restart_gc() const; + void print_on_inner(outputStream* st) const; + public: ZPageAllocator(size_t min_capacity, size_t initial_capacity, @@ -135,56 +247,61 @@ public: bool prime_cache(ZWorkers* workers, size_t size); - size_t initial_capacity() const; size_t min_capacity() const; size_t max_capacity() const; size_t soft_max_capacity() const; + size_t current_max_capacity() const; size_t capacity() const; size_t used() const; size_t used_generation(ZGenerationId id) const; size_t unused() const; - void promote_used(size_t size); + void increase_used_generation(ZGenerationId id, size_t size); + void decrease_used_generation(ZGenerationId id, size_t size); + + void promote_used(const ZPage* from, const ZPage* to); ZPageAllocatorStats stats(ZGeneration* generation) const; void reset_statistics(ZGenerationId id); ZPage* alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age); - ZPage* prepare_to_recycle(ZPage* page, bool allow_defragment); - void recycle_page(ZPage* page); void safe_destroy_page(ZPage* page); - void free_page(ZPage* page, bool allow_defragment); - void free_pages(const ZArray* pages); + void free_page(ZPage* page); + void free_pages(ZGenerationId id, const ZArray* pages); void enable_safe_destroy() const; void disable_safe_destroy() const; - void enable_safe_recycle() const; - void disable_safe_recycle() const; - bool is_alloc_stalling() const; bool is_alloc_stalling_for_old() const; void handle_alloc_stalling_for_young(); void handle_alloc_stalling_for_old(bool cleared_soft_refs); + ZPartitionConstIterator partition_iterator() const; + ZPartitionIterator partition_iterator(); + void threads_do(ThreadClosure* tc) const; + + void print_on(outputStream* st) const; + void print_extended_on_error(outputStream* st) const; + void print_on_error(outputStream* st) const; }; class ZPageAllocatorStats { private: - size_t _min_capacity; - size_t _max_capacity; - size_t _soft_max_capacity; - size_t _capacity; - size_t _used; - size_t _used_high; - size_t _used_low; - size_t _used_generation; - size_t _freed; - size_t _promoted; - size_t _compacted; - size_t _allocation_stalls; + const size_t _min_capacity; + const size_t _max_capacity; + const size_t _soft_max_capacity; + const size_t _capacity; + const size_t _used; + const size_t _used_high; + const size_t _used_low; + const size_t _used_generation; + const size_t _freed; + const size_t _promoted; + const size_t _compacted; + const size_t _allocation_stalls; public: ZPageAllocatorStats(size_t min_capacity, diff --git a/src/hotspot/share/gc/z/zPageCache.cpp b/src/hotspot/share/gc/z/zPageCache.cpp deleted file mode 100644 index c8e8ec9bdbd..00000000000 --- a/src/hotspot/share/gc/z/zPageCache.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "gc/z/zGlobals.hpp" -#include "gc/z/zList.inline.hpp" -#include "gc/z/zNUMA.inline.hpp" -#include "gc/z/zPage.inline.hpp" -#include "gc/z/zPageCache.hpp" -#include "gc/z/zStat.hpp" -#include "gc/z/zValue.inline.hpp" -#include "memory/allocation.hpp" -#include "runtime/globals.hpp" -#include "runtime/os.hpp" - -static const ZStatCounter ZCounterPageCacheHitL1("Memory", "Page Cache Hit L1", ZStatUnitOpsPerSecond); -static const ZStatCounter ZCounterPageCacheHitL2("Memory", "Page Cache Hit L2", ZStatUnitOpsPerSecond); -static const ZStatCounter ZCounterPageCacheHitL3("Memory", "Page Cache Hit L3", ZStatUnitOpsPerSecond); -static const ZStatCounter ZCounterPageCacheMiss("Memory", "Page Cache Miss", ZStatUnitOpsPerSecond); - -class ZPageCacheFlushClosure : public StackObj { - friend class ZPageCache; - -protected: - const size_t _requested; - size_t _flushed; - -public: - ZPageCacheFlushClosure(size_t requested); - virtual bool do_page(const ZPage* page) = 0; -}; - -ZPageCacheFlushClosure::ZPageCacheFlushClosure(size_t requested) - : _requested(requested), - _flushed(0) {} - -ZPageCache::ZPageCache() - : _small(), - _medium(), - _large(), - _last_commit(0) {} - -ZPage* ZPageCache::alloc_small_page() { - const uint32_t numa_id = ZNUMA::id(); - const uint32_t numa_count = ZNUMA::count(); - - // Try NUMA local page cache - ZPage* const l1_page = _small.get(numa_id).remove_first(); - if (l1_page != nullptr) { - ZStatInc(ZCounterPageCacheHitL1); - return l1_page; - } - - // Try NUMA remote page cache(s) - uint32_t remote_numa_id = numa_id + 1; - const uint32_t remote_numa_count = numa_count - 1; - for (uint32_t i = 0; i < remote_numa_count; i++) { - if (remote_numa_id == numa_count) { - remote_numa_id = 0; - } - - ZPage* const l2_page = _small.get(remote_numa_id).remove_first(); - if (l2_page != nullptr) { - ZStatInc(ZCounterPageCacheHitL2); - return l2_page; - } - - remote_numa_id++; - } - - return nullptr; -} - -ZPage* ZPageCache::alloc_medium_page() { - ZPage* const page = _medium.remove_first(); - if (page != nullptr) { - ZStatInc(ZCounterPageCacheHitL1); - return page; - } - - return nullptr; -} - -ZPage* ZPageCache::alloc_large_page(size_t size) { - // Find a page with the right size - ZListIterator iter(&_large); - for (ZPage* page; iter.next(&page);) { - if (size == page->size()) { - // Page found - _large.remove(page); - ZStatInc(ZCounterPageCacheHitL1); - return page; - } - } - - return nullptr; -} - -ZPage* ZPageCache::alloc_oversized_medium_page(size_t size) { - if (size <= ZPageSizeMedium) { - return _medium.remove_first(); - } - - return nullptr; -} - -ZPage* ZPageCache::alloc_oversized_large_page(size_t size) { - // Find a page that is large enough - ZListIterator iter(&_large); - for (ZPage* page; iter.next(&page);) { - if (size <= page->size()) { - // Page found - _large.remove(page); - return page; - } - } - - return nullptr; -} - -ZPage* ZPageCache::alloc_oversized_page(size_t size) { - ZPage* page = alloc_oversized_large_page(size); - if (page == nullptr) { - page = alloc_oversized_medium_page(size); - } - - if (page != nullptr) { - ZStatInc(ZCounterPageCacheHitL3); - } - - return page; -} - -ZPage* ZPageCache::alloc_page(ZPageType type, size_t size) { - ZPage* page; - - // Try allocate exact page - if (type == ZPageType::small) { - page = alloc_small_page(); - } else if (type == ZPageType::medium) { - page = alloc_medium_page(); - } else { - page = alloc_large_page(size); - } - - if (page == nullptr) { - // Try allocate potentially oversized page - ZPage* const oversized = alloc_oversized_page(size); - if (oversized != nullptr) { - if (size < oversized->size()) { - // Split oversized page - page = oversized->split(type, size); - - // Cache remainder - free_page(oversized); - } else { - // Re-type correctly sized page - page = oversized->retype(type); - } - } - } - - if (page == nullptr) { - ZStatInc(ZCounterPageCacheMiss); - } - - return page; -} - -void ZPageCache::free_page(ZPage* page) { - const ZPageType type = page->type(); - if (type == ZPageType::small) { - _small.get(page->numa_id()).insert_first(page); - } else if (type == ZPageType::medium) { - _medium.insert_first(page); - } else { - _large.insert_first(page); - } -} - -bool ZPageCache::flush_list_inner(ZPageCacheFlushClosure* cl, ZList* from, ZList* to) { - ZPage* const page = from->last(); - if (page == nullptr || !cl->do_page(page)) { - // Don't flush page - return false; - } - - // Flush page - from->remove(page); - to->insert_last(page); - return true; -} - -void ZPageCache::flush_list(ZPageCacheFlushClosure* cl, ZList* from, ZList* to) { - while (flush_list_inner(cl, from, to)); -} - -void ZPageCache::flush_per_numa_lists(ZPageCacheFlushClosure* cl, ZPerNUMA >* from, ZList* to) { - const uint32_t numa_count = ZNUMA::count(); - uint32_t numa_done = 0; - uint32_t numa_next = 0; - - // Flush lists round-robin - while (numa_done < numa_count) { - ZList* const numa_list = from->addr(numa_next); - if (++numa_next == numa_count) { - numa_next = 0; - } - - if (flush_list_inner(cl, numa_list, to)) { - // Not done - numa_done = 0; - } else { - // Done - numa_done++; - } - } -} - -void ZPageCache::flush(ZPageCacheFlushClosure* cl, ZList* to) { - // Prefer flushing large, then medium and last small pages - flush_list(cl, &_large, to); - flush_list(cl, &_medium, to); - flush_per_numa_lists(cl, &_small, to); - - if (cl->_flushed > cl->_requested) { - // Overflushed, re-insert part of last page into the cache - const size_t overflushed = cl->_flushed - cl->_requested; - ZPage* const reinsert = to->last()->split(overflushed); - free_page(reinsert); - cl->_flushed -= overflushed; - } -} - -class ZPageCacheFlushForAllocationClosure : public ZPageCacheFlushClosure { -public: - ZPageCacheFlushForAllocationClosure(size_t requested) - : ZPageCacheFlushClosure(requested) {} - - virtual bool do_page(const ZPage* page) { - if (_flushed < _requested) { - // Flush page - _flushed += page->size(); - return true; - } - - // Don't flush page - return false; - } -}; - -void ZPageCache::flush_for_allocation(size_t requested, ZList* to) { - ZPageCacheFlushForAllocationClosure cl(requested); - flush(&cl, to); -} - -class ZPageCacheFlushForUncommitClosure : public ZPageCacheFlushClosure { -private: - const uint64_t _now; - uint64_t* _timeout; - -public: - ZPageCacheFlushForUncommitClosure(size_t requested, uint64_t now, uint64_t* timeout) - : ZPageCacheFlushClosure(requested), - _now(now), - _timeout(timeout) { - // Set initial timeout - *_timeout = ZUncommitDelay; - } - - virtual bool do_page(const ZPage* page) { - const uint64_t expires = page->last_used() + ZUncommitDelay; - if (expires > _now) { - // Don't flush page, record shortest non-expired timeout - *_timeout = MIN2(*_timeout, expires - _now); - return false; - } - - if (_flushed >= _requested) { - // Don't flush page, requested amount flushed - return false; - } - - // Flush page - _flushed += page->size(); - return true; - } -}; - -size_t ZPageCache::flush_for_uncommit(size_t requested, ZList* to, uint64_t* timeout) { - const uint64_t now = (uint64_t)os::elapsedTime(); - const uint64_t expires = _last_commit + ZUncommitDelay; - if (expires > now) { - // Delay uncommit, set next timeout - *timeout = expires - now; - return 0; - } - - if (requested == 0) { - // Nothing to flush, set next timeout - *timeout = ZUncommitDelay; - return 0; - } - - ZPageCacheFlushForUncommitClosure cl(requested, now, timeout); - flush(&cl, to); - - return cl._flushed; -} - -void ZPageCache::set_last_commit() { - _last_commit = (uint64_t)ceil(os::elapsedTime()); -} diff --git a/src/hotspot/share/gc/z/zPageCache.hpp b/src/hotspot/share/gc/z/zPageCache.hpp deleted file mode 100644 index b28aaa6c10d..00000000000 --- a/src/hotspot/share/gc/z/zPageCache.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 - * 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_GC_Z_ZPAGECACHE_HPP -#define SHARE_GC_Z_ZPAGECACHE_HPP - -#include "gc/z/zList.hpp" -#include "gc/z/zPage.hpp" -#include "gc/z/zPageType.hpp" -#include "gc/z/zValue.hpp" - -class ZPageCacheFlushClosure; - -class ZPageCache { -private: - ZPerNUMA > _small; - ZList _medium; - ZList _large; - uint64_t _last_commit; - - ZPage* alloc_small_page(); - ZPage* alloc_medium_page(); - ZPage* alloc_large_page(size_t size); - - ZPage* alloc_oversized_medium_page(size_t size); - ZPage* alloc_oversized_large_page(size_t size); - ZPage* alloc_oversized_page(size_t size); - - bool flush_list_inner(ZPageCacheFlushClosure* cl, ZList* from, ZList* to); - void flush_list(ZPageCacheFlushClosure* cl, ZList* from, ZList* to); - void flush_per_numa_lists(ZPageCacheFlushClosure* cl, ZPerNUMA >* from, ZList* to); - void flush(ZPageCacheFlushClosure* cl, ZList* to); - -public: - ZPageCache(); - - ZPage* alloc_page(ZPageType type, size_t size); - void free_page(ZPage* page); - - void flush_for_allocation(size_t requested, ZList* to); - size_t flush_for_uncommit(size_t requested, ZList* to, uint64_t* timeout); - - void set_last_commit(); -}; - -#endif // SHARE_GC_Z_ZPAGECACHE_HPP diff --git a/src/hotspot/share/gc/z/zPageTable.cpp b/src/hotspot/share/gc/z/zPageTable.cpp index d960270c451..5bf94c6bae3 100644 --- a/src/hotspot/share/gc/z/zPageTable.cpp +++ b/src/hotspot/share/gc/z/zPageTable.cpp @@ -81,11 +81,9 @@ ZGenerationPagesParallelIterator::ZGenerationPagesParallelIterator(const ZPageTa _generation_id(id), _page_allocator(page_allocator) { _page_allocator->enable_safe_destroy(); - _page_allocator->enable_safe_recycle(); } ZGenerationPagesParallelIterator::~ZGenerationPagesParallelIterator() { - _page_allocator->disable_safe_recycle(); _page_allocator->disable_safe_destroy(); } @@ -94,10 +92,8 @@ ZGenerationPagesIterator::ZGenerationPagesIterator(const ZPageTable* page_table, _generation_id(id), _page_allocator(page_allocator) { _page_allocator->enable_safe_destroy(); - _page_allocator->enable_safe_recycle(); } ZGenerationPagesIterator::~ZGenerationPagesIterator() { - _page_allocator->disable_safe_recycle(); _page_allocator->disable_safe_destroy(); } diff --git a/src/hotspot/share/gc/z/zPageTable.inline.hpp b/src/hotspot/share/gc/z/zPageTable.inline.hpp index 583017d5c9c..6310a2104df 100644 --- a/src/hotspot/share/gc/z/zPageTable.inline.hpp +++ b/src/hotspot/share/gc/z/zPageTable.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,11 +103,9 @@ inline bool ZGenerationPagesIterator::next(ZPage** page) { template inline void ZGenerationPagesIterator::yield(Function function) { _page_allocator->disable_safe_destroy(); - _page_allocator->disable_safe_recycle(); function(); - _page_allocator->enable_safe_recycle(); _page_allocator->enable_safe_destroy(); } diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.cpp b/src/hotspot/share/gc/z/zPhysicalMemory.cpp deleted file mode 100644 index 5b209a4c01c..00000000000 --- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "gc/shared/gcLogPrecious.hpp" -#include "gc/z/zAddress.inline.hpp" -#include "gc/z/zArray.inline.hpp" -#include "gc/z/zGlobals.hpp" -#include "gc/z/zLargePages.inline.hpp" -#include "gc/z/zList.inline.hpp" -#include "gc/z/zNMT.hpp" -#include "gc/z/zNUMA.inline.hpp" -#include "gc/z/zPhysicalMemory.inline.hpp" -#include "logging/log.hpp" -#include "runtime/globals.hpp" -#include "runtime/globals_extension.hpp" -#include "runtime/init.hpp" -#include "runtime/os.hpp" -#include "utilities/align.hpp" -#include "utilities/debug.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/powerOfTwo.hpp" - -ZPhysicalMemory::ZPhysicalMemory() - : _segments() {} - -ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemorySegment& segment) - : _segments() { - _segments.append(segment); -} - -ZPhysicalMemory::ZPhysicalMemory(const ZPhysicalMemory& pmem) - : _segments(pmem.nsegments()) { - _segments.appendAll(&pmem._segments); -} - -const ZPhysicalMemory& ZPhysicalMemory::operator=(const ZPhysicalMemory& pmem) { - // Check for self-assignment - if (this == &pmem) { - return *this; - } - - // Free and copy segments - _segments.clear_and_deallocate(); - _segments.reserve(pmem.nsegments()); - _segments.appendAll(&pmem._segments); - - return *this; -} - -size_t ZPhysicalMemory::size() const { - size_t size = 0; - - for (int i = 0; i < _segments.length(); i++) { - size += _segments.at(i).size(); - } - - return size; -} - -void ZPhysicalMemory::insert_segment(int index, zoffset start, size_t size, bool committed) { - _segments.insert_before(index, ZPhysicalMemorySegment(start, size, committed)); -} - -void ZPhysicalMemory::replace_segment(int index, zoffset start, size_t size, bool committed) { - _segments.at_put(index, ZPhysicalMemorySegment(start, size, committed)); -} - -void ZPhysicalMemory::remove_segment(int index) { - _segments.remove_at(index); -} - -void ZPhysicalMemory::add_segments(const ZPhysicalMemory& pmem) { - for (int i = 0; i < pmem.nsegments(); i++) { - add_segment(pmem.segment(i)); - } -} - -void ZPhysicalMemory::remove_segments() { - _segments.clear_and_deallocate(); -} - -static bool is_mergable(const ZPhysicalMemorySegment& before, const ZPhysicalMemorySegment& after) { - return before.end() == after.start() && before.is_committed() == after.is_committed(); -} - -void ZPhysicalMemory::add_segment(const ZPhysicalMemorySegment& segment) { - // Insert segments in address order, merge segments when possible - for (int i = _segments.length(); i > 0; i--) { - const int current = i - 1; - - if (_segments.at(current).end() <= segment.start()) { - if (is_mergable(_segments.at(current), segment)) { - if (current + 1 < _segments.length() && is_mergable(segment, _segments.at(current + 1))) { - // Merge with end of current segment and start of next segment - const zoffset start = _segments.at(current).start(); - const size_t size = _segments.at(current).size() + segment.size() + _segments.at(current + 1).size(); - replace_segment(current, start, size, segment.is_committed()); - remove_segment(current + 1); - return; - } - - // Merge with end of current segment - const zoffset start = _segments.at(current).start(); - const size_t size = _segments.at(current).size() + segment.size(); - replace_segment(current, start, size, segment.is_committed()); - return; - } else if (current + 1 < _segments.length() && is_mergable(segment, _segments.at(current + 1))) { - // Merge with start of next segment - const zoffset start = segment.start(); - const size_t size = segment.size() + _segments.at(current + 1).size(); - replace_segment(current + 1, start, size, segment.is_committed()); - return; - } - - // Insert after current segment - insert_segment(current + 1, segment.start(), segment.size(), segment.is_committed()); - return; - } - } - - if (_segments.length() > 0 && is_mergable(segment, _segments.at(0))) { - // Merge with start of first segment - const zoffset start = segment.start(); - const size_t size = segment.size() + _segments.at(0).size(); - replace_segment(0, start, size, segment.is_committed()); - return; - } - - // Insert before first segment - insert_segment(0, segment.start(), segment.size(), segment.is_committed()); -} - -bool ZPhysicalMemory::commit_segment(int index, size_t size) { - assert(size <= _segments.at(index).size(), "Invalid size"); - assert(!_segments.at(index).is_committed(), "Invalid state"); - - if (size == _segments.at(index).size()) { - // Completely committed - _segments.at(index).set_committed(true); - return true; - } - - if (size > 0) { - // Partially committed, split segment - insert_segment(index + 1, _segments.at(index).start() + size, _segments.at(index).size() - size, false /* committed */); - replace_segment(index, _segments.at(index).start(), size, true /* committed */); - } - - return false; -} - -bool ZPhysicalMemory::uncommit_segment(int index, size_t size) { - assert(size <= _segments.at(index).size(), "Invalid size"); - assert(_segments.at(index).is_committed(), "Invalid state"); - - if (size == _segments.at(index).size()) { - // Completely uncommitted - _segments.at(index).set_committed(false); - return true; - } - - if (size > 0) { - // Partially uncommitted, split segment - insert_segment(index + 1, _segments.at(index).start() + size, _segments.at(index).size() - size, true /* committed */); - replace_segment(index, _segments.at(index).start(), size, false /* committed */); - } - - return false; -} - -ZPhysicalMemory ZPhysicalMemory::split(size_t size) { - ZPhysicalMemory pmem; - int nsegments = 0; - - for (int i = 0; i < _segments.length(); i++) { - const ZPhysicalMemorySegment& segment = _segments.at(i); - if (pmem.size() < size) { - if (pmem.size() + segment.size() <= size) { - // Transfer segment - pmem.add_segment(segment); - } else { - // Split segment - const size_t split_size = size - pmem.size(); - pmem.add_segment(ZPhysicalMemorySegment(segment.start(), split_size, segment.is_committed())); - _segments.at_put(nsegments++, ZPhysicalMemorySegment(segment.start() + split_size, segment.size() - split_size, segment.is_committed())); - } - } else { - // Keep segment - _segments.at_put(nsegments++, segment); - } - } - - _segments.trunc_to(nsegments); - - return pmem; -} - -ZPhysicalMemory ZPhysicalMemory::split_committed() { - ZPhysicalMemory pmem; - int nsegments = 0; - - for (int i = 0; i < _segments.length(); i++) { - const ZPhysicalMemorySegment& segment = _segments.at(i); - if (segment.is_committed()) { - // Transfer segment - pmem.add_segment(segment); - } else { - // Keep segment - _segments.at_put(nsegments++, segment); - } - } - - _segments.trunc_to(nsegments); - - return pmem; -} - -ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity) - : _backing(max_capacity) { - // Make the whole range free - _manager.register_range(zoffset(0), max_capacity); -} - -bool ZPhysicalMemoryManager::is_initialized() const { - return _backing.is_initialized(); -} - -void ZPhysicalMemoryManager::warn_commit_limits(size_t max_capacity) const { - _backing.warn_commit_limits(max_capacity); -} - -void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max_capacity) { - assert(!is_init_completed(), "Invalid state"); - - // If uncommit is not explicitly disabled, max capacity is greater than - // min capacity, and uncommit is supported by the platform, then uncommit - // will be enabled. - if (!ZUncommit) { - log_info_p(gc, init)("Uncommit: Disabled"); - return; - } - - if (max_capacity == min_capacity) { - log_info_p(gc, init)("Uncommit: Implicitly Disabled (-Xms equals -Xmx)"); - FLAG_SET_ERGO(ZUncommit, false); - return; - } - - // Test if uncommit is supported by the operating system by committing - // and then uncommitting a granule. - ZPhysicalMemory pmem(ZPhysicalMemorySegment(zoffset(0), ZGranuleSize, false /* committed */)); - if (!commit(pmem) || !uncommit(pmem)) { - log_info_p(gc, init)("Uncommit: Implicitly Disabled (Not supported by operating system)"); - FLAG_SET_ERGO(ZUncommit, false); - return; - } - - log_info_p(gc, init)("Uncommit: Enabled"); - log_info_p(gc, init)("Uncommit Delay: %zus", ZUncommitDelay); -} - -void ZPhysicalMemoryManager::alloc(ZPhysicalMemory& pmem, size_t size) { - assert(is_aligned(size, ZGranuleSize), "Invalid size"); - - // Allocate segments - while (size > 0) { - size_t allocated = 0; - const zoffset start = _manager.alloc_low_address_at_most(size, &allocated); - assert(start != zoffset(UINTPTR_MAX), "Allocation should never fail"); - pmem.add_segment(ZPhysicalMemorySegment(start, allocated, false /* committed */)); - size -= allocated; - } -} - -void ZPhysicalMemoryManager::free(const ZPhysicalMemory& pmem) { - // Free segments - for (int i = 0; i < pmem.nsegments(); i++) { - const ZPhysicalMemorySegment& segment = pmem.segment(i); - _manager.free(segment.start(), segment.size()); - } -} - -bool ZPhysicalMemoryManager::commit(ZPhysicalMemory& pmem) { - // Commit segments - for (int i = 0; i < pmem.nsegments(); i++) { - const ZPhysicalMemorySegment& segment = pmem.segment(i); - if (segment.is_committed()) { - // Segment already committed - continue; - } - - // Commit segment - const size_t committed = _backing.commit(segment.start(), segment.size()); - - // Register with NMT - if (committed > 0) { - ZNMT::commit(segment.start(), committed); - } - - // Register committed segment - if (!pmem.commit_segment(i, committed)) { - // Failed or partially failed - return false; - } - } - - // Success - return true; -} - -bool ZPhysicalMemoryManager::uncommit(ZPhysicalMemory& pmem) { - // Commit segments - for (int i = 0; i < pmem.nsegments(); i++) { - const ZPhysicalMemorySegment& segment = pmem.segment(i); - if (!segment.is_committed()) { - // Segment already uncommitted - continue; - } - - // Uncommit segment - const size_t uncommitted = _backing.uncommit(segment.start(), segment.size()); - - // Unregister with NMT - if (uncommitted > 0) { - ZNMT::uncommit(segment.start(), uncommitted); - } - - // Deregister uncommitted segment - if (!pmem.uncommit_segment(i, uncommitted)) { - // Failed or partially failed - return false; - } - } - - // Success - return true; -} - -// Map virtual memory to physcial memory -void ZPhysicalMemoryManager::map(zoffset offset, const ZPhysicalMemory& pmem) const { - const zaddress_unsafe addr = ZOffset::address_unsafe(offset); - - size_t size = 0; - - // Map segments - for (int i = 0; i < pmem.nsegments(); i++) { - const ZPhysicalMemorySegment& segment = pmem.segment(i); - _backing.map(addr + size, segment.size(), segment.start()); - size += segment.size(); - } - - // Setup NUMA interleaving for large pages - if (ZNUMA::is_enabled() && ZLargePages::is_explicit()) { - // To get granule-level NUMA interleaving when using large pages, - // we simply let the kernel interleave the memory for us at page - // fault time. - os::numa_make_global((char*)addr, size); - } -} - -// Unmap virtual memory from physical memory -void ZPhysicalMemoryManager::unmap(zoffset offset, size_t size) const { - const zaddress_unsafe addr = ZOffset::address_unsafe(offset); - - _backing.unmap(addr, size); -} diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.hpp b/src/hotspot/share/gc/z/zPhysicalMemory.hpp deleted file mode 100644 index 09f71013258..00000000000 --- a/src/hotspot/share/gc/z/zPhysicalMemory.hpp +++ /dev/null @@ -1,105 +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. - * - * 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_GC_Z_ZPHYSICALMEMORY_HPP -#define SHARE_GC_Z_ZPHYSICALMEMORY_HPP - -#include "gc/z/zAddress.hpp" -#include "gc/z/zArray.hpp" -#include "gc/z/zMemory.hpp" -#include "memory/allocation.hpp" -#include OS_HEADER(gc/z/zPhysicalMemoryBacking) - -class ZPhysicalMemorySegment : public CHeapObj { -private: - zoffset _start; - zoffset_end _end; - bool _committed; - -public: - ZPhysicalMemorySegment(); - ZPhysicalMemorySegment(zoffset start, size_t size, bool committed); - - zoffset start() const; - zoffset_end end() const; - size_t size() const; - - bool is_committed() const; - void set_committed(bool committed); -}; - -class ZPhysicalMemory { -private: - ZArray _segments; - - void insert_segment(int index, zoffset start, size_t size, bool committed); - void replace_segment(int index, zoffset start, size_t size, bool committed); - void remove_segment(int index); - -public: - ZPhysicalMemory(); - ZPhysicalMemory(const ZPhysicalMemorySegment& segment); - ZPhysicalMemory(const ZPhysicalMemory& pmem); - const ZPhysicalMemory& operator=(const ZPhysicalMemory& pmem); - - bool is_null() const; - size_t size() const; - - int nsegments() const; - const ZPhysicalMemorySegment& segment(int index) const; - - void add_segments(const ZPhysicalMemory& pmem); - void remove_segments(); - - void add_segment(const ZPhysicalMemorySegment& segment); - bool commit_segment(int index, size_t size); - bool uncommit_segment(int index, size_t size); - - ZPhysicalMemory split(size_t size); - ZPhysicalMemory split_committed(); -}; - -class ZPhysicalMemoryManager { -private: - ZPhysicalMemoryBacking _backing; - ZMemoryManager _manager; - -public: - ZPhysicalMemoryManager(size_t max_capacity); - - bool is_initialized() const; - - void warn_commit_limits(size_t max_capacity) const; - void try_enable_uncommit(size_t min_capacity, size_t max_capacity); - - void alloc(ZPhysicalMemory& pmem, size_t size); - void free(const ZPhysicalMemory& pmem); - - bool commit(ZPhysicalMemory& pmem); - bool uncommit(ZPhysicalMemory& pmem); - - void map(zoffset offset, const ZPhysicalMemory& pmem) const; - void unmap(zoffset offset, size_t size) const; -}; - -#endif // SHARE_GC_Z_ZPHYSICALMEMORY_HPP diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.inline.hpp b/src/hotspot/share/gc/z/zPhysicalMemory.inline.hpp deleted file mode 100644 index 6d2380c9013..00000000000 --- a/src/hotspot/share/gc/z/zPhysicalMemory.inline.hpp +++ /dev/null @@ -1,74 +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. - * - * 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_GC_Z_ZPHYSICALMEMORY_INLINE_HPP -#define SHARE_GC_Z_ZPHYSICALMEMORY_INLINE_HPP - -#include "gc/z/zPhysicalMemory.hpp" - -#include "gc/z/zAddress.inline.hpp" -#include "utilities/debug.hpp" - -inline ZPhysicalMemorySegment::ZPhysicalMemorySegment() - : _start(zoffset(UINTPTR_MAX)), - _end(zoffset_end(UINTPTR_MAX)), - _committed(false) {} - -inline ZPhysicalMemorySegment::ZPhysicalMemorySegment(zoffset start, size_t size, bool committed) - : _start(start), - _end(to_zoffset_end(start, size)), - _committed(committed) {} - -inline zoffset ZPhysicalMemorySegment::start() const { - return _start; -} - -inline zoffset_end ZPhysicalMemorySegment::end() const { - return _end; -} - -inline size_t ZPhysicalMemorySegment::size() const { - return _end - _start; -} - -inline bool ZPhysicalMemorySegment::is_committed() const { - return _committed; -} - -inline void ZPhysicalMemorySegment::set_committed(bool committed) { - _committed = committed; -} - -inline bool ZPhysicalMemory::is_null() const { - return _segments.length() == 0; -} - -inline int ZPhysicalMemory::nsegments() const { - return _segments.length(); -} - -inline const ZPhysicalMemorySegment& ZPhysicalMemory::segment(int index) const { - return _segments.at(index); -} - -#endif // SHARE_GC_Z_ZPHYSICALMEMORY_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp b/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp new file mode 100644 index 00000000000..8f9b8f2a285 --- /dev/null +++ b/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "gc/shared/gcLogPrecious.hpp" +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zArray.inline.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zLargePages.inline.hpp" +#include "gc/z/zList.inline.hpp" +#include "gc/z/zNMT.hpp" +#include "gc/z/zNUMA.inline.hpp" +#include "gc/z/zPhysicalMemoryManager.hpp" +#include "gc/z/zRangeRegistry.inline.hpp" +#include "gc/z/zUtils.inline.hpp" +#include "gc/z/zValue.inline.hpp" +#include "gc/z/zVirtualMemory.inline.hpp" +#include "logging/log.hpp" +#include "runtime/globals.hpp" +#include "runtime/globals_extension.hpp" +#include "runtime/init.hpp" +#include "runtime/os.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" + +ZPhysicalMemoryManager::ZPhysicalMemoryManager(size_t max_capacity) + : _backing(max_capacity), + _physical_mappings(ZAddressOffsetMax) { + assert(is_aligned(max_capacity, ZGranuleSize), "must be granule aligned"); + + // Setup backing storage limits + ZBackingOffsetMax = max_capacity; + ZBackingIndexMax = checked_cast(max_capacity >> ZGranuleSizeShift); + + // Install capacity into the registry + const size_t num_segments_total = max_capacity >> ZGranuleSizeShift; + zbacking_index_end next_index = zbacking_index_end::zero; + uint32_t numa_id; + ZPerNUMAIterator iter(&_partition_registries); + for (ZBackingIndexRegistry* registry; iter.next(®istry, &numa_id);) { + const size_t num_segments = ZNUMA::calculate_share(numa_id, num_segments_total, 1 /* granule */); + + if (num_segments == 0) { + // If the capacity consist of less granules than the number of partitions, + // some partitions will be empty. + break; + } + + const zbacking_index index = to_zbacking_index(next_index); + + // Insert the next number of segment indices into id's partition's registry + registry->insert({index, num_segments}); + + // Advance to next index by the inserted number of segment indices + next_index += num_segments; + } + + assert(untype(next_index) == ZBackingIndexMax, "must insert all capacity"); +} + +bool ZPhysicalMemoryManager::is_initialized() const { + return _backing.is_initialized(); +} + +void ZPhysicalMemoryManager::warn_commit_limits(size_t max_capacity) const { + _backing.warn_commit_limits(max_capacity); +} + +void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max_capacity) { + assert(!is_init_completed(), "Invalid state"); + + // If uncommit is not explicitly disabled, max capacity is greater than + // min capacity, and uncommit is supported by the platform, then uncommit + // will be enabled. + if (!ZUncommit) { + log_info_p(gc, init)("Uncommit: Disabled"); + return; + } + + if (max_capacity == min_capacity) { + log_info_p(gc, init)("Uncommit: Implicitly Disabled (-Xms equals -Xmx)"); + FLAG_SET_ERGO(ZUncommit, false); + return; + } + + // Test if uncommit is supported by the operating system by committing + // and then uncommitting a granule. + const ZVirtualMemory vmem(zoffset(0), ZGranuleSize); + if (!commit(vmem, (uint32_t)-1) || !uncommit(vmem)) { + log_info_p(gc, init)("Uncommit: Implicitly Disabled (Not supported by operating system)"); + FLAG_SET_ERGO(ZUncommit, false); + return; + } + + log_info_p(gc, init)("Uncommit: Enabled"); + log_info_p(gc, init)("Uncommit Delay: %zus", ZUncommitDelay); +} + +void ZPhysicalMemoryManager::alloc(const ZVirtualMemory& vmem, uint32_t numa_id) { + zbacking_index* const pmem = _physical_mappings.addr(vmem.start()); + const size_t size = vmem.size(); + + assert(is_aligned(size, ZGranuleSize), "Invalid size"); + + size_t current_segment = 0; + size_t remaining_segments = size >> ZGranuleSizeShift; + + while (remaining_segments != 0) { + // Allocate a range of backing segment indices + ZBackingIndexRegistry& registry = _partition_registries.get(numa_id); + const ZBackingIndexRange range = registry.remove_from_low_at_most(remaining_segments); + assert(!range.is_null(), "Allocation should never fail"); + + const size_t num_allocated_segments = range.size(); + + // Insert backing segment indices in pmem + const zbacking_index start_i = range.start(); + for (size_t i = 0; i < num_allocated_segments; i++) { + pmem[current_segment + i] = start_i + i; + } + + // Advance by number of allocated segments + remaining_segments -= num_allocated_segments; + current_segment += num_allocated_segments; + } +} + +template +struct IterateInvoker { + template + bool operator()(Function function, zbacking_offset segment_start, size_t segment_size) const { + return function(segment_start, segment_size); + } +}; + +template<> +struct IterateInvoker { + template + bool operator()(Function function, zbacking_offset segment_start, size_t segment_size) const { + function(segment_start, segment_size); + return true; + } +}; + +template +bool for_each_segment_apply(const zbacking_index* pmem, size_t size, Function function) { + IterateInvoker invoker; + + // Total number of segment indices + const size_t num_segments = size >> ZGranuleSizeShift; + + // Apply the function over all zbacking_offset ranges consisting of consecutive indices + for (size_t i = 0; i < num_segments; i++) { + const size_t start_i = i; + + // Find index corresponding to the last index in the consecutive range starting at start_i + while (i + 1 < num_segments && to_zbacking_index_end(pmem[i], 1) == pmem[i + 1]) { + i++; + } + + const size_t last_i = i; + + // [start_i, last_i] now forms a consecutive range of indicies in pmem + const size_t num_indicies = last_i - start_i + 1; + const zbacking_offset start = to_zbacking_offset(pmem[start_i]); + const size_t size = num_indicies * ZGranuleSize; + + // Invoke function on zbacking_offset Range [start, start + size[ + if (!invoker(function, start, size)) { + return false; + } + } + + return true; +} + +void ZPhysicalMemoryManager::free(const ZVirtualMemory& vmem, uint32_t numa_id) { + zbacking_index* const pmem = _physical_mappings.addr(vmem.start()); + const size_t size = vmem.size(); + + // Free segments + for_each_segment_apply(pmem, size, [&](zbacking_offset segment_start, size_t segment_size) { + const size_t num_segments = segment_size >> ZGranuleSizeShift; + const zbacking_index index = to_zbacking_index(segment_start); + + // Insert the free segment indices + _partition_registries.get(numa_id).insert({index, num_segments}); + }); +} + +size_t ZPhysicalMemoryManager::commit(const ZVirtualMemory& vmem, uint32_t numa_id) { + zbacking_index* const pmem = _physical_mappings.addr(vmem.start()); + const size_t size = vmem.size(); + + size_t total_committed = 0; + + // Commit segments + for_each_segment_apply(pmem, size, [&](zbacking_offset segment_start, size_t segment_size) { + // Commit segment + const size_t committed = _backing.commit(segment_start, segment_size, numa_id); + + total_committed += committed; + + // Register with NMT + if (committed > 0) { + ZNMT::commit(segment_start, committed); + } + + return segment_size == committed; + }); + + // Success + return total_committed; +} + +size_t ZPhysicalMemoryManager::uncommit(const ZVirtualMemory& vmem) { + zbacking_index* const pmem = _physical_mappings.addr(vmem.start()); + const size_t size = vmem.size(); + + size_t total_uncommitted = 0; + + // Uncommit segments + for_each_segment_apply(pmem, size, [&](zbacking_offset segment_start, size_t segment_size) { + // Uncommit segment + const size_t uncommitted = _backing.uncommit(segment_start, segment_size); + + total_uncommitted += uncommitted; + + // Unregister with NMT + if (uncommitted > 0) { + ZNMT::uncommit(segment_start, uncommitted); + } + + return segment_size == uncommitted; + }); + + // Success + return total_uncommitted; +} + +// Map virtual memory to physical memory +void ZPhysicalMemoryManager::map(const ZVirtualMemory& vmem, uint32_t numa_id) const { + const zbacking_index* const pmem = _physical_mappings.addr(vmem.start()); + const zaddress_unsafe addr = ZOffset::address_unsafe(vmem.start()); + const size_t size = vmem.size(); + + size_t mapped = 0; + + for_each_segment_apply(pmem, size, [&](zbacking_offset segment_start, size_t segment_size) { + _backing.map(addr + mapped, segment_size, segment_start); + mapped += segment_size; + }); + + postcond(mapped == size); + + // Setup NUMA preferred for large pages + if (ZNUMA::is_enabled() && ZLargePages::is_explicit()) { + os::numa_make_local((char*)addr, size, (int)numa_id); + } +} + +// Unmap virtual memory from physical memory +void ZPhysicalMemoryManager::unmap(const ZVirtualMemory& vmem) const { + const zaddress_unsafe addr = ZOffset::address_unsafe(vmem.start()); + const size_t size = vmem.size(); + _backing.unmap(addr, size); +} + +void ZPhysicalMemoryManager::copy_physical_segments(const ZVirtualMemory& to, const ZVirtualMemory& from) { + assert(to.size() == from.size(), "must be of the same size"); + + zbacking_index* const dest = _physical_mappings.addr(to.start()); + const zbacking_index* const src = _physical_mappings.addr(from.start()); + const int granule_count = from.granule_count(); + + ZUtils::copy_disjoint(dest, src, granule_count); +} + +static void sort_zbacking_index_array(zbacking_index* array, int count) { + ZUtils::sort(array, count, [](const zbacking_index* e1, const zbacking_index* e2) { + return *e1 < *e2 ? -1 : 1; + }); +} + +void ZPhysicalMemoryManager::sort_segments_physical(const ZVirtualMemory& vmem) { + zbacking_index* const pmem = _physical_mappings.addr(vmem.start()); + const int granule_count = vmem.granule_count(); + + // Sort physical segments + sort_zbacking_index_array(pmem, granule_count); +} + +void ZPhysicalMemoryManager::copy_to_stash(ZArraySlice stash, const ZVirtualMemory& vmem) const { + zbacking_index* const dest = stash.adr_at(0); + const zbacking_index* const src = _physical_mappings.addr(vmem.start()); + const int granule_count = vmem.granule_count(); + + // Check bounds + assert(granule_count <= stash.length(), "Copy overflow %d <= %d", granule_count, stash.length()); + + // Copy to stash + ZUtils::copy_disjoint(dest, src, granule_count); +} + +void ZPhysicalMemoryManager::copy_from_stash(const ZArraySlice stash, const ZVirtualMemory& vmem) { + zbacking_index* const dest = _physical_mappings.addr(vmem.start()); + const zbacking_index* const src = stash.adr_at(0); + const int granule_count = vmem.granule_count(); + + // Check bounds + assert(granule_count <= stash.length(), "Copy overflow %d <= %d", granule_count, stash.length()); + + // Copy from stash + ZUtils::copy_disjoint(dest, src, granule_count); +} + +void ZPhysicalMemoryManager::stash_segments(const ZVirtualMemory& vmem, ZArray* stash_out) const { + precond(stash_out->is_empty()); + + stash_out->at_grow(vmem.granule_count() - 1); + copy_to_stash(*stash_out, vmem); + sort_zbacking_index_array(stash_out->adr_at(0), stash_out->length()); +} + +void ZPhysicalMemoryManager::restore_segments(const ZVirtualMemory& vmem, const ZArray& stash) { + assert(vmem.granule_count() == stash.length(), "Must match stash size"); + + copy_from_stash(stash, vmem); +} + +void ZPhysicalMemoryManager::stash_segments(const ZArraySlice& vmems, ZArray* stash_out) const { + precond(stash_out->is_empty()); + + int stash_index = 0; + for (const ZVirtualMemory& vmem : vmems) { + const int granule_count = vmem.granule_count(); + stash_out->at_grow(stash_index + vmem.granule_count() - 1); + copy_to_stash(stash_out->slice_back(stash_index), vmem); + stash_index += granule_count; + } + + sort_zbacking_index_array(stash_out->adr_at(0), stash_out->length()); + +} + +void ZPhysicalMemoryManager::restore_segments(const ZArraySlice& vmems, const ZArray& stash) { + int stash_index = 0; + + for (const ZVirtualMemory& vmem : vmems) { + copy_from_stash(stash.slice_back(stash_index), vmem); + stash_index += vmem.granule_count(); + } + + assert(stash_index == stash.length(), "Must have emptied the stash"); +} diff --git a/src/hotspot/share/gc/z/zPhysicalMemoryManager.hpp b/src/hotspot/share/gc/z/zPhysicalMemoryManager.hpp new file mode 100644 index 00000000000..99de34beda7 --- /dev/null +++ b/src/hotspot/share/gc/z/zPhysicalMemoryManager.hpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZPHYSICALMEMORYMANAGER_HPP +#define SHARE_GC_Z_ZPHYSICALMEMORYMANAGER_HPP + +#include "gc/z/zAddress.hpp" +#include "gc/z/zArray.hpp" +#include "gc/z/zGranuleMap.hpp" +#include "gc/z/zRange.hpp" +#include "gc/z/zRangeRegistry.hpp" +#include "gc/z/zValue.hpp" +#include "memory/allocation.hpp" +#include OS_HEADER(gc/z/zPhysicalMemoryBacking) + +class ZVirtualMemory; + +using ZBackingIndexRange = ZRange; + +class ZPhysicalMemoryManager { +private: + using ZBackingIndexRegistry = ZRangeRegistry; + + ZPhysicalMemoryBacking _backing; + ZPerNUMA _partition_registries; + ZGranuleMap _physical_mappings; + + void copy_to_stash(ZArraySlice stash, const ZVirtualMemory& vmem) const; + void copy_from_stash(const ZArraySlice stash, const ZVirtualMemory& vmem); + +public: + ZPhysicalMemoryManager(size_t max_capacity); + + bool is_initialized() const; + + void warn_commit_limits(size_t max_capacity) const; + void try_enable_uncommit(size_t min_capacity, size_t max_capacity); + + void alloc(const ZVirtualMemory& vmem, uint32_t numa_id); + void free(const ZVirtualMemory& vmem, uint32_t numa_id); + + size_t commit(const ZVirtualMemory& vmem, uint32_t numa_id); + size_t uncommit(const ZVirtualMemory& vmem); + + void map(const ZVirtualMemory& vmem, uint32_t numa_id) const; + void unmap(const ZVirtualMemory& vmem) const; + + void copy_physical_segments(const ZVirtualMemory& to, const ZVirtualMemory& from); + + void sort_segments_physical(const ZVirtualMemory& vmem); + + void stash_segments(const ZVirtualMemory& vmem, ZArray* stash_out) const; + void restore_segments(const ZVirtualMemory& vmem, const ZArray& stash); + + void stash_segments(const ZArraySlice& vmems, ZArray* stash_out) const; + void restore_segments(const ZArraySlice& vmems, const ZArray& stash); +}; + +#endif // SHARE_GC_Z_ZPHYSICALMEMORYMANAGER_HPP diff --git a/src/hotspot/share/gc/z/zRange.hpp b/src/hotspot/share/gc/z/zRange.hpp new file mode 100644 index 00000000000..53c9980608e --- /dev/null +++ b/src/hotspot/share/gc/z/zRange.hpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZRANGE_HPP +#define SHARE_GC_Z_ZRANGE_HPP + +#include "utilities/globalDefinitions.hpp" + +template +class ZRange { + friend class VMStructs; + +public: + using offset = Start; + using offset_end = End; + +private: + End _start; + size_t _size; + + // Used internally to create a ZRange. + // + // The end parameter is only used for verification and to distinguish + // the constructors if End == Start. + ZRange(End start, size_t size, End end); + +public: + ZRange(); + ZRange(Start start, size_t size); + + bool is_null() const; + + Start start() const; + End end() const; + + size_t size() const; + + bool operator==(const ZRange& other) const; + bool operator!=(const ZRange& other) const; + + bool contains(const ZRange& other) const; + + void grow_from_front(size_t size); + void grow_from_back(size_t size); + + ZRange shrink_from_front(size_t size); + ZRange shrink_from_back(size_t size); + + ZRange partition(size_t offset, size_t partition_size) const; + ZRange first_part(size_t split_offset) const; + ZRange last_part(size_t split_offset) const; + + bool adjacent_to(const ZRange& other) const; +}; + +#endif // SHARE_GC_Z_ZRANGE_HPP diff --git a/src/hotspot/share/gc/z/zRange.inline.hpp b/src/hotspot/share/gc/z/zRange.inline.hpp new file mode 100644 index 00000000000..d99cbefd32a --- /dev/null +++ b/src/hotspot/share/gc/z/zRange.inline.hpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZRANGE_INLINE_HPP +#define SHARE_GC_Z_ZRANGE_INLINE_HPP + +#include "gc/z/zRange.hpp" + +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" + +template +inline ZRange::ZRange(End start, size_t size, End end) + : _start(start), + _size(size) { + postcond(this->end() == end); +} + +template +inline ZRange::ZRange() + : _start(End::invalid), + _size(0) {} + +template +inline ZRange::ZRange(Start start, size_t size) + : _start(to_end_type(start, 0)), + _size(size) {} + +template +inline bool ZRange::is_null() const { + return _start == End::invalid; +} + +template +inline Start ZRange::start() const { + return to_start_type(_start); +} + +template +inline End ZRange::end() const { + return _start + _size; +} + +template +inline size_t ZRange::size() const { + return _size; +} + +template +inline bool ZRange::operator==(const ZRange& other) const { + precond(!is_null()); + precond(!other.is_null()); + + return _start == other._start && _size == other._size; +} + +template +inline bool ZRange::operator!=(const ZRange& other) const { + return !operator==(other); +} + +template +inline bool ZRange::contains(const ZRange& other) const { + precond(!is_null()); + precond(!other.is_null()); + + return _start <= other._start && other.end() <= end(); +} + +template +inline void ZRange::grow_from_front(size_t size) { + precond(size_t(start()) >= size); + + _start -= size; + _size += size; +} + +template +inline void ZRange::grow_from_back(size_t size) { + _size += size; +} + +template +inline ZRange ZRange::shrink_from_front(size_t size) { + precond(this->size() >= size); + + _start += size; + _size -= size; + + return ZRange(_start - size, size, _start); +} + +template +inline ZRange ZRange::shrink_from_back(size_t size) { + precond(this->size() >= size); + + _size -= size; + + return ZRange(end(), size, end() + size); +} + +template +inline ZRange ZRange::partition(size_t offset, size_t partition_size) const { + precond(size() - offset >= partition_size); + + return ZRange(_start + offset, partition_size, _start + offset + partition_size); +} + +template +inline ZRange ZRange::first_part(size_t split_offset) const { + return partition(0, split_offset); +} + +template +inline ZRange ZRange::last_part(size_t split_offset) const { + return partition(split_offset, size() - split_offset); +} + +template +inline bool ZRange::adjacent_to(const ZRange& other) const { + return end() == other.start() || other.end() == start(); +} + +#endif // SHARE_GC_Z_ZRANGE_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zRangeRegistry.hpp b/src/hotspot/share/gc/z/zRangeRegistry.hpp new file mode 100644 index 00000000000..8a5ba74da6e --- /dev/null +++ b/src/hotspot/share/gc/z/zRangeRegistry.hpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZRANGEREGISTRY_HPP +#define SHARE_GC_Z_ZRANGEREGISTRY_HPP + +#include "gc/z/zAddress.hpp" +#include "gc/z/zList.hpp" +#include "gc/z/zLock.hpp" +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" + +template +class ZArray; + +template +class ZRangeRegistry { + friend class ZVirtualMemoryManagerTest; + +private: + // The node type for the list of Ranges + class Node; + +public: + using offset = typename Range::offset; + using offset_end = typename Range::offset_end; + + typedef void (*CallbackPrepare)(const Range& range); + typedef void (*CallbackResize)(const Range& from, const Range& to); + + struct Callbacks { + CallbackPrepare _prepare_for_hand_out; + CallbackPrepare _prepare_for_hand_back; + CallbackResize _grow; + CallbackResize _shrink; + + Callbacks(); + }; + +private: + mutable ZLock _lock; + ZList _list; + Callbacks _callbacks; + Range _limits; + + void move_into(const Range& range); + + void insert_inner(const Range& range); + void register_inner(const Range& range); + + void grow_from_front(Range* range, size_t size); + void grow_from_back(Range* range, size_t size); + + Range shrink_from_front(Range* range, size_t size); + Range shrink_from_back(Range* range, size_t size); + + Range remove_from_low_inner(size_t size); + Range remove_from_low_at_most_inner(size_t size); + + size_t remove_from_low_many_at_most_inner(size_t size, ZArray* out); + + bool check_limits(const Range& range) const; + +public: + ZRangeRegistry(); + + void register_callbacks(const Callbacks& callbacks); + + void register_range(const Range& range); + bool unregister_first(Range* out); + + bool is_empty() const; + bool is_contiguous() const; + + void anchor_limits(); + bool limits_contain(const Range& range) const; + + offset peek_low_address() const; + offset_end peak_high_address_end() const; + + void insert(const Range& range); + + void insert_and_remove_from_low_many(const Range& range, ZArray* out); + Range insert_and_remove_from_low_exact_or_many(size_t size, ZArray* in_out); + + Range remove_from_low(size_t size); + Range remove_from_low_at_most(size_t size); + size_t remove_from_low_many_at_most(size_t size, ZArray* out); + Range remove_from_high(size_t size); + + void transfer_from_low(ZRangeRegistry* other, size_t size); +}; + +template +class ZRangeRegistry::Node : public CHeapObj { + friend class ZList; + +private: + using offset = typename Range::offset; + using offset_end = typename Range::offset_end; + + Range _range; + ZListNode _node; + +public: + Node(offset start, size_t size) + : _range(start, size), + _node() {} + + Node(const Range& other) + : Node(other.start(), other.size()) {} + + Range* range() { + return &_range; + } + + offset start() const { + return _range.start(); + } + + offset_end end() const { + return _range.end(); + } + + size_t size() const { + return _range.size(); + } +}; + +#endif // SHARE_GC_Z_ZRANGEREGISTRY_HPP diff --git a/src/hotspot/share/gc/z/zRangeRegistry.inline.hpp b/src/hotspot/share/gc/z/zRangeRegistry.inline.hpp new file mode 100644 index 00000000000..de34aca07c4 --- /dev/null +++ b/src/hotspot/share/gc/z/zRangeRegistry.inline.hpp @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZRANGEREGISTRY_INLINE_HPP +#define SHARE_GC_Z_ZRANGEREGISTRY_INLINE_HPP + +#include "gc/z/zRangeRegistry.hpp" + +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zList.inline.hpp" +#include "gc/z/zLock.inline.hpp" + +template +void ZRangeRegistry::move_into(const Range& range) { + assert(!range.is_null(), "Invalid range"); + assert(check_limits(range), "Range outside limits"); + + const offset start = range.start(); + const offset_end end = range.end(); + const size_t size = range.size(); + + ZListIterator iter(&_list); + for (Node* node; iter.next(&node);) { + if (node->start() < start) { + continue; + } + + Node* const prev = _list.prev(node); + if (prev != nullptr && start == prev->end()) { + if (end == node->start()) { + // Merge with prev and current ranges + grow_from_back(prev->range(), size); + grow_from_back(prev->range(), node->size()); + _list.remove(node); + delete node; + } else { + // Merge with prev range + grow_from_back(prev->range(), size); + } + } else if (end == node->start()) { + // Merge with current range + grow_from_front(node->range(), size); + } else { + // Insert range before current range + assert(end < node->start(), "Areas must not overlap"); + Node* const new_node = new Node(start, size); + _list.insert_before(node, new_node); + } + + // Done + return; + } + + // Insert last + Node* const last = _list.last(); + if (last != nullptr && start == last->end()) { + // Merge with last range + grow_from_back(last->range(), size); + } else { + // Insert new node last + Node* const new_node = new Node(start, size); + _list.insert_last(new_node); + } +} + +template +void ZRangeRegistry::insert_inner(const Range& range) { + if (_callbacks._prepare_for_hand_back != nullptr) { + _callbacks._prepare_for_hand_back(range); + } + move_into(range); +} + +template +void ZRangeRegistry::register_inner(const Range& range) { + move_into(range); +} + +template +void ZRangeRegistry::grow_from_front(Range* range, size_t size) { + if (_callbacks._grow != nullptr) { + const Range from = *range; + const Range to = Range(from.start() - size, from.size() + size); + _callbacks._grow(from, to); + } + range->grow_from_front(size); +} + +template +void ZRangeRegistry::grow_from_back(Range* range, size_t size) { + if (_callbacks._grow != nullptr) { + const Range from = *range; + const Range to = Range(from.start(), from.size() + size); + _callbacks._grow(from, to); + } + range->grow_from_back(size); +} + +template +Range ZRangeRegistry::shrink_from_front(Range* range, size_t size) { + if (_callbacks._shrink != nullptr) { + const Range from = *range; + const Range to = from.last_part(size); + _callbacks._shrink(from, to); + } + return range->shrink_from_front(size); +} + +template +Range ZRangeRegistry::shrink_from_back(Range* range, size_t size) { + if (_callbacks._shrink != nullptr) { + const Range from = *range; + const Range to = from.first_part(from.size() - size); + _callbacks._shrink(from, to); + } + return range->shrink_from_back(size); +} + +template +Range ZRangeRegistry::remove_from_low_inner(size_t size) { + ZListIterator iter(&_list); + for (Node* node; iter.next(&node);) { + if (node->size() >= size) { + Range range; + + if (node->size() == size) { + // Exact match, remove range + _list.remove(node); + range = *node->range(); + delete node; + } else { + // Larger than requested, shrink range + range = shrink_from_front(node->range(), size); + } + + if (_callbacks._prepare_for_hand_out != nullptr) { + _callbacks._prepare_for_hand_out(range); + } + + return range; + } + } + + // Out of memory + return Range(); +} + +template +Range ZRangeRegistry::remove_from_low_at_most_inner(size_t size) { + Node* const node = _list.first(); + if (node == nullptr) { + // List is empty + return Range(); + } + + Range range; + + if (node->size() <= size) { + // Smaller than or equal to requested, remove range + _list.remove(node); + range = *node->range(); + delete node; + } else { + // Larger than requested, shrink range + range = shrink_from_front(node->range(), size); + } + + if (_callbacks._prepare_for_hand_out) { + _callbacks._prepare_for_hand_out(range); + } + + return range; +} + +template +size_t ZRangeRegistry::remove_from_low_many_at_most_inner(size_t size, ZArray* out) { + size_t to_remove = size; + + while (to_remove > 0) { + const Range range = remove_from_low_at_most_inner(to_remove); + + if (range.is_null()) { + // The requested amount is not available + return size - to_remove; + } + + to_remove -= range.size(); + out->append(range); + } + + return size; +} + +template +ZRangeRegistry::Callbacks::Callbacks() + : _prepare_for_hand_out(nullptr), + _prepare_for_hand_back(nullptr), + _grow(nullptr), + _shrink(nullptr) {} + +template +ZRangeRegistry::ZRangeRegistry() + : _list(), + _callbacks(), + _limits() {} + +template +void ZRangeRegistry::register_callbacks(const Callbacks& callbacks) { + _callbacks = callbacks; +} + +template +void ZRangeRegistry::register_range(const Range& range) { + ZLocker locker(&_lock); + register_inner(range); +} + +template +bool ZRangeRegistry::unregister_first(Range* out) { + // Unregistering a range doesn't call a "prepare_to_hand_out" callback + // because the range is unregistered and not handed out to be used. + + ZLocker locker(&_lock); + + if (_list.is_empty()) { + return false; + } + + // Don't invoke the "prepare_to_hand_out" callback + + Node* const node = _list.remove_first(); + + // Return the range + *out = *node->range(); + + delete node; + + return true; +} + +template +inline bool ZRangeRegistry::is_empty() const { + return _list.is_empty(); +} + +template +bool ZRangeRegistry::is_contiguous() const { + return _list.size() == 1; +} + +template +void ZRangeRegistry::anchor_limits() { + assert(_limits.is_null(), "Should only anchor limits once"); + + if (_list.is_empty()) { + return; + } + + const offset start = _list.first()->start(); + const size_t size = _list.last()->end() - start; + + _limits = Range(start, size); +} + +template +bool ZRangeRegistry::limits_contain(const Range& range) const { + if (_limits.is_null() || range.is_null()) { + return false; + } + + return range.start() >= _limits.start() && range.end() <= _limits.end(); +} + +template +bool ZRangeRegistry::check_limits(const Range& range) const { + if (_limits.is_null()) { + // Limits not anchored + return true; + } + + // Otherwise, check that other is within the limits + return limits_contain(range); +} + +template +typename ZRangeRegistry::offset ZRangeRegistry::peek_low_address() const { + ZLocker locker(&_lock); + + const Node* const node = _list.first(); + if (node != nullptr) { + return node->start(); + } + + // Out of memory + return offset::invalid; +} + +template +typename ZRangeRegistry::offset_end ZRangeRegistry::peak_high_address_end() const { + ZLocker locker(&_lock); + + const Node* const node = _list.last(); + if (node != nullptr) { + return node->end(); + } + + // Out of memory + return offset_end::invalid; +} + +template +void ZRangeRegistry::insert(const Range& range) { + ZLocker locker(&_lock); + insert_inner(range); +} + +template +void ZRangeRegistry::insert_and_remove_from_low_many(const Range& range, ZArray* out) { + ZLocker locker(&_lock); + + const size_t size = range.size(); + + // Insert the range + insert_inner(range); + + // Remove (hopefully) at a lower address + const size_t removed = remove_from_low_many_at_most_inner(size, out); + + // This should always succeed since we freed the same amount. + assert(removed == size, "must succeed"); +} + +template +Range ZRangeRegistry::insert_and_remove_from_low_exact_or_many(size_t size, ZArray* in_out) { + ZLocker locker(&_lock); + + size_t inserted = 0; + + // Insert everything + ZArrayIterator iter(in_out); + for (Range mem; iter.next(&mem);) { + insert_inner(mem); + inserted += mem.size(); + } + + // Clear stored memory so that we can populate it below + in_out->clear(); + + // Try to find and remove a contiguous chunk + Range range = remove_from_low_inner(size); + if (!range.is_null()) { + return range; + } + + // Failed to find a contiguous chunk, split it up into smaller chunks and + // only remove up to as much that has been inserted. + size_t removed = remove_from_low_many_at_most_inner(inserted, in_out); + assert(removed == inserted, "Should be able to get back as much as we previously inserted"); + return Range(); +} + +template +Range ZRangeRegistry::remove_from_low(size_t size) { + ZLocker locker(&_lock); + Range range = remove_from_low_inner(size); + return range; +} + +template +Range ZRangeRegistry::remove_from_low_at_most(size_t size) { + ZLocker lock(&_lock); + Range range = remove_from_low_at_most_inner(size); + return range; +} + +template +size_t ZRangeRegistry::remove_from_low_many_at_most(size_t size, ZArray* out) { + ZLocker lock(&_lock); + return remove_from_low_many_at_most_inner(size, out); +} + +template +Range ZRangeRegistry::remove_from_high(size_t size) { + ZLocker locker(&_lock); + + ZListReverseIterator iter(&_list); + for (Node* node; iter.next(&node);) { + if (node->size() >= size) { + Range range; + + if (node->size() == size) { + // Exact match, remove range + _list.remove(node); + range = *node->range(); + delete node; + } else { + // Larger than requested, shrink range + range = shrink_from_back(node->range(), size); + } + + if (_callbacks._prepare_for_hand_out != nullptr) { + _callbacks._prepare_for_hand_out(range); + } + + return range; + } + } + + // Out of memory + return Range(); +} + +template +void ZRangeRegistry::transfer_from_low(ZRangeRegistry* other, size_t size) { + assert(other->_list.is_empty(), "Should only be used for initialization"); + + ZLocker locker(&_lock); + size_t to_move = size; + + ZListIterator iter(&_list); + for (Node* node; iter.next(&node);) { + Node* to_transfer; + + if (node->size() <= to_move) { + // Smaller than or equal to requested, remove range + _list.remove(node); + to_transfer = node; + } else { + // Larger than requested, shrink range + const Range range = shrink_from_front(node->range(), to_move); + to_transfer = new Node(range); + } + + // Insert into the other list + // + // The from list is sorted, the other list starts empty, and the inserts + // come in sort order, so we can insert_last here. + other->_list.insert_last(to_transfer); + + to_move -= to_transfer->size(); + if (to_move == 0) { + break; + } + } + + assert(to_move == 0, "Should have transferred requested size"); +} + +#endif // SHARE_GC_Z_ZRANGEREGISTRY_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zRelocate.cpp b/src/hotspot/share/gc/z/zRelocate.cpp index 213452e8d05..b4ae78bc8d9 100644 --- a/src/hotspot/share/gc/z/zRelocate.cpp +++ b/src/hotspot/share/gc/z/zRelocate.cpp @@ -410,7 +410,7 @@ static void retire_target_page(ZGeneration* generation, ZPage* page) { // relocate the remaining objects, leaving the target page empty when // relocation completed. if (page->used() == 0) { - ZHeap::heap()->free_page(page, true /* allow_defragment */); + ZHeap::heap()->free_page(page); } } @@ -841,14 +841,12 @@ private: const bool promotion = _forwarding->is_promotion(); // Promotions happen through a new cloned page - ZPage* const to_page = promotion ? from_page->clone_limited() : from_page; + ZPage* const to_page = promotion + ? from_page->clone_for_promotion() + : from_page->reset(to_age); // Reset page for in-place relocation - to_page->reset(to_age); to_page->reset_top_for_allocation(); - if (promotion) { - to_page->remset_alloc(); - } // Verify that the inactive remset is clear when resetting the page for // in-place relocation. @@ -1011,7 +1009,7 @@ public: page->log_msg(" (relocate page done normal)"); // Free page - ZHeap::heap()->free_page(page, true /* allow_defragment */); + ZHeap::heap()->free_page(page); } } }; @@ -1260,14 +1258,12 @@ public: prev_page->log_msg(promotion ? " (flip promoted)" : " (flip survived)"); // Setup to-space page - ZPage* const new_page = promotion ? prev_page->clone_limited() : prev_page; + ZPage* const new_page = promotion + ? prev_page->clone_for_promotion() + : prev_page->reset(to_age); // Reset page for flip aging - new_page->reset(to_age); new_page->reset_livemap(); - if (promotion) { - new_page->remset_alloc(); - } if (promotion) { ZGeneration::young()->flip_promote(prev_page, new_page); diff --git a/src/hotspot/share/gc/z/zRemembered.cpp b/src/hotspot/share/gc/z/zRemembered.cpp index 3bb17152d41..b94d676242c 100644 --- a/src/hotspot/share/gc/z/zRemembered.cpp +++ b/src/hotspot/share/gc/z/zRemembered.cpp @@ -473,11 +473,9 @@ public: _remset_table_iterator(remembered) { _mark->prepare_work(); _remembered->_page_allocator->enable_safe_destroy(); - _remembered->_page_allocator->enable_safe_recycle(); } ~ZRememberedScanMarkFollowTask() { - _remembered->_page_allocator->disable_safe_recycle(); _remembered->_page_allocator->disable_safe_destroy(); _mark->finish_work(); // We are done scanning the set of old pages. diff --git a/src/hotspot/share/gc/z/zRememberedSet.cpp b/src/hotspot/share/gc/z/zRememberedSet.cpp index f833c5b2336..2de62752d91 100644 --- a/src/hotspot/share/gc/z/zRememberedSet.cpp +++ b/src/hotspot/share/gc/z/zRememberedSet.cpp @@ -54,12 +54,6 @@ void ZRememberedSet::initialize(size_t page_size) { _bitmap[1].initialize(size_in_bits, true /* clear */); } -void ZRememberedSet::delete_all() { - assert(is_initialized(), "precondition"); - _bitmap[0].resize(0); - _bitmap[1].resize(0); -} - bool ZRememberedSet::is_cleared_current() const { return current()->is_empty(); } diff --git a/src/hotspot/share/gc/z/zRememberedSet.hpp b/src/hotspot/share/gc/z/zRememberedSet.hpp index c3c6e8bc313..6aca8b2d74e 100644 --- a/src/hotspot/share/gc/z/zRememberedSet.hpp +++ b/src/hotspot/share/gc/z/zRememberedSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,7 +114,6 @@ public: bool is_initialized() const; void initialize(size_t page_size); - void delete_all(); bool at_current(uintptr_t offset) const; bool at_previous(uintptr_t offset) const; diff --git a/src/hotspot/share/gc/z/zUncommitter.cpp b/src/hotspot/share/gc/z/zUncommitter.cpp index 50731592108..7993bbd56a9 100644 --- a/src/hotspot/share/gc/z/zUncommitter.cpp +++ b/src/hotspot/share/gc/z/zUncommitter.cpp @@ -31,11 +31,12 @@ static const ZStatCounter ZCounterUncommit("Memory", "Uncommit", ZStatUnitBytesPerSecond); -ZUncommitter::ZUncommitter(ZPageAllocator* page_allocator) - : _page_allocator(page_allocator), +ZUncommitter::ZUncommitter(uint32_t id, ZPartition* partition) + : _id(id), + _partition(partition), _lock(), _stop(false) { - set_name("ZUncommitter"); + set_name("ZUncommitter#%u", id); create_and_start(); } @@ -46,7 +47,7 @@ bool ZUncommitter::wait(uint64_t timeout) const { } if (!_stop && timeout > 0) { - log_debug(gc, heap)("Uncommit Timeout: " UINT64_FORMAT "s", timeout); + log_debug(gc, heap)("Uncommitter (%u) Timeout: " UINT64_FORMAT "s", _id, timeout); _lock.wait(timeout * MILLIUNITS); } @@ -63,27 +64,27 @@ void ZUncommitter::run_thread() { while (wait(timeout)) { EventZUncommit event; - size_t uncommitted = 0; + size_t total_uncommitted = 0; while (should_continue()) { // Uncommit chunk - const size_t flushed = _page_allocator->uncommit(&timeout); - if (flushed == 0) { + const size_t uncommitted = _partition->uncommit(&timeout); + if (uncommitted == 0) { // Done break; } - uncommitted += flushed; + total_uncommitted += uncommitted; } - if (uncommitted > 0) { + if (total_uncommitted > 0) { // Update statistics - ZStatInc(ZCounterUncommit, uncommitted); - log_info(gc, heap)("Uncommitted: %zuM(%.0f%%)", - uncommitted / M, percent_of(uncommitted, ZHeap::heap()->max_capacity())); + ZStatInc(ZCounterUncommit, total_uncommitted); + log_info(gc, heap)("Uncommitter (%u) Uncommitted: %zuM(%.0f%%)", + _id, total_uncommitted / M, percent_of(total_uncommitted, ZHeap::heap()->max_capacity())); // Send event - event.commit(uncommitted); + event.commit(total_uncommitted); } } } diff --git a/src/hotspot/share/gc/z/zUncommitter.hpp b/src/hotspot/share/gc/z/zUncommitter.hpp index b626df8dddf..f8630f7b7fb 100644 --- a/src/hotspot/share/gc/z/zUncommitter.hpp +++ b/src/hotspot/share/gc/z/zUncommitter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,12 @@ #include "gc/z/zLock.hpp" #include "gc/z/zThread.hpp" -class ZPageAllocator; +class ZPartition; class ZUncommitter : public ZThread { private: - ZPageAllocator* const _page_allocator; + const uint32_t _id; + ZPartition* const _partition; mutable ZConditionLock _lock; bool _stop; @@ -43,7 +44,7 @@ protected: virtual void terminate(); public: - ZUncommitter(ZPageAllocator* page_allocator); + ZUncommitter(uint32_t id, ZPartition* partition); }; #endif // SHARE_GC_Z_ZUNCOMMITTER_HPP diff --git a/src/hotspot/share/gc/z/zUnmapper.cpp b/src/hotspot/share/gc/z/zUnmapper.cpp deleted file mode 100644 index edd31805c49..00000000000 --- a/src/hotspot/share/gc/z/zUnmapper.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "gc/shared/gc_globals.hpp" -#include "gc/shared/gcLogPrecious.hpp" -#include "gc/z/zList.inline.hpp" -#include "gc/z/zLock.inline.hpp" -#include "gc/z/zPage.inline.hpp" -#include "gc/z/zPageAllocator.hpp" -#include "gc/z/zUnmapper.hpp" -#include "jfr/jfrEvents.hpp" -#include "runtime/globals.hpp" - -ZUnmapper::ZUnmapper(ZPageAllocator* page_allocator) - : _page_allocator(page_allocator), - _lock(), - _queue(), - _enqueued_bytes(0), - _warned_sync_unmapping(false), - _stop(false) { - set_name("ZUnmapper"); - create_and_start(); -} - -ZPage* ZUnmapper::dequeue() { - ZLocker locker(&_lock); - - for (;;) { - if (_stop) { - return nullptr; - } - - ZPage* const page = _queue.remove_first(); - if (page != nullptr) { - _enqueued_bytes -= page->size(); - return page; - } - - _lock.wait(); - } -} - -bool ZUnmapper::try_enqueue(ZPage* page) { - // Enqueue for asynchronous unmap and destroy - ZLocker locker(&_lock); - if (is_saturated()) { - // The unmapper thread is lagging behind and is unable to unmap memory fast enough - if (!_warned_sync_unmapping) { - _warned_sync_unmapping = true; - log_warning_p(gc)("WARNING: Encountered synchronous unmapping because asynchronous unmapping could not keep up"); - } - log_debug(gc, unmap)("Synchronous unmapping %zuM page", page->size() / M); - return false; - } - - log_trace(gc, unmap)("Asynchronous unmapping %zuM page (%zuM / %zuM enqueued)", - page->size() / M, _enqueued_bytes / M, queue_capacity() / M); - - _queue.insert_last(page); - _enqueued_bytes += page->size(); - _lock.notify_all(); - - return true; -} - -size_t ZUnmapper::queue_capacity() const { - return align_up((size_t)(_page_allocator->max_capacity() * ZAsyncUnmappingLimit / 100.0), ZGranuleSize); -} - -bool ZUnmapper::is_saturated() const { - return _enqueued_bytes >= queue_capacity(); -} - -void ZUnmapper::do_unmap_and_destroy_page(ZPage* page) const { - EventZUnmap event; - const size_t unmapped = page->size(); - - // Unmap and destroy - _page_allocator->unmap_page(page); - _page_allocator->destroy_page(page); - - // Send event - event.commit(unmapped); -} - -void ZUnmapper::unmap_and_destroy_page(ZPage* page) { - if (!try_enqueue(page)) { - // Synchronously unmap and destroy - do_unmap_and_destroy_page(page); - } -} - -void ZUnmapper::run_thread() { - for (;;) { - ZPage* const page = dequeue(); - if (page == nullptr) { - // Stop - return; - } - - do_unmap_and_destroy_page(page); - } -} - -void ZUnmapper::terminate() { - ZLocker locker(&_lock); - _stop = true; - _lock.notify_all(); -} diff --git a/src/hotspot/share/gc/z/zUtils.hpp b/src/hotspot/share/gc/z/zUtils.hpp index 59e789d5b38..731136c4c99 100644 --- a/src/hotspot/share/gc/z/zUtils.hpp +++ b/src/hotspot/share/gc/z/zUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,16 @@ public: // Memory static void fill(uintptr_t* addr, size_t count, uintptr_t value); + template + static void copy_disjoint(T* dest, const T* src, size_t count); + template + static void copy_disjoint(T* dest, const T* src, int count); + + // Sort + template + static void sort(T* array, size_t count, Comparator comparator); + template + static void sort(T* array, int count, Comparator comparator); }; #endif // SHARE_GC_Z_ZUTILS_HPP diff --git a/src/hotspot/share/gc/z/zUtils.inline.hpp b/src/hotspot/share/gc/z/zUtils.inline.hpp index b6acf12df30..07a49f144e9 100644 --- a/src/hotspot/share/gc/z/zUtils.inline.hpp +++ b/src/hotspot/share/gc/z/zUtils.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,4 +69,35 @@ inline void ZUtils::object_copy_conjoint(zaddress from, zaddress to, size_t size } } +template +inline void ZUtils::copy_disjoint(T* dest, const T* src, size_t count) { + memcpy(dest, src, sizeof(T) * count); +} + +template +inline void ZUtils::copy_disjoint(T* dest, const T* src, int count) { + assert(count >= 0, "must be positive %d", count); + + copy_disjoint(dest, src, static_cast(count)); +} + +template +inline void ZUtils::sort(T* array, size_t count, Comparator comparator) { + using SortType = int(const void*, const void*); + using ComparatorType = int(const T*, const T*); + + static constexpr bool IsComparatorCompatible = std::is_assignable::value; + static_assert(IsComparatorCompatible, "Incompatible Comparator, must decay to plain function pointer"); + + // We rely on ABI compatibility between ComparatorType and SortType + qsort(array, count, sizeof(T), reinterpret_cast(static_cast(comparator))); +} + +template +inline void ZUtils::sort(T* array, int count, Comparator comparator) { + assert(count >= 0, "must be positive %d", count); + + sort(array, static_cast(count), comparator); +} + #endif // SHARE_GC_Z_ZUTILS_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zValue.hpp b/src/hotspot/share/gc/z/zValue.hpp index 2661a906dff..ab27c6a9227 100644 --- a/src/hotspot/share/gc/z/zValue.hpp +++ b/src/hotspot/share/gc/z/zValue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,8 +76,12 @@ public: // Value // +struct ZValueIdTagType {}; + template class ZValue : public CHeapObj { + friend class VMStructs; + private: const uintptr_t _addr; @@ -86,6 +90,8 @@ private: public: ZValue(); ZValue(const T& value); + template + ZValue(ZValueIdTagType, Args&&... args); const T* addr(uint32_t value_id = S::id()) const; T* addr(uint32_t value_id = S::id()); @@ -95,6 +101,8 @@ public: void set(const T& value, uint32_t value_id = S::id()); void set_all(const T& value); + + uint32_t count() const; }; template using ZContended = ZValue; @@ -106,16 +114,23 @@ template using ZPerWorker = ZValue; // Iterator // +template +class ZValueConstIterator; + template class ZValueIterator { + friend class ZValueConstIterator; + private: ZValue* const _value; uint32_t _value_id; public: ZValueIterator(ZValue* value); + ZValueIterator(const ZValueIterator&) = default; bool next(T** value); + bool next(T** value, uint32_t* value_id); }; template using ZPerCPUIterator = ZValueIterator; @@ -130,6 +145,8 @@ private: public: ZValueConstIterator(const ZValue* value); + ZValueConstIterator(const ZValueIterator& other); + ZValueConstIterator(const ZValueConstIterator&) = default; bool next(const T** value); }; diff --git a/src/hotspot/share/gc/z/zValue.inline.hpp b/src/hotspot/share/gc/z/zValue.inline.hpp index c2aa8bbbb40..f0ff891c3bc 100644 --- a/src/hotspot/share/gc/z/zValue.inline.hpp +++ b/src/hotspot/share/gc/z/zValue.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ #include "gc/shared/workerThread.hpp" #include "gc/z/zCPU.inline.hpp" #include "gc/z/zGlobals.hpp" -#include "gc/z/zNUMA.hpp" +#include "gc/z/zNUMA.inline.hpp" #include "gc/z/zUtils.inline.hpp" #include "runtime/globals.hpp" #include "utilities/align.hpp" @@ -142,6 +142,18 @@ inline ZValue::ZValue(const T& value) } } +template +template +inline ZValue::ZValue(ZValueIdTagType, Args&&... args) + : _addr(S::alloc(sizeof(T))) { + // Initialize all instances + uint32_t value_id; + ZValueIterator iter(this); + for (T* addr; iter.next(&addr, &value_id);) { + ::new (addr) T(value_id, args...); + } +} + template inline const T* ZValue::addr(uint32_t value_id) const { return reinterpret_cast(value_addr(value_id)); @@ -175,6 +187,11 @@ inline void ZValue::set_all(const T& value) { } } +template +uint32_t ZValue::count() const { + return S::count(); +} + // // Iterator // @@ -192,12 +209,26 @@ inline bool ZValueIterator::next(T** value) { } return false; } +template +inline bool ZValueIterator::next(T** value, uint32_t* value_id) { + if (_value_id < S::count()) { + *value_id = _value_id; + *value = _value->addr(_value_id++); + return true; + } + return false; +} template inline ZValueConstIterator::ZValueConstIterator(const ZValue* value) : _value(value), _value_id(0) {} +template +inline ZValueConstIterator::ZValueConstIterator(const ZValueIterator& other) + : _value(other._value), + _value_id(other._value_id) {} + template inline bool ZValueConstIterator::next(const T** value) { if (_value_id < S::count()) { diff --git a/src/hotspot/share/gc/z/zVirtualMemory.cpp b/src/hotspot/share/gc/z/zVirtualMemory.cpp deleted file mode 100644 index 471fc6f505e..00000000000 --- a/src/hotspot/share/gc/z/zVirtualMemory.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "gc/shared/gc_globals.hpp" -#include "gc/shared/gcLogPrecious.hpp" -#include "gc/z/zAddress.inline.hpp" -#include "gc/z/zAddressSpaceLimit.hpp" -#include "gc/z/zGlobals.hpp" -#include "gc/z/zInitialize.hpp" -#include "gc/z/zNMT.hpp" -#include "gc/z/zVirtualMemory.inline.hpp" -#include "utilities/align.hpp" -#include "utilities/debug.hpp" - -ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity) - : _manager(), - _reserved(0), - _initialized(false) { - - assert(max_capacity <= ZAddressOffsetMax, "Too large max_capacity"); - - // Initialize platform specific parts before reserving address space - pd_initialize_before_reserve(); - - // Register the Windows callbacks - pd_register_callbacks(&_manager); - - // Reserve address space - if (!reserve(max_capacity)) { - ZInitialize::error_d("Failed to reserve enough address space for Java heap"); - return; - } - - // Set ZAddressOffsetMax to the highest address end available after reservation - ZAddressOffsetMax = untype(highest_available_address_end()); - - // Successfully initialized - _initialized = true; -} - -#ifdef ASSERT -size_t ZVirtualMemoryManager::force_reserve_discontiguous(size_t size) { - const size_t min_range = calculate_min_range(size); - const size_t max_range = MAX2(align_down(size / ZForceDiscontiguousHeapReservations, ZGranuleSize), min_range); - size_t reserved = 0; - - // Try to reserve ZForceDiscontiguousHeapReservations number of virtual memory - // ranges. Starting with higher addresses. - uintptr_t end = ZAddressOffsetMax; - while (reserved < size && end >= max_range) { - const size_t remaining = size - reserved; - const size_t reserve_size = MIN2(max_range, remaining); - const uintptr_t reserve_start = end - reserve_size; - - if (reserve_contiguous(to_zoffset(reserve_start), reserve_size)) { - reserved += reserve_size; - } - - end -= reserve_size * 2; - } - - // If (reserved < size) attempt to reserve the rest via normal divide and conquer - uintptr_t start = 0; - while (reserved < size && start < ZAddressOffsetMax) { - const size_t remaining = MIN2(size - reserved, ZAddressOffsetMax - start); - reserved += reserve_discontiguous(to_zoffset(start), remaining, min_range); - start += remaining; - } - - return reserved; -} -#endif - -size_t ZVirtualMemoryManager::reserve_discontiguous(zoffset start, size_t size, size_t min_range) { - if (size < min_range) { - // Too small - return 0; - } - - assert(is_aligned(size, ZGranuleSize), "Misaligned"); - - if (reserve_contiguous(start, size)) { - return size; - } - - const size_t half = size / 2; - if (half < min_range) { - // Too small - return 0; - } - - // Divide and conquer - const size_t first_part = align_down(half, ZGranuleSize); - const size_t second_part = size - first_part; - const size_t first_size = reserve_discontiguous(start, first_part, min_range); - const size_t second_size = reserve_discontiguous(start + first_part, second_part, min_range); - return first_size + second_size; -} - -size_t ZVirtualMemoryManager::calculate_min_range(size_t size) { - // Don't try to reserve address ranges smaller than 1% of the requested size. - // This avoids an explosion of reservation attempts in case large parts of the - // address space is already occupied. - return align_up(size / ZMaxVirtualReservations, ZGranuleSize); -} - -size_t ZVirtualMemoryManager::reserve_discontiguous(size_t size) { - const size_t min_range = calculate_min_range(size); - uintptr_t start = 0; - size_t reserved = 0; - - // Reserve size somewhere between [0, ZAddressOffsetMax) - while (reserved < size && start < ZAddressOffsetMax) { - const size_t remaining = MIN2(size - reserved, ZAddressOffsetMax - start); - reserved += reserve_discontiguous(to_zoffset(start), remaining, min_range); - start += remaining; - } - - return reserved; -} - -bool ZVirtualMemoryManager::reserve_contiguous(zoffset start, size_t size) { - assert(is_aligned(size, ZGranuleSize), "Must be granule aligned 0x%zx", size); - - // Reserve address views - const zaddress_unsafe addr = ZOffset::address_unsafe(start); - - // Reserve address space - if (!pd_reserve(addr, size)) { - return false; - } - - // Register address views with native memory tracker - ZNMT::reserve(addr, size); - - // Make the address range free - _manager.register_range(start, size); - - return true; -} - -bool ZVirtualMemoryManager::reserve_contiguous(size_t size) { - // Allow at most 8192 attempts spread evenly across [0, ZAddressOffsetMax) - const size_t unused = ZAddressOffsetMax - size; - const size_t increment = MAX2(align_up(unused / 8192, ZGranuleSize), ZGranuleSize); - - for (uintptr_t start = 0; start + size <= ZAddressOffsetMax; start += increment) { - if (reserve_contiguous(to_zoffset(start), size)) { - // Success - return true; - } - } - - // Failed - return false; -} - -bool ZVirtualMemoryManager::reserve(size_t max_capacity) { - const size_t limit = MIN2(ZAddressOffsetMax, ZAddressSpaceLimit::heap()); - const size_t size = MIN2(max_capacity * ZVirtualToPhysicalRatio, limit); - - auto do_reserve = [&]() { -#ifdef ASSERT - if (ZForceDiscontiguousHeapReservations > 0) { - return force_reserve_discontiguous(size); - } -#endif - - // Prefer a contiguous address space - if (reserve_contiguous(size)) { - return size; - } - - // Fall back to a discontiguous address space - return reserve_discontiguous(size); - }; - - const size_t reserved = do_reserve(); - - const bool contiguous = _manager.free_is_contiguous(); - - log_info_p(gc, init)("Address Space Type: %s/%s/%s", - (contiguous ? "Contiguous" : "Discontiguous"), - (limit == ZAddressOffsetMax ? "Unrestricted" : "Restricted"), - (reserved == size ? "Complete" : "Degraded")); - log_info_p(gc, init)("Address Space Size: %zuM", reserved / M); - - // Record reserved - _reserved = reserved; - - return reserved >= max_capacity; -} - -void ZVirtualMemoryManager::unreserve(zoffset start, size_t size) { - const zaddress_unsafe addr = ZOffset::address_unsafe(start); - - // Unregister the reserved memory from NMT - ZNMT::unreserve(addr, size); - - // Unreserve address space - pd_unreserve(addr, size); -} - -void ZVirtualMemoryManager::unreserve_all() { - zoffset start; - size_t size; - - while (_manager.unregister_first(&start, &size)) { - unreserve(start, size); - } -} - -bool ZVirtualMemoryManager::is_initialized() const { - return _initialized; -} - -ZVirtualMemory ZVirtualMemoryManager::alloc(size_t size, bool force_low_address) { - zoffset start; - - // Small pages are allocated at low addresses, while medium/large pages - // are allocated at high addresses (unless forced to be at a low address). - if (force_low_address || size <= ZPageSizeSmall) { - start = _manager.alloc_low_address(size); - } else { - start = _manager.alloc_high_address(size); - } - - if (start == zoffset(UINTPTR_MAX)) { - return ZVirtualMemory(); - } - - return ZVirtualMemory(start, size); -} - -void ZVirtualMemoryManager::free(const ZVirtualMemory& vmem) { - _manager.free(vmem.start(), vmem.size()); -} diff --git a/src/hotspot/share/gc/z/zVirtualMemory.hpp b/src/hotspot/share/gc/z/zVirtualMemory.hpp index f5185549e8a..46fec6ac79e 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.hpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,67 +25,16 @@ #define SHARE_GC_Z_ZVIRTUALMEMORY_HPP #include "gc/z/zAddress.hpp" -#include "gc/z/zMemory.hpp" - -class ZVirtualMemory { - friend class VMStructs; - -private: - zoffset _start; - zoffset_end _end; +#include "gc/z/zRange.hpp" +#include "utilities/globalDefinitions.hpp" +class ZVirtualMemory : public ZRange { public: ZVirtualMemory(); ZVirtualMemory(zoffset start, size_t size); + ZVirtualMemory(const ZRange& range); - bool is_null() const; - zoffset start() const; - zoffset_end end() const; - size_t size() const; - - ZVirtualMemory split(size_t size); -}; - -class ZVirtualMemoryManager { - friend class ZMapperTest; - friend class ZVirtualMemoryManagerTest; - -private: - static size_t calculate_min_range(size_t size); - - ZMemoryManager _manager; - size_t _reserved; - bool _initialized; - - // Platform specific implementation - void pd_initialize_before_reserve(); - void pd_register_callbacks(ZMemoryManager* manager); - bool pd_reserve(zaddress_unsafe addr, size_t size); - void pd_unreserve(zaddress_unsafe addr, size_t size); - - bool reserve_contiguous(zoffset start, size_t size); - bool reserve_contiguous(size_t size); - size_t reserve_discontiguous(zoffset start, size_t size, size_t min_range); - size_t reserve_discontiguous(size_t size); - bool reserve(size_t max_capacity); - - void unreserve(zoffset start, size_t size); - - DEBUG_ONLY(size_t force_reserve_discontiguous(size_t size);) - -public: - ZVirtualMemoryManager(size_t max_capacity); - - bool is_initialized() const; - - size_t reserved() const; - zoffset lowest_available_address() const; - zoffset_end highest_available_address_end() const; - - ZVirtualMemory alloc(size_t size, bool force_low_address); - void free(const ZVirtualMemory& vmem); - - void unreserve_all(); + int granule_count() const; }; #endif // SHARE_GC_Z_ZVIRTUALMEMORY_HPP diff --git a/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp b/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp index 9d5fe7dd57a..3cbe1409b52 100644 --- a/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp +++ b/src/hotspot/share/gc/z/zVirtualMemory.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,47 +26,32 @@ #include "gc/z/zVirtualMemory.hpp" -#include "gc/z/zMemory.inline.hpp" +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zRange.inline.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" inline ZVirtualMemory::ZVirtualMemory() - : _start(zoffset(UINTPTR_MAX)), - _end(zoffset_end(UINTPTR_MAX)) {} + : ZRange() {} inline ZVirtualMemory::ZVirtualMemory(zoffset start, size_t size) - : _start(start), - _end(to_zoffset_end(start, size)) {} - -inline bool ZVirtualMemory::is_null() const { - return _start == zoffset(UINTPTR_MAX); + : ZRange(start, size) { + // ZVirtualMemory is only used for ZGranuleSize multiple ranges + assert(is_aligned(untype(start), ZGranuleSize), "must be multiple of ZGranuleSize"); + assert(is_aligned(size, ZGranuleSize), "must be multiple of ZGranuleSize"); } -inline zoffset ZVirtualMemory::start() const { - return _start; -} +inline ZVirtualMemory::ZVirtualMemory(const ZRange& range) + : ZVirtualMemory(range.start(), range.size()) {} -inline zoffset_end ZVirtualMemory::end() const { - return _end; -} +inline int ZVirtualMemory::granule_count() const { + const size_t granule_count = size() >> ZGranuleSizeShift; -inline size_t ZVirtualMemory::size() const { - return _end - _start; -} + assert(granule_count <= static_cast(std::numeric_limits::max()), + "must not overflow an int %zu", granule_count); -inline ZVirtualMemory ZVirtualMemory::split(size_t size) { - _start += size; - return ZVirtualMemory(_start - size, size); -} - -inline size_t ZVirtualMemoryManager::reserved() const { - return _reserved; -} - -inline zoffset ZVirtualMemoryManager::lowest_available_address() const { - return _manager.peek_low_address(); -} - -inline zoffset_end ZVirtualMemoryManager::highest_available_address_end() const { - return _manager.peak_high_address_end(); + return static_cast(granule_count); } #endif // SHARE_GC_Z_ZVIRTUALMEMORY_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zVirtualMemoryManager.cpp b/src/hotspot/share/gc/z/zVirtualMemoryManager.cpp new file mode 100644 index 00000000000..2f81a5cfe09 --- /dev/null +++ b/src/hotspot/share/gc/z/zVirtualMemoryManager.cpp @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zAddressSpaceLimit.hpp" +#include "gc/z/zArray.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zInitialize.hpp" +#include "gc/z/zNMT.hpp" +#include "gc/z/zNUMA.inline.hpp" +#include "gc/z/zValue.inline.hpp" +#include "gc/z/zVirtualMemory.inline.hpp" +#include "gc/z/zVirtualMemoryManager.inline.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" + +ZVirtualMemoryReserver::ZVirtualMemoryReserver(size_t size) + : _registry(), + _reserved(reserve(size)) {} + +void ZVirtualMemoryReserver::initialize_partition_registry(ZVirtualMemoryRegistry* partition_registry, size_t size) { + assert(partition_registry->is_empty(), "Should be empty when initializing"); + + // Registers the Windows callbacks + pd_register_callbacks(partition_registry); + + _registry.transfer_from_low(partition_registry, size); + + // Set the limits according to the virtual memory given to this partition + partition_registry->anchor_limits(); +} + +void ZVirtualMemoryReserver::unreserve(const ZVirtualMemory& vmem) { + const zaddress_unsafe addr = ZOffset::address_unsafe(vmem.start()); + + // Unregister the reserved memory from NMT + ZNMT::unreserve(addr, vmem.size()); + + // Unreserve address space + pd_unreserve(addr, vmem.size()); +} + +void ZVirtualMemoryReserver::unreserve_all() { + for (ZVirtualMemory vmem; _registry.unregister_first(&vmem);) { + unreserve(vmem); + } +} + +bool ZVirtualMemoryReserver::is_empty() const { + return _registry.is_empty(); +} + +bool ZVirtualMemoryReserver::is_contiguous() const { + return _registry.is_contiguous(); +} + +size_t ZVirtualMemoryReserver::reserved() const { + return _reserved; +} + +zoffset_end ZVirtualMemoryReserver::highest_available_address_end() const { + return _registry.peak_high_address_end(); +} + +#ifdef ASSERT +size_t ZVirtualMemoryReserver::force_reserve_discontiguous(size_t size) { + const size_t min_range = calculate_min_range(size); + const size_t max_range = MAX2(align_down(size / ZForceDiscontiguousHeapReservations, ZGranuleSize), min_range); + size_t reserved = 0; + + // Try to reserve ZForceDiscontiguousHeapReservations number of virtual memory + // ranges. Starting with higher addresses. + uintptr_t end = ZAddressOffsetMax; + while (reserved < size && end >= max_range) { + const size_t remaining = size - reserved; + const size_t reserve_size = MIN2(max_range, remaining); + const uintptr_t reserve_start = end - reserve_size; + + if (reserve_contiguous(to_zoffset(reserve_start), reserve_size)) { + reserved += reserve_size; + } + + end -= reserve_size * 2; + } + + // If (reserved < size) attempt to reserve the rest via normal divide and conquer + uintptr_t start = 0; + while (reserved < size && start < ZAddressOffsetMax) { + const size_t remaining = MIN2(size - reserved, ZAddressOffsetMax - start); + reserved += reserve_discontiguous(to_zoffset(start), remaining, min_range); + start += remaining; + } + + return reserved; +} +#endif + +size_t ZVirtualMemoryReserver::reserve_discontiguous(zoffset start, size_t size, size_t min_range) { + if (size < min_range) { + // Too small + return 0; + } + + assert(is_aligned(size, ZGranuleSize), "Misaligned"); + + if (reserve_contiguous(start, size)) { + return size; + } + + const size_t half = size / 2; + if (half < min_range) { + // Too small + return 0; + } + + // Divide and conquer + const size_t first_part = align_down(half, ZGranuleSize); + const size_t second_part = size - first_part; + const size_t first_size = reserve_discontiguous(start, first_part, min_range); + const size_t second_size = reserve_discontiguous(start + first_part, second_part, min_range); + return first_size + second_size; +} + +size_t ZVirtualMemoryReserver::calculate_min_range(size_t size) { + // Don't try to reserve address ranges smaller than 1% of the requested size. + // This avoids an explosion of reservation attempts in case large parts of the + // address space is already occupied. + return align_up(size / ZMaxVirtualReservations, ZGranuleSize); +} + +size_t ZVirtualMemoryReserver::reserve_discontiguous(size_t size) { + const size_t min_range = calculate_min_range(size); + uintptr_t start = 0; + size_t reserved = 0; + + // Reserve size somewhere between [0, ZAddressOffsetMax) + while (reserved < size && start < ZAddressOffsetMax) { + const size_t remaining = MIN2(size - reserved, ZAddressOffsetMax - start); + reserved += reserve_discontiguous(to_zoffset(start), remaining, min_range); + start += remaining; + } + + return reserved; +} + +bool ZVirtualMemoryReserver::reserve_contiguous(zoffset start, size_t size) { + assert(is_aligned(size, ZGranuleSize), "Must be granule aligned 0x%zx", size); + + // Reserve address views + const zaddress_unsafe addr = ZOffset::address_unsafe(start); + + // Reserve address space + if (!pd_reserve(addr, size)) { + return false; + } + + // Register address views with native memory tracker + ZNMT::reserve(addr, size); + + // Register the memory reservation + _registry.register_range({start, size}); + + return true; +} + +bool ZVirtualMemoryReserver::reserve_contiguous(size_t size) { + // Allow at most 8192 attempts spread evenly across [0, ZAddressOffsetMax) + const size_t unused = ZAddressOffsetMax - size; + const size_t increment = MAX2(align_up(unused / 8192, ZGranuleSize), ZGranuleSize); + + for (uintptr_t start = 0; start + size <= ZAddressOffsetMax; start += increment) { + if (reserve_contiguous(to_zoffset(start), size)) { + // Success + return true; + } + } + + // Failed + return false; +} + +size_t ZVirtualMemoryReserver::reserve(size_t size) { + // Register Windows callbacks + pd_register_callbacks(&_registry); + + // Reserve address space + +#ifdef ASSERT + if (ZForceDiscontiguousHeapReservations > 0) { + return force_reserve_discontiguous(size); + } +#endif + + // Prefer a contiguous address space + if (reserve_contiguous(size)) { + return size; + } + + // Fall back to a discontiguous address space + return reserve_discontiguous(size); +} + +ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity) + : _partition_registries(), + _multi_partition_registry(), + _is_multi_partition_enabled(false), + _initialized(false) { + + assert(max_capacity <= ZAddressOffsetMax, "Too large max_capacity"); + + ZAddressSpaceLimit::print_limits(); + + const size_t limit = MIN2(ZAddressOffsetMax, ZAddressSpaceLimit::heap()); + + const size_t desired_for_partitions = max_capacity * ZVirtualToPhysicalRatio; + const size_t desired_for_multi_partition = ZNUMA::count() > 1 ? desired_for_partitions : 0; + + const size_t desired = desired_for_partitions + desired_for_multi_partition; + const size_t requested = desired <= limit + ? desired + : MIN2(desired_for_partitions, limit); + + // Reserve virtual memory for the heap + ZVirtualMemoryReserver reserver(requested); + + const size_t reserved = reserver.reserved(); + const bool is_contiguous = reserver.is_contiguous(); + + log_debug_p(gc, init)("Reserved Space: limit " EXACTFMT ", desired " EXACTFMT ", requested " EXACTFMT, + EXACTFMTARGS(limit), EXACTFMTARGS(desired), EXACTFMTARGS(requested)); + + if (reserved < max_capacity) { + ZInitialize::error_d("Failed to reserve " EXACTFMT " address space for Java heap", EXACTFMTARGS(max_capacity)); + return; + } + + // Set ZAddressOffsetMax to the highest address end available after reservation + ZAddressOffsetMax = untype(reserver.highest_available_address_end()); + + const size_t size_for_partitions = MIN2(reserved, desired_for_partitions); + + // Divide size_for_partitions virtual memory over the NUMA nodes + initialize_partitions(&reserver, size_for_partitions); + + // Set up multi-partition or unreserve the surplus memory + if (desired_for_multi_partition > 0 && reserved == desired) { + // Enough left to setup the multi-partition memory reservation + reserver.initialize_partition_registry(&_multi_partition_registry, desired_for_multi_partition); + _is_multi_partition_enabled = true; + } else { + // Failed to reserve enough memory for multi-partition, unreserve unused memory + reserver.unreserve_all(); + } + + assert(reserver.is_empty(), "Must have handled all reserved memory"); + + log_info_p(gc, init)("Reserved Space Type: %s/%s/%s", + (is_contiguous ? "Contiguous" : "Discontiguous"), + (requested == desired ? "Unrestricted" : "Restricted"), + (reserved == desired ? "Complete" : ((reserved < desired_for_partitions) ? "Degraded" : "NUMA-Degraded"))); + log_info_p(gc, init)("Reserved Space Size: " EXACTFMT, EXACTFMTARGS(reserved)); + + // Successfully initialized + _initialized = true; +} + +void ZVirtualMemoryManager::initialize_partitions(ZVirtualMemoryReserver* reserver, size_t size_for_partitions) { + precond(is_aligned(size_for_partitions, ZGranuleSize)); + + // If the capacity consist of less granules than the number of partitions + // some partitions will be empty. Distribute these shares on the none empty + // partitions. + const uint32_t first_empty_numa_id = MIN2(static_cast(size_for_partitions >> ZGranuleSizeShift), ZNUMA::count()); + const uint32_t ignore_count = ZNUMA::count() - first_empty_numa_id; + + // Install reserved memory into registry(s) + uint32_t numa_id; + ZPerNUMAIterator iter(&_partition_registries); + for (ZVirtualMemoryRegistry* registry; iter.next(®istry, &numa_id);) { + if (numa_id == first_empty_numa_id) { + break; + } + + // Calculate how much reserved memory this partition gets + const size_t reserved_for_partition = ZNUMA::calculate_share(numa_id, size_for_partitions, ZGranuleSize, ignore_count); + + // Transfer reserved memory + reserver->initialize_partition_registry(registry, reserved_for_partition); + } +} + +bool ZVirtualMemoryManager::is_initialized() const { + return _initialized; +} + +ZVirtualMemoryRegistry& ZVirtualMemoryManager::registry(uint32_t partition_id) { + return _partition_registries.get(partition_id); +} + +const ZVirtualMemoryRegistry& ZVirtualMemoryManager::registry(uint32_t partition_id) const { + return _partition_registries.get(partition_id); +} + +zoffset ZVirtualMemoryManager::lowest_available_address(uint32_t partition_id) const { + return registry(partition_id).peek_low_address(); +} + +void ZVirtualMemoryManager::insert(const ZVirtualMemory& vmem, uint32_t partition_id) { + assert(partition_id == lookup_partition_id(vmem), "wrong partition_id for vmem"); + registry(partition_id).insert(vmem); +} + +void ZVirtualMemoryManager::insert_multi_partition(const ZVirtualMemory& vmem) { + _multi_partition_registry.insert(vmem); +} + +size_t ZVirtualMemoryManager::remove_from_low_many_at_most(size_t size, uint32_t partition_id, ZArray* vmems_out) { + return registry(partition_id).remove_from_low_many_at_most(size, vmems_out); +} + +ZVirtualMemory ZVirtualMemoryManager::remove_from_low(size_t size, uint32_t partition_id) { + return registry(partition_id).remove_from_low(size); +} + +ZVirtualMemory ZVirtualMemoryManager::remove_from_low_multi_partition(size_t size) { + return _multi_partition_registry.remove_from_low(size); +} + +void ZVirtualMemoryManager::insert_and_remove_from_low_many(const ZVirtualMemory& vmem, uint32_t partition_id, ZArray* vmems_out) { + registry(partition_id).insert_and_remove_from_low_many(vmem, vmems_out); +} + +ZVirtualMemory ZVirtualMemoryManager::insert_and_remove_from_low_exact_or_many(size_t size, uint32_t partition_id, ZArray* vmems_in_out) { + return registry(partition_id).insert_and_remove_from_low_exact_or_many(size, vmems_in_out); +} diff --git a/src/hotspot/share/gc/z/zVirtualMemoryManager.hpp b/src/hotspot/share/gc/z/zVirtualMemoryManager.hpp new file mode 100644 index 00000000000..a9ab86761ac --- /dev/null +++ b/src/hotspot/share/gc/z/zVirtualMemoryManager.hpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZVIRTUALMEMORYMANAGER_HPP +#define SHARE_GC_Z_ZVIRTUALMEMORYMANAGER_HPP + +#include "gc/z/zAddress.hpp" +#include "gc/z/zArray.hpp" +#include "gc/z/zRangeRegistry.hpp" +#include "gc/z/zValue.hpp" +#include "gc/z/zVirtualMemory.hpp" + +using ZVirtualMemoryRegistry = ZRangeRegistry; + +class ZVirtualMemoryReserver { + friend class ZMapperTest; + friend class ZVirtualMemoryManagerTest; + +private: + + ZVirtualMemoryRegistry _registry; + const size_t _reserved; + + static size_t calculate_min_range(size_t size); + + // Platform specific implementation + void pd_register_callbacks(ZVirtualMemoryRegistry* registry); + bool pd_reserve(zaddress_unsafe addr, size_t size); + void pd_unreserve(zaddress_unsafe addr, size_t size); + + bool reserve_contiguous(zoffset start, size_t size); + bool reserve_contiguous(size_t size); + size_t reserve_discontiguous(zoffset start, size_t size, size_t min_range); + size_t reserve_discontiguous(size_t size); + + size_t reserve(size_t size); + void unreserve(const ZVirtualMemory& vmem); + + DEBUG_ONLY(size_t force_reserve_discontiguous(size_t size);) + +public: + ZVirtualMemoryReserver(size_t size); + + void initialize_partition_registry(ZVirtualMemoryRegistry* partition_registry, size_t size); + + void unreserve_all(); + + bool is_empty() const; + bool is_contiguous() const; + + size_t reserved() const; + + zoffset_end highest_available_address_end() const; +}; + +class ZVirtualMemoryManager { +private: + ZPerNUMA _partition_registries; + ZVirtualMemoryRegistry _multi_partition_registry; + bool _is_multi_partition_enabled; + bool _initialized; + + ZVirtualMemoryRegistry& registry(uint32_t partition_id); + const ZVirtualMemoryRegistry& registry(uint32_t partition_id) const; + +public: + ZVirtualMemoryManager(size_t max_capacity); + + void initialize_partitions(ZVirtualMemoryReserver* reserver, size_t size_for_partitions); + + bool is_initialized() const; + bool is_multi_partition_enabled() const; + bool is_in_multi_partition(const ZVirtualMemory& vmem) const; + + uint32_t lookup_partition_id(const ZVirtualMemory& vmem) const; + zoffset lowest_available_address(uint32_t partition_id) const; + + void insert(const ZVirtualMemory& vmem, uint32_t partition_id); + void insert_multi_partition(const ZVirtualMemory& vmem); + + size_t remove_from_low_many_at_most(size_t size, uint32_t partition_id, ZArray* vmems_out); + ZVirtualMemory remove_from_low(size_t size, uint32_t partition_id); + ZVirtualMemory remove_from_low_multi_partition(size_t size); + + void insert_and_remove_from_low_many(const ZVirtualMemory& vmem, uint32_t partition_id, ZArray* vmems_out); + ZVirtualMemory insert_and_remove_from_low_exact_or_many(size_t size, uint32_t partition_id, ZArray* vmems_in_out); +}; + +#endif // SHARE_GC_Z_ZVIRTUALMEMORYMANAGER_HPP diff --git a/src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp b/src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp new file mode 100644 index 00000000000..78f966d0f84 --- /dev/null +++ b/src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZVIRTUALMEMORYMANAGER_INLINE_HPP +#define SHARE_GC_Z_ZVIRTUALMEMORYMANAGER_INLINE_HPP + +#include "gc/z/zVirtualMemoryManager.hpp" + +#include "utilities/globalDefinitions.hpp" +#include "gc/z/zRangeRegistry.inline.hpp" + + +inline bool ZVirtualMemoryManager::is_multi_partition_enabled() const { + return _is_multi_partition_enabled; +} + +inline bool ZVirtualMemoryManager::is_in_multi_partition(const ZVirtualMemory& vmem) const { + return _multi_partition_registry.limits_contain(vmem); +} + +inline uint32_t ZVirtualMemoryManager::lookup_partition_id(const ZVirtualMemory& vmem) const { + const uint32_t num_partitions = _partition_registries.count(); + for (uint32_t partition_id = 0; partition_id < num_partitions; partition_id++) { + if (registry(partition_id).limits_contain(vmem)) { + return partition_id; + } + } + + ShouldNotReachHere(); +} + +#endif // SHARE_GC_Z_ZVIRTUALMEMORYMANAGER_INLINE_HPP diff --git a/src/hotspot/share/gc/z/z_globals.hpp b/src/hotspot/share/gc/z/z_globals.hpp index 4555b470cac..17a77a12ca4 100644 --- a/src/hotspot/share/gc/z/z_globals.hpp +++ b/src/hotspot/share/gc/z/z_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,13 +68,6 @@ product(bool, ZCollectionIntervalOnly, false, \ "Only use timers for GC heuristics") \ \ - product(double, ZAsyncUnmappingLimit, 100.0, DIAGNOSTIC, \ - "Specify the max amount (percentage of max heap size) of async " \ - "unmapping that can be in-flight before unmapping requests are " \ - "temporarily forced to be synchronous instead. " \ - "The default means after an amount of pages proportional to the " \ - "max capacity is enqueued, we resort to synchronous unmapping.") \ - \ product(uint, ZStatisticsInterval, 10, DIAGNOSTIC, \ "Time between statistics print outs (in seconds)") \ range(1, (uint)-1) \ @@ -118,6 +111,11 @@ develop(bool, ZVerifyOops, false, \ "Verify accessed oops") \ \ + develop(uint, ZFakeNUMA, 1, \ + "ZFakeNUMA is used to test the internal NUMA memory support " \ + "without the need for UseNUMA") \ + range(1, 16) \ + \ develop(size_t, ZForceDiscontiguousHeapReservations, 0, \ "The gc will attempt to split the heap reservation into this " \ "many reservations, subject to available virtual address space " \ diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 562d31b828d..6aa3e05cda1 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -1,7 +1,7 @@ U+2015 - return ((outChar != '\u2014')? outChar: '\u2015'); - } else { - int adjust = c2 < 0x9F ? 1 : 0; - int rowOffset = c1 < 0xA0 ? 0x70 : 0xB0; - int cellOffset = (adjust == 1) ? (c2 > 0x7F ? 0x20 : 0x1F) : 0x7E; - int b1 = ((c1 - rowOffset) << 1) - adjust; - int b2 = c2 - cellOffset; - char outChar2 = jis0208.decodeDouble(b1, b2); - return outChar2; - } - } - } - - private static class Encoder extends SJIS_OLD.Encoder { - - private JIS_X_0201_OLD.Encoder jis0201; - - private static final short[] j0208Index1 = - JIS_X_0208_Solaris_Encoder.getIndex1(); - private static final String[] j0208Index2 = - JIS_X_0208_Solaris_Encoder.getIndex2(); - - private Encoder(Charset cs) { - super(cs); - jis0201 = new JIS_X_0201_OLD.Encoder(cs); - } - - protected int encodeDouble(char ch) { - int result = 0; - - // PCK uses JIS_X_0208:1983 rather than JIS_X_0208:1997 - - switch (ch) { - case '\u2015': - return 0x815C; - case '\u2014': - return 0; - default: - break; - } - - if ((result = super.encodeDouble(ch)) != 0) { - return result; - } - else { - int offset = j0208Index1[ch >> 8] << 8; - int pos = j0208Index2[offset >> 12].charAt((offset & 0xfff) + (ch & 0xff)); - if (pos != 0) { - int c1 = (pos >> 8) & 0xff; - int c2 = pos & 0xff; - int rowOffset = c1 < 0x5F ? 0x70 : 0xB0; - int cellOffset = (c1 % 2 == 1) ? (c2 > 0x5F ? 0x20 : 0x1F) : 0x7E; - result = ((((c1 + 1 ) >> 1) + rowOffset) << 8) | (c2 + cellOffset); - } - } - return result; - } - } -} diff --git a/test/jdk/sun/nio/cs/OLD/SJIS_OLD.java b/test/jdk/sun/nio/cs/OLD/SJIS_OLD.java deleted file mode 100644 index 2647e3a7d19..00000000000 --- a/test/jdk/sun/nio/cs/OLD/SJIS_OLD.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. - * 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.nio.*; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import sun.nio.cs.HistoricallyNamedCharset; - -public class SJIS_OLD - extends Charset - implements HistoricallyNamedCharset -{ - - public SJIS_OLD() { - super("Shift_JIS_OLD", null); - } - - public String historicalName() { - return "SJIS"; - } - - public boolean contains(Charset cs) { - return ((cs.name().equals("US-ASCII")) - || (cs instanceof JIS_X_0201_OLD) - || (cs instanceof SJIS_OLD) - || (cs instanceof JIS_X_0208_OLD)); - } - - public CharsetDecoder newDecoder() { - return new Decoder(this); - } - - public CharsetEncoder newEncoder() { - - // Need to force the replacement byte to 0x3f - // because JIS_X_0208_Encoder defines its own - // alternative 2 byte substitution to permit it - // to exist as a self-standing Encoder - - byte[] replacementBytes = { (byte)0x3f }; - return new Encoder(this).replaceWith(replacementBytes); - } - - static class Decoder extends JIS_X_0208_Decoder { - - JIS_X_0201_OLD.Decoder jis0201; - - protected Decoder(Charset cs) { - super(cs); - jis0201 = new JIS_X_0201_OLD.Decoder(cs); - } - - protected char decodeSingle(int b) { - // If the high bits are all off, it's ASCII == Unicode - if ((b & 0xFF80) == 0) { - return (char)b; - } - return jis0201.decode(b); - } - - protected char decodeDouble(int c1, int c2) { - int adjust = c2 < 0x9F ? 1 : 0; - int rowOffset = c1 < 0xA0 ? 0x70 : 0xB0; - int cellOffset = (adjust == 1) ? (c2 > 0x7F ? 0x20 : 0x1F) : 0x7E; - int b1 = ((c1 - rowOffset) << 1) - adjust; - int b2 = c2 - cellOffset; - return super.decodeDouble(b1, b2); - } - - // Make some protected methods public for use by JISAutoDetect - public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { - return super.decodeLoop(src, dst); - } - public void implReset() { - super.implReset(); - } - public CoderResult implFlush(CharBuffer out) { - return super.implFlush(out); - } - } - - static class Encoder extends JIS_X_0208_Encoder { - - private JIS_X_0201_OLD.Encoder jis0201; - - private static final short[] j0208Index1 = - JIS_X_0208_Encoder.getIndex1(); - private static final String[] j0208Index2 = - JIS_X_0208_Encoder.getIndex2(); - - protected Encoder(Charset cs) { - super(cs); - jis0201 = new JIS_X_0201_OLD.Encoder(cs); - } - - protected int encodeSingle(char inputChar) { - byte b; - - // \u0000 - \u007F map straight through - if ((inputChar & 0xFF80) == 0) - return (byte)inputChar; - - if ((b = jis0201.encode(inputChar)) == 0) - return -1; - else - return b; - } - - protected int encodeDouble(char ch) { - int offset = j0208Index1[ch >> 8] << 8; - int pos = j0208Index2[offset >> 12].charAt((offset & 0xfff) + (ch & 0xff)); - if (pos == 0) { - /* Zero value indicates this Unicode has no mapping to - * JIS0208. - * We bail here because the JIS -> SJIS algorithm produces - * bogus SJIS values for invalid JIS input. Zero should be - * the only invalid JIS value in our table. - */ - return 0; - } - /* - * This algorithm for converting from JIS to SJIS comes from - * Ken Lunde's "Understanding Japanese Information Processing", - * pg 163. - */ - int c1 = (pos >> 8) & 0xff; - int c2 = pos & 0xff; - int rowOffset = c1 < 0x5F ? 0x70 : 0xB0; - int cellOffset = (c1 % 2 == 1) ? (c2 > 0x5F ? 0x20 : 0x1F) : 0x7E; - return ((((c1 + 1 ) >> 1) + rowOffset) << 8) | (c2 + cellOffset); - } - } -} diff --git a/test/jdk/sun/nio/cs/OLD/SimpleEUCDecoder.java b/test/jdk/sun/nio/cs/OLD/SimpleEUCDecoder.java deleted file mode 100644 index ee9e267e6cf..00000000000 --- a/test/jdk/sun/nio/cs/OLD/SimpleEUCDecoder.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. - * 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. - */ - -/* - */ - -/** - * Simple EUC-like decoder used by IBM01383 and IBM970 - * supports G1 - no support for G2 or G3 - */ - - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; - -abstract class SimpleEUCDecoder - extends CharsetDecoder -{ - private final int SS2 = 0x8E; - private final int SS3 = 0x8F; - - protected static String mappingTableG1; - protected static String byteToCharTable; - - protected SimpleEUCDecoder(Charset cs) { - super(cs, 0.5f, 1.0f); - } - - private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { - byte[] sa = src.array(); - int sp = src.arrayOffset() + src.position(); - int sl = src.arrayOffset() + src.limit(); - assert (sp <= sl); - sp = (sp <= sl ? sp : sl); - char[] da = dst.array(); - int dp = dst.arrayOffset() + dst.position(); - int dl = dst.arrayOffset() + dst.limit(); - assert (dp <= dl); - dp = (dp <= dl ? dp : dl); - - try { - while (sp < sl) { - int byte1, byte2; - int inputSize = 1; - char outputChar = '\uFFFD'; - - byte1 = sa[sp] & 0xff; - - if ( byte1 <= 0x9f ) { // < 0x9f has its own table (G0) - if (byte1 == SS2 || byte1 == SS3 ) { - // No support provided for G2/G3 at this time. - return CoderResult.malformedForLength(1); - } - outputChar = byteToCharTable.charAt(byte1); - } else if (byte1 < 0xa1 || byte1 > 0xfe) { // invalid range? - return CoderResult.malformedForLength(1); - } else { // (G1) - if (sl - sp < 2) { - return CoderResult.UNDERFLOW; - } - byte2 = sa[sp + 1] & 0xff; - inputSize++; - if ( byte2 < 0xa1 || byte2 > 0xfe) { - return CoderResult.malformedForLength(2); - } - outputChar = mappingTableG1.charAt(((byte1 - 0xa1) * 94) + byte2 - 0xa1); - } - if (outputChar == '\uFFFD') { - return CoderResult.unmappableForLength(inputSize); - } - if (dl - dp < 1) - return CoderResult.OVERFLOW; - da[dp++] = outputChar; - sp += inputSize; - } - return CoderResult.UNDERFLOW; - } finally { - src.position(sp - src.arrayOffset()); - dst.position(dp - dst.arrayOffset()); - } - } - - private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) { - int mark = src.position(); - - try { - while (src.hasRemaining()) { - char outputChar = '\uFFFD'; - int inputSize = 1; - int byte1, byte2; - - byte1 = src.get() & 0xff; - if ( byte1 <= 0x9f ) { - if (byte1 == SS2 || byte1 == SS3 ) { - return CoderResult.malformedForLength(1); - } - outputChar = byteToCharTable.charAt(byte1); - } else if (byte1 < 0xa1 || byte1 > 0xfe) { - return CoderResult.malformedForLength(1); - } else { - if (!src.hasRemaining()) { - return CoderResult.UNDERFLOW; - } - byte2 = src.get() & 0xff; - inputSize++; - if ( byte2 < 0xa1 || byte2 > 0xfe) { - return CoderResult.malformedForLength(2); - } - outputChar = mappingTableG1.charAt(((byte1 - 0xa1) * 94) + byte2 - 0xa1); - } - if (outputChar == '\uFFFD') { - return CoderResult.unmappableForLength(inputSize); - } - if (!dst.hasRemaining()) - return CoderResult.OVERFLOW; - dst.put(outputChar); - mark += inputSize; - } - return CoderResult.UNDERFLOW; - } finally { - src.position(mark); - } - } - - protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { - if (src.hasArray() && dst.hasArray()) - return decodeArrayLoop(src, dst); - else - return decodeBufferLoop(src, dst); - } -} diff --git a/test/jdk/sun/nio/cs/OLD/SingleByteDecoder.java b/test/jdk/sun/nio/cs/OLD/SingleByteDecoder.java deleted file mode 100644 index b3d1972bf58..00000000000 --- a/test/jdk/sun/nio/cs/OLD/SingleByteDecoder.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. - * 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.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.MalformedInputException; -import java.nio.charset.UnmappableCharacterException; - - -public abstract class SingleByteDecoder - extends CharsetDecoder -{ - - private final String byteToCharTable; - - protected SingleByteDecoder(Charset cs, String byteToCharTable) { - super(cs, 1.0f, 1.0f); - this.byteToCharTable = byteToCharTable; - } - - private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { - byte[] sa = src.array(); - int sp = src.arrayOffset() + src.position(); - int sl = src.arrayOffset() + src.limit(); - assert (sp <= sl); - sp = (sp <= sl ? sp : sl); - char[] da = dst.array(); - int dp = dst.arrayOffset() + dst.position(); - int dl = dst.arrayOffset() + dst.limit(); - assert (dp <= dl); - dp = (dp <= dl ? dp : dl); - - try { - while (sp < sl) { - int b = sa[sp]; - - char c = decode(b); - if (c == '\uFFFD') - return CoderResult.unmappableForLength(1); - if (dl - dp < 1) - return CoderResult.OVERFLOW; - da[dp++] = c; - sp++; - } - return CoderResult.UNDERFLOW; - } finally { - src.position(sp - src.arrayOffset()); - dst.position(dp - dst.arrayOffset()); - } - } - - private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) { - int mark = src.position(); - try { - while (src.hasRemaining()) { - int b = src.get(); - - char c = decode(b); - if (c == '\uFFFD') - return CoderResult.unmappableForLength(1); - if (!dst.hasRemaining()) - return CoderResult.OVERFLOW; - mark++; - dst.put(c); - } - return CoderResult.UNDERFLOW; - } finally { - src.position(mark); - } - } - - protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { - if (true && src.hasArray() && dst.hasArray()) - return decodeArrayLoop(src, dst); - else - return decodeBufferLoop(src, dst); - } - - public char decode(int byteIndex) { - int n = byteIndex + 128; - if (n >= byteToCharTable.length() || n < 0) - return '\uFFFD'; - return byteToCharTable.charAt(n); - } -} diff --git a/test/jdk/sun/nio/cs/OLD/SingleByteEncoder.java b/test/jdk/sun/nio/cs/OLD/SingleByteEncoder.java deleted file mode 100644 index fb488297367..00000000000 --- a/test/jdk/sun/nio/cs/OLD/SingleByteEncoder.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. - * 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.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.MalformedInputException; -import java.nio.charset.UnmappableCharacterException; -import sun.nio.cs.Surrogate; - - -public abstract class SingleByteEncoder - extends CharsetEncoder -{ - - private final short index1[]; - private final String index2; - private final int mask1; - private final int mask2; - private final int shift; - - private final Surrogate.Parser sgp = new Surrogate.Parser(); - - protected SingleByteEncoder(Charset cs, - short[] index1, String index2, - int mask1, int mask2, int shift) - { - super(cs, 1.0f, 1.0f); - this.index1 = index1; - this.index2 = index2; - this.mask1 = mask1; - this.mask2 = mask2; - this.shift = shift; - } - - public boolean canEncode(char c) { - char testEncode = index2.charAt(index1[(c & mask1) >> shift] - + (c & mask2)); - return testEncode != '\u0000' || c == '\u0000'; - } - - private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { - char[] sa = src.array(); - int sp = src.arrayOffset() + src.position(); - int sl = src.arrayOffset() + src.limit(); - assert (sp <= sl); - sp = (sp <= sl ? sp : sl); - byte[] da = dst.array(); - int dp = dst.arrayOffset() + dst.position(); - int dl = dst.arrayOffset() + dst.limit(); - assert (dp <= dl); - dp = (dp <= dl ? dp : dl); - - try { - while (sp < sl) { - char c = sa[sp]; - if (Character.isSurrogate(c)) { - if (sgp.parse(c, sa, sp, sl) < 0) - return sgp.error(); - return sgp.unmappableResult(); - } - if (c >= '\uFFFE') - return CoderResult.unmappableForLength(1); - if (dl - dp < 1) - return CoderResult.OVERFLOW; - - char e = index2.charAt(index1[(c & mask1) >> shift] - + (c & mask2)); - - // If output byte is zero because input char is zero - // then character is mappable, o.w. fail - if (e == '\u0000' && c != '\u0000') - return CoderResult.unmappableForLength(1); - - sp++; - da[dp++] = (byte)e; - } - return CoderResult.UNDERFLOW; - } finally { - src.position(sp - src.arrayOffset()); - dst.position(dp - dst.arrayOffset()); - } - } - - private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { - int mark = src.position(); - try { - while (src.hasRemaining()) { - char c = src.get(); - if (Character.isSurrogate(c)) { - if (sgp.parse(c, src) < 0) - return sgp.error(); - return sgp.unmappableResult(); - } - if (c >= '\uFFFE') - return CoderResult.unmappableForLength(1); - if (!dst.hasRemaining()) - return CoderResult.OVERFLOW; - - char e = index2.charAt(index1[(c & mask1) >> shift] - + (c & mask2)); - - // If output byte is zero because input char is zero - // then character is mappable, o.w. fail - if (e == '\u0000' && c != '\u0000') - return CoderResult.unmappableForLength(1); - - mark++; - dst.put((byte)e); - } - return CoderResult.UNDERFLOW; - } finally { - src.position(mark); - } - } - - protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { - if (true && src.hasArray() && dst.hasArray()) - return encodeArrayLoop(src, dst); - else - return encodeBufferLoop(src, dst); - } - - public byte encode(char inputChar) { - return (byte)index2.charAt(index1[(inputChar & mask1) >> shift] + - (inputChar & mask2)); - } -} diff --git a/test/jdk/sun/nio/cs/OLD/TestIBMDB.java b/test/jdk/sun/nio/cs/OLD/TestIBMDB.java deleted file mode 100644 index f2e3cbcee79..00000000000 --- a/test/jdk/sun/nio/cs/OLD/TestIBMDB.java +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. - * 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 6843578 - * @summary Test old and new implementation of db charsets - * @build IBM930_OLD IBM933_OLD IBM935_OLD IBM937_OLD IBM939_OLD IBM942_OLD IBM943_OLD IBM948_OLD IBM949_OLD IBM950_OLD IBM970_OLD IBM942C_OLD IBM943C_OLD IBM949C_OLD IBM1381_OLD IBM1383_OLD EUC_CN_OLD EUC_KR_OLD GBK_OLD Johab_OLD MS932_OLD MS936_OLD MS949_OLD MS950_OLD SJIS_OLD PCK_OLD EUC_JP_OLD EUC_JP_LINUX_OLD EUC_JP_Open_OLD - * @modules java.base/sun.nio.cs jdk.charsets/sun.nio.cs.ext - * @run main TestIBMDB - */ - -import java.nio.charset.*; -import java.nio.*; -import java.util.*; - -public class TestIBMDB { - static class Time { - long t; - } - static int iteration = 200; - - static char[] decode(byte[] bb, Charset cs, boolean testDirect, Time t) - throws Exception { - String csn = cs.name(); - CharsetDecoder dec = cs.newDecoder(); - ByteBuffer bbf; - CharBuffer cbf; - if (testDirect) { - bbf = ByteBuffer.allocateDirect(bb.length); - cbf = ByteBuffer.allocateDirect(bb.length*2).asCharBuffer(); - bbf.put(bb); - } else { - bbf = ByteBuffer.wrap(bb); - cbf = CharBuffer.allocate(bb.length); - } - CoderResult cr = null; - long t1 = System.nanoTime()/1000; - for (int i = 0; i < iteration; i++) { - bbf.rewind(); - cbf.clear(); - dec.reset(); - cr = dec.decode(bbf, cbf, true); - } - long t2 = System.nanoTime()/1000; - t.t = (t2 - t1)/iteration; - if (cr != CoderResult.UNDERFLOW) { - System.out.println("DEC-----------------"); - int pos = bbf.position(); - System.out.printf(" cr=%s, bbf.pos=%d, bb[pos]=%x,%x,%x,%x%n", - cr.toString(), pos, - bb[pos++]&0xff, bb[pos++]&0xff,bb[pos++]&0xff, bb[pos++]&0xff); - throw new RuntimeException("Decoding err: " + csn); - } - char[] cc = new char[cbf.position()]; - cbf.flip(); cbf.get(cc); - return cc; - - } - - static CoderResult decodeCR(byte[] bb, Charset cs, boolean testDirect) - throws Exception { - CharsetDecoder dec = cs.newDecoder(); - ByteBuffer bbf; - CharBuffer cbf; - if (testDirect) { - bbf = ByteBuffer.allocateDirect(bb.length); - cbf = ByteBuffer.allocateDirect(bb.length*2).asCharBuffer(); - bbf.put(bb).flip(); - } else { - bbf = ByteBuffer.wrap(bb); - cbf = CharBuffer.allocate(bb.length); - } - CoderResult cr = null; - for (int i = 0; i < iteration; i++) { - bbf.rewind(); - cbf.clear(); - dec.reset(); - cr = dec.decode(bbf, cbf, true); - } - return cr; - } - - static byte[] encode(char[] cc, Charset cs, boolean testDirect, Time t) - throws Exception { - ByteBuffer bbf; - CharBuffer cbf; - CharsetEncoder enc = cs.newEncoder(); - String csn = cs.name(); - if (testDirect) { - bbf = ByteBuffer.allocateDirect(cc.length * 4); - cbf = ByteBuffer.allocateDirect(cc.length * 2).asCharBuffer(); - cbf.put(cc).flip(); - } else { - bbf = ByteBuffer.allocate(cc.length * 4); - cbf = CharBuffer.wrap(cc); - } - CoderResult cr = null; - long t1 = System.nanoTime()/1000; - for (int i = 0; i < iteration; i++) { - cbf.rewind(); - bbf.clear(); - enc.reset(); - cr = enc.encode(cbf, bbf, true); - } - long t2 = System.nanoTime()/1000; - t.t = (t2 - t1)/iteration; - if (cr != CoderResult.UNDERFLOW) { - System.out.println("ENC-----------------"); - int pos = cbf.position(); - System.out.printf(" cr=%s, cbf.pos=%d, cc[pos]=%x%n", - cr.toString(), pos, cc[pos]&0xffff); - throw new RuntimeException("Encoding err: " + csn); - } - byte[] bb = new byte[bbf.position()]; - bbf.flip(); bbf.get(bb); - return bb; - } - - static CoderResult encodeCR(char[] cc, Charset cs, boolean testDirect) - throws Exception { - ByteBuffer bbf; - CharBuffer cbf; - CharsetEncoder enc = cs.newEncoder(); - if (testDirect) { - bbf = ByteBuffer.allocateDirect(cc.length * 4); - cbf = ByteBuffer.allocateDirect(cc.length * 2).asCharBuffer(); - cbf.put(cc).flip(); - } else { - bbf = ByteBuffer.allocate(cc.length * 4); - cbf = CharBuffer.wrap(cc); - } - CoderResult cr = null; - for (int i = 0; i < iteration; i++) { - cbf.rewind(); - bbf.clear(); - enc.reset(); - cr = enc.encode(cbf, bbf, true); - } - return cr; - } - - static void printEntry(char c, Charset cs) { - byte[] bb = new String(new char[] {c}).getBytes(cs); - for (byte b:bb) - System.out.printf("%x", b&0xff); - System.out.printf(" %x", c & 0xffff); - String s2 = new String(bb, cs); - System.out.printf(" %x%n", s2.charAt(0) & 0xffff); - } - - // check and compare canEncoding/Encoding - static char[] checkEncoding(Charset oldCS, Charset newCS) - throws Exception { - System.out.printf("Encoding <%s> <%s>...%n", oldCS.name(), newCS.name()); - CharsetEncoder encOLD = oldCS.newEncoder(); - CharsetEncoder encNew = newCS.newEncoder(); - char[] cc = new char[0x10000]; - int pos = 0; - boolean is970 = "x-IBM970-Old".equals(oldCS.name()); - - for (char c = 0; c < 0xffff; c++) { - boolean canOld = encOLD.canEncode(c); - boolean canNew = encNew.canEncode(c); - - if (is970 && c == 0x2299) - continue; - - if (canOld != canNew) { - if (canNew) { - System.out.printf(" NEW(only): "); - printEntry(c, newCS); - } else { - if (is970) { - byte[] bb = new String(new char[] {c}).getBytes(oldCS); - if (bb.length == 2 && bb[0] == (byte)0xa2 && bb[1] == (byte)0xc1) { - // we know 970 has bogus nnnn -> a2c1 -> 2299 - continue; - } - } - System.out.printf(" OLD(only): "); - printEntry(c, oldCS); - } - } else if (canNew) { - byte[] bbNew = new String(new char[] {c}).getBytes(newCS); - byte[] bbOld = new String(new char[] {c}).getBytes(oldCS); - if (!Arrays.equals(bbNew, bbOld)) { - System.out.printf(" c->b NEW: "); - printEntry(c, newCS); - System.out.printf(" c->b OLD: "); - printEntry(c, oldCS); - } else { - String sNew = new String(bbNew, newCS); - String sOld = new String(bbOld, oldCS); - if (!sNew.equals(sOld)) { - System.out.printf(" b2c NEW (c=%x):", c&0xffff); - printEntry(sNew.charAt(0), newCS); - System.out.printf(" b2c OLD:"); - printEntry(sOld.charAt(0), oldCS); - } - } - } - if (canNew & canOld) { // added only both for now - cc[pos++] = c; - } - } - return Arrays.copyOf(cc, pos); - } - - - // check and compare canEncoding/Encoding - static void checkDecoding(Charset oldCS, Charset newCS) - throws Exception - { - System.out.printf("Decoding <%s> <%s>...%n", oldCS.name(), newCS.name()); - boolean isEBCDIC = oldCS.name().startsWith("x-IBM93"); - - //Try singlebyte first - byte[] bb = new byte[1]; - System.out.printf(" trying SB...%n"); - for (int b = 0; b < 0x100; b++) { - bb[0] = (byte)b; - String sOld = new String(bb, oldCS); - String sNew = new String(bb, newCS); - if (!sOld.equals(sNew)) { - System.out.printf(" b=%x: %x/%d(old) %x/%d(new)%n", - b& 0xff, - sOld.charAt(0) & 0xffff, sOld.length(), - sNew.charAt(0) & 0xffff, sNew.length()); - } - } - - System.out.printf(" trying DB...%n"); - bb = new byte[isEBCDIC?4:2]; - int b1Min = 0x40; - int b1Max = 0xfe; - for (int b1 = 0x40; b1 < 0xff; b1++) { - if (!isEBCDIC) { - // decodable singlebyte b1 - bb[0] = (byte)b1; - String sOld = new String(bb, oldCS); - String sNew = new String(bb, newCS); - if (!sOld.equals(sNew)) { - if (sOld.length() != 2 && sOld.charAt(0) != 0) { - // only prints we are NOT expected. above two are known issue - System.out.printf(" b1=%x: %x/%d(old) %x/%d(new)%n", - b1 & 0xff, - sOld.charAt(0) & 0xffff, sOld.length(), - sNew.charAt(0) & 0xffff, sNew.length()); - continue; - } - } - } - for (int b2 = 0x40; b2 < 0xff; b2++) { - if (isEBCDIC) { - bb[0] = 0x0e; - bb[1] = (byte)b1; - bb[2] = (byte)b2; - bb[3] = 0x0f; - } else { - bb[0] = (byte)b1; - bb[1] = (byte)b2; - } - String sOld = new String(bb, oldCS); - String sNew = new String(bb, newCS); - //if (!sOld.equals(sNew)) { - if (sOld.charAt(0) != sNew.charAt(0)) { - -if (sOld.charAt(0) == 0 && sNew.charAt(0) == 0xfffd) - continue; // known issude in old implementation - - System.out.printf(" bb=<%x,%x> c(old)=%x, c(new)=%x%n", - b1, b2, sOld.charAt(0) & 0xffff, sNew.charAt(0) & 0xffff); - } - } - } - } - - static void checkInit(String csn) throws Exception { - System.out.printf("Check init <%s>...%n", csn); - Charset.forName("Big5"); // load in the ExtendedCharsets - long t1 = System.nanoTime()/1000; - Charset cs = Charset.forName(csn); - long t2 = System.nanoTime()/1000; - System.out.printf(" charset :%d%n", t2 - t1); - t1 = System.nanoTime()/1000; - cs.newDecoder(); - t2 = System.nanoTime()/1000; - System.out.printf(" new Decoder :%d%n", t2 - t1); - - t1 = System.nanoTime()/1000; - cs.newEncoder(); - t2 = System.nanoTime()/1000; - System.out.printf(" new Encoder :%d%n", t2 - t1); - } - - static void compare(Charset cs1, Charset cs2, char[] cc) throws Exception { - System.gc(); // enqueue finalizable objects - Thread.sleep(1000); - System.gc(); // enqueue finalizable objects - - String csn1 = cs1.name(); - String csn2 = cs2.name(); - System.out.printf("Diff <%s> <%s>...%n", csn1, csn2); - - Time t1 = new Time(); - Time t2 = new Time(); - - byte[] bb1 = encode(cc, cs1, false, t1); - byte[] bb2 = encode(cc, cs2, false, t2); - - System.out.printf(" Encoding TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - if (!Arrays.equals(bb1, bb2)) { - System.out.printf(" encoding failed%n"); - } - - char[] cc2 = decode(bb1, cs2, false, t2); - char[] cc1 = decode(bb1, cs1, false, t1); - System.out.printf(" Decoding TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - if (!Arrays.equals(cc1, cc2)) { - System.out.printf(" decoding failed%n"); - } - - bb1 = encode(cc, cs1, true, t1); - bb2 = encode(cc, cs2, true, t2); - - System.out.printf(" Encoding(dir) TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - - if (!Arrays.equals(bb1, bb2)) - System.out.printf(" encoding (direct) failed%n"); - - cc1 = decode(bb1, cs1, true, t1); - cc2 = decode(bb1, cs2, true, t2); - System.out.printf(" Decoding(dir) TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - if (!Arrays.equals(cc1, cc2)) { - System.out.printf(" decoding (direct) failed%n"); - } - } - - /* The first byte is the length of malformed bytes - byte[][] malformed = { - {5, (byte)0xF8, (byte)0x80, (byte)0x80, (byte)0x9F, (byte)0x80, (byte)0xC0 }, - }; - */ - - static void checkMalformed(Charset cs, byte[][] malformed) - throws Exception - { - boolean failed = false; - String csn = cs.name(); - System.out.printf("Check malformed <%s>...%n", csn); - for (boolean direct: new boolean[] {false, true}) { - for (byte[] bins : malformed) { - int mlen = bins[0]; - byte[] bin = Arrays.copyOfRange(bins, 1, bins.length); - CoderResult cr = decodeCR(bin, cs, direct); - String ashex = ""; - for (int i = 0; i < bin.length; i++) { - if (i > 0) ashex += " "; - ashex += Integer.toString((int)bin[i] & 0xff, 16); - } - if (!cr.isMalformed()) { - System.out.printf(" FAIL(direct=%b): [%s] not malformed. -->cr=%s\n", direct, ashex, cr.toString()); - failed = true; - } else if (cr.length() != mlen) { - System.out.printf(" FAIL(direct=%b): [%s] malformed[len=%d].\n", direct, ashex, cr.length()); - failed = true; - } - } - } - if (failed) - throw new RuntimeException("Check malformed failed " + csn); - } - - static boolean check(CharsetDecoder dec, byte[] bytes, boolean direct, int[] flow) { - int inPos = flow[0]; - int inLen = flow[1]; - int outPos = flow[2]; - int outLen = flow[3]; - int expedInPos = flow[4]; - int expedOutPos = flow[5]; - CoderResult expedCR = (flow[6]==0)?CoderResult.UNDERFLOW - :CoderResult.OVERFLOW; - ByteBuffer bbf; - CharBuffer cbf; - if (direct) { - bbf = ByteBuffer.allocateDirect(inPos + bytes.length); - cbf = ByteBuffer.allocateDirect((outPos + outLen)*2).asCharBuffer(); - } else { - bbf = ByteBuffer.allocate(inPos + bytes.length); - cbf = CharBuffer.allocate(outPos + outLen); - } - bbf.position(inPos); - bbf.put(bytes).flip().position(inPos).limit(inPos + inLen); - cbf.position(outPos); - dec.reset(); - CoderResult cr = dec.decode(bbf, cbf, false); - if (cr != expedCR || - bbf.position() != expedInPos || - cbf.position() != expedOutPos) { - System.out.printf("Expected(direct=%5b): [", direct); - for (int i:flow) System.out.print(" " + i); - System.out.println("] CR=" + cr + - ", inPos=" + bbf.position() + - ", outPos=" + cbf.position()); - return false; - } - return true; - } - - static void checkUnderOverflow(Charset cs) throws Exception { - String csn = cs.name(); - System.out.printf("Check under/overflow <%s>...%n", csn); - CharsetDecoder dec = cs.newDecoder(); - boolean failed = false; - - //7f, a1a1, 8ea2a1a1, 8ea3a1a1, 8ea7a1a1 - //0 1 2 3 7 11 - byte[] bytes = new String("\u007f\u3000\u4e42\u4e28\ud840\udc55").getBytes("EUC_TW"); - int inlen = bytes.length; - - int MAXOFF = 20; - for (int inoff = 0; inoff < MAXOFF; inoff++) { - for (int outoff = 0; outoff < MAXOFF; outoff++) { - int[][] Flows = { - //inpos, inLen, outPos, outLen, inPosEP, outposEP, under(0)/over(1) - //overflow - {inoff, inlen, outoff, 1, inoff + 1, outoff + 1, 1}, - {inoff, inlen, outoff, 2, inoff + 3, outoff + 2, 1}, - {inoff, inlen, outoff, 3, inoff + 7, outoff + 3, 1}, - {inoff, inlen, outoff, 4, inoff + 11, outoff + 4, 1}, - {inoff, inlen, outoff, 5, inoff + 11, outoff + 4, 1}, - {inoff, inlen, outoff, 6, inoff + 15, outoff + 6, 0}, - //underflow - {inoff, 1, outoff, 6, inoff + 1, outoff + 1, 0}, - {inoff, 2, outoff, 6, inoff + 1, outoff + 1, 0}, - {inoff, 3, outoff, 6, inoff + 3, outoff + 2, 0}, - {inoff, 4, outoff, 6, inoff + 3, outoff + 2, 0}, - {inoff, 5, outoff, 6, inoff + 3, outoff + 2, 0}, - {inoff, 8, outoff, 6, inoff + 7, outoff + 3, 0}, - {inoff, 9, outoff, 6, inoff + 7, outoff + 3, 0}, - {inoff, 10, outoff, 6, inoff + 7, outoff + 3, 0}, - {inoff, 11, outoff, 6, inoff +11, outoff + 4, 0}, - {inoff, 12, outoff, 6, inoff +11, outoff + 4, 0}, - {inoff, 15, outoff, 6, inoff +15, outoff + 6, 0}, - // 2-byte under/overflow - {inoff, 2, outoff, 1, inoff + 1, outoff + 1, 0}, - {inoff, 3, outoff, 1, inoff + 1, outoff + 1, 1}, - {inoff, 3, outoff, 2, inoff + 3, outoff + 2, 0}, - }; - for (boolean direct: new boolean[] {false, true}) { - for (int[] flow: Flows) { - if (!check(dec, bytes, direct, flow)) - failed = true; - } - }}} - if (failed) - throw new RuntimeException("Check under/overflow failed " + csn); - } - - static String[] csnames = new String[] { - - "IBM930", - "IBM933", - "IBM935", - "IBM937", - "IBM939", - "IBM942", - "IBM943", - "IBM948", - "IBM949", - "IBM950", - "IBM970", - "IBM942C", - "IBM943C", - "IBM949C", - "IBM1381", - "IBM1383", - - "EUC_CN", - "EUC_KR", - "GBK", - "Johab", - "MS932", - "MS936", - "MS949", - "MS950", - - "EUC_JP", - "EUC_JP_LINUX", - "EUC_JP_Open", - "SJIS", - "PCK", - }; - - public static void main(String[] args) throws Exception { - for (String csname: csnames) { - System.out.printf("-----------------------------------%n"); - String oldname = csname + "_OLD"; - if ("EUC_JP_Open".equals(csname)) - csname = "eucjp-open"; - checkInit(csname); - Charset csOld = (Charset)Class.forName(oldname).newInstance(); - Charset csNew = Charset.forName(csname); - char[] cc = checkEncoding(csOld, csNew); - checkDecoding(csOld, csNew); - compare(csNew, csOld, cc); - - if (csname.startsWith("x-IBM93")) { - //ecdbic - checkMalformed(csNew, new byte[][] { - {1, 0x26, 0x0f, 0x27}, // in SBSC, no SI - {1, 0x0e, 0x41, 0x41, 0xe}, // in DBSC, no SO - {2, 0x0e, 0x40, 0x41, 0xe}, // illegal DB - }); - } else if (csname.equals("x-IBM970") || - csname.equals("x-IBM1383")) { - //euc_simple - checkMalformed(csNew, new byte[][] { - {1, 0x26, (byte)0x8f, 0x27}, // SS2 - {1, (byte)0xa1, (byte)0xa1, (byte)0x8e, 0x51}, // SS3 - }); - } - } - } -} diff --git a/test/jdk/sun/nio/cs/TestEUC_TW.java b/test/jdk/sun/nio/cs/TestEUC_TW.java index 4453a2cbead..ef663bbb309 100644 --- a/test/jdk/sun/nio/cs/TestEUC_TW.java +++ b/test/jdk/sun/nio/cs/TestEUC_TW.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6831794 6229811 + * @bug 6831794 6229811 8343157 * @summary Test EUC_TW charset * @modules java.base/sun.nio.cs */ @@ -131,25 +131,7 @@ public class TestEUC_TW { return bb; } - static CoderResult encodeCR(char[] cc, Charset cs, boolean testDirect) - throws Exception { - ByteBuffer bbf; - CharBuffer cbf; - CharsetEncoder enc = cs.newEncoder(); - if (testDirect) { - bbf = ByteBuffer.allocateDirect(cc.length * 4); - cbf = ByteBuffer.allocateDirect(cc.length * 2).asCharBuffer(); - cbf.put(cc).flip(); - } else { - bbf = ByteBuffer.allocate(cc.length * 4); - cbf = CharBuffer.wrap(cc); - } - return enc.encode(cbf, bbf, true); - } - static char[] getEUC_TWChars(boolean skipNR) { - //CharsetEncoder encOLD = Charset.forName("EUC_TW_OLD").newEncoder(); - CharsetEncoder encOLD = new EUC_TW_OLD().newEncoder(); CharsetEncoder enc = Charset.forName("EUC_TW").newEncoder(); char[] cc = new char[0x20000]; char[] c2 = new char[2]; @@ -160,12 +142,6 @@ public class TestEUC_TW { //SKIP these 3 NR codepoints if compared to EUC_TW if (skipNR && (i == 0x4ea0 || i == 0x51ab || i == 0x52f9)) continue; - if (encOLD.canEncode((char)i) != enc.canEncode((char)i)) { - System.out.printf(" Err i=%x: old=%b new=%b%n", i, - encOLD.canEncode((char)i), - enc.canEncode((char)i)); - throw new RuntimeException("canEncode() err!"); - } if (enc.canEncode((char)i)) { cc[pos++] = (char)i; @@ -178,10 +154,6 @@ public class TestEUC_TW { Character.toChars(i, c2, 0); cb.clear();cb.put(c2[0]);cb.put(c2[1]);cb.flip(); - if (encOLD.canEncode(cb) != enc.canEncode(cb)) { - throw new RuntimeException("canEncode() err!"); - } - if (enc.canEncode(cb)) { //System.out.printf("cp=%x, (%x, %x) %n", i, c2[0] & 0xffff, c2[1] & 0xffff); cc[pos++] = c2[0]; @@ -227,91 +199,6 @@ public class TestEUC_TW { System.out.printf(" new Encoder :%d%n", t2 - t1); } - static void compare(Charset cs1, Charset cs2) throws Exception { - char[] cc = getEUC_TWChars(true); - - String csn1 = cs1.name(); - String csn2 = cs2.name(); - System.out.printf("Diff <%s> <%s>...%n", csn1, csn2); - - Time t1 = new Time(); - Time t2 = new Time(); - - byte[] bb1 = encode(cc, cs1, false, t1); - byte[] bb2 = encode(cc, cs2, false, t2); - - System.out.printf(" Encoding TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - if (!Arrays.equals(bb1, bb2)) { - System.out.printf(" encoding failed%n"); - } - - char[] cc2 = decode(bb1, cs2, false, t2); - char[] cc1 = decode(bb1, cs1, false, t1); - System.out.printf(" Decoding TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - if (!Arrays.equals(cc1, cc2)) { - System.out.printf(" decoding failed%n"); - } - - bb1 = encode(cc, cs1, true, t1); - bb2 = encode(cc, cs2, true, t2); - - System.out.printf(" Encoding(dir) TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - - if (!Arrays.equals(bb1, bb2)) - System.out.printf(" encoding (direct) failed%n"); - - cc1 = decode(bb1, cs1, true, t1); - cc2 = decode(bb1, cs2, true, t2); - System.out.printf(" Decoding(dir) TimeRatio %s/%s: %d,%d :%f%n", - csn2, csn1, - t2.t, t1.t, - (double)(t2.t)/(t1.t)); - if (!Arrays.equals(cc1, cc2)) { - System.out.printf(" decoding (direct) failed%n"); - } - } - - // The first byte is the length of malformed bytes - static byte[][] malformed = { - //{5, (byte)0xF8, (byte)0x80, (byte)0x80, (byte)0x9F, (byte)0x80, (byte)0xC0 }, - }; - - static void checkMalformed(Charset cs) throws Exception { - boolean failed = false; - String csn = cs.name(); - System.out.printf("Check malformed <%s>...%n", csn); - for (boolean direct: new boolean[] {false, true}) { - for (byte[] bins : malformed) { - int mlen = bins[0]; - byte[] bin = Arrays.copyOfRange(bins, 1, bins.length); - CoderResult cr = decodeCR(bin, cs, direct); - String ashex = ""; - for (int i = 0; i < bin.length; i++) { - if (i > 0) ashex += " "; - ashex += Integer.toBinaryString((int)bin[i] & 0xff); - } - if (!cr.isMalformed()) { - System.out.printf(" FAIL(direct=%b): [%s] not malformed.\n", direct, ashex); - failed = true; - } else if (cr.length() != mlen) { - System.out.printf(" FAIL(direct=%b): [%s] malformed[len=%d].\n", direct, ashex, cr.length()); - failed = true; - } - } - } - if (failed) - throw new RuntimeException("Check malformed failed " + csn); - } - static boolean check(CharsetDecoder dec, byte[] bytes, boolean direct, int[] flow) { int inPos = flow[0]; int inLen = flow[1]; @@ -419,12 +306,9 @@ public class TestEUC_TW { public static void main(String[] args) throws Exception { // be the first one - //checkInit("EUC_TW_OLD"); checkInit("EUC_TW"); Charset euctw = Charset.forName("EUC_TW"); checkRoundtrip(euctw); - compare(euctw, new EUC_TW_OLD()); - checkMalformed(euctw); checkUnderOverflow(euctw); } } From 43b194741cc307a73bd8dd2da877ab1b16250fc1 Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Mon, 14 Apr 2025 16:22:07 +0000 Subject: [PATCH 164/843] 8344883: Force clients to explicitly pass mem_tag value, even if it is mtNone Co-authored-by: Stefan Karlsson Reviewed-by: stefank, jsjolen --- .../cpu/aarch64/compressedKlass_aarch64.cpp | 4 +-- .../bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp | 2 +- src/hotspot/os/linux/os_linux.cpp | 4 +-- src/hotspot/os/posix/os_posix.cpp | 4 +-- src/hotspot/os/posix/perfMemory_posix.cpp | 2 +- src/hotspot/os/windows/os_windows.cpp | 20 ++++++------- src/hotspot/os/windows/perfMemory_windows.cpp | 2 +- src/hotspot/share/cds/archiveBuilder.cpp | 3 +- src/hotspot/share/cds/filemap.cpp | 10 +++---- src/hotspot/share/cds/metaspaceShared.cpp | 12 +++++--- .../share/classfile/compactHashtable.cpp | 2 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 3 +- .../share/gc/parallel/parMarkBitMap.cpp | 3 +- .../share/gc/parallel/psParallelCompact.cpp | 3 +- src/hotspot/share/gc/shared/cardTable.cpp | 2 +- .../gc/shenandoah/shenandoahCardTable.cpp | 4 +-- .../share/gc/shenandoah/shenandoahHeap.cpp | 6 ++-- .../jfr/recorder/storage/jfrVirtualMemory.cpp | 3 +- .../share/memory/allocation.inline.hpp | 4 +-- src/hotspot/share/memory/memoryReserver.cpp | 8 +++--- src/hotspot/share/memory/memoryReserver.hpp | 4 +-- src/hotspot/share/memory/metaspace.cpp | 5 ++-- .../share/memory/metaspace/testHelpers.cpp | 3 +- .../memory/metaspace/virtualSpaceNode.cpp | 2 +- src/hotspot/share/nmt/memReporter.cpp | 2 +- src/hotspot/share/nmt/memReporter.hpp | 2 +- src/hotspot/share/nmt/memTracker.hpp | 4 +-- .../share/nmt/virtualMemoryTracker.hpp | 4 +-- src/hotspot/share/prims/jni.cpp | 2 +- src/hotspot/share/prims/whitebox.cpp | 6 ++-- src/hotspot/share/runtime/os.cpp | 12 ++++---- src/hotspot/share/runtime/os.hpp | 16 +++++------ .../share/runtime/safepointMechanism.cpp | 2 +- src/hotspot/share/utilities/debug.cpp | 2 +- .../gtest/gc/g1/test_stressCommitUncommit.cpp | 10 ++++--- test/hotspot/gtest/gc/z/test_zForwarding.cpp | 2 +- .../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 | 28 +++++++++---------- test/hotspot/gtest/runtime/test_os_aix.cpp | 4 +-- test/hotspot/gtest/runtime/test_os_linux.cpp | 2 +- .../gtest/runtime/test_os_reserve_between.cpp | 6 ++-- .../runtime/NMT/MallocRoundingReportTest.java | 4 +-- .../jtreg/runtime/NMT/MallocTestType.java | 6 ++-- .../runtime/NMT/MallocTrackingVerify.java | 4 +-- .../runtime/NMT/ThreadedMallocTestType.java | 4 +-- 47 files changed, 143 insertions(+), 126 deletions(-) diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp index 0c2d9a32c8c..3874c8cd54e 100644 --- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp @@ -70,7 +70,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, mtNone); if (result == nullptr) { log_trace(metaspace, map)("Failed to attach at " UINT64_FORMAT_X, immediate); } @@ -114,7 +114,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, mtNone); } return result; diff --git a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp index 86549e878cb..861fda7a71d 100644 --- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp @@ -77,7 +77,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) _initialized(false) { // Reserve address space for backing memory - _base = (uintptr_t)os::reserve_memory(max_capacity, false, mtJavaHeap); + _base = (uintptr_t)os::reserve_memory(max_capacity, mtJavaHeap); if (_base == 0) { // Failed ZInitialize::error("Failed to reserve address space for backing memory"); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 4e26797cd5b..a8dce39ce5d 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -4577,7 +4577,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, false, mtThread); + char* codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread); if (codebuf == nullptr) { // JDK-8197429: There may be a stack gap of one megabyte between @@ -4585,7 +4585,7 @@ 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, false, mtThread); + codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread); } if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, true))) { diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index a36d6b87641..8df488768be 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -491,9 +491,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, MemTag mem_tag, bool exec) { 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, mem_tag, exec); if (extra_base == nullptr) { return nullptr; } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 4d6fc1e4b8c..cbbecea3a6a 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -64,7 +64,7 @@ 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, mtInternal); if (mapAddress == nullptr) { return nullptr; diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 84e89334feb..843272f57b5 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3019,7 +3019,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, mtNone); 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) @@ -3080,7 +3080,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, mtNone); os::release_memory(p_buf, bytes_to_release); } #ifdef ASSERT @@ -3098,9 +3098,9 @@ 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); + MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC, mtNone); } else { - MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC, mtNone); } // made it this far, success @@ -3240,7 +3240,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, MemTag mem_tag = mtNone) { +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag) { 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()), @@ -3254,7 +3254,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, mem_tag) : - os::reserve_memory(extra_size, false, mem_tag); + os::reserve_memory(extra_size, mem_tag); if (extra_base == nullptr) { return nullptr; } @@ -3271,7 +3271,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, mem_tag) : - os::attempt_reserve_memory_at(aligned_base, size, false, mem_tag); + os::attempt_reserve_memory_at(aligned_base, size, mem_tag); } assert(aligned_base != nullptr, @@ -3280,9 +3280,9 @@ 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, MemTag mem_tag, bool exec) { // 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 */, mem_tag); } char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag) { @@ -5187,7 +5187,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, } // Record virtual memory allocation - MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC, mtNone); DWORD bytes_read; OVERLAPPED overlapped; diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index dda0acde793..322b844f413 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -54,7 +54,7 @@ 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, mtInternal); if (mapAddress == nullptr) { return nullptr; diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index c309de17b4c..fa65d7d27bf 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -309,7 +309,8 @@ address ArchiveBuilder::reserve_buffer() { size_t buffer_size = LP64_ONLY(CompressedClassSpaceSize) NOT_LP64(256 * M); ReservedSpace rs = MemoryReserver::reserve(buffer_size, MetaspaceShared::core_region_alignment(), - os::vm_page_size()); + os::vm_page_size(), + mtClassShared); if (!rs.is_reserved()) { log_error(cds)("Failed to reserve %zu 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 580699b60b5..1b5d455485c 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1066,10 +1066,10 @@ void FileMapInfo::close() { */ 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, MemTag mem_tag = mtNone) { + bool allow_exec, MemTag mem_tag) { char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes, - AlwaysPreTouch ? false : read_only, - allow_exec, mem_tag); + mem_tag, AlwaysPreTouch ? false : read_only, + allow_exec); if (mem != nullptr && AlwaysPreTouch) { os::pretouch_memory(mem, mem + bytes); } @@ -1094,7 +1094,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() { assert(WINDOWS_ONLY(false) NOT_WINDOWS(true), "Don't call on Windows"); // 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 */, + addr, size, mtNone, false /* !read_only */, r->allow_exec()); close(); // These have to be errors because the shared region is now unmapped. @@ -1620,7 +1620,7 @@ bool FileMapInfo::map_heap_region_impl() { } else { base = map_memory(_fd, _full_path, r->file_offset(), addr, _mapped_heap_memregion.byte_size(), r->read_only(), - r->allow_exec()); + 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 ef2a6dcb8e6..3ca19858430 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -1537,7 +1537,8 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma archive_space_rs = MemoryReserver::reserve((char*)base_address, archive_space_size, archive_space_alignment, - os::vm_page_size()); + os::vm_page_size(), + mtNone); if (archive_space_rs.is_reserved()) { assert(base_address == nullptr || (address)archive_space_rs.base() == base_address, "Sanity"); @@ -1605,11 +1606,13 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma archive_space_rs = MemoryReserver::reserve((char*)base_address, archive_space_size, archive_space_alignment, - os::vm_page_size()); + os::vm_page_size(), + mtNone); class_space_rs = MemoryReserver::reserve((char*)ccs_base, class_space_size, class_space_alignment, - os::vm_page_size()); + os::vm_page_size(), + mtNone); } if (!archive_space_rs.is_reserved() || !class_space_rs.is_reserved()) { release_reserved_spaces(total_space_rs, archive_space_rs, class_space_rs); @@ -1622,7 +1625,8 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma total_space_rs = MemoryReserver::reserve((char*) base_address, total_range_size, base_address_alignment, - os::vm_page_size()); + os::vm_page_size(), + mtNone); } 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 8d50e8136a3..15ae5ba8013 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -226,7 +226,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, mtNone, 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 31f0cc12aa5..44fb790f705 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1230,7 +1230,8 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des // Allocate a new reserved space, preferring to use large pages. ReservedSpace rs = MemoryReserver::reserve(size, alignment, - preferred_page_size); + preferred_page_size, + mtGC); size_t page_size = rs.page_size(); G1RegionToSpaceMapper* result = diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp index f33d7f93f1d..d2d168cc2c0 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp @@ -48,7 +48,8 @@ ParMarkBitMap::initialize(MemRegion covered_region) ReservedSpace rs = MemoryReserver::reserve(_reserved_byte_size, rs_align, - page_sz); + page_sz, + mtGC); if (!rs.is_reserved()) { // Failed to reserve memory for the bitmap, diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 99b975c282a..84ed7798691 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -246,7 +246,8 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) ReservedSpace rs = MemoryReserver::reserve(_reserved_byte_size, rs_align, - page_sz); + page_sz, + mtGC); if (!rs.is_reserved()) { // Failed to reserve memory. diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 3236d73933c..24546618edb 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -80,7 +80,7 @@ void CardTable::initialize(void* region0_start, void* region1_start) { HeapWord* high_bound = _whole_heap.end(); const size_t rs_align = MAX2(_page_size, os::vm_allocation_granularity()); - ReservedSpace rs = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size); + ReservedSpace rs = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC); if (!rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for the " diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp index 00f11938489..e9e52475fb9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp @@ -45,7 +45,7 @@ void ShenandoahCardTable::initialize() { // ReservedSpace constructor would assert rs_align >= os::vm_page_size(). const size_t rs_align = MAX2(_page_size, granularity); - ReservedSpace write_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size); + ReservedSpace write_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC); initialize(write_space); // The assembler store_check code will do an unsigned shift of the oop, @@ -60,7 +60,7 @@ void ShenandoahCardTable::initialize() { _write_byte_map = _byte_map; _write_byte_map_base = _byte_map_base; - ReservedSpace read_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size); + ReservedSpace read_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC); initialize(read_space); _read_byte_map = (CardValue*) read_space.base(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 045f485090d..ce4b9fc2406 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -166,7 +166,7 @@ static ReservedSpace reserve(size_t size, size_t preferred_page_size) { size = align_up(size, alignment); } - const ReservedSpace reserved = MemoryReserver::reserve(size, alignment, preferred_page_size); + const ReservedSpace reserved = MemoryReserver::reserve(size, alignment, preferred_page_size, mtGC); if (!reserved.is_reserved()) { vm_exit_during_initialization("Could not reserve space"); } @@ -380,7 +380,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 = MemoryReserver::reserve(req_addr, cset_size, cset_align, cset_page_size); + cset_rs = MemoryReserver::reserve(req_addr, cset_size, cset_align, cset_page_size, mtGC); 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()); @@ -389,7 +389,7 @@ jint ShenandoahHeap::initialize() { } if (_collection_set == nullptr) { - cset_rs = MemoryReserver::reserve(cset_size, cset_align, os::vm_page_size()); + cset_rs = MemoryReserver::reserve(cset_size, cset_align, os::vm_page_size(), mtGC); if (!cset_rs.is_reserved()) { vm_exit_during_initialization("Cannot reserve memory for collection set"); } diff --git a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp index 97f2b8a1990..0ba54fc79be 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp @@ -106,7 +106,8 @@ bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes) assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant"); _rs = MemoryReserver::reserve(reservation_size_request_bytes, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), + mtTracing); if (!_rs.is_reserved()) { return false; } diff --git a/src/hotspot/share/memory/allocation.inline.hpp b/src/hotspot/share/memory/allocation.inline.hpp index 8d531c6dd23..01af1616ce1 100644 --- a/src/hotspot/share/memory/allocation.inline.hpp +++ b/src/hotspot/share/memory/allocation.inline.hpp @@ -58,7 +58,7 @@ template E* MmapArrayAllocator::allocate_or_null(size_t length, MemTag mem_tag) { size_t size = size_for(length); - char* addr = os::reserve_memory(size, !ExecMem, mem_tag); + char* addr = os::reserve_memory(size, mem_tag); if (addr == nullptr) { return nullptr; } @@ -75,7 +75,7 @@ template E* MmapArrayAllocator::allocate(size_t length, MemTag mem_tag) { size_t size = size_for(length); - char* addr = os::reserve_memory(size, !ExecMem, mem_tag); + char* addr = os::reserve_memory(size, mem_tag); if (addr == nullptr) { vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)"); } diff --git a/src/hotspot/share/memory/memoryReserver.cpp b/src/hotspot/share/memory/memoryReserver.cpp index 43cc71355ff..457818139cd 100644 --- a/src/hotspot/share/memory/memoryReserver.cpp +++ b/src/hotspot/share/memory/memoryReserver.cpp @@ -90,13 +90,13 @@ static char* reserve_memory_inner(char* requested_address, assert(is_aligned(requested_address, alignment), "Requested address " PTR_FORMAT " must be aligned to %zu", p2i(requested_address), alignment); - return os::attempt_reserve_memory_at(requested_address, size, exec, mem_tag); + return os::attempt_reserve_memory_at(requested_address, size, mem_tag, exec); } // 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. - char* base = os::reserve_memory(size, exec, mem_tag); + char* base = os::reserve_memory(size, mem_tag, exec); if (is_aligned(base, alignment)) { return base; } @@ -107,7 +107,7 @@ static char* reserve_memory_inner(char* requested_address, } // Map using the requested alignment. - return os::reserve_memory_aligned(size, alignment, exec); + return os::reserve_memory_aligned(size, alignment, mem_tag, exec); } ReservedSpace MemoryReserver::reserve_memory(char* requested_address, @@ -261,7 +261,7 @@ static char* map_memory_to_file(char* requested_address, // 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. - char* base = os::map_memory_to_file(size, fd); + char* base = os::map_memory_to_file(size, fd, mem_tag); if (is_aligned(base, alignment)) { return base; } diff --git a/src/hotspot/share/memory/memoryReserver.hpp b/src/hotspot/share/memory/memoryReserver.hpp index 1e16ec252a9..f8f642cca95 100644 --- a/src/hotspot/share/memory/memoryReserver.hpp +++ b/src/hotspot/share/memory/memoryReserver.hpp @@ -58,12 +58,12 @@ public: size_t size, size_t alignment, size_t page_size, - MemTag mem_tag = mtNone); + MemTag mem_tag); static ReservedSpace reserve(size_t size, size_t alignment, size_t page_size, - MemTag mem_tag = mtNone); + MemTag mem_tag); static ReservedSpace reserve(size_t size, MemTag mem_tag); diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 04e5d807f32..33cd4a75d7e 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -594,7 +594,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(), mtClass); } // Wrap resulting range in ReservedSpace @@ -767,7 +767,8 @@ void Metaspace::global_initialize() { rs = MemoryReserver::reserve((char*)base, size, Metaspace::reserve_alignment(), - os::vm_page_size()); + os::vm_page_size(), + mtClass); if (rs.is_reserved()) { log_info(metaspace)("Successfully forced class space address to " PTR_FORMAT, p2i(base)); diff --git a/src/hotspot/share/memory/metaspace/testHelpers.cpp b/src/hotspot/share/memory/metaspace/testHelpers.cpp index 76fa1e36c45..f06f6c855be 100644 --- a/src/hotspot/share/memory/metaspace/testHelpers.cpp +++ b/src/hotspot/share/memory/metaspace/testHelpers.cpp @@ -82,7 +82,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 = MemoryReserver::reserve(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size()); + _rs = MemoryReserver::reserve(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size(), mtTest); _context = MetaspaceContext::create_nonexpandable_context(name, _rs, &_commit_limiter); } else { // no reserve limit -> expandable vslist @@ -142,4 +142,3 @@ size_t MetaspaceTestContext::reserved_words() const { } } // namespace metaspace - diff --git a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp index 66644c805a9..bb59192cf16 100644 --- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp +++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp @@ -256,7 +256,7 @@ VirtualSpaceNode* VirtualSpaceNode::create_node(size_t word_size, ReservedSpace rs = MemoryReserver::reserve(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"); } diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp index c7327782a4a..512e1975929 100644 --- a/src/hotspot/share/nmt/memReporter.cpp +++ b/src/hotspot/share/nmt/memReporter.cpp @@ -249,7 +249,7 @@ void MemSummaryReporter::report_summary_of_tag(MemTag mem_tag, // report malloc'd memory if (amount_in_current_scale(MAX2(malloc_memory->malloc_size(), pk_malloc)) > 0) { - print_malloc(malloc_memory->malloc_counter()); + print_malloc(malloc_memory->malloc_counter(), mem_tag); out->cr(); } diff --git a/src/hotspot/share/nmt/memReporter.hpp b/src/hotspot/share/nmt/memReporter.hpp index 05b1588f38b..2238d42f15f 100644 --- a/src/hotspot/share/nmt/memReporter.hpp +++ b/src/hotspot/share/nmt/memReporter.hpp @@ -108,7 +108,7 @@ class MemReporterBase : public StackObj { // Print summary total, malloc and virtual memory void print_total(size_t reserved, size_t committed, size_t peak = 0) const; - void print_malloc(const MemoryCounter* c, MemTag mem_tag = mtNone) const; + void print_malloc(const MemoryCounter* c, MemTag mem_tag) const; void print_virtual_memory(size_t reserved, size_t committed, size_t peak) const; void print_arena(const MemoryCounter* c) const; diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp index 981e991a41e..3918e81dab7 100644 --- a/src/hotspot/share/nmt/memTracker.hpp +++ b/src/hotspot/share/nmt/memTracker.hpp @@ -127,7 +127,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, - MemTag mem_tag = mtNone) { + MemTag mem_tag) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { @@ -153,7 +153,7 @@ class MemTracker : AllStatic { } static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, - const NativeCallStack& stack, MemTag mem_tag = mtNone) { + const NativeCallStack& stack, MemTag mem_tag) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.hpp b/src/hotspot/share/nmt/virtualMemoryTracker.hpp index 74d299e6637..2b3b5722571 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.hpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.hpp @@ -297,7 +297,7 @@ class ReservedMemoryRegion : public VirtualMemoryRegion { public: ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack, - MemTag mem_tag = mtNone) : + MemTag mem_tag) : VirtualMemoryRegion(base, size), _stack(stack), _mem_tag(mem_tag) { } @@ -380,7 +380,7 @@ class VirtualMemoryTracker : AllStatic { public: static bool initialize(NMT_TrackingLevel level); - static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag = mtNone); + static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag); 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); diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index d2916fad185..c988745f7b6 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -2400,7 +2400,7 @@ 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, false, mtInternal); + bad_address = os::reserve_memory(size, mtInternal); if (bad_address != nullptr) { os::protect_memory(bad_address, size, os::MEM_PROT_READ, /*is_committed*/false); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index e08a5ba5ebd..884fbf98138 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -728,11 +728,11 @@ WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem)) WB_END WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) - return (jlong)(uintptr_t)os::reserve_memory(size, false, mtTest); + return (jlong)(uintptr_t)os::reserve_memory(size, mtTest); WB_END WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size)) - return (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, false, mtTest); + return (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, mtTest); WB_END WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) @@ -1524,7 +1524,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(), 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 cbe40ca214b..7695fed564d 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1916,7 +1916,7 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) { return os::pd_create_stack_guard_pages(addr, bytes); } -char* os::reserve_memory(size_t bytes, bool executable, MemTag mem_tag) { +char* os::reserve_memory(size_t bytes, MemTag mem_tag, bool executable) { char* result = pd_reserve_memory(bytes, executable); if (result != nullptr) { MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC, mem_tag); @@ -1927,7 +1927,7 @@ char* os::reserve_memory(size_t bytes, bool executable, MemTag mem_tag) { return result; } -char* os::attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MemTag mem_tag) { +char* os::attempt_reserve_memory_at(char* addr, size_t bytes, MemTag mem_tag, bool executable) { 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, mem_tag); @@ -2133,7 +2133,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, mtNone); } else { log_debug(os, map)("failed to attach anywhere in [" PTR_FORMAT "-" PTR_FORMAT ")", p2i(min), p2i(max)); } @@ -2300,8 +2300,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, MemTag mem_tag) { + char *addr, size_t bytes, MemTag mem_tag, + bool read_only, bool allow_exec) { 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, mem_tag); @@ -2339,7 +2339,7 @@ char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size 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); + MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC, mtNone); 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 242959034af..b9a3bf564f7 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -457,14 +457,14 @@ class os: AllStatic { inline static size_t cds_core_region_alignment(); // Reserves virtual memory. - static char* reserve_memory(size_t bytes, bool executable = false, MemTag mem_tag = mtNone); + static char* reserve_memory(size_t bytes, MemTag mem_tag, bool executable = false); // 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, MemTag mem_tag, 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 = false, MemTag mem_tag = mtNone); + static char* attempt_reserve_memory_at(char* addr, size_t bytes, MemTag mem_tag, bool executable = false); // 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. @@ -516,16 +516,16 @@ 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, MemTag mem_tag = mtNone); - static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag = mtNone); + static char* map_memory_to_file(size_t size, int fd, MemTag mem_tag); + static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag); 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, MemTag mem_tag = mtNone); + static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MemTag mem_tag); // 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, MemTag mem_tag = mtNone); + char *addr, size_t bytes, MemTag mem_tag, bool read_only = false, + bool allow_exec = false); static bool unmap_memory(char *addr, size_t bytes); static void disclaim_memory(char *addr, size_t bytes); static void realign_memory(char *addr, size_t bytes, size_t alignment_hint); diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index 51038d764bb..71224bbff4c 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -57,7 +57,7 @@ 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); + char* polling_page = os::reserve_memory(allocation_size, mtSafepoint); os::commit_memory_or_exit(polling_page, allocation_size, !ExecMem, "Unable to commit Safepoint polling page"); char* bad_page = polling_page; diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 9413f1f72d7..abe3d6757b5 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -712,7 +712,7 @@ struct TestMultipleStaticAssertFormsInClassScope { // Support for showing register content on asserts/guarantees. #ifdef CAN_SHOW_REGISTERS_ON_ASSERT void initialize_assert_poison() { - char* page = os::reserve_memory(os::vm_page_size(), !ExecMem, mtInternal); + char* page = os::reserve_memory(os::vm_page_size(), mtInternal); if (page) { if (os::commit_memory(page, os::vm_page_size(), !ExecMem) && os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) { diff --git a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp index bc0ed0f3c59..45da22ce116 100644 --- a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp +++ b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp @@ -82,7 +82,8 @@ TEST_VM(G1RegionToSpaceMapper, smallStressAdjacent) { ReservedSpace rs = MemoryReserver::reserve(size, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), + mtTest); G1RegionToSpaceMapper* small_mapper = G1RegionToSpaceMapper::create_mapper(rs, @@ -90,7 +91,7 @@ TEST_VM(G1RegionToSpaceMapper, smallStressAdjacent) { page_size, region_size, G1BlockOffsetTable::heap_map_factor(), - mtGC); + mtTest); @@ -108,14 +109,15 @@ TEST_VM(G1RegionToSpaceMapper, largeStressAdjacent) { ReservedSpace rs = MemoryReserver::reserve(size, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), + mtTest); G1RegionToSpaceMapper* large_mapper = G1RegionToSpaceMapper::create_mapper(rs, size, page_size, region_size, G1BlockOffsetTable::heap_map_factor(), - mtGC); + mtTest); G1TestCommitUncommit task(large_mapper); G1MapperWorkers::run_task(&task); diff --git a/test/hotspot/gtest/gc/z/test_zForwarding.cpp b/test/hotspot/gtest/gc/z/test_zForwarding.cpp index 71fb83827c7..f22eef50858 100644 --- a/test/hotspot/gtest/gc/z/test_zForwarding.cpp +++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp @@ -56,7 +56,7 @@ public: 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, mtTest); if (reserved != nullptr) { // Success return reserved; diff --git a/test/hotspot/gtest/memory/test_virtualspace.cpp b/test/hotspot/gtest/memory/test_virtualspace.cpp index d3fed31da0b..d2f8927ba28 100644 --- a/test/hotspot/gtest/memory/test_virtualspace.cpp +++ b/test/hotspot/gtest/memory/test_virtualspace.cpp @@ -73,7 +73,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 = MemoryReserver::reserve(size, alignment, page_size); + ReservedSpace rs = MemoryReserver::reserve(size, alignment, page_size, mtTest); ASSERT_TRUE(rs.base() != nullptr) << "rs.special = " << rs.special(); ASSERT_EQ(size, rs.size()) << "rs.special = " << rs.special(); @@ -101,7 +101,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 = MemoryReserver::reserve(size, alignment, page_size); + ReservedSpace rs = MemoryReserver::reserve(size, alignment, page_size, mtTest); MemoryReleaser releaser(&rs); EXPECT_TRUE(rs.base() != nullptr) << "rs.special: " << rs.special(); @@ -217,7 +217,8 @@ namespace { case Commit: return MemoryReserver::reserve(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), + mtTest); } } @@ -296,7 +297,7 @@ TEST_VM(VirtualSpace, actual_committed_space_one_large_page) { size_t large_page_size = os::large_page_size(); - ReservedSpace reserved = MemoryReserver::reserve(large_page_size, large_page_size, large_page_size); + ReservedSpace reserved = MemoryReserver::reserve(large_page_size, large_page_size, large_page_size, mtTest); ReservedSpaceReleaser releaser(&reserved); ASSERT_TRUE(reserved.is_reserved()); @@ -365,7 +366,8 @@ class TestReservedSpace : AllStatic { size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); ReservedSpace rs = MemoryReserver::reserve(size, alignment, - page_size); + page_size, + mtTest); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -410,7 +412,8 @@ class TestReservedSpace : AllStatic { ReservedSpace rs = MemoryReserver::reserve(size, alignment, - page_size); + page_size, + mtTest); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -514,12 +517,14 @@ class TestVirtualSpace : AllStatic { default: case Default: case Reserve: - return MemoryReserver::reserve(reserve_size_aligned, mtTest); + return MemoryReserver::reserve(reserve_size_aligned, + mtTest); case Disable: case Commit: return MemoryReserver::reserve(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size()); + os::vm_page_size(), + mtTest); } } @@ -576,7 +581,8 @@ class TestVirtualSpace : AllStatic { ReservedSpace reserved = MemoryReserver::reserve(large_page_size, large_page_size, - large_page_size); + large_page_size, + mtTest); ASSERT_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 e0e3c289102..c8711004f10 100644 --- a/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp @@ -113,7 +113,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, 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 de63e1807c1..f07b45bc32d 100644 --- a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp +++ b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp @@ -91,7 +91,7 @@ public: static void test_committed_region_impl(size_t num_pages, size_t touch_pages, int* page_num) { 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); + char* base = os::reserve_memory(size, mtThreadStack); bool result = os::commit_memory(base, size, !ExecMem); size_t index; ASSERT_NE(base, (char*)nullptr); @@ -159,7 +159,7 @@ public: const size_t page_sz = os::vm_page_size(); const size_t num_pages = 4; const size_t size = num_pages * page_sz; - char* base = os::reserve_memory(size, !ExecMem, mtTest); + char* base = os::reserve_memory(size, mtTest); ASSERT_NE(base, (char*)nullptr); result = os::commit_memory(base, size, !ExecMem); @@ -205,7 +205,7 @@ public: const size_t page_sz = os::vm_page_size(); const size_t size = num_pages * page_sz; - char* base = os::reserve_memory(size, !ExecMem, mtTest); + char* base = os::reserve_memory(size, mtTest); ASSERT_NE(base, (char*)nullptr); result = os::commit_memory(base, size, !ExecMem); diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index ee6d1427d0b..6b7653f5eec 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -258,7 +258,7 @@ TEST_VM(os, test_print_hex_dump) { // two pages, first one protected. const size_t ps = os::vm_page_size(); - char* two_pages = os::reserve_memory(ps * 2, false, mtTest); + char* two_pages = os::reserve_memory(ps * 2, mtTest); os::commit_memory(two_pages, ps * 2, false); os::protect_memory(two_pages, ps, os::MEM_PROT_NONE, true); @@ -492,7 +492,7 @@ TEST_VM(os, realpath) { 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, mtTest, executable); bool exec_supported = (p != nullptr); if (exec_supported) { os::release_memory(p, len); @@ -530,7 +530,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, mtTest); EXPECT_NE(p, (address)nullptr); // .. release it... EXPECT_TRUE(os::release_memory((char*)p, total_range_len)); @@ -544,7 +544,7 @@ 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, mtTest, executable); if (q == nullptr) { // Someone grabbed that area concurrently. Cleanup, then retry. tty->print_cr("reserve_multiple: retry (%d)...", stripe); @@ -564,7 +564,7 @@ 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, mtTest); EXPECT_NE(p, (address)nullptr); for (int stripe = 0; stripe < num_stripes; stripe++) { address q = p + (stripe * stripe_len); @@ -631,7 +631,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, mtTest); ASSERT_EQ(p2, p_middle_stripes); @@ -654,7 +654,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, mtTest); ASSERT_NE(p, (char*)nullptr); // Release part of range ASSERT_FALSE(os::release_memory(p, M)); @@ -689,7 +689,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, mtTest); PRINT_MAPPINGS("B"); ASSERT_TRUE(p2 == nullptr || p2 == border); @@ -730,7 +730,7 @@ 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, mtTest); if (p != nullptr) { if (os::commit_memory(p, 1 * M, false)) { strcpy(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); @@ -754,7 +754,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, mtTest); ASSERT_NE(p, (address)nullptr); PRINT_MAPPINGS("A"); for (size_t offset = 0; offset < total_range_len; offset += 4711) { @@ -1059,9 +1059,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, mtTest); ASSERT_NE(p1, nullptr); - char* p2 = os::attempt_reserve_memory_at(p1, M); + char* p2 = os::attempt_reserve_memory_at(p1, M, mtTest); ASSERT_EQ(p2, nullptr); // should have failed os::release_memory(p1, M); } @@ -1069,7 +1069,7 @@ 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, mtTest); ASSERT_NE(p1, nullptr); char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, false); ASSERT_EQ(p2, nullptr); // should have failed @@ -1095,7 +1095,7 @@ TEST_VM(os, free_without_uncommit) { const size_t pages = 64; const size_t size = pages * page_sz; - char* base = os::reserve_memory(size, false, mtTest); + char* base = os::reserve_memory(size, mtTest); ASSERT_NE(base, (char*) nullptr); ASSERT_TRUE(os::commit_memory(base, size, false)); diff --git a/test/hotspot/gtest/runtime/test_os_aix.cpp b/test/hotspot/gtest/runtime/test_os_aix.cpp index 9fcb2f9c691..73ed55dc3ce 100644 --- a/test/hotspot/gtest/runtime/test_os_aix.cpp +++ b/test/hotspot/gtest/runtime/test_os_aix.cpp @@ -34,9 +34,9 @@ TEST_VM(os_aix, aix_reserve_at_non_shmlba_aligned_address) { if (os::vm_page_size() != 4*K && !os::Aix::supports_64K_mmap_pages()) { // With this condition true shmget() is used inside - char* p = os::attempt_reserve_memory_at((char*)0x1f00000, M); + char* p = os::attempt_reserve_memory_at((char*)0x1f00000, M, 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, 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 caa227c5e35..21133788a36 100644 --- a/test/hotspot/gtest/runtime/test_os_linux.cpp +++ b/test/hotspot/gtest/runtime/test_os_linux.cpp @@ -354,7 +354,7 @@ 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, mtTest); EXPECT_NE(heap, nullptr); EXPECT_TRUE(os::commit_memory(heap, size, false)); diff --git a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp index 34dd26dcf17..ee91ff49ded 100644 --- a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp +++ b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp @@ -157,7 +157,7 @@ public: // 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, mtTest); } } if (_base == nullptr) { @@ -165,8 +165,8 @@ public: } // 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, mtTest); + _p2 = os::attempt_reserve_memory_at(_base + _p2_offset, _p2_size, mtTest); if (_p1 == nullptr || _p2 == nullptr) { return false; } diff --git a/test/hotspot/jtreg/runtime/NMT/MallocRoundingReportTest.java b/test/hotspot/jtreg/runtime/NMT/MallocRoundingReportTest.java index 30a03f973bf..a0c14d70831 100644 --- a/test/hotspot/jtreg/runtime/NMT/MallocRoundingReportTest.java +++ b/test/hotspot/jtreg/runtime/NMT/MallocRoundingReportTest.java @@ -57,7 +57,7 @@ public class MallocRoundingReportTest { // NMT does not track memory allocations less than 1KB, and rounds to the nearest KB NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=" + numKB + "KB, committed=" + numKB + "KB)", - "(malloc=" + numKB + "KB #1) (at peak)" + "(malloc=" + numKB + "KB tag=Test #1) (at peak)" // (malloc=1KB tag=Test #1) (at peak) ); wb.NMTFree(mallocd_total); @@ -65,7 +65,7 @@ public class MallocRoundingReportTest { // Run 'jcmd VM.native_memory summary', check for expected output NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=0KB, committed=0KB)", - "(malloc=0KB) (peak=" + numKB + "KB #1)" + "(malloc=0KB tag=Test) (peak=" + numKB + "KB #1)" ); } } diff --git a/test/hotspot/jtreg/runtime/NMT/MallocTestType.java b/test/hotspot/jtreg/runtime/NMT/MallocTestType.java index 67df864e7b4..1612cbd81c0 100644 --- a/test/hotspot/jtreg/runtime/NMT/MallocTestType.java +++ b/test/hotspot/jtreg/runtime/NMT/MallocTestType.java @@ -46,7 +46,7 @@ public class MallocTestType { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( new String[]{"Test (reserved=384KB, committed=384KB)", - "(malloc=384KB #2) (at peak)"}); + "(malloc=384KB tag=Test #2) (at peak)"}); wb.NMTFree(memAlloc3); // current +256K #1 peak +384K #2 long memAlloc1 = wb.NMTMalloc(512 * 1024); // current +768K #2 peak +768K #2 @@ -54,13 +54,13 @@ public class MallocTestType { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( new String[]{"Test (reserved=512KB, committed=512KB)", - "(malloc=512KB #1) (peak=768KB #2)"}); + "(malloc=512KB tag=Test #1) (peak=768KB #2)"}); // Free the memory allocated by NMTAllocTest wb.NMTFree(memAlloc1); // current 0K #0 peak +768K #2 NMTTestUtils.runJcmdSummaryReportAndCheckOutput( new String[]{"Test (reserved=0KB, committed=0KB)", - "(malloc=0KB) (peak=768KB #2)"}); + "(malloc=0KB tag=Test) (peak=768KB #2)"}); } } diff --git a/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java b/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java index 0c08e07fd25..141ef9f2ac3 100644 --- a/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java +++ b/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java @@ -72,7 +72,7 @@ public class MallocTrackingVerify { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=4KB, committed=4KB)", - "(malloc=4KB #" + mallocd_memory.size() + ") (at peak)" + "(malloc=4KB tag=Test #" + mallocd_memory.size() + ") (at peak)" ); // Free @@ -83,7 +83,7 @@ public class MallocTrackingVerify { // Run 'jcmd VM.native_memory summary', check for expected output NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=0KB, committed=0KB)", - "(malloc=0KB) (peak=4KB #" + + mallocd_memory.size() + ")" + "(malloc=0KB tag=Test) (peak=4KB #" + + mallocd_memory.size() + ")" ); } diff --git a/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java b/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java index 290984c4185..f6b0f3baf04 100644 --- a/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java +++ b/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java @@ -61,7 +61,7 @@ public class ThreadedMallocTestType { // Run 'jcmd VM.native_memory summary' NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=896KB, committed=896KB)", - "(malloc=896KB #3) (at peak)" + "(malloc=896KB tag=Test #3) (at peak)" ); Thread freeThread = new Thread() { @@ -78,7 +78,7 @@ public class ThreadedMallocTestType { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=0KB, committed=0KB)", - "(malloc=0KB) (peak=896KB #3)" + "(malloc=0KB tag=Test) (peak=896KB #3)" ); } } From d684867066edb886bc444c864ef9db3eff318c34 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 14 Apr 2025 16:55:37 +0000 Subject: [PATCH 165/843] 8346230: [perf] scalability issue for the specjvm2008::xml.transform workload Reviewed-by: joehw, jbhateja --- .../xml/internal/utils/XMLReaderManager.java | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java index 91a6597a603..f0cd5062d2b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/XMLReaderManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -37,7 +37,7 @@ import org.xml.sax.XMLReader; * Creates XMLReader objects and caches them for re-use. * This class follows the singleton pattern. * - * @LastModified: Nov 2024 + * @LastModified: Apr 2025 */ public class XMLReaderManager { @@ -52,11 +52,6 @@ public class XMLReaderManager { */ private ThreadLocal m_readers; - /** - * Keeps track of whether an XMLReader object is in use. - */ - private HashMap m_inUse; - private boolean m_overrideDefaultParser; private boolean _secureProcessing; @@ -89,11 +84,10 @@ public class XMLReaderManager { /** * Retrieves a cached XMLReader for this thread, or creates a new - * XMLReader, if the existing reader is in use. When the caller no - * longer needs the reader, it must release it with a call to - * {@link #releaseXMLReader}. + * XMLReader. When the caller no longer needs the reader, it must + * release it with a call to {@link #releaseXMLReader}. */ - public synchronized XMLReader getXMLReader() throws SAXException { + public XMLReader getXMLReader() throws SAXException { XMLReader reader; if (m_readers == null) { @@ -101,14 +95,9 @@ public class XMLReaderManager { // on a thread, a new XMLReader will automatically be created. m_readers = new ThreadLocal<>(); } - - if (m_inUse == null) { - m_inUse = new HashMap<>(); - } - /** * Constructs a new XMLReader if: - * (1) the cached reader for this thread is in use, or + * (1) the cached reader for this thread is not defined, or * (2) the requirement for overriding has changed, * (3) the cached reader isn't an instance of the class set in the * 'org.xml.sax.driver' property @@ -119,10 +108,9 @@ public class XMLReaderManager { boolean threadHasReader = (rw != null); reader = threadHasReader ? rw.reader : null; String factory = System.getProperty(property); - if (threadHasReader && m_inUse.get(reader) != Boolean.TRUE && + if (threadHasReader && (rw.overrideDefaultParser == m_overrideDefaultParser) && ( factory == null || reader.getClass().getName().equals(factory))) { - m_inUse.put(reader, Boolean.TRUE); JdkXmlUtils.setReaderProperty(reader, _xmlSecurityManager, _useCatalog, _catalogFeatures); } else { @@ -133,10 +121,9 @@ public class XMLReaderManager { // a reader for this thread. if (!threadHasReader) { m_readers.set(new ReaderWrapper(reader, m_overrideDefaultParser)); - m_inUse.put(reader, Boolean.TRUE); } - } + } //reader is cached, but this property might have been reset JdkXmlUtils.setXMLReaderPropertyIfSupport(reader, XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD, true); @@ -153,9 +140,9 @@ public class XMLReaderManager { * * @param reader The XMLReader that's being released. */ - public synchronized void releaseXMLReader(XMLReader reader) { + public void releaseXMLReader(XMLReader reader) { // If the reader that's being released is the cached reader - // for this thread, remove it from the m_inUse list. + // for this thread, reset it. ReaderWrapper rw = m_readers.get(); if (rw != null && rw.reader == reader && reader != null) { // reset the reader for reuse @@ -167,7 +154,6 @@ public class XMLReaderManager { } catch (SAXNotRecognizedException | SAXNotSupportedException ex) { // shouldn't happen as the property is supported. } - m_inUse.remove(reader); } } From 46a6fc84ef17f38eedd49f59a3c05f7c95fe23bc Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 14 Apr 2025 16:58:06 +0000 Subject: [PATCH 166/843] 8353483: Open source some JProgressBar tests Reviewed-by: honkar, serb --- .../JProgressBar/RightLeftOrientation.java | 147 ++++++++++++++++++ .../javax/swing/JProgressBar/bug4230391.java | 139 +++++++++++++++++ .../javax/swing/JProgressBar/bug4393042.java | 90 +++++++++++ .../javax/swing/JProgressBar/bug5003022.java | 82 ++++++++++ 4 files changed, 458 insertions(+) create mode 100644 test/jdk/javax/swing/JProgressBar/RightLeftOrientation.java create mode 100644 test/jdk/javax/swing/JProgressBar/bug4230391.java create mode 100644 test/jdk/javax/swing/JProgressBar/bug4393042.java create mode 100644 test/jdk/javax/swing/JProgressBar/bug5003022.java diff --git a/test/jdk/javax/swing/JProgressBar/RightLeftOrientation.java b/test/jdk/javax/swing/JProgressBar/RightLeftOrientation.java new file mode 100644 index 00000000000..5cc183b1e8e --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/RightLeftOrientation.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4230355 + * @summary + * This test checks if progress bars lay out correctly when their + * ComponentOrientation property is set to RIGHT_TO_LEFT. This test is + * manual. The tester is asked to compare left-to-right and + * right-to-left progress bars and judge whether they are mirror images + * of each other. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RightLeftOrientation + */ + +import java.awt.ComponentOrientation; +import java.awt.Container; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.LookAndFeel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.UIManager; + +public class RightLeftOrientation { + + static final String INSTRUCTIONS = """ + This test checks progress bars for correct Right-To-Left Component Orientation. + The progress bars in the left column should fill up from the left while the bars in + the right column should fill up from the right. + If this is so, the test PASSES, otherwise it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Progress Bar Orientation Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(RightLeftOrientation::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Progress Bar Orientation Test"); + Container contentPane = frame.getContentPane(); + contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS)); + contentPane.add(createBarSet(ComponentOrientation.LEFT_TO_RIGHT)); + contentPane.add(createBarSet(ComponentOrientation.RIGHT_TO_LEFT)); + frame.pack(); + return frame; + } + + static JPanel createBarSet(ComponentOrientation o) { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + JLabel header; + if (o.isLeftToRight()) + header = new JLabel("Left To Right"); + else + header = new JLabel("Right To Left"); + panel.add(header); + + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (int i = 0; i < lafs.length; i++) { + if (i > 0) + panel.add(Box.createVerticalStrut(10)); + panel.add(createProgressBars(lafs[i].getName(), + lafs[i].getClassName(), o)); + } + + return panel; + } + + static JPanel createProgressBars(String name, String plaf, + ComponentOrientation o) { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + JLabel label = new JLabel(name); + panel.add(label); + try { + LookAndFeel save = UIManager.getLookAndFeel(); + UIManager.setLookAndFeel(plaf); + + panel.add(createProgressBar(true, 0, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(true, 5, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(true, 10, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(true, 20, o)); + panel.add(Box.createVerticalStrut(5)); + + UIManager.put("ProgressBar.cellSpacing", Integer.valueOf(2)); + UIManager.put("ProgressBar.cellLength", Integer.valueOf(7)); + + panel.add(createProgressBar(false, 5, o)); + panel.add(Box.createVerticalStrut(5)); + + panel.add(createProgressBar(false, 20, o)); + + UIManager.setLookAndFeel(save); + } catch (Exception e) { + System.err.println(e); + } + return panel; + } + + static JProgressBar createProgressBar(boolean paintStr, int value, + ComponentOrientation o) { + JProgressBar p = new JProgressBar(JProgressBar.HORIZONTAL, 0, 20); + p.setStringPainted(paintStr); + p.setValue(value); + p.setComponentOrientation(o); + return p; + } + +} diff --git a/test/jdk/javax/swing/JProgressBar/bug4230391.java b/test/jdk/javax/swing/JProgressBar/bug4230391.java new file mode 100644 index 00000000000..473862d83a3 --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/bug4230391.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4230391 + * @summary Tests that JProgressBar draws correctly when Insets are not zero + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4230391 +*/ + +import java.awt.ComponentOrientation; +import java.awt.Container; +import java.awt.Insets; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.LookAndFeel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.UIManager; + +public class bug4230391 { + + static final String INSTRUCTIONS = """ + Tests that progress bars honor insets in different L&Fs. + Different L&Fs render the progress bar differently, and may or may + not have a different colored background around the progress bar, + and may or may not draw a border around the bar+background. + The progress bars should be of equal width and the progress + rendering line/bar should not extend past/overlap any border. + If it is as described, the test PASSES. + """; + + static class InsetProgressBar extends JProgressBar { + private Insets insets = new Insets(12, 12, 12, 12); + + public InsetProgressBar(boolean horiz, int low, int hi) { + super((horiz)?JProgressBar.HORIZONTAL:JProgressBar.VERTICAL, low, hi); + } + + public Insets getInsets() { + return insets; + } + } + + static JPanel createBarSet() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels(); + for (int i = 0; i < lafs.length; i++) { + if (i > 0) { + panel.add(Box.createVerticalStrut(10)); + } + panel.add(createProgressBars(lafs[i].getName(), lafs[i].getClassName())); + } + return panel; + } + + static JPanel createProgressBars(String name, String plaf) { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + try { + LookAndFeel save = UIManager.getLookAndFeel(); + UIManager.setLookAndFeel(plaf); + + ComponentOrientation ltr = ComponentOrientation.LEFT_TO_RIGHT; + + Box b = Box.createVerticalBox(); + panel.add(b); + panel.add(Box.createHorizontalStrut(5)); + panel.add(createProgressBar(false, true, ltr)); + UIManager.setLookAndFeel(save); + } catch (Exception e) { + System.err.println(e); + } + return panel; + } + + static JProgressBar createProgressBar(boolean solid, boolean horiz, + ComponentOrientation o) { + if (solid) { + UIManager.put("ProgressBar.cellSpacing", Integer.valueOf(0)); + UIManager.put("ProgressBar.cellLength", Integer.valueOf(1)); + } else { + UIManager.put("ProgressBar.cellSpacing", Integer.valueOf(2)); + UIManager.put("ProgressBar.cellLength", Integer.valueOf(7)); + } + + JProgressBar p = new InsetProgressBar(horiz, 0, 20); + p.setStringPainted(solid); + p.setValue(20); + p.setComponentOrientation(o); + + return p; + } + + static JFrame createUI() { + JFrame frame = new JFrame("Progress Bar Insets Test"); + Container contentPane = frame.getContentPane(); + contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS)); + contentPane.add(createBarSet()); + frame.setSize(400, 300); + return frame; + } + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Progress Bar Insets Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4230391::createUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JProgressBar/bug4393042.java b/test/jdk/javax/swing/JProgressBar/bug4393042.java new file mode 100644 index 00000000000..f17d70a1309 --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/bug4393042.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4393042 + * @summary JProgressBar should update painting when maximum value is very large + * @key headful + */ + +import java.awt.Graphics; +import javax.swing.JFrame; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4393042 extends JProgressBar { + + static final int MAXIMUM = Integer.MAX_VALUE - 100; + static volatile int value = 0; + static volatile bug4393042 progressBar; + static JFrame frame; + static volatile int paintCount = 0; + + public void paintComponent(Graphics g) { + super.paintComponent(g); + System.out.println("paint count=" + (++paintCount)); + } + + public bug4393042(int min, int max) { + super(min, max); + } + + public static void main(String[] args) throws Exception { + + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + try { + SwingUtilities.invokeAndWait(bug4393042::createUI); + + value = 0; + for (int i = 0; i <= 10; i++) { + Thread.sleep(1000); + SwingUtilities.invokeAndWait(() -> { + progressBar.setValue(value); + }); + value += MAXIMUM / 10; + } + + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + if (paintCount < 10 || paintCount > 100) { + throw new RuntimeException("Unexpected paint count : " + paintCount); + } + } + + static void createUI() { + frame = new JFrame("bug4393042"); + progressBar = new bug4393042(0, MAXIMUM); + progressBar.setStringPainted(true); + progressBar.setValue(0); + frame.add(progressBar); + frame.setSize(400, 200); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JProgressBar/bug5003022.java b/test/jdk/javax/swing/JProgressBar/bug5003022.java new file mode 100644 index 00000000000..57f5fdfc45d --- /dev/null +++ b/test/jdk/javax/swing/JProgressBar/bug5003022.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5003022 + * @summary Test that setting zero value on JProgressBar works in GTK L&F + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug5003022 +*/ + +import java.awt.FlowLayout; +import javax.swing.JFrame; +import javax.swing.JProgressBar; +import javax.swing.UIManager; + +public class bug5003022 { + + static final String INSTRUCTIONS = """ + There are two progress bars, they should display progress strings. + The first progress bar should display 0% and the bar should show no progress color fill. + The second progress bar should display 30% and the bar should show 30% progress color fill. + If it is as described, the test PASSES, otherwise it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug5003022 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug5003022::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + /* This will only succeed on Linux, but the test is valid for other platforms and L&Fs */ + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch (Exception e) { + e.printStackTrace(); + } + + JFrame frame = new JFrame("bug5003022"); + JProgressBar pb1 = new JProgressBar(); + pb1.setValue(0); + pb1.setStringPainted(true); + + JProgressBar pb2 = new JProgressBar(); + pb2.setValue(30); + pb2.setStringPainted(true); + + frame.setLayout(new FlowLayout()); + frame.add(pb1); + frame.add(pb2); + + frame.setSize(300, 300); + return frame; + } + +} From de0e6488449303bd15d4590480a2e47b8026a9b1 Mon Sep 17 00:00:00 2001 From: Andrej Pecimuth Date: Mon, 14 Apr 2025 18:31:27 +0000 Subject: [PATCH 167/843] 8352724: Verify bounds for primitive array reads in JVMCI Reviewed-by: dnsimon --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 13 ++++-- .../test/TestConstantReflectionProvider.java | 46 ++++++++++++++++--- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 2e42d5df55b..cffac62c1c8 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2253,14 +2253,21 @@ static jobject read_field_value(Handle obj, long displacement, jchar type_char, if (!aligned) { JVMCI_THROW_MSG_NULL(IllegalArgumentException, "read is unaligned"); } + if (obj->is_array()) { + // Disallow reading after the last element of an array + size_t array_length = arrayOop(obj())->length(); + int lh = obj->klass()->layout_helper(); + size_t size_in_bytes = array_length << Klass::layout_helper_log2_element_size(lh); + size_in_bytes += Klass::layout_helper_header_size(lh); + if ((size_t) displacement + basic_type_elemsize > size_in_bytes) { + JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading after last array element"); + } + } if (basic_type == T_OBJECT) { if (obj->is_objArray()) { if (displacement < arrayOopDesc::base_offset_in_bytes(T_OBJECT)) { JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading from array header"); } - if (displacement + heapOopSize > arrayOopDesc::base_offset_in_bytes(T_OBJECT) + arrayOop(obj())->length() * heapOopSize) { - JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading after last array element"); - } if (((displacement - arrayOopDesc::base_offset_in_bytes(T_OBJECT)) % heapOopSize) != 0) { JVMCI_THROW_MSG_NULL(IllegalArgumentException, "misaligned object read from array"); } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java index 4a9585d995f..128430b1902 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,11 +41,7 @@ import org.junit.Test; import java.lang.reflect.Array; import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * Tests for {@link ConstantReflectionProvider}. It assumes an implementation of the interface that @@ -138,4 +134,42 @@ public class TestConstantReflectionProvider extends TypeUniverse { assertNull(constantReflection.unboxPrimitive(JavaConstant.NULL_POINTER)); } + + static class ArrayConstants { + static final byte[] BYTE_ARRAY_CONST = new byte[]{0}; + static final Object[] OBJECT_ARRAY_CONST = new Object[]{null}; + } + + @Test + public void readOnePastLastArrayElementTest() { + for (ConstantValue cv : readConstants(ArrayConstants.class)) { + if (cv.boxed != null && cv.boxed.getClass().isArray()) { + JavaKind kind = metaAccess.lookupJavaType(cv.value).getComponentType().getJavaKind(); + long offset = metaAccess.getArrayBaseOffset(kind) + (long) metaAccess.getArrayIndexScale(kind) * Array.getLength(cv.boxed); + // read array[array.length] + assertThrows(IllegalArgumentException.class, () -> { + if (kind == JavaKind.Object) { + constantReflection.getMemoryAccessProvider().readObjectConstant(cv.value, offset); + } else { + constantReflection.getMemoryAccessProvider().readPrimitiveConstant(kind, cv.value, offset, kind.getBitCount()); + } + }); + } + } + } + + static class IntArrayConstants { + static final int[] INT_ARRAY_CONST = new int[]{0}; + } + + @Test + public void readPartiallyOutOfBoundsTest() { + for (ConstantValue cv : readConstants(IntArrayConstants.class)) { + JavaKind kind = metaAccess.lookupJavaType(cv.value).getComponentType().getJavaKind(); + long offset = metaAccess.getArrayBaseOffset(kind) + (long) metaAccess.getArrayIndexScale(kind) * (Array.getLength(cv.boxed) - 1); + // read a long from array[array.length - 1], which is partially out of bounds + JavaKind accessKind = JavaKind.Long; + assertThrows(IllegalArgumentException.class, () -> constantReflection.getMemoryAccessProvider().readPrimitiveConstant(accessKind, cv.value, offset, accessKind.getBitCount())); + } + } } From 0da480a91d31ee8dc2532cfec76bbf5b1d6c4eeb Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Mon, 14 Apr 2025 18:47:59 +0000 Subject: [PATCH 168/843] 8354535: [BACKOUT] Force clients to explicitly pass mem_tag value, even if it is mtNone Reviewed-by: stefank, jsjolen --- .../cpu/aarch64/compressedKlass_aarch64.cpp | 4 +-- .../bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp | 2 +- src/hotspot/os/linux/os_linux.cpp | 4 +-- src/hotspot/os/posix/os_posix.cpp | 4 +-- src/hotspot/os/posix/perfMemory_posix.cpp | 2 +- src/hotspot/os/windows/os_windows.cpp | 20 ++++++------- src/hotspot/os/windows/perfMemory_windows.cpp | 2 +- src/hotspot/share/cds/archiveBuilder.cpp | 3 +- src/hotspot/share/cds/filemap.cpp | 10 +++---- src/hotspot/share/cds/metaspaceShared.cpp | 12 +++----- .../share/classfile/compactHashtable.cpp | 2 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 3 +- .../share/gc/parallel/parMarkBitMap.cpp | 3 +- .../share/gc/parallel/psParallelCompact.cpp | 3 +- src/hotspot/share/gc/shared/cardTable.cpp | 2 +- .../gc/shenandoah/shenandoahCardTable.cpp | 4 +-- .../share/gc/shenandoah/shenandoahHeap.cpp | 6 ++-- .../jfr/recorder/storage/jfrVirtualMemory.cpp | 3 +- .../share/memory/allocation.inline.hpp | 4 +-- src/hotspot/share/memory/memoryReserver.cpp | 8 +++--- src/hotspot/share/memory/memoryReserver.hpp | 4 +-- src/hotspot/share/memory/metaspace.cpp | 5 ++-- .../share/memory/metaspace/testHelpers.cpp | 3 +- .../memory/metaspace/virtualSpaceNode.cpp | 2 +- src/hotspot/share/nmt/memReporter.cpp | 2 +- src/hotspot/share/nmt/memReporter.hpp | 2 +- src/hotspot/share/nmt/memTracker.hpp | 4 +-- .../share/nmt/virtualMemoryTracker.hpp | 4 +-- src/hotspot/share/prims/jni.cpp | 2 +- src/hotspot/share/prims/whitebox.cpp | 6 ++-- src/hotspot/share/runtime/os.cpp | 12 ++++---- src/hotspot/share/runtime/os.hpp | 16 +++++------ .../share/runtime/safepointMechanism.cpp | 2 +- src/hotspot/share/utilities/debug.cpp | 2 +- .../gtest/gc/g1/test_stressCommitUncommit.cpp | 10 +++---- test/hotspot/gtest/gc/z/test_zForwarding.cpp | 2 +- .../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 | 28 +++++++++---------- test/hotspot/gtest/runtime/test_os_aix.cpp | 4 +-- test/hotspot/gtest/runtime/test_os_linux.cpp | 2 +- .../gtest/runtime/test_os_reserve_between.cpp | 6 ++-- .../runtime/NMT/MallocRoundingReportTest.java | 4 +-- .../jtreg/runtime/NMT/MallocTestType.java | 6 ++-- .../runtime/NMT/MallocTrackingVerify.java | 4 +-- .../runtime/NMT/ThreadedMallocTestType.java | 4 +-- 47 files changed, 126 insertions(+), 143 deletions(-) diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp index 3874c8cd54e..0c2d9a32c8c 100644 --- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp @@ -70,7 +70,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, mtNone); + 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); } @@ -114,7 +114,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, mtNone); + result = os::reserve_memory_aligned(size, alignment, false); } return result; diff --git a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp index 861fda7a71d..86549e878cb 100644 --- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp @@ -77,7 +77,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity) _initialized(false) { // Reserve address space for backing memory - _base = (uintptr_t)os::reserve_memory(max_capacity, mtJavaHeap); + _base = (uintptr_t)os::reserve_memory(max_capacity, false, mtJavaHeap); if (_base == 0) { // Failed ZInitialize::error("Failed to reserve address space for backing memory"); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index a8dce39ce5d..4e26797cd5b 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -4577,7 +4577,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, mtThread); + char* codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread); if (codebuf == nullptr) { // JDK-8197429: There may be a stack gap of one megabyte between @@ -4585,7 +4585,7 @@ 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, mtThread); + codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread); } if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, true))) { diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 8df488768be..a36d6b87641 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -491,9 +491,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, MemTag mem_tag, bool exec) { +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, mem_tag, exec); + char* extra_base = os::reserve_memory(extra_size, exec); if (extra_base == nullptr) { return nullptr; } diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index cbbecea3a6a..4d6fc1e4b8c 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -64,7 +64,7 @@ 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, mtInternal); + char* mapAddress = os::reserve_memory(size); if (mapAddress == nullptr) { return nullptr; diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 843272f57b5..84e89334feb 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3019,7 +3019,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, mtNone); + 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) @@ -3080,7 +3080,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, mtNone); + bytes_to_release, CALLER_PC); os::release_memory(p_buf, bytes_to_release); } #ifdef ASSERT @@ -3098,9 +3098,9 @@ 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, mtNone); + 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, mtNone); + MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC); } // made it this far, success @@ -3240,7 +3240,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, MemTag mem_tag) { +static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag = 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()), @@ -3254,7 +3254,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, mem_tag) : - os::reserve_memory(extra_size, mem_tag); + os::reserve_memory(extra_size, false, mem_tag); if (extra_base == nullptr) { return nullptr; } @@ -3271,7 +3271,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, mem_tag) : - os::attempt_reserve_memory_at(aligned_base, size, mem_tag); + os::attempt_reserve_memory_at(aligned_base, size, false, mem_tag); } assert(aligned_base != nullptr, @@ -3280,9 +3280,9 @@ 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, MemTag mem_tag, bool exec) { +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 */, mem_tag); + 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, MemTag mem_tag) { @@ -5187,7 +5187,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, } // Record virtual memory allocation - MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC, mtNone); + MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC); DWORD bytes_read; OVERLAPPED overlapped; diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index 322b844f413..dda0acde793 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -54,7 +54,7 @@ typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)( static char* create_standard_memory(size_t size) { // allocate an aligned chuck of memory - char* mapAddress = os::reserve_memory(size, mtInternal); + char* mapAddress = os::reserve_memory(size); if (mapAddress == nullptr) { return nullptr; diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index fa65d7d27bf..c309de17b4c 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -309,8 +309,7 @@ address ArchiveBuilder::reserve_buffer() { size_t buffer_size = LP64_ONLY(CompressedClassSpaceSize) NOT_LP64(256 * M); ReservedSpace rs = MemoryReserver::reserve(buffer_size, MetaspaceShared::core_region_alignment(), - os::vm_page_size(), - mtClassShared); + os::vm_page_size()); if (!rs.is_reserved()) { log_error(cds)("Failed to reserve %zu 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 1b5d455485c..580699b60b5 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1066,10 +1066,10 @@ void FileMapInfo::close() { */ 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, MemTag mem_tag) { + bool allow_exec, MemTag mem_tag = mtNone) { char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes, - mem_tag, AlwaysPreTouch ? false : read_only, - allow_exec); + AlwaysPreTouch ? false : read_only, + allow_exec, mem_tag); if (mem != nullptr && AlwaysPreTouch) { os::pretouch_memory(mem, mem + bytes); } @@ -1094,7 +1094,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() { assert(WINDOWS_ONLY(false) NOT_WINDOWS(true), "Don't call on Windows"); // Replace old mapping with new one that is writable. char *base = os::map_memory(_fd, _full_path, r->file_offset(), - addr, size, mtNone, false /* !read_only */, + addr, size, false /* !read_only */, r->allow_exec()); close(); // These have to be errors because the shared region is now unmapped. @@ -1620,7 +1620,7 @@ bool FileMapInfo::map_heap_region_impl() { } else { base = map_memory(_fd, _full_path, r->file_offset(), addr, _mapped_heap_memregion.byte_size(), r->read_only(), - r->allow_exec(), mtJavaHeap); + 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 3ca19858430..ef2a6dcb8e6 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -1537,8 +1537,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma archive_space_rs = MemoryReserver::reserve((char*)base_address, archive_space_size, archive_space_alignment, - os::vm_page_size(), - mtNone); + os::vm_page_size()); if (archive_space_rs.is_reserved()) { assert(base_address == nullptr || (address)archive_space_rs.base() == base_address, "Sanity"); @@ -1606,13 +1605,11 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma archive_space_rs = MemoryReserver::reserve((char*)base_address, archive_space_size, archive_space_alignment, - os::vm_page_size(), - mtNone); + os::vm_page_size()); class_space_rs = MemoryReserver::reserve((char*)ccs_base, class_space_size, class_space_alignment, - os::vm_page_size(), - mtNone); + os::vm_page_size()); } if (!archive_space_rs.is_reserved() || !class_space_rs.is_reserved()) { release_reserved_spaces(total_space_rs, archive_space_rs, class_space_rs); @@ -1625,8 +1622,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma total_space_rs = MemoryReserver::reserve((char*) base_address, total_range_size, base_address_alignment, - os::vm_page_size(), - mtNone); + os::vm_page_size()); } 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 15ae5ba8013..8d50e8136a3 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -226,7 +226,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, mtNone, true, false); + _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 44fb790f705..31f0cc12aa5 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1230,8 +1230,7 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des // Allocate a new reserved space, preferring to use large pages. ReservedSpace rs = MemoryReserver::reserve(size, alignment, - preferred_page_size, - mtGC); + preferred_page_size); size_t page_size = rs.page_size(); G1RegionToSpaceMapper* result = diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp index d2d168cc2c0..f33d7f93f1d 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp @@ -48,8 +48,7 @@ ParMarkBitMap::initialize(MemRegion covered_region) ReservedSpace rs = MemoryReserver::reserve(_reserved_byte_size, rs_align, - page_sz, - mtGC); + page_sz); if (!rs.is_reserved()) { // Failed to reserve memory for the bitmap, diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 84ed7798691..99b975c282a 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -246,8 +246,7 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) ReservedSpace rs = MemoryReserver::reserve(_reserved_byte_size, rs_align, - page_sz, - mtGC); + page_sz); if (!rs.is_reserved()) { // Failed to reserve memory. diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 24546618edb..3236d73933c 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -80,7 +80,7 @@ void CardTable::initialize(void* region0_start, void* region1_start) { HeapWord* high_bound = _whole_heap.end(); const size_t rs_align = MAX2(_page_size, os::vm_allocation_granularity()); - ReservedSpace rs = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC); + ReservedSpace rs = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size); if (!rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for the " diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp index e9e52475fb9..00f11938489 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp @@ -45,7 +45,7 @@ void ShenandoahCardTable::initialize() { // ReservedSpace constructor would assert rs_align >= os::vm_page_size(). const size_t rs_align = MAX2(_page_size, granularity); - ReservedSpace write_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC); + ReservedSpace write_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size); initialize(write_space); // The assembler store_check code will do an unsigned shift of the oop, @@ -60,7 +60,7 @@ void ShenandoahCardTable::initialize() { _write_byte_map = _byte_map; _write_byte_map_base = _byte_map_base; - ReservedSpace read_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC); + ReservedSpace read_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size); initialize(read_space); _read_byte_map = (CardValue*) read_space.base(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index ce4b9fc2406..045f485090d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -166,7 +166,7 @@ static ReservedSpace reserve(size_t size, size_t preferred_page_size) { size = align_up(size, alignment); } - const ReservedSpace reserved = MemoryReserver::reserve(size, alignment, preferred_page_size, mtGC); + const ReservedSpace reserved = MemoryReserver::reserve(size, alignment, preferred_page_size); if (!reserved.is_reserved()) { vm_exit_during_initialization("Could not reserve space"); } @@ -380,7 +380,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 = MemoryReserver::reserve(req_addr, cset_size, cset_align, cset_page_size, mtGC); + cset_rs = MemoryReserver::reserve(req_addr, cset_size, cset_align, cset_page_size); 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()); @@ -389,7 +389,7 @@ jint ShenandoahHeap::initialize() { } if (_collection_set == nullptr) { - cset_rs = MemoryReserver::reserve(cset_size, cset_align, os::vm_page_size(), mtGC); + cset_rs = MemoryReserver::reserve(cset_size, cset_align, os::vm_page_size()); if (!cset_rs.is_reserved()) { vm_exit_during_initialization("Cannot reserve memory for collection set"); } diff --git a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp index 0ba54fc79be..97f2b8a1990 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp @@ -106,8 +106,7 @@ bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes) assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant"); _rs = MemoryReserver::reserve(reservation_size_request_bytes, os::vm_allocation_granularity(), - os::vm_page_size(), - mtTracing); + os::vm_page_size()); if (!_rs.is_reserved()) { return false; } diff --git a/src/hotspot/share/memory/allocation.inline.hpp b/src/hotspot/share/memory/allocation.inline.hpp index 01af1616ce1..8d531c6dd23 100644 --- a/src/hotspot/share/memory/allocation.inline.hpp +++ b/src/hotspot/share/memory/allocation.inline.hpp @@ -58,7 +58,7 @@ template E* MmapArrayAllocator::allocate_or_null(size_t length, MemTag mem_tag) { size_t size = size_for(length); - char* addr = os::reserve_memory(size, mem_tag); + char* addr = os::reserve_memory(size, !ExecMem, mem_tag); if (addr == nullptr) { return nullptr; } @@ -75,7 +75,7 @@ template E* MmapArrayAllocator::allocate(size_t length, MemTag mem_tag) { size_t size = size_for(length); - char* addr = os::reserve_memory(size, mem_tag); + char* addr = os::reserve_memory(size, !ExecMem, mem_tag); if (addr == nullptr) { vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)"); } diff --git a/src/hotspot/share/memory/memoryReserver.cpp b/src/hotspot/share/memory/memoryReserver.cpp index 457818139cd..43cc71355ff 100644 --- a/src/hotspot/share/memory/memoryReserver.cpp +++ b/src/hotspot/share/memory/memoryReserver.cpp @@ -90,13 +90,13 @@ static char* reserve_memory_inner(char* requested_address, assert(is_aligned(requested_address, alignment), "Requested address " PTR_FORMAT " must be aligned to %zu", p2i(requested_address), alignment); - return os::attempt_reserve_memory_at(requested_address, size, mem_tag, exec); + return os::attempt_reserve_memory_at(requested_address, size, exec, mem_tag); } // 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. - char* base = os::reserve_memory(size, mem_tag, exec); + char* base = os::reserve_memory(size, exec, mem_tag); if (is_aligned(base, alignment)) { return base; } @@ -107,7 +107,7 @@ static char* reserve_memory_inner(char* requested_address, } // Map using the requested alignment. - return os::reserve_memory_aligned(size, alignment, mem_tag, exec); + return os::reserve_memory_aligned(size, alignment, exec); } ReservedSpace MemoryReserver::reserve_memory(char* requested_address, @@ -261,7 +261,7 @@ static char* map_memory_to_file(char* requested_address, // 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. - char* base = os::map_memory_to_file(size, fd, mem_tag); + char* base = os::map_memory_to_file(size, fd); if (is_aligned(base, alignment)) { return base; } diff --git a/src/hotspot/share/memory/memoryReserver.hpp b/src/hotspot/share/memory/memoryReserver.hpp index f8f642cca95..1e16ec252a9 100644 --- a/src/hotspot/share/memory/memoryReserver.hpp +++ b/src/hotspot/share/memory/memoryReserver.hpp @@ -58,12 +58,12 @@ public: size_t size, size_t alignment, size_t page_size, - MemTag mem_tag); + MemTag mem_tag = mtNone); static ReservedSpace reserve(size_t size, size_t alignment, size_t page_size, - MemTag mem_tag); + MemTag mem_tag = mtNone); static ReservedSpace reserve(size_t size, MemTag mem_tag); diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 33cd4a75d7e..04e5d807f32 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -594,7 +594,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(), mtClass); + result = os::reserve_memory_aligned(size, Metaspace::reserve_alignment(), false); } // Wrap resulting range in ReservedSpace @@ -767,8 +767,7 @@ void Metaspace::global_initialize() { rs = MemoryReserver::reserve((char*)base, size, Metaspace::reserve_alignment(), - os::vm_page_size(), - mtClass); + os::vm_page_size()); if (rs.is_reserved()) { log_info(metaspace)("Successfully forced class space address to " PTR_FORMAT, p2i(base)); diff --git a/src/hotspot/share/memory/metaspace/testHelpers.cpp b/src/hotspot/share/memory/metaspace/testHelpers.cpp index f06f6c855be..76fa1e36c45 100644 --- a/src/hotspot/share/memory/metaspace/testHelpers.cpp +++ b/src/hotspot/share/memory/metaspace/testHelpers.cpp @@ -82,7 +82,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 = MemoryReserver::reserve(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size(), mtTest); + _rs = MemoryReserver::reserve(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 @@ -142,3 +142,4 @@ size_t MetaspaceTestContext::reserved_words() const { } } // namespace metaspace + diff --git a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp index bb59192cf16..66644c805a9 100644 --- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp +++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp @@ -256,7 +256,7 @@ VirtualSpaceNode* VirtualSpaceNode::create_node(size_t word_size, ReservedSpace rs = MemoryReserver::reserve(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"); } diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp index 512e1975929..c7327782a4a 100644 --- a/src/hotspot/share/nmt/memReporter.cpp +++ b/src/hotspot/share/nmt/memReporter.cpp @@ -249,7 +249,7 @@ void MemSummaryReporter::report_summary_of_tag(MemTag mem_tag, // report malloc'd memory if (amount_in_current_scale(MAX2(malloc_memory->malloc_size(), pk_malloc)) > 0) { - print_malloc(malloc_memory->malloc_counter(), mem_tag); + print_malloc(malloc_memory->malloc_counter()); out->cr(); } diff --git a/src/hotspot/share/nmt/memReporter.hpp b/src/hotspot/share/nmt/memReporter.hpp index 2238d42f15f..05b1588f38b 100644 --- a/src/hotspot/share/nmt/memReporter.hpp +++ b/src/hotspot/share/nmt/memReporter.hpp @@ -108,7 +108,7 @@ class MemReporterBase : public StackObj { // Print summary total, malloc and virtual memory void print_total(size_t reserved, size_t committed, size_t peak = 0) const; - void print_malloc(const MemoryCounter* c, MemTag mem_tag) const; + void print_malloc(const MemoryCounter* c, MemTag mem_tag = mtNone) const; void print_virtual_memory(size_t reserved, size_t committed, size_t peak) const; void print_arena(const MemoryCounter* c) const; diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp index 3918e81dab7..981e991a41e 100644 --- a/src/hotspot/share/nmt/memTracker.hpp +++ b/src/hotspot/share/nmt/memTracker.hpp @@ -127,7 +127,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, - MemTag mem_tag) { + MemTag mem_tag = mtNone) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { @@ -153,7 +153,7 @@ class MemTracker : AllStatic { } static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, - const NativeCallStack& stack, MemTag mem_tag) { + const NativeCallStack& stack, MemTag mem_tag = mtNone) { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.hpp b/src/hotspot/share/nmt/virtualMemoryTracker.hpp index 2b3b5722571..74d299e6637 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.hpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.hpp @@ -297,7 +297,7 @@ class ReservedMemoryRegion : public VirtualMemoryRegion { public: ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack, - MemTag mem_tag) : + MemTag mem_tag = mtNone) : VirtualMemoryRegion(base, size), _stack(stack), _mem_tag(mem_tag) { } @@ -380,7 +380,7 @@ class VirtualMemoryTracker : AllStatic { public: static bool initialize(NMT_TrackingLevel level); - static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag); + static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag = mtNone); 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); diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index c988745f7b6..d2916fad185 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -2400,7 +2400,7 @@ 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, mtInternal); + bad_address = os::reserve_memory(size, false, mtInternal); if (bad_address != nullptr) { os::protect_memory(bad_address, size, os::MEM_PROT_READ, /*is_committed*/false); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 884fbf98138..e08a5ba5ebd 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -728,11 +728,11 @@ WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem)) WB_END WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) - return (jlong)(uintptr_t)os::reserve_memory(size, mtTest); + return (jlong)(uintptr_t)os::reserve_memory(size, false, mtTest); WB_END WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size)) - return (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, mtTest); + return (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, false, mtTest); WB_END WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) @@ -1524,7 +1524,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(), 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 7695fed564d..cbe40ca214b 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1916,7 +1916,7 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) { return os::pd_create_stack_guard_pages(addr, bytes); } -char* os::reserve_memory(size_t bytes, MemTag mem_tag, bool executable) { +char* os::reserve_memory(size_t bytes, bool executable, MemTag mem_tag) { char* result = pd_reserve_memory(bytes, executable); if (result != nullptr) { MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC, mem_tag); @@ -1927,7 +1927,7 @@ char* os::reserve_memory(size_t bytes, MemTag mem_tag, bool executable) { return result; } -char* os::attempt_reserve_memory_at(char* addr, size_t bytes, MemTag mem_tag, bool executable) { +char* os::attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MemTag mem_tag) { 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, mem_tag); @@ -2133,7 +2133,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, mtNone); + 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)); } @@ -2300,8 +2300,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, MemTag mem_tag, - bool read_only, bool allow_exec) { + char *addr, size_t bytes, bool read_only, + bool allow_exec, MemTag mem_tag) { 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, mem_tag); @@ -2339,7 +2339,7 @@ char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size 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, mtNone); + 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 b9a3bf564f7..242959034af 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -457,14 +457,14 @@ class os: AllStatic { inline static size_t cds_core_region_alignment(); // Reserves virtual memory. - static char* reserve_memory(size_t bytes, MemTag mem_tag, bool executable = false); + static char* reserve_memory(size_t bytes, bool executable = false, MemTag mem_tag = 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, MemTag mem_tag, bool executable = false); + 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, MemTag mem_tag, bool executable = false); + static char* attempt_reserve_memory_at(char* addr, size_t bytes, bool executable = false, MemTag mem_tag = 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. @@ -516,16 +516,16 @@ 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, MemTag mem_tag); - static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag); + static char* map_memory_to_file(size_t size, int fd, MemTag mem_tag = mtNone); + static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag = 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, MemTag mem_tag); + static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MemTag mem_tag = 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, MemTag mem_tag, bool read_only = false, - bool allow_exec = false); + char *addr, size_t bytes, bool read_only = false, + bool allow_exec = false, MemTag mem_tag = mtNone); static bool unmap_memory(char *addr, size_t bytes); static void disclaim_memory(char *addr, size_t bytes); static void realign_memory(char *addr, size_t bytes, size_t alignment_hint); diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index 71224bbff4c..51038d764bb 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -57,7 +57,7 @@ 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, mtSafepoint); + char* polling_page = os::reserve_memory(allocation_size, !ExecMem, mtSafepoint); os::commit_memory_or_exit(polling_page, allocation_size, !ExecMem, "Unable to commit Safepoint polling page"); char* bad_page = polling_page; diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index abe3d6757b5..9413f1f72d7 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -712,7 +712,7 @@ struct TestMultipleStaticAssertFormsInClassScope { // Support for showing register content on asserts/guarantees. #ifdef CAN_SHOW_REGISTERS_ON_ASSERT void initialize_assert_poison() { - char* page = os::reserve_memory(os::vm_page_size(), mtInternal); + char* page = os::reserve_memory(os::vm_page_size(), !ExecMem, mtInternal); if (page) { if (os::commit_memory(page, os::vm_page_size(), !ExecMem) && os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) { diff --git a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp index 45da22ce116..bc0ed0f3c59 100644 --- a/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp +++ b/test/hotspot/gtest/gc/g1/test_stressCommitUncommit.cpp @@ -82,8 +82,7 @@ TEST_VM(G1RegionToSpaceMapper, smallStressAdjacent) { ReservedSpace rs = MemoryReserver::reserve(size, os::vm_allocation_granularity(), - os::vm_page_size(), - mtTest); + os::vm_page_size()); G1RegionToSpaceMapper* small_mapper = G1RegionToSpaceMapper::create_mapper(rs, @@ -91,7 +90,7 @@ TEST_VM(G1RegionToSpaceMapper, smallStressAdjacent) { page_size, region_size, G1BlockOffsetTable::heap_map_factor(), - mtTest); + mtGC); @@ -109,15 +108,14 @@ TEST_VM(G1RegionToSpaceMapper, largeStressAdjacent) { ReservedSpace rs = MemoryReserver::reserve(size, os::vm_allocation_granularity(), - os::vm_page_size(), - mtTest); + os::vm_page_size()); G1RegionToSpaceMapper* large_mapper = G1RegionToSpaceMapper::create_mapper(rs, size, page_size, region_size, G1BlockOffsetTable::heap_map_factor(), - mtTest); + mtGC); G1TestCommitUncommit task(large_mapper); G1MapperWorkers::run_task(&task); diff --git a/test/hotspot/gtest/gc/z/test_zForwarding.cpp b/test/hotspot/gtest/gc/z/test_zForwarding.cpp index f22eef50858..71fb83827c7 100644 --- a/test/hotspot/gtest/gc/z/test_zForwarding.cpp +++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp @@ -56,7 +56,7 @@ public: 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, mtTest); + char* const reserved = os::attempt_reserve_memory_at((char*)ZAddressHeapBase + start, ZGranuleSize, false /* executable */); if (reserved != nullptr) { // Success return reserved; diff --git a/test/hotspot/gtest/memory/test_virtualspace.cpp b/test/hotspot/gtest/memory/test_virtualspace.cpp index d2f8927ba28..d3fed31da0b 100644 --- a/test/hotspot/gtest/memory/test_virtualspace.cpp +++ b/test/hotspot/gtest/memory/test_virtualspace.cpp @@ -73,7 +73,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 = MemoryReserver::reserve(size, alignment, page_size, mtTest); + ReservedSpace rs = MemoryReserver::reserve(size, alignment, page_size); ASSERT_TRUE(rs.base() != nullptr) << "rs.special = " << rs.special(); ASSERT_EQ(size, rs.size()) << "rs.special = " << rs.special(); @@ -101,7 +101,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 = MemoryReserver::reserve(size, alignment, page_size, mtTest); + ReservedSpace rs = MemoryReserver::reserve(size, alignment, page_size); MemoryReleaser releaser(&rs); EXPECT_TRUE(rs.base() != nullptr) << "rs.special: " << rs.special(); @@ -217,8 +217,7 @@ namespace { case Commit: return MemoryReserver::reserve(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size(), - mtTest); + os::vm_page_size()); } } @@ -297,7 +296,7 @@ TEST_VM(VirtualSpace, actual_committed_space_one_large_page) { size_t large_page_size = os::large_page_size(); - ReservedSpace reserved = MemoryReserver::reserve(large_page_size, large_page_size, large_page_size, mtTest); + ReservedSpace reserved = MemoryReserver::reserve(large_page_size, large_page_size, large_page_size); ReservedSpaceReleaser releaser(&reserved); ASSERT_TRUE(reserved.is_reserved()); @@ -366,8 +365,7 @@ class TestReservedSpace : AllStatic { size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); ReservedSpace rs = MemoryReserver::reserve(size, alignment, - page_size, - mtTest); + page_size); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -412,8 +410,7 @@ class TestReservedSpace : AllStatic { ReservedSpace rs = MemoryReserver::reserve(size, alignment, - page_size, - mtTest); + page_size); EXPECT_TRUE(rs.base() != nullptr); EXPECT_EQ(rs.size(), size) << "rs.size: " << rs.size(); @@ -517,14 +514,12 @@ class TestVirtualSpace : AllStatic { default: case Default: case Reserve: - return MemoryReserver::reserve(reserve_size_aligned, - mtTest); + return MemoryReserver::reserve(reserve_size_aligned, mtTest); case Disable: case Commit: return MemoryReserver::reserve(reserve_size_aligned, os::vm_allocation_granularity(), - os::vm_page_size(), - mtTest); + os::vm_page_size()); } } @@ -581,8 +576,7 @@ class TestVirtualSpace : AllStatic { ReservedSpace reserved = MemoryReserver::reserve(large_page_size, large_page_size, - large_page_size, - mtTest); + large_page_size); ASSERT_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 c8711004f10..e0e3c289102 100644 --- a/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_locationprinting.cpp @@ -113,7 +113,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, 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 f07b45bc32d..de63e1807c1 100644 --- a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp +++ b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp @@ -91,7 +91,7 @@ public: static void test_committed_region_impl(size_t num_pages, size_t touch_pages, int* page_num) { const size_t page_sz = os::vm_page_size(); const size_t size = num_pages * page_sz; - char* base = os::reserve_memory(size, mtThreadStack); + char* base = os::reserve_memory(size, !ExecMem, mtThreadStack); bool result = os::commit_memory(base, size, !ExecMem); size_t index; ASSERT_NE(base, (char*)nullptr); @@ -159,7 +159,7 @@ public: const size_t page_sz = os::vm_page_size(); const size_t num_pages = 4; const size_t size = num_pages * page_sz; - char* base = os::reserve_memory(size, mtTest); + char* base = os::reserve_memory(size, !ExecMem, mtTest); ASSERT_NE(base, (char*)nullptr); result = os::commit_memory(base, size, !ExecMem); @@ -205,7 +205,7 @@ public: const size_t page_sz = os::vm_page_size(); const size_t size = num_pages * page_sz; - char* base = os::reserve_memory(size, mtTest); + char* base = os::reserve_memory(size, !ExecMem, mtTest); ASSERT_NE(base, (char*)nullptr); result = os::commit_memory(base, size, !ExecMem); diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index 6b7653f5eec..ee6d1427d0b 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -258,7 +258,7 @@ TEST_VM(os, test_print_hex_dump) { // two pages, first one protected. const size_t ps = os::vm_page_size(); - char* two_pages = os::reserve_memory(ps * 2, mtTest); + char* two_pages = os::reserve_memory(ps * 2, false, mtTest); os::commit_memory(two_pages, ps * 2, false); os::protect_memory(two_pages, ps, os::MEM_PROT_NONE, true); @@ -492,7 +492,7 @@ TEST_VM(os, realpath) { static inline bool can_reserve_executable_memory(void) { bool executable = true; size_t len = 128; - char* p = os::reserve_memory(len, mtTest, executable); + char* p = os::reserve_memory(len, executable); bool exec_supported = (p != nullptr); if (exec_supported) { os::release_memory(p, len); @@ -530,7 +530,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, 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)); @@ -544,7 +544,7 @@ 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, mtTest, executable); + 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); @@ -564,7 +564,7 @@ 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, 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); @@ -631,7 +631,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, mtTest); + address p2 = (address)os::attempt_reserve_memory_at((char*)p_middle_stripes, middle_stripe_len); ASSERT_EQ(p2, p_middle_stripes); @@ -654,7 +654,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, mtTest); + char* p = os::reserve_memory(4 * M); ASSERT_NE(p, (char*)nullptr); // Release part of range ASSERT_FALSE(os::release_memory(p, M)); @@ -689,7 +689,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, mtTest); + address p2 = (address)os::attempt_reserve_memory_at((char*)border, stripe_len); PRINT_MAPPINGS("B"); ASSERT_TRUE(p2 == nullptr || p2 == border); @@ -730,7 +730,7 @@ 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, mtTest); + char* p = os::reserve_memory(1 * M, false, mtInternal); if (p != nullptr) { if (os::commit_memory(p, 1 * M, false)) { strcpy(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); @@ -754,7 +754,7 @@ TEST_VM(os, find_mapping_simple) { // A simple allocation { - address p = (address)os::reserve_memory(total_range_len, 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) { @@ -1059,9 +1059,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, mtTest); + char* p1 = os::reserve_memory(M, false, mtTest); ASSERT_NE(p1, nullptr); - char* p2 = os::attempt_reserve_memory_at(p1, M, mtTest); + char* p2 = os::attempt_reserve_memory_at(p1, M); ASSERT_EQ(p2, nullptr); // should have failed os::release_memory(p1, M); } @@ -1069,7 +1069,7 @@ 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, mtTest); + char* p1 = os::reserve_memory_aligned(lpsz, lpsz, false); ASSERT_NE(p1, nullptr); char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, false); ASSERT_EQ(p2, nullptr); // should have failed @@ -1095,7 +1095,7 @@ TEST_VM(os, free_without_uncommit) { const size_t pages = 64; const size_t size = pages * page_sz; - char* base = os::reserve_memory(size, mtTest); + char* base = os::reserve_memory(size, false, mtTest); ASSERT_NE(base, (char*) nullptr); ASSERT_TRUE(os::commit_memory(base, size, false)); diff --git a/test/hotspot/gtest/runtime/test_os_aix.cpp b/test/hotspot/gtest/runtime/test_os_aix.cpp index 73ed55dc3ce..9fcb2f9c691 100644 --- a/test/hotspot/gtest/runtime/test_os_aix.cpp +++ b/test/hotspot/gtest/runtime/test_os_aix.cpp @@ -34,9 +34,9 @@ TEST_VM(os_aix, aix_reserve_at_non_shmlba_aligned_address) { if (os::vm_page_size() != 4*K && !os::Aix::supports_64K_mmap_pages()) { // With this condition true shmget() is used inside - char* p = os::attempt_reserve_memory_at((char*)0x1f00000, M, 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, 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 21133788a36..caa227c5e35 100644 --- a/test/hotspot/gtest/runtime/test_os_linux.cpp +++ b/test/hotspot/gtest/runtime/test_os_linux.cpp @@ -354,7 +354,7 @@ 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, mtTest); + char* const heap = os::reserve_memory(size, false, mtInternal); EXPECT_NE(heap, nullptr); EXPECT_TRUE(os::commit_memory(heap, size, false)); diff --git a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp index ee91ff49ded..34dd26dcf17 100644 --- a/test/hotspot/gtest/runtime/test_os_reserve_between.cpp +++ b/test/hotspot/gtest/runtime/test_os_reserve_between.cpp @@ -157,7 +157,7 @@ public: // 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, mtTest); + _base = os::attempt_reserve_memory_at((char*)candidate, _len); } } if (_base == nullptr) { @@ -165,8 +165,8 @@ public: } // 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, mtTest); - _p2 = os::attempt_reserve_memory_at(_base + _p2_offset, _p2_size, 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/jtreg/runtime/NMT/MallocRoundingReportTest.java b/test/hotspot/jtreg/runtime/NMT/MallocRoundingReportTest.java index a0c14d70831..30a03f973bf 100644 --- a/test/hotspot/jtreg/runtime/NMT/MallocRoundingReportTest.java +++ b/test/hotspot/jtreg/runtime/NMT/MallocRoundingReportTest.java @@ -57,7 +57,7 @@ public class MallocRoundingReportTest { // NMT does not track memory allocations less than 1KB, and rounds to the nearest KB NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=" + numKB + "KB, committed=" + numKB + "KB)", - "(malloc=" + numKB + "KB tag=Test #1) (at peak)" // (malloc=1KB tag=Test #1) (at peak) + "(malloc=" + numKB + "KB #1) (at peak)" ); wb.NMTFree(mallocd_total); @@ -65,7 +65,7 @@ public class MallocRoundingReportTest { // Run 'jcmd VM.native_memory summary', check for expected output NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=0KB, committed=0KB)", - "(malloc=0KB tag=Test) (peak=" + numKB + "KB #1)" + "(malloc=0KB) (peak=" + numKB + "KB #1)" ); } } diff --git a/test/hotspot/jtreg/runtime/NMT/MallocTestType.java b/test/hotspot/jtreg/runtime/NMT/MallocTestType.java index 1612cbd81c0..67df864e7b4 100644 --- a/test/hotspot/jtreg/runtime/NMT/MallocTestType.java +++ b/test/hotspot/jtreg/runtime/NMT/MallocTestType.java @@ -46,7 +46,7 @@ public class MallocTestType { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( new String[]{"Test (reserved=384KB, committed=384KB)", - "(malloc=384KB tag=Test #2) (at peak)"}); + "(malloc=384KB #2) (at peak)"}); wb.NMTFree(memAlloc3); // current +256K #1 peak +384K #2 long memAlloc1 = wb.NMTMalloc(512 * 1024); // current +768K #2 peak +768K #2 @@ -54,13 +54,13 @@ public class MallocTestType { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( new String[]{"Test (reserved=512KB, committed=512KB)", - "(malloc=512KB tag=Test #1) (peak=768KB #2)"}); + "(malloc=512KB #1) (peak=768KB #2)"}); // Free the memory allocated by NMTAllocTest wb.NMTFree(memAlloc1); // current 0K #0 peak +768K #2 NMTTestUtils.runJcmdSummaryReportAndCheckOutput( new String[]{"Test (reserved=0KB, committed=0KB)", - "(malloc=0KB tag=Test) (peak=768KB #2)"}); + "(malloc=0KB) (peak=768KB #2)"}); } } diff --git a/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java b/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java index 141ef9f2ac3..0c08e07fd25 100644 --- a/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java +++ b/test/hotspot/jtreg/runtime/NMT/MallocTrackingVerify.java @@ -72,7 +72,7 @@ public class MallocTrackingVerify { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=4KB, committed=4KB)", - "(malloc=4KB tag=Test #" + mallocd_memory.size() + ") (at peak)" + "(malloc=4KB #" + mallocd_memory.size() + ") (at peak)" ); // Free @@ -83,7 +83,7 @@ public class MallocTrackingVerify { // Run 'jcmd VM.native_memory summary', check for expected output NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=0KB, committed=0KB)", - "(malloc=0KB tag=Test) (peak=4KB #" + + mallocd_memory.size() + ")" + "(malloc=0KB) (peak=4KB #" + + mallocd_memory.size() + ")" ); } diff --git a/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java b/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java index f6b0f3baf04..290984c4185 100644 --- a/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java +++ b/test/hotspot/jtreg/runtime/NMT/ThreadedMallocTestType.java @@ -61,7 +61,7 @@ public class ThreadedMallocTestType { // Run 'jcmd VM.native_memory summary' NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=896KB, committed=896KB)", - "(malloc=896KB tag=Test #3) (at peak)" + "(malloc=896KB #3) (at peak)" ); Thread freeThread = new Thread() { @@ -78,7 +78,7 @@ public class ThreadedMallocTestType { NMTTestUtils.runJcmdSummaryReportAndCheckOutput( "Test (reserved=0KB, committed=0KB)", - "(malloc=0KB tag=Test) (peak=896KB #3)" + "(malloc=0KB) (peak=896KB #3)" ); } } From f6d8c8cb0c6b226d68791ffd126908d3fea11473 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Mon, 14 Apr 2025 19:16:17 +0000 Subject: [PATCH 169/843] 8351339: WebSocket::sendBinary assume that user supplied buffers are BIG_ENDIAN Reviewed-by: michaelm, dfuchs --- .../internal/net/http/websocket/Frame.java | 86 +-- .../net/http/websocket/MessageDecoder.java | 4 +- .../net/http/websocket/MessageEncoder.java | 6 +- .../httpclient/websocket/AutomaticPong.java | 7 +- .../websocket/DummyWebSocketServer.java | 88 +++- .../java/net/httpclient/websocket/Frame.java | 497 ------------------ .../net/httpclient/websocket/TEST.properties | 5 + .../websocket/WebSocketBuilderTest.java | 4 +- .../websocket/WebSocketEndiannessTest.java | 178 +++++++ .../websocket/WebSocketExtendedTest.java | 127 +---- .../net/http/websocket/MaskerTest.java | 12 +- 11 files changed, 359 insertions(+), 655 deletions(-) delete mode 100644 test/jdk/java/net/httpclient/websocket/Frame.java create mode 100644 test/jdk/java/net/httpclient/websocket/TEST.properties create mode 100644 test/jdk/java/net/httpclient/websocket/WebSocketEndiannessTest.java diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/Frame.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/Frame.java index 838e7c6a26b..0827d64a28d 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/Frame.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/Frame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package jdk.internal.net.http.websocket; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import static jdk.internal.net.http.common.Utils.dump; import static jdk.internal.net.http.websocket.Frame.Opcode.ofCode; @@ -33,14 +34,14 @@ import static jdk.internal.net.http.websocket.Frame.Opcode.ofCode; /* * A collection of utilities for reading, writing, and masking frames. */ -final class Frame { +public final class Frame { private Frame() { } static final int MAX_HEADER_SIZE_BYTES = 2 + 8 + 4; - static final int MAX_CONTROL_FRAME_PAYLOAD_LENGTH = 125; + public static final int MAX_CONTROL_FRAME_PAYLOAD_LENGTH = 125; - enum Opcode { + public enum Opcode { CONTINUATION (0x0), TEXT (0x1), @@ -87,13 +88,13 @@ final class Frame { /* * A utility for masking frame payload data. */ - static final class Masker { + public static final class Masker { - // Exploiting ByteBuffer's ability to read/write multi-byte integers private final ByteBuffer acc = ByteBuffer.allocate(8); - private final int[] maskBytes = new int[4]; + private final byte[] maskBytes = new byte[4]; private int offset; - private long maskLong; + private long maskLongBe; + private long maskLongLe; /* * Reads all remaining bytes from the given input buffer, masks them @@ -102,11 +103,11 @@ final class Frame { * * The source and the destination buffers may be the same instance. */ - static void transferMasking(ByteBuffer src, ByteBuffer dst, int mask) { + static void applyMask(ByteBuffer src, ByteBuffer dst, int mask) { if (src.remaining() > dst.remaining()) { throw new IllegalArgumentException(dump(src, dst)); } - new Masker().mask(mask).transferMasking(src, dst); + new Masker().setMask(mask).applyMask(src, dst); } /* @@ -114,13 +115,14 @@ final class Frame { * * The behaviour is as if the mask was set on a newly created instance. */ - Masker mask(int value) { - acc.clear().putInt(value).putInt(value).flip(); + public Masker setMask(int mask) { + acc.clear().putInt(mask).putInt(mask).flip(); for (int i = 0; i < maskBytes.length; i++) { maskBytes[i] = acc.get(i); } offset = 0; - maskLong = acc.getLong(0); + maskLongBe = acc.getLong(0); + maskLongLe = Long.reverseBytes(maskLongBe); return this; } @@ -132,18 +134,25 @@ final class Frame { * The source and the destination buffers may be the same instance. If * the mask hasn't been previously set it is assumed to be 0. */ - Masker transferMasking(ByteBuffer src, ByteBuffer dst) { - begin(src, dst); - loop(src, dst); - end(src, dst); - return this; + public void applyMask(ByteBuffer src, ByteBuffer dst) { + if (canVectorMask(src, dst)) { + initVectorMask(src, dst); + applyVectorMask(src, dst); + } + applyPlainMask(src, dst); } - /* - * Applies up to 3 remaining from the previous pass bytes of the mask. + private static boolean canVectorMask(ByteBuffer src, ByteBuffer dst) { + return src.order() == dst.order() && Math.min(src.remaining(), dst.remaining()) >= 8; + } + + /** + * Positions the {@link #offset} at 0, which is needed for vectorized + * masking, by masking up to 3 remaining bytes from the previous pass. */ - private void begin(ByteBuffer src, ByteBuffer dst) { - if (offset == 0) { // No partially applied mask from the previous invocation + private void initVectorMask(ByteBuffer src, ByteBuffer dst) { + assert src.order() == dst.order() : "vectorized masking is only allowed on matching byte orders"; + if (offset == 0) { return; } int i = src.position(), j = dst.position(); @@ -158,12 +167,16 @@ final class Frame { } /* - * Gallops one long (mask + mask) at a time. + * Masks one {@code long} (mask + mask) at a time. */ - private void loop(ByteBuffer src, ByteBuffer dst) { + private void applyVectorMask(ByteBuffer src, ByteBuffer dst) { + assert src.order() == dst.order() : "vectorized masking is only allowed on matching byte orders"; + long maskLong = ByteOrder.LITTLE_ENDIAN == src.order() ? maskLongLe : maskLongBe; int i = src.position(); int j = dst.position(); final int srcLongLim = src.limit() - 7, dstLongLim = dst.limit() - 7; + assert !(i < srcLongLim && j < dstLongLim) || // That is, if loop will run at least once + offset == 0 : "offset must have been positioned at 0"; for (; i < srcLongLim && j < dstLongLim; i += 8, j += 8) { dst.putLong(j, src.getLong(i) ^ maskLong); } @@ -180,11 +193,9 @@ final class Frame { } /* - * Applies up to 7 remaining from the "galloping" phase bytes of the - * mask. + * Masks one {@code byte} at a time. */ - private void end(ByteBuffer src, ByteBuffer dst) { - assert Math.min(src.remaining(), dst.remaining()) < 8; + private void applyPlainMask(ByteBuffer src, ByteBuffer dst) { final int srcLim = src.limit(), dstLim = dst.limit(); int i = src.position(), j = dst.position(); for (; i < srcLim && j < dstLim; @@ -195,6 +206,7 @@ final class Frame { src.position(i); dst.position(j); } + } /* @@ -204,14 +216,14 @@ final class Frame { * header structure to the given buffer. The order of calls to intermediate * methods is NOT significant. */ - static final class HeaderWriter { + public static final class HeaderWriter { private char firstChar; private long payloadLen; private int maskingKey; private boolean mask; - HeaderWriter fin(boolean value) { + public HeaderWriter fin(boolean value) { if (value) { firstChar |= 0b10000000_00000000; } else { @@ -254,12 +266,12 @@ final class Frame { return this; } - HeaderWriter opcode(Opcode value) { + public HeaderWriter opcode(Opcode value) { firstChar = (char) ((firstChar & 0xF0FF) | (value.code << 8)); return this; } - HeaderWriter payloadLen(long value) { + public HeaderWriter payloadLen(long value) { if (value < 0) { throw new IllegalArgumentException("Negative: " + value); } @@ -282,7 +294,7 @@ final class Frame { return this; } - HeaderWriter noMask() { + public HeaderWriter noMask() { // Explicit cast required: see fin() above firstChar &= (char) ~0b00000000_10000000; mask = false; @@ -295,7 +307,7 @@ final class Frame { * The buffer must have at least MAX_HEADER_SIZE_BYTES remaining. The * buffer's position is incremented by the number of bytes written. */ - void write(ByteBuffer buffer) { + public void write(ByteBuffer buffer) { buffer.putChar(firstChar); if (payloadLen >= 126) { if (payloadLen < 65536) { @@ -317,7 +329,7 @@ final class Frame { * * fin rsv1 rsv2 rsv3 opcode mask payloadLength maskingKey? payloadData+ endFrame */ - interface Consumer { + public interface Consumer { void fin(boolean value); @@ -358,7 +370,7 @@ final class Frame { * * No protocol-level rules are checked. */ - static final class Reader { + public static final class Reader { private static final int AWAITING_FIRST_BYTE = 1; private static final int AWAITING_SECOND_BYTE = 2; @@ -382,7 +394,7 @@ final class Frame { * * Throws FailWebSocketException if detects the frame is malformed. */ - void readFrame(ByteBuffer input, Consumer consumer) { + public void readFrame(ByteBuffer input, Consumer consumer) { loop: while (true) { byte b; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageDecoder.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageDecoder.java index 9e66327b7c8..e8923188489 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageDecoder.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,7 +248,7 @@ class MessageDecoder implements Frame.Consumer { int pos = src.position(); int size = src.remaining(); ByteBuffer temp = ByteBuffer.allocate(size); - Frame.Masker.transferMasking(src, temp, maskingKey); + Frame.Masker.applyMask(src, temp, maskingKey); temp.flip(); src.position(pos); src.put(temp); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageEncoder.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageEncoder.java index 0dd03e8f4c3..b8d17ce12ba 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageEncoder.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/MessageEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,7 +257,7 @@ public class MessageEncoder { private int maskAvailable(ByteBuffer src, ByteBuffer dst) { int r0 = dst.remaining(); - payloadMasker.transferMasking(src, dst); + payloadMasker.applyMask(src, dst); int masked = r0 - dst.remaining(); return src.hasRemaining() ? -masked : masked; } @@ -393,6 +393,6 @@ public class MessageEncoder { .write(headerBuffer); } headerBuffer.flip(); - payloadMasker.mask(mask); + payloadMasker.setMask(mask); } } diff --git a/test/jdk/java/net/httpclient/websocket/AutomaticPong.java b/test/jdk/java/net/httpclient/websocket/AutomaticPong.java index e6e760dba43..1999781b82f 100644 --- a/test/jdk/java/net/httpclient/websocket/AutomaticPong.java +++ b/test/jdk/java/net/httpclient/websocket/AutomaticPong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * -Djdk.internal.httpclient.websocket.debug=true * AutomaticPong */ +import jdk.internal.net.http.websocket.Frame; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -186,12 +187,12 @@ public class AutomaticPong { @Override public void maskingKey(int value) { - masker.mask(value); + masker.setMask(value); } @Override public void payloadData(ByteBuffer src) { - masker.transferMasking(src, number); + masker.applyMask(src, number); if (closed) { return; } diff --git a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java index 176634d6907..9034cf9f28a 100644 --- a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java +++ b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,8 @@ * questions. */ +import jdk.internal.net.http.websocket.Frame; + import java.io.Closeable; import java.io.IOException; import java.io.UncheckedIOException; @@ -217,6 +219,90 @@ public class DummyWebSocketServer implements Closeable { } } + public List readFrames() throws InterruptedException { + ByteBuffer buffer = read(); + Frame.Reader reader = new Frame.Reader(); + DecodedFrameCollector consumer = new DecodedFrameCollector(); + while (buffer.hasRemaining()) { + reader.readFrame(buffer, consumer); + } + return consumer.frames; + } + + private static final class DecodedFrameCollector implements Frame.Consumer { + + private final Frame.Masker masker = new Frame.Masker(); + + private final List frames = new ArrayList<>(); + + private ByteBuffer data; + + private Frame.Opcode opcode; + + private boolean last; + + @Override + public void fin(boolean value) { + last = value; + } + + @Override + public void rsv1(boolean value) { + if (value) { + throw new AssertionError(); + } + } + + @Override + public void rsv2(boolean value) { + if (value) { + throw new AssertionError(); + } + } + + @Override + public void rsv3(boolean value) { + if (value) { + throw new AssertionError(); + } + } + + @Override + public void opcode(Frame.Opcode value) { + opcode = value; + } + + @Override + public void mask(boolean value) { + if (!value) { // Frames from the client MUST be masked + throw new AssertionError(); + } + } + + @Override + public void payloadLen(long value) { + data = ByteBuffer.allocate((int) value); + } + + @Override + public void maskingKey(int value) { + masker.setMask(value); + } + + @Override + public void payloadData(ByteBuffer data) { + masker.applyMask(data, this.data); + } + + @Override + public void endFrame() { + frames.add(new DecodedFrame(opcode, this.data.flip(), last)); + } + + } + + public record DecodedFrame(Frame.Opcode opcode, ByteBuffer data, boolean last) {} + public ByteBuffer read() throws InterruptedException { readReady.await(); return read.duplicate().asReadOnlyBuffer().flip(); diff --git a/test/jdk/java/net/httpclient/websocket/Frame.java b/test/jdk/java/net/httpclient/websocket/Frame.java deleted file mode 100644 index 99c7f4ac65c..00000000000 --- a/test/jdk/java/net/httpclient/websocket/Frame.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (c) 2016, 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. - * - * 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.nio.ByteBuffer; - -/* Copied from jdk.internal.net.http.websocket.Frame */ -final class Frame { - - final Opcode opcode; - final ByteBuffer data; - final boolean last; - - public Frame(Opcode opcode, ByteBuffer data, boolean last) { - this.opcode = opcode; - /* copy */ - this.data = ByteBuffer.allocate(data.remaining()).put(data.slice()).flip(); - this.last = last; - } - - static final int MAX_HEADER_SIZE_BYTES = 2 + 8 + 4; - static final int MAX_CONTROL_FRAME_PAYLOAD_SIZE = 125; - - enum Opcode { - - CONTINUATION (0x0), - TEXT (0x1), - BINARY (0x2), - NON_CONTROL_0x3(0x3), - NON_CONTROL_0x4(0x4), - NON_CONTROL_0x5(0x5), - NON_CONTROL_0x6(0x6), - NON_CONTROL_0x7(0x7), - CLOSE (0x8), - PING (0x9), - PONG (0xA), - CONTROL_0xB (0xB), - CONTROL_0xC (0xC), - CONTROL_0xD (0xD), - CONTROL_0xE (0xE), - CONTROL_0xF (0xF); - - private static final Opcode[] opcodes; - - static { - Opcode[] values = values(); - opcodes = new Opcode[values.length]; - for (Opcode c : values) { - opcodes[c.code] = c; - } - } - - private final byte code; - - Opcode(int code) { - this.code = (byte) code; - } - - boolean isControl() { - return (code & 0x8) != 0; - } - - static Opcode ofCode(int code) { - return opcodes[code & 0xF]; - } - } - - /* - * A utility for masking frame payload data. - */ - static final class Masker { - - // Exploiting ByteBuffer's ability to read/write multi-byte integers - private final ByteBuffer acc = ByteBuffer.allocate(8); - private final int[] maskBytes = new int[4]; - private int offset; - private long maskLong; - - /* - * Reads all remaining bytes from the given input buffer, masks them - * with the supplied mask and writes the resulting bytes to the given - * output buffer. - * - * The source and the destination buffers may be the same instance. - */ - static void transferMasking(ByteBuffer src, ByteBuffer dst, int mask) { - if (src.remaining() > dst.remaining()) { - throw new IllegalArgumentException(); - } - new Masker().mask(mask).transferMasking(src, dst); - } - - /* - * Clears this instance's state and sets the mask. - * - * The behaviour is as if the mask was set on a newly created instance. - */ - Masker mask(int value) { - acc.clear().putInt(value).putInt(value).flip(); - for (int i = 0; i < maskBytes.length; i++) { - maskBytes[i] = acc.get(i); - } - offset = 0; - maskLong = acc.getLong(0); - return this; - } - - /* - * Reads as many remaining bytes as possible from the given input - * buffer, masks them with the previously set mask and writes the - * resulting bytes to the given output buffer. - * - * The source and the destination buffers may be the same instance. If - * the mask hasn't been previously set it is assumed to be 0. - */ - Masker transferMasking(ByteBuffer src, ByteBuffer dst) { - begin(src, dst); - loop(src, dst); - end(src, dst); - return this; - } - - /* - * Applies up to 3 remaining from the previous pass bytes of the mask. - */ - private void begin(ByteBuffer src, ByteBuffer dst) { - if (offset == 0) { // No partially applied mask from the previous invocation - return; - } - int i = src.position(), j = dst.position(); - final int srcLim = src.limit(), dstLim = dst.limit(); - for (; offset < 4 && i < srcLim && j < dstLim; i++, j++, offset++) - { - dst.put(j, (byte) (src.get(i) ^ maskBytes[offset])); - } - offset &= 3; // Will become 0 if the mask has been fully applied - src.position(i); - dst.position(j); - } - - /* - * Gallops one long (mask + mask) at a time. - */ - private void loop(ByteBuffer src, ByteBuffer dst) { - int i = src.position(); - int j = dst.position(); - final int srcLongLim = src.limit() - 7, dstLongLim = dst.limit() - 7; - for (; i < srcLongLim && j < dstLongLim; i += 8, j += 8) { - dst.putLong(j, src.getLong(i) ^ maskLong); - } - if (i > src.limit()) { - src.position(i - 8); - } else { - src.position(i); - } - if (j > dst.limit()) { - dst.position(j - 8); - } else { - dst.position(j); - } - } - - /* - * Applies up to 7 remaining from the "galloping" phase bytes of the - * mask. - */ - private void end(ByteBuffer src, ByteBuffer dst) { - assert Math.min(src.remaining(), dst.remaining()) < 8; - final int srcLim = src.limit(), dstLim = dst.limit(); - int i = src.position(), j = dst.position(); - for (; i < srcLim && j < dstLim; - i++, j++, offset = (offset + 1) & 3) // offset cycles through 0..3 - { - dst.put(j, (byte) (src.get(i) ^ maskBytes[offset])); - } - src.position(i); - dst.position(j); - } - } - - /* - * A builder-style writer of frame headers. - * - * The writer does not enforce any protocol-level rules, it simply writes a - * header structure to the given buffer. The order of calls to intermediate - * methods is NOT significant. - */ - static final class HeaderWriter { - - private char firstChar; - private long payloadLen; - private int maskingKey; - private boolean mask; - - HeaderWriter fin(boolean value) { - if (value) { - firstChar |= 0b10000000_00000000; - } else { - firstChar &= ~0b10000000_00000000; - } - return this; - } - - HeaderWriter rsv1(boolean value) { - if (value) { - firstChar |= 0b01000000_00000000; - } else { - firstChar &= ~0b01000000_00000000; - } - return this; - } - - HeaderWriter rsv2(boolean value) { - if (value) { - firstChar |= 0b00100000_00000000; - } else { - firstChar &= ~0b00100000_00000000; - } - return this; - } - - HeaderWriter rsv3(boolean value) { - if (value) { - firstChar |= 0b00010000_00000000; - } else { - firstChar &= ~0b00010000_00000000; - } - return this; - } - - HeaderWriter opcode(Opcode value) { - firstChar = (char) ((firstChar & 0xF0FF) | (value.code << 8)); - return this; - } - - HeaderWriter payloadLen(long value) { - if (value < 0) { - throw new IllegalArgumentException("Negative: " + value); - } - payloadLen = value; - firstChar &= 0b11111111_10000000; // Clear previous payload length leftovers - if (payloadLen < 126) { - firstChar |= payloadLen; - } else if (payloadLen < 65536) { - firstChar |= 126; - } else { - firstChar |= 127; - } - return this; - } - - HeaderWriter mask(int value) { - firstChar |= 0b00000000_10000000; - maskingKey = value; - mask = true; - return this; - } - - HeaderWriter noMask() { - firstChar &= ~0b00000000_10000000; - mask = false; - return this; - } - - /* - * Writes the header to the given buffer. - * - * The buffer must have at least MAX_HEADER_SIZE_BYTES remaining. The - * buffer's position is incremented by the number of bytes written. - */ - void write(ByteBuffer buffer) { - buffer.putChar(firstChar); - if (payloadLen >= 126) { - if (payloadLen < 65536) { - buffer.putChar((char) payloadLen); - } else { - buffer.putLong(payloadLen); - } - } - if (mask) { - buffer.putInt(maskingKey); - } - } - } - - /* - * A consumer of frame parts. - * - * Frame.Reader invokes the consumer's methods in the following order: - * - * fin rsv1 rsv2 rsv3 opcode mask payloadLength maskingKey? payloadData+ endFrame - */ - interface Consumer { - - void fin(boolean value); - - void rsv1(boolean value); - - void rsv2(boolean value); - - void rsv3(boolean value); - - void opcode(Opcode value); - - void mask(boolean value); - - void payloadLen(long value); - - void maskingKey(int value); - - /* - * Called by the Frame.Reader when a part of the (or a complete) payload - * is ready to be consumed. - * - * The sum of numbers of bytes consumed in each invocation of this - * method corresponding to the given frame WILL be equal to - * 'payloadLen', reported to `void payloadLen(long value)` before that. - * - * In particular, if `payloadLen` is 0, then there WILL be a single - * invocation to this method. - * - * No unmasking is done. - */ - void payloadData(ByteBuffer data); - - void endFrame(); - } - - /* - * A Reader of frames. - * - * No protocol-level rules are checked. - */ - static final class Reader { - - private static final int AWAITING_FIRST_BYTE = 1; - private static final int AWAITING_SECOND_BYTE = 2; - private static final int READING_16_LENGTH = 4; - private static final int READING_64_LENGTH = 8; - private static final int READING_MASK = 16; - private static final int READING_PAYLOAD = 32; - - // Exploiting ByteBuffer's ability to read multi-byte integers - private final ByteBuffer accumulator = ByteBuffer.allocate(8); - private int state = AWAITING_FIRST_BYTE; - private boolean mask; - private long remainingPayloadLength; - - /* - * Reads at most one frame from the given buffer invoking the consumer's - * methods corresponding to the frame parts found. - * - * As much of the frame's payload, if any, is read. The buffer's - * position is updated to reflect the number of bytes read. - * - * Throws FailWebSocketException if detects the frame is malformed. - */ - void readFrame(ByteBuffer input, Consumer consumer) { - loop: - while (true) { - byte b; - switch (state) { - case AWAITING_FIRST_BYTE: - if (!input.hasRemaining()) { - break loop; - } - b = input.get(); - consumer.fin( (b & 0b10000000) != 0); - consumer.rsv1((b & 0b01000000) != 0); - consumer.rsv2((b & 0b00100000) != 0); - consumer.rsv3((b & 0b00010000) != 0); - consumer.opcode(Opcode.ofCode(b)); - state = AWAITING_SECOND_BYTE; - continue loop; - case AWAITING_SECOND_BYTE: - if (!input.hasRemaining()) { - break loop; - } - b = input.get(); - consumer.mask(mask = (b & 0b10000000) != 0); - byte p1 = (byte) (b & 0b01111111); - if (p1 < 126) { - assert p1 >= 0 : p1; - consumer.payloadLen(remainingPayloadLength = p1); - state = mask ? READING_MASK : READING_PAYLOAD; - } else if (p1 < 127) { - state = READING_16_LENGTH; - } else { - state = READING_64_LENGTH; - } - continue loop; - case READING_16_LENGTH: - if (!input.hasRemaining()) { - break loop; - } - b = input.get(); - if (accumulator.put(b).position() < 2) { - continue loop; - } - remainingPayloadLength = accumulator.flip().getChar(); - if (remainingPayloadLength < 126) { - throw notMinimalEncoding(remainingPayloadLength); - } - consumer.payloadLen(remainingPayloadLength); - accumulator.clear(); - state = mask ? READING_MASK : READING_PAYLOAD; - continue loop; - case READING_64_LENGTH: - if (!input.hasRemaining()) { - break loop; - } - b = input.get(); - if (accumulator.put(b).position() < 8) { - continue loop; - } - remainingPayloadLength = accumulator.flip().getLong(); - if (remainingPayloadLength < 0) { - throw negativePayload(remainingPayloadLength); - } else if (remainingPayloadLength < 65536) { - throw notMinimalEncoding(remainingPayloadLength); - } - consumer.payloadLen(remainingPayloadLength); - accumulator.clear(); - state = mask ? READING_MASK : READING_PAYLOAD; - continue loop; - case READING_MASK: - if (!input.hasRemaining()) { - break loop; - } - b = input.get(); - if (accumulator.put(b).position() != 4) { - continue loop; - } - consumer.maskingKey(accumulator.flip().getInt()); - accumulator.clear(); - state = READING_PAYLOAD; - continue loop; - case READING_PAYLOAD: - // This state does not require any bytes to be available - // in the input buffer in order to proceed - int deliverable = (int) Math.min(remainingPayloadLength, - input.remaining()); - int oldLimit = input.limit(); - input.limit(input.position() + deliverable); - if (deliverable != 0 || remainingPayloadLength == 0) { - consumer.payloadData(input); - } - int consumed = deliverable - input.remaining(); - if (consumed < 0) { - // Consumer cannot consume more than there was available - throw new InternalError(); - } - input.limit(oldLimit); - remainingPayloadLength -= consumed; - if (remainingPayloadLength == 0) { - consumer.endFrame(); - state = AWAITING_FIRST_BYTE; - } - break loop; - default: - throw new InternalError(String.valueOf(state)); - } - } - } - - private static IllegalArgumentException negativePayload(long payloadLength) - { - return new IllegalArgumentException("Negative payload length: " - + payloadLength); - } - - private static IllegalArgumentException notMinimalEncoding(long payloadLength) - { - return new IllegalArgumentException("Not minimally-encoded payload length:" - + payloadLength); - } - } -} diff --git a/test/jdk/java/net/httpclient/websocket/TEST.properties b/test/jdk/java/net/httpclient/websocket/TEST.properties new file mode 100644 index 00000000000..685dab02627 --- /dev/null +++ b/test/jdk/java/net/httpclient/websocket/TEST.properties @@ -0,0 +1,5 @@ +modules=java.net.http/jdk.internal.net.http.common \ + java.net.http/jdk.internal.net.http.frame \ + java.net.http/jdk.internal.net.http.hpack \ + java.net.http/jdk.internal.net.http.websocket +maxOutputSize = 2500000 diff --git a/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java b/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java index 6fb94a9fa2e..b28b8f59875 100644 --- a/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java +++ b/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,8 @@ /* * @test * @bug 8159053 + * @build DummyWebSocketServer + * Support * @run testng/othervm WebSocketBuilderTest */ diff --git a/test/jdk/java/net/httpclient/websocket/WebSocketEndiannessTest.java b/test/jdk/java/net/httpclient/websocket/WebSocketEndiannessTest.java new file mode 100644 index 00000000000..0d532669a10 --- /dev/null +++ b/test/jdk/java/net/httpclient/websocket/WebSocketEndiannessTest.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8351339 + * @summary Verify the intact transmission of the binary payload regardless of its endianness + * @modules java.net.http/jdk.internal.net.http.websocket + * @library /test/lib + * @build DummyWebSocketServer + * jdk.test.lib.Asserts + * @run main WebSocketEndiannessTest + */ + +import jdk.internal.net.http.websocket.Frame; + +import java.net.http.HttpClient; +import java.net.http.WebSocket; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.List; +import java.util.function.Supplier; + +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static java.nio.ByteOrder.BIG_ENDIAN; +import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertEqualsByteArray; +import static jdk.test.lib.Asserts.assertTrue; + +public class WebSocketEndiannessTest { + + public static void main(String[] args) throws Exception { + assertEndiannessAgnosticTransfer(); + assertSuccessfulMasking(); + } + + private static void assertEndiannessAgnosticTransfer() throws Exception { + Supplier bufferSupplier = () -> ByteBuffer + .wrap(new byte[]{ + // 4-byte words + 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, + // 2-byte words + 0x10, 0x11, + 0x12, 0x13, + 0x14, 0x15, + 0x16, 0x17, + 0x18, 0x19, + 0x1a, 0x1b, + 0x1c, 0x1d, + 0x1e, 0x1f, + // negative ones + -1, -2, -3, 4, + -5, -6 + }); + assertEndiannessAgnosticTransfer(bufferSupplier.get().order(LITTLE_ENDIAN)); + assertEndiannessAgnosticTransfer(bufferSupplier.get().order(BIG_ENDIAN)); + } + + private static void assertEndiannessAgnosticTransfer(ByteBuffer data) throws Exception { + List frames = sendDataAndReadFrames(data); + assertEquals(frames.size(), 1); + DummyWebSocketServer.DecodedFrame frame = frames.getFirst(); + assertEquals(frame.opcode(), Frame.Opcode.BINARY); + assertTrue(frame.last()); + assertEqualsByteArray(data.array(), frame.data().array()); + } + + private static List sendDataAndReadFrames(ByteBuffer data) throws Exception { + try (var server = new DummyWebSocketServer(); + var client = HttpClient.newBuilder().proxy(NO_PROXY).build()) { + server.open(); + WebSocket webSocket = client + .newWebSocketBuilder() + .buildAsync(server.getURI(), new WebSocket.Listener() {}) + .join(); + try { + webSocket.sendBinary(data, true).join(); + } finally { + webSocket.abort(); + } + return server.readFrames(); + } + } + + private static void assertSuccessfulMasking() { + assertSuccessfulMasking(LITTLE_ENDIAN, LITTLE_ENDIAN); + assertSuccessfulMasking(LITTLE_ENDIAN, BIG_ENDIAN); + assertSuccessfulMasking(BIG_ENDIAN, LITTLE_ENDIAN); + assertSuccessfulMasking(BIG_ENDIAN, BIG_ENDIAN); + } + + private static void assertSuccessfulMasking(ByteOrder srcOrder, ByteOrder dstOrder) { + + // Create the masker + Frame.Masker masker = new Frame.Masker() + // `0xB0` and `0xD0` is used instead of `0x0B` and `0x0D` to cover the negative `byte` range: + // + // (byte) 0x0A -> 10 + // (byte) 0xB0 -> -80 + // (byte) 0x0C -> 12 + // (byte) 0xD0 -> -48 + .setMask(0x0AB00CD0); + + // Perform dummy masking to advance `Frame::offset` 1 byte, and effectively make it non-zero. + // A non-zero `Frame::offset` will trigger `Frame::initVectorMask` invocation. + masker.applyMask(ByteBuffer.wrap(new byte[1]), ByteBuffer.wrap(new byte[1])); + + // Perform the actual masking + ByteBuffer src = ByteBuffer + .wrap(new byte[]{ + // `initVectorMask` will mask 3 bytes to position the `offset` back to 0. + // It is 3 bytes, because of the 1 byte dummy advancement above. + -0x1, -0x2, 0x3, + // `applyVectorMask` will make a single 8-byte pass + 0x1, 0x2, 0x3, 0x4, -0x5, 0x6, -0x7, -0x8, + // `applyPlainMask` will mask 3 bytes + 0x1, -0x2, -0x3 + // Note minus signs sprinkled above to cover the negative `byte` range in a certain structure: + // Some will get masked with a positive number, some with a negative. + // For instance, for `applyPlainMask`: + // - `0x1` will be masked with `0xA` + // - `-0x2` will be masked with `0xB0` + }) + .order(srcOrder); + ByteBuffer dst = ByteBuffer.allocate(src.capacity()).order(dstOrder); + masker.applyMask(src, dst); + + // Verify the masking + assertEqualsByteArray( + new byte[]{ + // 3 bytes for `initVectorMask`. + // Remember 0xA is consumed by the initial dummy masking. + (byte) (-0x1 ^ 0xB0), + -0x2 ^ 0xC, + (byte) (0x3 ^ 0xD0), + // 8 bytes for `applyVectorMask` + 0x1 ^ 0xA, + (byte) (0x2 ^ 0xB0), + 0x3 ^ 0xC, + (byte) (0x4 ^ 0xD0), + -0x5 ^ 0xA, + (byte) (0x6 ^ 0xB0), + -0x7 ^ 0xC, + (byte) (-0x8 ^ 0xD0), + // 3 bytes for `applyPlainMask` + 0x1 ^ 0xA, + (byte) (-0x2 ^ 0xB0), + -0x3 ^ 0xC + }, + dst.array()); + + } + +} diff --git a/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java b/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java index e739c5ef795..0099104e872 100644 --- a/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java +++ b/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ /* * @test * @bug 8159053 - * - * * @run testng/othervm * -Djdk.internal.httpclient.websocket.debug=true * -Djdk.internal.httpclient.debug=true @@ -33,6 +31,7 @@ * -Djdk.httpclient.websocket.intermediateBufferSize=2048 WebSocketExtendedTest */ +import jdk.internal.net.http.websocket.Frame; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -40,7 +39,6 @@ import java.io.IOException; import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.List; import java.util.Random; import static java.net.http.HttpClient.Builder.NO_PROXY; @@ -77,91 +75,15 @@ public class WebSocketExtendedTest { .join(); ws.sendBinary(expected.duplicate(), true).join(); ws.abort(); - ByteBuffer data = server.read(); - List frames = readFrames(data); + List frames = server.readFrames(); assertEquals(frames.size(), 1); - Frame f = frames.get(0); - assertTrue(f.last); - assertEquals(f.opcode, Frame.Opcode.BINARY); - assertEquals(f.data, expected); + DummyWebSocketServer.DecodedFrame f = frames.get(0); + assertTrue(f.last()); + assertEquals(f.opcode(), Frame.Opcode.BINARY); + assertEquals(f.data(), expected); } } - private static List readFrames(ByteBuffer src) { - List frames = new ArrayList<>(); - Frame.Consumer consumer = new Frame.Consumer() { - - ByteBuffer data; - Frame.Opcode opcode; - Frame.Masker masker = new Frame.Masker(); - boolean last; - - @Override - public void fin(boolean value) { - last = value; - } - - @Override - public void rsv1(boolean value) { - if (value) { - throw new AssertionError(); - } - } - - @Override - public void rsv2(boolean value) { - if (value) { - throw new AssertionError(); - } - } - - @Override - public void rsv3(boolean value) { - if (value) { - throw new AssertionError(); - } - } - - @Override - public void opcode(Frame.Opcode value) { - opcode = value; - } - - @Override - public void mask(boolean value) { - if (!value) { // Frames from the client MUST be masked - throw new AssertionError(); - } - } - - @Override - public void payloadLen(long value) { - data = ByteBuffer.allocate((int) value); - } - - @Override - public void maskingKey(int value) { - masker.mask(value); - } - - @Override - public void payloadData(ByteBuffer data) { - masker.transferMasking(data, this.data); - } - - @Override - public void endFrame() { - frames.add(new Frame(opcode, this.data.flip(), last)); - } - }; - - Frame.Reader r = new Frame.Reader(); - while (src.hasRemaining()) { - r.readFrame(src, consumer); - } - return frames; - } - @Test(dataProvider = "pingPong") public void ping(ByteBuffer expected) throws Exception { try (DummyWebSocketServer server = new DummyWebSocketServer()) { @@ -172,13 +94,12 @@ public class WebSocketExtendedTest { .join(); ws.sendPing(expected.duplicate()).join(); ws.abort(); - ByteBuffer data = server.read(); - List frames = readFrames(data); + List frames = server.readFrames(); assertEquals(frames.size(), 1); - Frame f = frames.get(0); - assertEquals(f.opcode, Frame.Opcode.PING); + DummyWebSocketServer.DecodedFrame f = frames.get(0); + assertEquals(f.opcode(), Frame.Opcode.PING); ByteBuffer actual = ByteBuffer.allocate(expected.remaining()); - actual.put(f.data); + actual.put(f.data()); actual.flip(); assertEquals(actual, expected); } @@ -194,13 +115,12 @@ public class WebSocketExtendedTest { .join(); ws.sendPong(expected.duplicate()).join(); ws.abort(); - ByteBuffer data = server.read(); - List frames = readFrames(data); + List frames = server.readFrames(); assertEquals(frames.size(), 1); - Frame f = frames.get(0); - assertEquals(f.opcode, Frame.Opcode.PONG); + DummyWebSocketServer.DecodedFrame f = frames.get(0); + assertEquals(f.opcode(), Frame.Opcode.PONG); ByteBuffer actual = ByteBuffer.allocate(expected.remaining()); - actual.put(f.data); + actual.put(f.data()); actual.flip(); assertEquals(actual, expected); } @@ -216,13 +136,12 @@ public class WebSocketExtendedTest { .join(); ws.sendClose(statusCode, reason).join(); ws.abort(); - ByteBuffer data = server.read(); - List frames = readFrames(data); + List frames = server.readFrames(); assertEquals(frames.size(), 1); - Frame f = frames.get(0); - assertEquals(f.opcode, Frame.Opcode.CLOSE); - ByteBuffer actual = ByteBuffer.allocate(Frame.MAX_CONTROL_FRAME_PAYLOAD_SIZE); - actual.put(f.data); + DummyWebSocketServer.DecodedFrame f = frames.get(0); + assertEquals(f.opcode(), Frame.Opcode.CLOSE); + ByteBuffer actual = ByteBuffer.allocate(Frame.MAX_CONTROL_FRAME_PAYLOAD_LENGTH); + actual.put(f.data()); actual.flip(); assertEquals(actual.getChar(), statusCode); assertEquals(StandardCharsets.UTF_8.decode(actual).toString(), reason); @@ -239,12 +158,10 @@ public class WebSocketExtendedTest { .join(); ws.sendText(expected, true).join(); ws.abort(); - ByteBuffer data = server.read(); - List frames = readFrames(data); - + List frames = server.readFrames(); int maxBytes = (int) StandardCharsets.UTF_8.newEncoder().maxBytesPerChar() * expected.length(); ByteBuffer actual = ByteBuffer.allocate(maxBytes); - frames.stream().forEachOrdered(f -> actual.put(f.data)); + frames.stream().forEachOrdered(f -> actual.put(f.data())); actual.flip(); assertEquals(StandardCharsets.UTF_8.decode(actual).toString(), expected); } diff --git a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java index 35270203773..7eb892f12ea 100644 --- a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java +++ b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java @@ -30,7 +30,7 @@ import java.security.SecureRandom; import java.util.stream.IntStream; import static org.testng.Assert.assertEquals; -import static jdk.internal.net.http.websocket.Frame.Masker.transferMasking; +import static jdk.internal.net.http.websocket.Frame.Masker.applyMask; import static jdk.internal.net.http.websocket.TestSupport.forEachBufferPartition; import static jdk.internal.net.http.websocket.TestSupport.fullCopy; @@ -46,7 +46,7 @@ public class MaskerTest { ByteBuffer src = createSourceBuffer(r); ByteBuffer dst = createDestinationBuffer(r); verify(src, dst, maskArray(m), 0, - () -> transferMasking(src, dst, m)); + () -> applyMask(src, dst, m)); }); } @@ -67,11 +67,11 @@ public class MaskerTest { forEachBufferPartition(src, buffers -> { int offset = 0; - masker.mask(mask); + masker.setMask(mask); int[] maskBytes = maskArray(mask); for (ByteBuffer s : buffers) { offset = verify(s, dst, maskBytes, offset, - () -> masker.transferMasking(s, dst)); + () -> masker.applyMask(s, dst)); } }); } @@ -79,11 +79,11 @@ public class MaskerTest { @Test public void stateful1() { int m = random.nextInt(); - masker.mask(m); + masker.setMask(m); ByteBuffer src = ByteBuffer.allocate(0); ByteBuffer dst = ByteBuffer.allocate(16); verify(src, dst, maskArray(m), 0, - () -> masker.transferMasking(src, dst)); + () -> masker.applyMask(src, dst)); } private static int verify(ByteBuffer src, From 9e7763d44274ad1ac633120553d5c67f494bf3ef Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Mon, 14 Apr 2025 19:27:16 +0000 Subject: [PATCH 170/843] 8354536: Problem-list java/util/logging/LoggingDeadlock5.java due to JDK-8354424 Reviewed-by: smarks --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index b85e5bb21db..4ff6ea1fe74 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -727,6 +727,7 @@ com/sun/jdi/InvokeHangTest.java 8218463 linux-al # jdk_util java/util/zip/CloseInflaterDeflaterTest.java 8339216 linux-s390x +java/util/logging/LoggingDeadlock5.java 8354424 generic-all ############################################################################ From 5280b7b031bb3dc44fb923c3be7ae04ec22fd364 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Mon, 14 Apr 2025 22:07:26 +0000 Subject: [PATCH 171/843] 8353592: Open source several scrollbar tests Reviewed-by: psadhukhan, honkar --- .../java/awt/Scrollbar/ListScrollbarTest.java | 139 ++++++++++++++++++ .../awt/Scrollbar/ScrollbarCtrlClickTest.java | 114 ++++++++++++++ .../java/awt/Scrollbar/UnitIncrementTest.java | 129 ++++++++++++++++ 3 files changed, 382 insertions(+) create mode 100644 test/jdk/java/awt/Scrollbar/ListScrollbarTest.java create mode 100644 test/jdk/java/awt/Scrollbar/ScrollbarCtrlClickTest.java create mode 100644 test/jdk/java/awt/Scrollbar/UnitIncrementTest.java diff --git a/test/jdk/java/awt/Scrollbar/ListScrollbarTest.java b/test/jdk/java/awt/Scrollbar/ListScrollbarTest.java new file mode 100644 index 00000000000..fb441fe44ba --- /dev/null +++ b/test/jdk/java/awt/Scrollbar/ListScrollbarTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4029465 + * @summary Win95 Multiselect List doesn't display scrollbar + * @key headful + * @run main ListScrollbarTest + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.List; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; + +public class ListScrollbarTest { + + private static final Color BG_COLOR = Color.RED; + private static Robot robot; + private static Frame frame; + private static List list; + private static int counter = 0; + private static volatile Rectangle listBounds; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ListScrollbarTest::createAndShowUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + EventQueue.invokeAndWait(() -> { + Point locationOnScreen = list.getLocationOnScreen(); + Dimension size = list.getSize(); + listBounds = new Rectangle(locationOnScreen, size); + }); + + Point point = new Point(listBounds.x + listBounds.width - 5, + listBounds.y + listBounds.height / 2); + + + for (int i = 0; i < 4; i++) { + scrollbarCheck(point, false); + addListItem(); + } + scrollbarCheck(point, true); + } + + public static boolean areColorsSimilar(Color c1, Color c2, int tolerance) { + return Math.abs(c1.getRed() - c2.getRed()) <= tolerance + && Math.abs(c1.getGreen() - c2.getGreen()) <= tolerance + && Math.abs(c1.getBlue() - c2.getBlue()) <= tolerance; + } + + private static void scrollbarCheck(Point point, boolean isScrollbarExpected) { + Color pixelColor = robot.getPixelColor(point.x, point.y); + boolean areColorsSimilar = areColorsSimilar(BG_COLOR, pixelColor, 5); + + if (isScrollbarExpected && areColorsSimilar) { + throw new RuntimeException((""" + Scrollbar is expected, but pixel color \ + is similar to the background color + %s pixel color + %s bg color""") + .formatted(pixelColor, BG_COLOR)); + } + + if (!isScrollbarExpected && !areColorsSimilar) { + throw new RuntimeException((""" + Scrollbar is not expected, but pixel color \ + is not similar to the background color + %s pixel color + %s bg color""") + .formatted(pixelColor, BG_COLOR)); + } + } + + private static void addListItem() throws Exception { + EventQueue.invokeAndWait(() -> { + counter++; + System.out.println("Adding list item " + counter); + list.add("List Item " + counter); + frame.validate(); + }); + robot.waitForIdle(); + robot.delay(150); + } + + private static void createAndShowUI() { + frame = new Frame("ListScrollbarTest"); + list = new List(3, true); + list.setBackground(BG_COLOR); + + // do not draw border around items, it can affect screen capture + list.setFocusable(false); + + frame.add(list); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/java/awt/Scrollbar/ScrollbarCtrlClickTest.java b/test/jdk/java/awt/Scrollbar/ScrollbarCtrlClickTest.java new file mode 100644 index 00000000000..3b5a24008fd --- /dev/null +++ b/test/jdk/java/awt/Scrollbar/ScrollbarCtrlClickTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4075950 + * @summary Test for functionality of Control Click on Scrollbar + * @key headful + * @run main ScrollbarCtrlClickTest + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class ScrollbarCtrlClickTest { + private static Frame frame; + private static TextArea ta; + private static Scrollbar scrollbar; + private static final CountDownLatch latch = new CountDownLatch(1); + private static volatile Rectangle sbBounds; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ScrollbarCtrlClickTest::initAndShowGUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void initAndShowGUI() { + frame = new Frame("ScrollbarDimensionTest"); + ta = new TextArea("", 30, 100); + + + scrollbar = new Scrollbar(Scrollbar.VERTICAL, + 0, 10, 0, 20); + + // Just setting layout so scrollbar thumb will be big enough to use + frame.setLayout(new BorderLayout()); + frame.add("East", scrollbar); + frame.add("West", ta); + + scrollbar.addAdjustmentListener(e -> { + System.out.println(e.paramString()); + ta.append(e.paramString() + "\n"); + latch.countDown(); + }); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.setAutoDelay(25); + robot.delay(500); + + EventQueue.invokeAndWait(() -> { + Point locationOnScreen = scrollbar.getLocationOnScreen(); + Dimension size = scrollbar.getSize(); + sbBounds = new Rectangle(locationOnScreen, size); + }); + + robot.mouseMove(sbBounds.x + sbBounds.width / 2, + sbBounds.y + sbBounds.height - 50); + + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + + if (!latch.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("Timed out waiting for latch"); + } + } +} diff --git a/test/jdk/java/awt/Scrollbar/UnitIncrementTest.java b/test/jdk/java/awt/Scrollbar/UnitIncrementTest.java new file mode 100644 index 00000000000..03dba0f3a99 --- /dev/null +++ b/test/jdk/java/awt/Scrollbar/UnitIncrementTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4169461 + * @summary Test for Motif Scrollbar unit increment + * @key headful + * @run main UnitIncrementTest + */ + +import javax.swing.UIManager; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Scrollbar; +import java.awt.event.AdjustmentEvent; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +public class UnitIncrementTest { + private static Frame frame; + private static Scrollbar scrollbar; + private static final java.util.List eventsList = new ArrayList<>(); + private static final int UNIT_INCREMENT_VALUE = 5; + private static final int INCREMENTS_COUNT = 10; + private static volatile Rectangle scrollbarBounds; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + + try { + EventQueue.invokeAndWait(UnitIncrementTest::createAndShowUI); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void createAndShowUI() { + frame = new Frame("UnitIncrementTest"); + + scrollbar = new Scrollbar(Scrollbar.HORIZONTAL); + + scrollbar.setUnitIncrement(UNIT_INCREMENT_VALUE); + scrollbar.setBlockIncrement(20); + + scrollbar.addAdjustmentListener(e -> { + eventsList.add(e); + System.out.println(e); + }); + + frame.add(scrollbar); + + frame.setSize(300, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.setAutoDelay(25); + robot.delay(500); + + EventQueue.invokeAndWait(() -> { + Point locationOnScreen = scrollbar.getLocationOnScreen(); + Dimension size = scrollbar.getSize(); + scrollbarBounds = new Rectangle(locationOnScreen, size); + }); + + robot.mouseMove(scrollbarBounds.x + scrollbarBounds.width - 10, + scrollbarBounds.y + scrollbarBounds.height / 2); + + for (int i = 0; i < INCREMENTS_COUNT; i++) { + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(150); + } + + robot.waitForIdle(); + robot.delay(250); + + if (eventsList.size() != INCREMENTS_COUNT) { + throw new RuntimeException("Wrong number of events: " + eventsList.size()); + } + + int oldValue = 0; + for (AdjustmentEvent event : eventsList) { + System.out.println("\nChecking event " + event); + + int diff = event.getValue() - oldValue; + System.out.printf("diff: %d - %d = %d\n", event.getValue(), oldValue, diff); + + if (diff != UNIT_INCREMENT_VALUE) { + throw new RuntimeException("Unexpected adjustment value: %d".formatted(diff)); + } + + oldValue = event.getValue(); + } + } +} From 92e52fe1df84efd94d713afed5acd9c7281a77d7 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 15 Apr 2025 02:00:49 +0000 Subject: [PATCH 172/843] 8353946: Incorrect WINDOWS ifdef in os::build_agent_function_name Reviewed-by: kbarrett --- src/hotspot/share/runtime/os.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index cbe40ca214b..99559cee287 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -2535,7 +2535,7 @@ char* os::build_agent_function_name(const char *sym_name, const char *lib_name, if ((start = strrchr(lib_name, *os::file_separator())) != nullptr) { lib_name = ++start; } -#ifdef WINDOWS +#ifdef _WINDOWS else { // Need to check for drive prefix e.g. C:L.dll if ((start = strchr(lib_name, ':')) != nullptr) { lib_name = ++start; From c7b70a138ff592fdf1cd4f1d063103491a8aa7db Mon Sep 17 00:00:00 2001 From: "Dr Heinz M. Kabutz" Date: Tue, 15 Apr 2025 02:48:32 +0000 Subject: [PATCH 173/843] 8354111: JavaDoc states that Iterator.remove() is linear in the LinkedBlockingDeque Reviewed-by: liach, smarks --- .../classes/java/util/concurrent/LinkedBlockingDeque.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 7c112eb8008..8d0bc7ccdde 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -61,8 +61,8 @@ import java.util.function.Predicate; * blocking). Exceptions include {@link #remove(Object) remove}, * {@link #removeFirstOccurrence removeFirstOccurrence}, {@link * #removeLastOccurrence removeLastOccurrence}, {@link #contains - * contains}, {@link #iterator iterator.remove()}, and the bulk - * operations, all of which run in linear time. + * contains}, and the bulk operations, all of which run in linear + * time. * *

This class and its iterator implement all of the optional * methods of the {@link Collection} and {@link Iterator} interfaces. From 76ff97811abf5a4eaede6303e25ff9582302e436 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 15 Apr 2025 05:11:40 +0000 Subject: [PATCH 174/843] 8354510: Skipped gtest cause test failure Reviewed-by: rehn, erikj --- make/RunTests.gmk | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 7aa0082e0ae..80c1ff99b2e 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -534,22 +534,21 @@ define SetupRunGtestTestBody $$(eval $1_PASSED := $$(shell $$(AWK) '/\[ PASSED \] .* tests?./ \ { print $$$$4 }' $$($1_RESULT_FILE))) \ $$(if $$($1_PASSED), , $$(eval $1_PASSED := 0)) \ - $$(eval $1_SKIPPED := $$(shell $$(AWK) \ - '/YOU HAVE [0-9]+ DISABLED TEST/ { \ - if (match($$$$0, /[0-9]+/, arr)) { \ - print arr[0]; \ - found=1; \ - } \ - } \ - END { if (!found) print 0; }' \ - $$($1_RESULT_FILE))) \ + $$(eval $1_GTEST_DISABLED := $$(shell $$(AWK) '/YOU HAVE .* DISABLED TEST/ \ + { print $$$$3 }' $$($1_RESULT_FILE))) \ + $$(if $$($1_GTEST_DISABLED), , $$(eval $1_GTEST_DISABLED := 0)) \ + $$(eval $1_GTEST_SKIPPED := $$(shell $$(AWK) '/\[ SKIPPED \] .* tests?.*/ \ + { print $$$$4 }' $$($1_RESULT_FILE))) \ + $$(if $$($1_GTEST_SKIPPED), , $$(eval $1_GTEST_SKIPPED := 0)) \ + $$(eval $1_SKIPPED := $$(shell \ + $$(EXPR) $$($1_GTEST_DISABLED) + $$($1_GTEST_SKIPPED))) \ $$(eval $1_FAILED := $$(shell $$(AWK) '/\[ FAILED \] .* tests?, \ listed below/ { print $$$$4 }' $$($1_RESULT_FILE))) \ $$(if $$($1_FAILED), , $$(eval $1_FAILED := 0)) \ $$(eval $1_ERROR := $$(shell \ - $$(EXPR) $$($1_RUN) - $$($1_PASSED) - $$($1_FAILED))) \ + $$(EXPR) $$($1_RUN) - $$($1_PASSED) - $$($1_FAILED) - $$($1_GTEST_SKIPPED))) \ $$(eval $1_TOTAL := $$(shell \ - $$(EXPR) $$($1_RUN) + $$($1_SKIPPED))) \ + $$(EXPR) $$($1_RUN) + $$($1_GTEST_DISABLED))) \ , \ $$(eval $1_PASSED := 0) \ $$(eval $1_FAILED := 0) \ From 3090e2187c2cbbbc08f27305d152664a83736dfa Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 15 Apr 2025 06:03:50 +0000 Subject: [PATCH 175/843] 8353572: x86: AMD platforms miss the check for CLWB feature flag Reviewed-by: vlivanov, kvn --- src/hotspot/cpu/x86/vm_version_x86.cpp | 38 ++++++++++---------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index f7c9ebef3ef..32e6e33d133 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -3062,6 +3062,10 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const { result |= CPU_TSCINV_BIT; if (std_cpuid1_ecx.bits.aes != 0) result |= CPU_AES; + if (ext_cpuid1_ecx.bits.lzcnt != 0) + result |= CPU_LZCNT; + if (ext_cpuid1_ecx.bits.prefetchw != 0) + result |= CPU_3DNOW_PREFETCH; if (sef_cpuid7_ebx.bits.erms != 0) result |= CPU_ERMS; if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0) @@ -3080,48 +3084,36 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const { result |= CPU_FMA; if (sef_cpuid7_ebx.bits.clflushopt != 0) result |= CPU_FLUSHOPT; + if (sef_cpuid7_ebx.bits.clwb != 0) + result |= CPU_CLWB; if (ext_cpuid1_edx.bits.rdtscp != 0) result |= CPU_RDTSCP; if (sef_cpuid7_ecx.bits.rdpid != 0) result |= CPU_RDPID; - // AMD|Hygon features. + // AMD|Hygon additional features. if (is_amd_family()) { - if ((ext_cpuid1_edx.bits.tdnow != 0) || - (ext_cpuid1_ecx.bits.prefetchw != 0)) + // PREFETCHW was checked above, check TDNOW here. + if ((ext_cpuid1_edx.bits.tdnow != 0)) result |= CPU_3DNOW_PREFETCH; - if (ext_cpuid1_ecx.bits.lzcnt != 0) - result |= CPU_LZCNT; if (ext_cpuid1_ecx.bits.sse4a != 0) result |= CPU_SSE4A; } - // Intel features. + // Intel additional features. if (is_intel()) { - if (ext_cpuid1_ecx.bits.lzcnt != 0) { - result |= CPU_LZCNT; - } - if (ext_cpuid1_ecx.bits.prefetchw != 0) { - result |= CPU_3DNOW_PREFETCH; - } - if (sef_cpuid7_ebx.bits.clwb != 0) { - result |= CPU_CLWB; - } if (sef_cpuid7_edx.bits.serialize != 0) result |= CPU_SERIALIZE; - if (_cpuid_info.sef_cpuid7_edx.bits.avx512_fp16 != 0) result |= CPU_AVX512_FP16; } - // ZX features. + // ZX additional features. if (is_zx()) { - if (ext_cpuid1_ecx.bits.lzcnt != 0) { - result |= CPU_LZCNT; - } - if (ext_cpuid1_ecx.bits.prefetchw != 0) { - result |= CPU_3DNOW_PREFETCH; - } + // We do not know if these are supported by ZX, so we cannot trust + // common CPUID bit for them. + assert((result & CPU_CLWB) == 0, "Check if it is supported?"); + result &= ~CPU_CLWB; } // Protection key features. From b78378437cf911a527331e6aaf36f968169c0574 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 15 Apr 2025 08:41:37 +0000 Subject: [PATCH 176/843] 8354163: Open source Swing tests Batch 1 Reviewed-by: psadhukhan --- .../swing/AbstractButton/bug4133768.java | 162 +++++++++++++++++ .../swing/AbstractButton/bug4391622.java | 142 +++++++++++++++ test/jdk/javax/swing/JList/bug4183379.java | 85 +++++++++ test/jdk/javax/swing/JList/bug4251306.java | 115 ++++++++++++ test/jdk/javax/swing/JMenu/bug4624845.java | 164 ++++++++++++++++++ 5 files changed, 668 insertions(+) create mode 100644 test/jdk/javax/swing/AbstractButton/bug4133768.java create mode 100644 test/jdk/javax/swing/AbstractButton/bug4391622.java create mode 100644 test/jdk/javax/swing/JList/bug4183379.java create mode 100644 test/jdk/javax/swing/JList/bug4251306.java create mode 100644 test/jdk/javax/swing/JMenu/bug4624845.java diff --git a/test/jdk/javax/swing/AbstractButton/bug4133768.java b/test/jdk/javax/swing/AbstractButton/bug4133768.java new file mode 100644 index 00000000000..ad5f56c0149 --- /dev/null +++ b/test/jdk/javax/swing/AbstractButton/bug4133768.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4133768 4363569 + * @summary Tests how button displays its icons + * @key headful + * @run main bug4133768 + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.io.IOException; +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JToggleButton; +import javax.swing.SwingUtilities; + +public class bug4133768 { + private static Icon RED, GREEN; + private static JFrame f; + private static AbstractButton[] buttons; + private static volatile Point buttonLocation; + private static volatile int buttonWidth; + private static volatile int buttonHeight; + private static Robot robot; + + public static void main(String[] args) throws Exception { + try { + createTestImages(); + createUI(); + robot = new Robot(); + robot.delay(1000); + for (AbstractButton b : buttons) { + testEnabledButton(b); + } + for (AbstractButton b : buttons) { + b.setEnabled(false); + robot.delay(1000); + testDisabledButton(b); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void createTestImages() throws IOException { + int imageWidth = 32; + int imageHeight = 32; + BufferedImage redImg = new BufferedImage(imageWidth, imageHeight, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = redImg.createGraphics(); + g.setColor(Color.RED); + g.fillRect(0, 0, imageWidth, imageHeight); + g.dispose(); + RED = new ImageIcon(redImg); + BufferedImage greenImg = new BufferedImage(imageWidth, imageHeight, + BufferedImage.TYPE_INT_RGB); + g = greenImg.createGraphics(); + g.setColor(Color.GREEN); + g.fillRect(0, 0, imageWidth, imageHeight); + g.dispose(); + GREEN = new ImageIcon(greenImg); + } + + private static void createUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("ButtonIconsTest"); + buttons = new AbstractButton[] { + new JToggleButton(), + new JRadioButton(), + new JCheckBox() + }; + + JPanel buttonPanel = new JPanel(); + for (int i = 0; i < buttons.length; i++) { + AbstractButton b = buttons[i]; + b.setIcon(RED); + b.setSelected(true); + b.setRolloverSelectedIcon(GREEN); + buttonPanel.add(b); + } + f.setLayout(new GridLayout(2, 1)); + f.add(buttonPanel); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + } + + private static void testEnabledButton(AbstractButton button) throws Exception { + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + buttonLocation = button.getLocationOnScreen(); + buttonWidth = button.getWidth(); + buttonHeight = button.getHeight(); + }); + robot.mouseMove(buttonLocation.x + buttonWidth / 2, + buttonLocation.y + buttonHeight / 2 ); + robot.delay(1000); + Color buttonColor = robot.getPixelColor(buttonLocation.x + + buttonWidth / 2, buttonLocation.y + buttonHeight / 2); + if (!buttonColor.equals(Color.GREEN)) { + throw new RuntimeException("Button roll over color is : " + + buttonColor + " but it should be : " + Color.GREEN); + } + } + + private static void testDisabledButton(AbstractButton button) throws Exception { + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + buttonLocation = button.getLocationOnScreen(); + buttonWidth = button.getWidth(); + buttonHeight = button.getHeight(); + }); + robot.mouseMove(buttonLocation.x + buttonWidth / 2, + buttonLocation.y + buttonHeight / 2 ); + robot.delay(1000); + Color buttonColor = robot.getPixelColor(buttonLocation.x + + buttonWidth / 2, buttonLocation.y + buttonHeight / 2); + if (buttonColor.equals(Color.GREEN) || + buttonColor.equals(Color.RED)) { + throw new RuntimeException("Disabled button color should not be : " + + buttonColor); + } + } +} diff --git a/test/jdk/javax/swing/AbstractButton/bug4391622.java b/test/jdk/javax/swing/AbstractButton/bug4391622.java new file mode 100644 index 00000000000..7d3e8588f17 --- /dev/null +++ b/test/jdk/javax/swing/AbstractButton/bug4391622.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.image.BufferedImage; +import java.io.IOException; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4391622 + * @summary The toolbar's button which is added as action should ignore text + * @key headful + * @run main bug4391622 + */ + +public class bug4391622 { + private static Icon RED, GREEN; + private static JButton bt; + private static JFrame f; + private static volatile Point buttonLocation; + private static volatile int buttonWidth; + private static volatile int buttonHeight; + + public static void main(String[] args) throws Exception { + try { + createTestImages(); + createUI(); + runTest(); + verifyTest(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void createTestImages() throws IOException { + int imageWidth = 32; + int imageHeight = 32; + BufferedImage redImg = new BufferedImage(imageWidth, imageHeight, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = redImg.createGraphics(); + g.setColor(Color.RED); + g.fillRect(0, 0, imageWidth, imageHeight); + g.dispose(); + RED = new ImageIcon(redImg); + BufferedImage greenImg = new BufferedImage(imageWidth, imageHeight, + BufferedImage.TYPE_INT_RGB); + g = greenImg.createGraphics(); + g.setColor(Color.GREEN); + g.fillRect(0, 0, imageWidth, imageHeight); + g.dispose(); + GREEN = new ImageIcon(greenImg); + } + + private static void createUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4391622"); + Action changeIt = new ChangeIt(); + + JToolBar toolbar = new JToolBar(); + bt = toolbar.add(changeIt); + f.add(bt); + f.pack(); + f.setLocationRelativeTo(null); + f.setVisible(true); + }); + } + + private static void runTest() throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(500); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + buttonLocation = bt.getLocationOnScreen(); + buttonWidth = bt.getWidth(); + buttonHeight = bt.getHeight(); + }); + robot.mouseMove(buttonLocation.x + buttonWidth / 2, + buttonLocation.y + buttonHeight / 2 ); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + } + + private static void verifyTest() { + if (bt.getText() != null) { + throw new RuntimeException("The toolbar's button shouldn't" + + " have any text."); + } + } + + public static class ChangeIt extends AbstractAction { + private boolean c = true; + + public ChangeIt() { + putValue(Action.NAME, "Red"); + putValue(Action.SMALL_ICON, RED); + } + + public void actionPerformed(ActionEvent event) { + c = !c; + putValue(Action.NAME, c ? "Red" : "Green"); + putValue(Action.SMALL_ICON, c ? RED : GREEN); + } + } +} diff --git a/test/jdk/javax/swing/JList/bug4183379.java b/test/jdk/javax/swing/JList/bug4183379.java new file mode 100644 index 00000000000..784b92a6f16 --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4183379.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4183379 + * @summary JList has wrong scrolling behavior when you click in the "troth" + * of a scrollbar, in a scrollpane. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4183379 + */ + +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; + +public class bug4183379 { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + Click mouse several times in the "troth" of a scrollbars + in a scrollpane containing a list. + The list should scrolls by one block, i.e.: + + For vertical scrolling: + - if scrolling down the last visible element should become the + first completely visible element + - if scrolling up, the first visible element should become the + last completely visible element + + For horizontal scrolling: + - for scrolling left if the beginning of the first column is not + visible it should become visible, otherwise the beginning of the + previous column should become visible; + - for scrolling right the next colunm after first visible column + should become visible. + """; + PassFailJFrame.builder() + .title("bug4183379 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4183379::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JFrame fr = new JFrame("bug4183379"); + + String[] data = new String[90]; + for (int i=0; i<90; i++) { + data[i] = "item number "+i; + } + + JList lst = new JList(data); + lst.setLayoutOrientation(JList.VERTICAL_WRAP); + lst.setVisibleRowCount(20); + + JScrollPane jsp = new JScrollPane(lst); + fr.add(jsp); + fr.setSize(210,200); + fr.setAlwaysOnTop(true); + return fr; + } +} diff --git a/test/jdk/javax/swing/JList/bug4251306.java b/test/jdk/javax/swing/JList/bug4251306.java new file mode 100644 index 00000000000..ec530946088 --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4251306.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4251306 + * @summary Test that Shift-Space keybinding works properly in JList. + * @key headful + * @run main bug4251306 + */ + +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + +public class bug4251306 { + private static JFrame f; + private static JList lst; + private static CountDownLatch listGainedFocusLatch; + private static volatile boolean failed; + public static void main(String[] args) throws Exception { + try { + listGainedFocusLatch = new CountDownLatch(1); + createUI(); + runTest(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void createUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4251306"); + lst = new JList<>(new String[]{"anaheim", "bill", + "chicago", "dingo"}); + lst.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + listGainedFocusLatch.countDown(); + } + }); + JScrollPane sp = new JScrollPane(lst); + f.add(sp); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + } + + private static void runTest() throws Exception { + if (!listGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't gain focus for list"); + } + Robot robot = new Robot(); + robot.setAutoDelay(500); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SHIFT); + + SwingUtilities.invokeAndWait(() -> { + if (!lst.isSelectedIndex(0) || + !lst.isSelectedIndex(1) || + !lst.isSelectedIndex(2) || + !lst.isSelectedIndex(3)) { + failed = true; + } + }); + if (failed) { + throw new RuntimeException("Required list items are not selected"); + } + } +} diff --git a/test/jdk/javax/swing/JMenu/bug4624845.java b/test/jdk/javax/swing/JMenu/bug4624845.java new file mode 100644 index 00000000000..54524b7a42e --- /dev/null +++ b/test/jdk/javax/swing/JMenu/bug4624845.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4624845 + * @requires (os.family == "windows") + * @summary Tests how submenus in WinLAF are painted + * @key headful + * @run main bug4624845 + */ + +import java.awt.Color; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4624845 { + private static JFrame f; + private static JMenu menu, subMenu; + private static JMenuItem menuItem; + private static volatile Point menuLocation; + private static volatile Point subMenuLocation; + private static volatile Point menuItemLocation; + private static volatile int menuWidth; + private static volatile int menuHeight; + private static volatile int subMenuWidth; + private static volatile int subMenuHeight; + private static volatile int menuItemWidth; + private static volatile int menuItemHeight; + private static Color menuItemColor; + private static Color subMenuColor; + private static boolean passed; + private final static int OFFSET = 2; + private static final int COLOR_TOLERANCE = 10; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel + ("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("Failed to set Windows LAF"); + } + try { + bug4624845 test = new bug4624845(); + SwingUtilities.invokeAndWait(() -> test.createUI()); + runTest(); + verifyColor(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + if (!passed) { + throw new RuntimeException("Nested MenuItem color : " + + menuItemColor + " is not similar to sub Menu color : " + + subMenuColor); + } + } + private void createUI() { + f = new JFrame("bug4624845"); + menu = new JMenu("Menu"); + menu.add(new JMenuItem("Item 1")); + + subMenu = new JMenu("Submenu"); + menuItem = new JMenuItem("This"); + subMenu.add(menuItem); + subMenu.add(new JMenuItem("That")); + menu.add(subMenu); + + JMenuBar mBar = new JMenuBar(); + mBar.add(menu); + f.add(mBar); + f.pack(); + f.setLocationRelativeTo(null); + f.setVisible(true); + } + + private static void runTest() throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(200); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + menuLocation = menu.getLocationOnScreen(); + menuWidth = menu.getWidth(); + menuHeight = menu.getHeight(); + }); + robot.mouseMove(menuLocation.x + menuWidth / 2, + menuLocation.y + menuHeight / 2 ); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + subMenuLocation = subMenu.getLocationOnScreen(); + subMenuWidth = subMenu.getWidth(); + subMenuHeight = subMenu.getHeight(); + }); + robot.mouseMove(subMenuLocation.x + subMenuWidth / 2, + subMenuLocation.y + subMenuHeight / 2 ); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + subMenuColor = robot. + getPixelColor(subMenuLocation.x + OFFSET, + subMenuLocation.y + OFFSET); + SwingUtilities.invokeAndWait(() -> { + menuItemLocation = menuItem.getLocationOnScreen(); + menuItemWidth = subMenu.getWidth(); + menuItemHeight = subMenu.getHeight(); + }); + robot.mouseMove(menuItemLocation.x + menuItemWidth / 2, + menuItemLocation.y + menuItemHeight / 2 ); + robot.waitForIdle(); + menuItemColor = robot. + getPixelColor(menuItemLocation.x + OFFSET, + menuItemLocation.y + OFFSET); + } + + private static void verifyColor() { + + int red1 = subMenuColor.getRed(); + int blue1 = subMenuColor.getBlue(); + int green1 = subMenuColor.getGreen(); + + int red2 = menuItemColor.getRed(); + int blue2 = menuItemColor.getBlue(); + int green2 = menuItemColor.getGreen(); + + passed = true; + if ((Math.abs(red1 - red2) > COLOR_TOLERANCE) + || (Math.abs(green1 - green2) > COLOR_TOLERANCE) + || (Math.abs(blue1 - blue2) > COLOR_TOLERANCE)) { + passed = false; + } + } +} From 24be888d655a5227cfb9fc22f36d6ba30d732b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Lund=C3=A9n?= Date: Tue, 15 Apr 2025 08:58:02 +0000 Subject: [PATCH 177/843] 8351833: Unexpected increase in live nodes when splitting Phis through MergeMems in PhiNode::Ideal Reviewed-by: chagedorn, rcastanedalo, kvn --- src/hotspot/share/opto/cfgnode.cpp | 20 ++---- src/hotspot/share/opto/phaseX.cpp | 20 +++++- test/hotspot/jtreg/TEST.groups | 1 + .../igvn/TestSplitPhiThroughMergeMem.java | 70 +++++++++++++++++++ 4 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/igvn/TestSplitPhiThroughMergeMem.java diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 4cf080a2e19..5bf0d6facc1 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2530,11 +2530,9 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { // MergeMem(Phi(...m0...), Phi:AT1(...m1...), Phi:AT2(...m2...)) PhaseIterGVN* igvn = phase->is_IterGVN(); assert(igvn != nullptr, "sanity check"); - Node* hook = new Node(1); PhiNode* new_base = (PhiNode*) clone(); // Must eagerly register phis, since they participate in loops. igvn->register_new_node_with_optimizer(new_base); - hook->add_req(new_base); MergeMemNode* result = MergeMemNode::make(new_base); for (uint i = 1; i < req(); ++i) { @@ -2548,7 +2546,6 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* new_phi = new_base->slice_memory(mms.adr_type(phase->C)); made_new_phi = true; igvn->register_new_node_with_optimizer(new_phi); - hook->add_req(new_phi); mms.set_memory(new_phi); } Node* phi = mms.memory(); @@ -2566,19 +2563,12 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { } } } - // Already replace this phi node to cut it off from the graph to not interfere in dead loop checks during the - // transformations of the new phi nodes below. Otherwise, we could wrongly conclude that there is no dead loop - // because we are finding this phi node again. Also set the type of the new MergeMem node in case we are also - // visiting it in the transformations below. - igvn->replace_node(this, result); - igvn->set_type(result, result->bottom_type()); - // now transform the new nodes, and return the mergemem - for (MergeMemStream mms(result); mms.next_non_empty(); ) { - Node* phi = mms.memory(); - mms.set_memory(phase->transform(phi)); - } - hook->destruct(igvn); + // We could immediately transform the new Phi nodes here, but that can + // result in creating an excessive number of new nodes within a single + // IGVN iteration. We have put the Phi nodes on the IGVN worklist, so + // they are transformed later on in any case. + // Replace self with the result. return result; } diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 90bc9231873..f0c8f9d7649 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1024,11 +1024,18 @@ void PhaseIterGVN::optimize() { shuffle_worklist(); } + // The node count check in the loop below (check_node_count) assumes that we + // increase the live node count with at most + // max_live_nodes_increase_per_iteration in between checks. If this + // assumption does not hold, there is a risk that we exceed the max node + // limit in between checks and trigger an assert during node creation. + const int max_live_nodes_increase_per_iteration = NodeLimitFudgeFactor * 2; + uint loop_count = 0; // Pull from worklist and transform the node. If the node has changed, // update edge info and put uses on worklist. - while(_worklist.size()) { - if (C->check_node_count(NodeLimitFudgeFactor * 2, "Out of nodes")) { + while (_worklist.size() > 0) { + if (C->check_node_count(max_live_nodes_increase_per_iteration, "Out of nodes")) { C->print_method(PHASE_AFTER_ITER_GVN, 3); return; } @@ -1043,7 +1050,16 @@ void PhaseIterGVN::optimize() { if (n->outcnt() != 0) { NOT_PRODUCT(const Type* oldtype = type_or_null(n)); // Do the transformation + DEBUG_ONLY(int live_nodes_before = C->live_nodes();) Node* nn = transform_old(n); + DEBUG_ONLY(int live_nodes_after = C->live_nodes();) + // Ensure we did not increase the live node count with more than + // max_live_nodes_increase_per_iteration during the call to transform_old + DEBUG_ONLY(int increase = live_nodes_after - live_nodes_before;) + assert(increase < max_live_nodes_increase_per_iteration, + "excessive live node increase in single iteration of IGVN: %d " + "(should be at most %d)", + increase, max_live_nodes_increase_per_iteration); NOT_PRODUCT(trace_PhaseIterGVN(n, nn, oldtype);) } else if (!n->is_top()) { remove_dead_node(n); diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index eb80d74e5f0..4624d74f557 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -185,6 +185,7 @@ tier1_compiler_2 = \ compiler/integerArithmetic/ \ compiler/interpreter/ \ compiler/jvmci/ \ + compiler/igvn/ \ -compiler/classUnloading/methodUnloading/TestOverloadCompileQueues.java \ -compiler/codecache/stress \ -compiler/codegen/aes \ diff --git a/test/hotspot/jtreg/compiler/igvn/TestSplitPhiThroughMergeMem.java b/test/hotspot/jtreg/compiler/igvn/TestSplitPhiThroughMergeMem.java new file mode 100644 index 00000000000..5c999dd61c2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/TestSplitPhiThroughMergeMem.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8351833 + * @summary Splitting Phi memory nodes through MergeMem nodes in PhiNode::Ideal + * could sometimes result in a too large number of added nodes within + * a single iteration of the main loop in PhaseIterGVN::optimize. This + * test, reduced from TestScalarReplacementMaxLiveNodes, triggers an + * assert added as part of the fix for the linked bug/issue (the + * assert naturally triggers only before the fix). The test's ability + * to trigger the issue is quite sensitive to the specific String + * constants used. The current set of chosen String constants happened + * to work particularly well. + * @run main/othervm -Xbatch + * -XX:CompileCommand=CompileOnly,compiler.igvn.TestSplitPhiThroughMergeMem::test + * compiler.igvn.TestSplitPhiThroughMergeMem + * @run main compiler.igvn.TestSplitPhiThroughMergeMem + */ + +package compiler.igvn; + +public class TestSplitPhiThroughMergeMem { + + public static void main(String[] args) { + for (int i = 0; i < 10_000; i++) { + int val = i % 50; + test(val == 0, val % 10, val % 20); + } + } + + static void test(boolean flag, int param1, int param2) { + if (flag) { + new String("tenth" + param1); + new String("eleventh" + param2); + new String("fifteenth" + param2); + new String("sixteenth" + param1); + new String("seventeenth" + param1); + new String("nineteenth" + param2); + new String("tweenth" + param1); + new String("nineth" + param1); + new String("nineth" + param1); + new String("eighteenth" + param1); + new String("abcdef" + param2); + new String("ghijklmn" + param1); + new String("ghijklmn" + param1); + } + } +} From 81d4c80742305b72c73a59cf6a596b49bc68bab9 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 15 Apr 2025 09:02:41 +0000 Subject: [PATCH 178/843] 8354507: [ubsan] subnode.cpp:406:36: runtime error: negation of -9223372036854775808 cannot be represented in type 'long int' Reviewed-by: mdoerr, thartmann --- src/hotspot/share/opto/subnode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 24d1f820ffb..d1384384101 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -403,7 +403,7 @@ Node *SubLNode::Ideal(PhaseGVN *phase, bool can_reshape) { return new SubLNode(sub2, in21); } else { Node* sub2 = phase->transform(new SubLNode(in1, in21)); - Node* neg_c0 = phase->longcon(-c0); + Node* neg_c0 = phase->longcon(java_negate(c0)); return new AddLNode(sub2, neg_c0); } } From d7676c39b648bd55f72a50494432b02862a4e111 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 15 Apr 2025 09:48:11 +0000 Subject: [PATCH 179/843] 8354508: JFR: Strengthen metadata checks for labels Reviewed-by: shade --- src/hotspot/share/jfr/metadata/metadata.xml | 18 ++-- .../jfr/event/metadata/TestEventMetadata.java | 85 ++++++++++++++----- 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 2b04b433c29..644abcc324c 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -453,10 +453,10 @@ - - - - + + + + - + @@ -1007,7 +1007,7 @@ - + @@ -1030,10 +1030,10 @@ - + - - + + diff --git a/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java b/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java index e3255909fcc..78a92d9a2d9 100644 --- a/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java +++ b/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java @@ -23,6 +23,7 @@ package jdk.jfr.event.metadata; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -51,7 +52,7 @@ public class TestEventMetadata { * ---- * * Symbolic name that is used to identify an event, or a field. Referred to - * as "id" and "field" in trace.xml-files and @Name in the Java API. If it is + * as "name" in metadata.xml and @Name in the Java API. If it is * the name of an event, the name should be prefixed "jdk.", which * happens automatically for native events. * @@ -61,10 +62,10 @@ public class TestEventMetadata { * "allocationRate" for a field. Do not use "_" and don't add the word * "Event" to the event name. * - * Abbreviations should be avoided, but may be acceptable if the name - * becomes long, or if it is a well established acronym. Write whole words, - * i.e. "allocation" instead of "alloc". The name should not be a reserved - * Java keyword, i.e "void" or "class". + * Abbreviations, such as info, alloc, num, gen, conf, stat, and evac, should + * be avoided. For example, use "allocation" instead of "alloc". Acronyms should be + * avoided unless they are well-established. The name should not be a reserved + * Java keyword, such as "void" or "class". * * Label * ----- @@ -84,8 +85,8 @@ public class TestEventMetadata { * period should not be included. * * - * Do not forget to set proper units for fields, i.e "NANOS", "MILLS", - * "TICKSPAN" ,"BYETS", "PECENTAGE" etc. in native and @Timespan, @Timespan + * Do not forget to set proper units for fields, such as "NANOS", "MILLIS", + * "TICKSPAN", "BYTES", and "PERCENTAGE", in native and @Timespan, @Timespan * etc. in Java. */ public static void main(String[] args) throws Exception { @@ -161,16 +162,61 @@ public class TestEventMetadata { } private static void verifyLabel(String label) { + System.out.println("Verifying label: " + label); Asserts.assertNotEquals(label, null, "Label not allowed to be null"); - Asserts.assertTrue(label.length() > 1, "Name must be at least two characters"); - Asserts.assertTrue(label.length() < 45, "Label should not exceed 45 characters, use description to explain " + label); - Asserts.assertTrue(label.length() == label.trim().length(), "Label should not have trim character at start and end"); - Asserts.assertTrue(Character.isUpperCase(label.charAt(0)), "Label should start with upper case letter"); - for (int i = 0; i < label.length(); i++) { - char c = label.charAt(i); - Asserts.assertTrue(Character.isDigit(c) || Character.isAlphabetic(label.charAt(i)) || c == ' ' || c == '(' || c == ')' || c == '-', "Label should only consist of letters or space, found '" + label.charAt(i) - + "'"); + Asserts.assertTrue(label.length() > 1, "Label must be at least two characters"); + Asserts.assertTrue(label.length() <= 45, "Label should not exceed 45 characters, use description to explain"); + Asserts.assertTrue(label.length() == label.trim().length(), "Label should not have superfluous whitespace at start or end"); + + String[] words = label.split(" "); + String[] middleWords = words.length > 2 ? Arrays.copyOfRange(words, 1, words.length - 1) : new String[0]; + String firstWord = words[0]; + String lastWord = words[words.length - 1]; + Asserts.assertTrue(isCapitalized(firstWord), "Label should capitalize first word"); + + // The isNumeric check is a workaround so "GC Phase Pause Level 1" doesn't fail. + if (!isNumeric(lastWord)) { + Asserts.assertTrue(isCapitalized(lastWord), "Label should capitalize last word"); } + for (String word : words) { + Asserts.assertFalse(word.endsWith("-") || word.startsWith("-"), "Word in label should not start or end with hyphen"); + Asserts.assertTrue(word.length() != 0, "Label should not contain superfluous whitespace"); + if (isCapitalized(word)) { + for (String w : word.split("-")) { + Asserts.assertTrue(isCapitalized(w), "Label should capitalize all words in a hyphenated word"); + } + } + } + for (String word : middleWords) { + if (isShortCommonPreposition(word)) { + Asserts.assertFalse(isCapitalized(word), "Preposition in label should be lower case, unless first and last word"); + } + } + for (char c : label.toCharArray()) { + Asserts.assertTrue(isAllowedCharacter(c), "Label should only consist of letters, numbers, hyphens, parentheses or whitespace, found '" + c + "'"); + } + } + + private static boolean isAllowedCharacter(char c) { + return Character.isDigit(c) || Character.isAlphabetic(c) || c == ' ' || c == '(' || c == ')' || c == '-'; + } + + private static boolean isCapitalized(String word) { + String w = word.replace("(", "").replace(")", ""); + return !w.isEmpty() && Character.isUpperCase(w.charAt(0)); + } + + private static boolean isNumeric(String word) { + return word.chars().allMatch(Character::isDigit); + } + + private static boolean isShortCommonPreposition(String word) { + String[] prepositions = { "in", "on", "at", "by", "to", "of" }; + return containsWord(prepositions, word); + } + + private static boolean containsWord(String[] words, String match) { + return Arrays.asList(words).contains(match); } private static void verifyEventType(EventType eventType) { @@ -182,7 +228,7 @@ public class TestEventMetadata { String name = eventType.getName().substring(EventNames.PREFIX.length()); Asserts.assertFalse(isReservedKeyword(name),"Name must not be reserved keyword in the Java language (" + name + ")"); checkCommonAbbreviations(name); - char firstChar = name.charAt(0); + char firstChar = name.charAt(0); Asserts.assertFalse(name.contains("ID"), "'ID' should not be used in name, consider using 'Id'"); Asserts.assertTrue(Character.isAlphabetic(firstChar), "Name " + name + " must start with a character"); Asserts.assertTrue(Character.isUpperCase(firstChar), "Name " + name + " must start with upper case letter"); @@ -198,12 +244,7 @@ public class TestEventMetadata { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" }; - for (int i = 0; i < keywords.length; i++) { - if (s.equals(keywords[i])) { - return true; - } - } - return false; + return containsWord(keywords, s); } private static void checkCommonAbbreviations(String name) { From 4e24dc003c2304041b342371adf430b120a9fec8 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Tue, 15 Apr 2025 10:16:31 +0000 Subject: [PATCH 180/843] 8353185: Introduce the concept of upgradeable files in context of JEP 493 Reviewed-by: clanger, ihse, alanb --- make/modules/jdk.jlink/Java.gmk | 32 ++++ .../jdk/tools/jlink/internal/JRTArchive.java | 22 ++- .../jlink/internal/LinkableRuntimeImage.java | 47 +++++- .../runtimelink/upgrade_files_java.base.conf | 4 + .../UpgradeableFileCacertsTest.java | 153 ++++++++++++++++++ 5 files changed, 254 insertions(+), 4 deletions(-) create mode 100644 make/modules/jdk.jlink/Java.gmk create mode 100644 src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf create mode 100644 test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java diff --git a/make/modules/jdk.jlink/Java.gmk b/make/modules/jdk.jlink/Java.gmk new file mode 100644 index 00000000000..4ddd1eab03d --- /dev/null +++ b/make/modules/jdk.jlink/Java.gmk @@ -0,0 +1,32 @@ +# +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +################################################################################ + +# Instruct SetupJavaCompilation for the jdk.jlink module to include +# upgrade_files_.conf files +COPY += .conf + +################################################################################ diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java index df7d35ac777..aac220e5b94 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JRTArchive.java @@ -45,6 +45,7 @@ import java.util.HexFormat; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -76,6 +77,7 @@ public class JRTArchive implements Archive { private final Map resDiff; private final boolean errorOnModifiedFile; private final TaskHelper taskHelper; + private final Set upgradeableFiles; /** * JRTArchive constructor @@ -86,12 +88,15 @@ public class JRTArchive implements Archive { * install aborts the link. * @param perModDiff The lib/modules (a.k.a jimage) diff for this module, * possibly an empty list if there are no differences. + * @param taskHelper The task helper instance. + * @param upgradeableFiles The set of files that are allowed for upgrades. */ JRTArchive(String module, Path path, boolean errorOnModifiedFile, List perModDiff, - TaskHelper taskHelper) { + TaskHelper taskHelper, + Set upgradeableFiles) { this.module = module; this.path = path; this.ref = ModuleFinder.ofSystem() @@ -105,6 +110,7 @@ public class JRTArchive implements Archive { this.resDiff = Objects.requireNonNull(perModDiff).stream() .collect(Collectors.toMap(ResourceDiff::getName, Function.identity())); this.taskHelper = taskHelper; + this.upgradeableFiles = upgradeableFiles; } @Override @@ -217,7 +223,8 @@ public class JRTArchive implements Archive { // Read from the base JDK image. Path path = BASE.resolve(m.resPath); - if (shaSumMismatch(path, m.hashOrTarget, m.symlink)) { + if (!isUpgradeableFile(m.resPath) && + shaSumMismatch(path, m.hashOrTarget, m.symlink)) { if (errorOnModifiedFile) { String msg = taskHelper.getMessage("err.runtime.link.modified.file", path.toString()); IOException cause = new IOException(msg); @@ -239,6 +246,17 @@ public class JRTArchive implements Archive { } } + /** + * Certain files in a module are considered upgradeable. That is, + * their hash sums aren't checked. + * + * @param resPath The resource path of the file to check for upgradeability. + * @return {@code true} if the file is upgradeable. {@code false} otherwise. + */ + private boolean isUpgradeableFile(String resPath) { + return upgradeableFiles.contains(resPath); + } + static boolean shaSumMismatch(Path res, String expectedSha, boolean isSymlink) { if (isSymlink) { return false; diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java index 935af4585ad..d564ed0bad8 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/LinkableRuntimeImage.java @@ -28,7 +28,10 @@ package jdk.tools.jlink.internal; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; +import java.util.HashSet; import java.util.List; +import java.util.Scanner; +import java.util.Set; import jdk.tools.jlink.internal.runtimelink.ResourceDiff; @@ -42,6 +45,9 @@ public class LinkableRuntimeImage { public static final String RESPATH_PATTERN = "jdk/tools/jlink/internal/runtimelink/fs_%s_files"; // The diff files per module for supporting linking from the run-time image public static final String DIFF_PATTERN = "jdk/tools/jlink/internal/runtimelink/diff_%s"; + // meta data for upgradable files + private static final String UPGRADEABLE_FILES_PATTERN = "jdk/tools/jlink/internal/runtimelink/upgrade_files_%s.conf"; + private static final Module JDK_JLINK_MOD = LinkableRuntimeImage.class.getModule(); /** * In order to be able to show whether or not a runtime is capable of @@ -62,7 +68,38 @@ public class LinkableRuntimeImage { private static InputStream getDiffInputStream(String module) throws IOException { String resourceName = String.format(DIFF_PATTERN, module); - return LinkableRuntimeImage.class.getModule().getResourceAsStream(resourceName); + return JDK_JLINK_MOD.getResourceAsStream(resourceName); + } + + private static Set upgradeableFiles(String module) { + String resourceName = String.format(UPGRADEABLE_FILES_PATTERN, module); + InputStream filesIn = null; + try { + filesIn = JDK_JLINK_MOD.getResourceAsStream(resourceName); + } catch (IOException e) { + throw new AssertionError("Unexpected IO error getting res stream"); + } + if (filesIn == null) { + // no upgradeable files + return Set.of(); + } + Set upgradeableFiles = new HashSet<>(); + final InputStream in = filesIn; + try (in; + Scanner scanner = new Scanner(filesIn)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.trim().startsWith("#")) { + // Skip comments + continue; + } + upgradeableFiles.add(scanner.nextLine()); + } + } catch (IOException e) { + throw new AssertionError("Failure to retrieve upgradeable files for " + + "module " + module, e); + } + return upgradeableFiles; } public static Archive newArchive(String module, @@ -81,7 +118,13 @@ public class LinkableRuntimeImage { throw new AssertionError("Failure to retrieve resource diff for " + "module " + module, e); } - return new JRTArchive(module, path, !ignoreModifiedRuntime, perModuleDiff, taskHelper); + Set upgradeableFiles = upgradeableFiles(module); + return new JRTArchive(module, + path, + !ignoreModifiedRuntime, + perModuleDiff, + taskHelper, + upgradeableFiles); } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf new file mode 100644 index 00000000000..df2ca809f08 --- /dev/null +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/upgrade_files_java.base.conf @@ -0,0 +1,4 @@ +# Configuration for resource paths of files allowed to be +# upgraded (in java.base) +lib/tzdb.dat +lib/security/cacerts diff --git a/test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java b/test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java new file mode 100644 index 00000000000..86e0f8cefd5 --- /dev/null +++ b/test/jdk/tools/jlink/runtimeImage/UpgradeableFileCacertsTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2025, Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import jdk.test.lib.process.OutputAnalyzer; +import tests.Helper; + +/* + * @test + * @summary Verify that no errors are reported for files that have been + * upgraded when linking from the run-time image + * @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g) + * @library ../../lib /test/lib + * @modules java.base/jdk.internal.jimage + * jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jlink.plugin + * jdk.jlink/jdk.tools.jimage + * @build tests.* jdk.test.lib.process.OutputAnalyzer + * jdk.test.lib.process.ProcessTools + * @run main/othervm -Xmx1g UpgradeableFileCacertsTest + */ +public class UpgradeableFileCacertsTest extends ModifiedFilesTest { + + /* + * Generated with: + * $ rm -f server.keystore && keytool -genkey -alias jlink-upgrade-test \ + * -keyalg RSA -dname CN=jlink-upgrade-test \ + * -storepass changeit -keysize 3072 -sigalg SHA512withRSA \ + * -validity 7300 -keystore server.keystore + * $ keytool -export -alias jlink-upgrade-test -storepass changeit \ + * -keystore server.keystore -rfc + */ + private static final String CERT = """ + -----BEGIN CERTIFICATE----- + MIID3jCCAkagAwIBAgIJALiT/+HXBkSIMA0GCSqGSIb3DQEBDQUAMB0xGzAZBgNV + BAMTEmpsaW5rLXVwZ3JhZGUtdGVzdDAeFw0yNTA0MDQxMjA3MjJaFw00NTAzMzAx + MjA3MjJaMB0xGzAZBgNVBAMTEmpsaW5rLXVwZ3JhZGUtdGVzdDCCAaIwDQYJKoZI + hvcNAQEBBQADggGPADCCAYoCggGBANmrnCDKqSXEJRIiSi4yHWN97ILls3RqYjED + la3AZTeXnZrrEIgSjVFUMxCztYqbWoVzKa2lov42Vue2BXVYffcQ8TKc2EJDNO+2 + uRKQZpsN7RI4QoVBR2Rq8emrO8CrdOQT7Hh4agxkN9AOvGKMFdt+fXeCIPIuflKP + f+RfvhLfC2A70Y+Uu74C5uWgLloA/HF0SsVxf9KmqS9fZBQaiTYhKyoDghCRlWpa + nPIHB1XVaRdw8aSpCuzIOQzSCTTlLcammJkBjbFwMZdQG7eglTWzIYryZwe/cyY2 + xctLVW3xhUHvnMFG+MajeFny2mxNu163Rxf/rBu4e7jRC/LGSU784nJGapq5K170 + WbaeceKp+YORJBviFFORrmkPIwIgE+iGCD6PD6Xwu8vcpeuTVDgsSWMlfgCL3NoI + GXmdGiI2Xc/hQX7uzu3UBF6IcPDMTcYr2JKYbgu3v2/vDlJu3qO2ycUeePo5jhuG + X2WgcHkb6uOU4W5qdbCA+wFPVZBuwQIDAQABoyEwHzAdBgNVHQ4EFgQUtMJM0+ct + ssKqryRckk4YEWdYAZkwDQYJKoZIhvcNAQENBQADggGBAI8A6gJQ8wDx12sy2ZI4 + 1q9b+WG6w3LcFEF6Fko5NBizhtfmVycQv4mBa/NJgx4DZmd+5d60gJcTp/hJXGY0 + LZyFilm/AgxsLNUUQLbHAV6TWqd3ODWwswAuew9sFU6izl286a9W65tbMWL5r1EA + t34ZYVWZYbCS9+czU98WomH4uarRAOlzcEUui3ZX6ZcQxWbz/R2wtKcUPUAYnsqH + JPivpE25G5xW2Dp/yeQTrlffq9OLgZWVz0jtOguBUMnsUsgCcpQZtqZX08//wtpz + ohLHFGvpXTPbRumRasWWtnRR/QqGRT66tYDqybXXz37UtKZ8VKW0sv2ypVbmAEs5 + pLkA/3XiXlstJuCD6cW0Gfbpb5rrPPD46O3FDVlmqlTH3b/MsiQREdydqGzqY7uG + AA2GFVaKFASA5ls01CfHLAcrKxSVixditXvsjeIqhddB7Pnbsx20RdzPQoeo9/hF + WeIrh4zePDPZChuLR8ZyxeVJhLB71nTrTDDjwXarVez9Xw== + -----END CERTIFICATE----- + """; + + private static final String CERT_ALIAS = "jlink-upgrade-test"; + + public static void main(String[] args) throws Exception { + UpgradeableFileCacertsTest test = new UpgradeableFileCacertsTest(); + test.run(); + } + + @Override + String initialImageName() { + return "java-base-jlink-upgrade-cacerts"; + } + + @Override + void testAndAssert(Path modifiedFile, Helper helper, Path initialImage) throws Exception { + CapturingHandler handler = new CapturingHandler(); + jlinkUsingImage(new JlinkSpecBuilder() + .helper(helper) + .imagePath(initialImage) + .name("java-base-jlink-upgrade-cacerts-target") + .addModule("java.base") + .validatingModule("java.base") + .build(), handler); + OutputAnalyzer analyzer = handler.analyzer(); + // verify we don't get any modified warning + analyzer.stdoutShouldNotContain(modifiedFile.toString() + " has been modified"); + analyzer.stdoutShouldNotContain("java.lang.IllegalArgumentException"); + analyzer.stdoutShouldNotContain("IOException"); + } + + // Add an extra certificate in the cacerts file so that it no longer matches + // the recorded hash sum at build time. + protected Path modifyFileInImage(Path jmodLessImg) + throws IOException, AssertionError { + Path cacerts = jmodLessImg.resolve(Path.of("lib", "security", "cacerts")); + try (FileInputStream fin = new FileInputStream(cacerts.toFile())) { + KeyStore certStore = KeyStore.getInstance(cacerts.toFile(), + (char[])null); + certStore.load(fin, (char[])null); + X509Certificate cert; + try (ByteArrayInputStream bin = new ByteArrayInputStream(CERT.getBytes())) { + cert = (X509Certificate)generateCertificate(bin); + } catch (ClassCastException | CertificateException ce) { + throw new AssertionError("Test failed unexpectedly", ce); + } + certStore.setCertificateEntry(CERT_ALIAS, cert); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + certStore.store(bout, (char[])null); + try (FileOutputStream fout = new FileOutputStream(cacerts.toFile())) { + fout.write(bout.toByteArray()); + } + } catch (Exception e) { + throw new AssertionError("Test failed unexpectedly: ", e); + } + return cacerts; + } + + private Certificate generateCertificate(InputStream in) + throws CertificateException, IOException { + byte[] data = in.readAllBytes(); + return CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(data)); + } +} From 03fd43fc91ea383418c1c7e0fd96a61a1f42c75e Mon Sep 17 00:00:00 2001 From: Patrick Strawderman Date: Tue, 15 Apr 2025 11:26:36 +0000 Subject: [PATCH 181/843] 8353453: URLDecoder should use HexFormat Reviewed-by: rriggs, jpai --- src/java.base/share/classes/java/net/URLDecoder.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/net/URLDecoder.java b/src/java.base/share/classes/java/net/URLDecoder.java index 45d18c9a470..c7cdd7c4931 100644 --- a/src/java.base/share/classes/java/net/URLDecoder.java +++ b/src/java.base/share/classes/java/net/URLDecoder.java @@ -29,6 +29,7 @@ import java.io.*; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; +import java.util.HexFormat; import java.util.Objects; /** @@ -204,11 +205,7 @@ public final class URLDecoder { while ( ((i+2) < numChars) && (c=='%')) { - int v = Integer.parseInt(s, i + 1, i + 3, 16); - if (v < 0) - throw new IllegalArgumentException( - "URLDecoder: Illegal hex characters in escape " - + "(%) pattern - negative value"); + int v = HexFormat.fromHexDigits(s, i + 1, i + 3); bytes[pos++] = (byte) v; i+= 3; if (i < numChars) From 5fc18f5b8aa1b5f4fb4313b8d11fd15330795959 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Tue, 15 Apr 2025 11:41:47 +0000 Subject: [PATCH 182/843] 8350279: HttpClient: Add a new HttpResponse method to identify connections Reviewed-by: dfuchs, jpai --- .../classes/java/net/http/HttpResponse.java | 22 + .../net/http/AbstractAsyncSSLConnection.java | 5 +- .../internal/net/http/AsyncSSLConnection.java | 7 +- .../net/http/AsyncSSLTunnelConnection.java | 7 +- .../jdk/internal/net/http/HttpConnection.java | 49 +- .../internal/net/http/HttpResponseImpl.java | 16 +- .../net/http/PlainHttpConnection.java | 6 +- .../net/http/PlainProxyConnection.java | 6 +- .../net/http/PlainTunnelingConnection.java | 9 +- .../jdk/internal/net/http/SocketTube.java | 13 +- .../HttpResponseConnectionLabelTest.java | 491 ++++++++++++++++++ .../internal/net/http/ConnectionPoolTest.java | 4 +- 12 files changed, 600 insertions(+), 35 deletions(-) create mode 100644 test/jdk/java/net/httpclient/HttpResponseConnectionLabelTest.java diff --git a/src/java.net.http/share/classes/java/net/http/HttpResponse.java b/src/java.net.http/share/classes/java/net/http/HttpResponse.java index 5a274980fa3..52f5298452a 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpResponse.java +++ b/src/java.net.http/share/classes/java/net/http/HttpResponse.java @@ -99,6 +99,28 @@ public interface HttpResponse { */ public int statusCode(); + /** + * {@return if present, a label identifying the connection on which the + * response was received} + *

+ * The format of the string is opaque, but the value is fixed and unique + * for any connection in the scope of the associated {@link HttpClient} + * instance. + * + * @implSpec + * The default implementation of this method returns + * {@link Optional#empty() Optional.empty()}. + * + * @implNote + * Instances of {@code HttpResponse} returned by the JDK built-in + * implementation of {@code HttpClient} always return a non-empty value. + * + * @since 25 + */ + default Optional connectionLabel() { + return Optional.empty(); + } + /** * Returns the {@link HttpRequest} corresponding to this response. * diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java index 20f727a9932..52037ba497f 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AbstractAsyncSSLConnection.java @@ -74,8 +74,9 @@ abstract class AbstractAsyncSSLConnection extends HttpConnection AbstractAsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client, ServerName serverName, int port, - String[] alpn) { - super(addr, client); + String[] alpn, + String label) { + super(addr, client, label); this.sniServerNames = formSNIServerNames(serverName, client); SSLContext context = client.theSSLContext(); sslParameters = createSSLParameters(client, this.sniServerNames, alpn); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java index 598af68e37a..56477e9604e 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLConnection.java @@ -44,9 +44,10 @@ class AsyncSSLConnection extends AbstractAsyncSSLConnection { AsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client, - String[] alpn) { - super(addr, client, Utils.getServerName(addr), addr.getPort(), alpn); - plainConnection = new PlainHttpConnection(addr, client); + String[] alpn, + String label) { + super(addr, client, Utils.getServerName(addr), addr.getPort(), alpn, label); + plainConnection = new PlainHttpConnection(addr, client, label); writePublisher = new PlainHttpPublisher(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java index 862013cbf93..1210f4dd62b 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/AsyncSSLTunnelConnection.java @@ -47,10 +47,11 @@ class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection { HttpClientImpl client, String[] alpn, InetSocketAddress proxy, - ProxyHeaders proxyHeaders) + ProxyHeaders proxyHeaders, + String label) { - super(addr, client, Utils.getServerName(addr), addr.getPort(), alpn); - this.plainConnection = new PlainTunnelingConnection(addr, proxy, client, proxyHeaders); + super(addr, client, Utils.getServerName(addr), addr.getPort(), alpn, label); + this.plainConnection = new PlainTunnelingConnection(addr, proxy, client, proxyHeaders, label); this.writePublisher = new PlainHttpPublisher(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java index d9dd533c0f0..dd8f6652290 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ package jdk.internal.net.http; import java.io.Closeable; import java.io.IOException; import java.net.InetSocketAddress; +import java.net.http.HttpResponse; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Arrays; @@ -39,6 +40,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.Flow; +import java.util.concurrent.atomic.AtomicLong; import java.util.function.BiPredicate; import java.util.function.Predicate; import java.net.http.HttpClient; @@ -76,17 +78,46 @@ abstract class HttpConnection implements Closeable { public static final Comparator COMPARE_BY_ID = Comparator.comparing(HttpConnection::id); + private static final AtomicLong LABEL_COUNTER = new AtomicLong(); + /** The address this connection is connected to. Could be a server or a proxy. */ final InetSocketAddress address; private final HttpClientImpl client; private final TrailingOperations trailingOperations; + + /** + * A unique identifier that provides a total order among instances. + */ private final long id; - HttpConnection(InetSocketAddress address, HttpClientImpl client) { + /** + * A label to identify the connection. + *

+ * This label helps with associating multiple components participating in a + * connection. For instance, an {@link AsyncSSLConnection} and the + * {@link PlainHttpConnection} it wraps will share the same label. + *

+ */ + private final String label; + + HttpConnection(InetSocketAddress address, HttpClientImpl client, String label) { this.address = address; this.client = client; trailingOperations = new TrailingOperations(); this.id = newConnectionId(client); + this.label = label; + } + + private static String nextLabel() { + return "" + LABEL_COUNTER.incrementAndGet(); + } + + /** + * {@return a label identifying the connection to facilitate + * {@link HttpResponse#connectionLabel() HttpResponse::connectionLabel}} + */ + public final String label() { + return label; } // This is overridden in tests @@ -303,11 +334,13 @@ abstract class HttpConnection implements Closeable { String[] alpn, HttpRequestImpl request, HttpClientImpl client) { + String label = nextLabel(); if (proxy != null) return new AsyncSSLTunnelConnection(addr, client, alpn, proxy, - proxyTunnelHeaders(request)); + proxyTunnelHeaders(request), + label); else - return new AsyncSSLConnection(addr, client, alpn); + return new AsyncSSLConnection(addr, client, alpn, label); } /** @@ -381,14 +414,16 @@ abstract class HttpConnection implements Closeable { InetSocketAddress proxy, HttpRequestImpl request, HttpClientImpl client) { + String label = nextLabel(); if (request.isWebSocket() && proxy != null) return new PlainTunnelingConnection(addr, proxy, client, - proxyTunnelHeaders(request)); + proxyTunnelHeaders(request), + label); if (proxy == null) - return new PlainHttpConnection(addr, client); + return new PlainHttpConnection(addr, client, label); else - return new PlainProxyConnection(proxy, client); + return new PlainProxyConnection(proxy, client, label); } void closeOrReturnToCache(HttpHeaders hdrs) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpResponseImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpResponseImpl.java index 52d281cc04e..1552cd40ede 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpResponseImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpResponseImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ import jdk.internal.net.http.websocket.RawChannel; class HttpResponseImpl implements HttpResponse, RawChannel.Provider { final int responseCode; + private final String connectionLabel; final HttpRequest initialRequest; final Optional> previousResponse; final HttpHeaders headers; @@ -59,6 +60,7 @@ class HttpResponseImpl implements HttpResponse, RawChannel.Provider { T body, Exchange exch) { this.responseCode = response.statusCode(); + this.connectionLabel = connectionLabel(exch).orElse(null); this.initialRequest = initialRequest; this.previousResponse = Optional.ofNullable(previousResponse); this.headers = response.headers(); @@ -70,11 +72,23 @@ class HttpResponseImpl implements HttpResponse, RawChannel.Provider { this.body = body; } + private static Optional connectionLabel(Exchange exchange) { + return Optional.ofNullable(exchange) + .map(e -> e.exchImpl) + .map(ExchangeImpl::connection) + .map(HttpConnection::label); + } + @Override public int statusCode() { return responseCode; } + @Override + public Optional connectionLabel() { + return Optional.ofNullable(connectionLabel); + } + @Override public HttpRequest request() { return initialRequest; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java index 76fbebe6cd0..190df8a00ba 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java @@ -310,8 +310,8 @@ class PlainHttpConnection extends HttpConnection { return tube; } - PlainHttpConnection(InetSocketAddress addr, HttpClientImpl client) { - super(addr, client); + PlainHttpConnection(InetSocketAddress addr, HttpClientImpl client, String label) { + super(addr, client, label); try { this.chan = SocketChannel.open(); chan.configureBlocking(false); @@ -335,7 +335,7 @@ class PlainHttpConnection extends HttpConnection { } chan.setOption(StandardSocketOptions.TCP_NODELAY, true); // wrap the channel in a Tube for async reading and writing - tube = new SocketTube(client(), chan, Utils::getBuffer); + tube = new SocketTube(client(), chan, Utils::getBuffer, label); } catch (IOException e) { throw new InternalError(e); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java index 5cd9a1d9c8f..c11fd489177 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainProxyConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,8 @@ import java.net.InetSocketAddress; class PlainProxyConnection extends PlainHttpConnection { - PlainProxyConnection(InetSocketAddress proxy, HttpClientImpl client) { - super(proxy, client); + PlainProxyConnection(InetSocketAddress proxy, HttpClientImpl client, String label) { + super(proxy, client, label); } @Override diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java index 80ca6ba8a3a..7a8eb9c79c5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,11 +54,12 @@ final class PlainTunnelingConnection extends HttpConnection { protected PlainTunnelingConnection(InetSocketAddress addr, InetSocketAddress proxy, HttpClientImpl client, - ProxyHeaders proxyHeaders) { - super(addr, client); + ProxyHeaders proxyHeaders, + String label) { + super(addr, client, label); this.proxyAddr = proxy; this.proxyHeaders = proxyHeaders; - delegate = new PlainHttpConnection(proxy, client); + delegate = new PlainHttpConnection(proxy, client, label); } @Override diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java b/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java index d0e30806d53..cc083d7e066 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; @@ -59,7 +58,6 @@ import jdk.internal.net.http.common.Utils; final class SocketTube implements FlowTube { final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG); - static final AtomicLong IDS = new AtomicLong(); private final HttpClientImpl client; private final SocketChannel channel; @@ -68,14 +66,15 @@ final class SocketTube implements FlowTube { private final AtomicReference errorRef = new AtomicReference<>(); private final InternalReadPublisher readPublisher; private final InternalWriteSubscriber writeSubscriber; - private final long id = IDS.incrementAndGet(); + private final String connectionLabel; public SocketTube(HttpClientImpl client, SocketChannel channel, - Supplier buffersFactory) { + Supplier buffersFactory, + String connectionLabel) { this.client = client; this.channel = channel; this.sliceBuffersSource = new SliceBufferSource(buffersFactory); - + this.connectionLabel = connectionLabel; this.readPublisher = new InternalReadPublisher(); this.writeSubscriber = new InternalWriteSubscriber(); } @@ -1343,7 +1342,7 @@ final class SocketTube implements FlowTube { } final String dbgString() { - return "SocketTube("+id+")"; + return "SocketTube("+ connectionLabel +")"; } final String channelDescr() { diff --git a/test/jdk/java/net/httpclient/HttpResponseConnectionLabelTest.java b/test/jdk/java/net/httpclient/HttpResponseConnectionLabelTest.java new file mode 100644 index 00000000000..b6c13c51ee1 --- /dev/null +++ b/test/jdk/java/net/httpclient/HttpResponseConnectionLabelTest.java @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Verifies `HttpResponse::connectionLabel` + * @library /test/lib + * /test/jdk/java/net/httpclient/lib + * @build jdk.httpclient.test.lib.common.HttpServerAdapters + * jdk.test.lib.net.SimpleSSLContext + * + * @comment Use a higher idle timeout to increase the chances of the same connection being used for sequential HTTP requests + * @run junit/othervm -Djdk.httpclient.keepalive.timeout=120 HttpResponseConnectionLabelTest + */ + +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; +import jdk.internal.net.http.common.Logger; +import jdk.internal.net.http.common.Utils; +import jdk.test.lib.net.SimpleSSLContext; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.System.Logger.Level; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpClient.Version; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.charset.Charset; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Stream; + +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class HttpResponseConnectionLabelTest { + + private static final String CLASS_NAME = HttpResponseConnectionLabelTest.class.getSimpleName(); + + private static final Logger LOGGER = Utils.getDebugLogger(CLASS_NAME::toString, Utils.DEBUG); + + private static final Charset CHARSET = US_ASCII; + + private static final String CONNECTION_KEY_HEADER_NAME = "X-Connection-Key"; + + private static final String SERVER_ID_HEADER_NAME = "X-Server-Id"; + + private static final SSLContext SSL_CONTEXT = createSslContext(); + + // Start with a fresh client having no connections in the pool + private final HttpClient client = HttpClient.newBuilder().sslContext(SSL_CONTEXT).proxy(NO_PROXY).build(); + + // Primary server-client pairs + + private static final ServerRequestPair PRI_HTTP1 = ServerRequestPair.of(Version.HTTP_1_1, false); + + private static final ServerRequestPair PRI_HTTPS1 = ServerRequestPair.of(Version.HTTP_1_1, true); + + private static final ServerRequestPair PRI_HTTP2 = ServerRequestPair.of(Version.HTTP_2, false); + + private static final ServerRequestPair PRI_HTTPS2 = ServerRequestPair.of(Version.HTTP_2, true); + + // Secondary server-client pairs + + private static final ServerRequestPair SEC_HTTP1 = ServerRequestPair.of(Version.HTTP_1_1, false); + + private static final ServerRequestPair SEC_HTTPS1 = ServerRequestPair.of(Version.HTTP_1_1, true); + + private static final ServerRequestPair SEC_HTTP2 = ServerRequestPair.of(Version.HTTP_2, false); + + private static final ServerRequestPair SEC_HTTPS2 = ServerRequestPair.of(Version.HTTP_2, true); + + private static SSLContext createSslContext() { + try { + return new SimpleSSLContext().get(); + } catch (IOException exception) { + throw new UncheckedIOException(exception); + } + } + + private record ServerRequestPair( + HttpTestServer server, + ExecutorService executor, + HttpRequest request, + boolean secure, + AtomicReference serverResponseLatchRef) { + + private static final AtomicInteger SERVER_COUNTER = new AtomicInteger(); + + private static final AtomicInteger SERVER_RESPONSE_COUNTER = new AtomicInteger(); + + private static ServerRequestPair of(Version version, boolean secure) { + + // Create the server and the request URI + SSLContext sslContext = secure ? SSL_CONTEXT : null; + String serverId = "" + SERVER_COUNTER.getAndIncrement(); + ExecutorService[] executorRef = {null}; + HttpTestServer server = createServer(version, secure, sslContext, serverId, executorRef); + String handlerPath = "/%s/".formatted(CLASS_NAME); + String requestUriScheme = secure ? "https" : "http"; + URI requestUri = URI.create("%s://%s%sx".formatted(requestUriScheme, server.serverAuthority(), handlerPath)); + + // Register the request handler + AtomicReference serverResponseLatchRef = new AtomicReference<>(); + server.addHandler(createServerHandler(serverId, serverResponseLatchRef), handlerPath); + + // Create the client and the request + HttpRequest request = HttpRequest.newBuilder(requestUri).version(version).build(); + + // Create the pair + ServerRequestPair pair = new ServerRequestPair( + server, + executorRef[0], + request, + secure, + serverResponseLatchRef); + pair.server.start(); + LOGGER.log("Server[%s] is started at `%s`", serverId, server.serverAuthority()); + return pair; + + } + + private static HttpTestServer createServer( + Version version, + boolean secure, + SSLContext sslContext, + String serverId, + ExecutorService[] executorRef) { + try { + // Only create a dedicated executor for HTTP/1.1, because + // + // - Only the HTTP/1.1 test server gets wedged when running + // tests involving parallel request handling. + // + // - The HTTP/2 test server creates its own sufficiently sized + // executor, and the thread names used there makes it easy to + // find which server they belong to. + executorRef[0] = Version.HTTP_1_1.equals(version) + ? createExecutor(version, secure, serverId) + : null; + return HttpTestServer.create(version, sslContext, executorRef[0]); + } catch (IOException exception) { + throw new UncheckedIOException(exception); + } + } + + private static ExecutorService createExecutor(Version version, boolean secure, String serverId) { + return Executors.newThreadPerTaskExecutor(runnable -> { + String name = "%s-%s-%c-%s".formatted( + CLASS_NAME, version, secure ? 's' : 'c', serverId); + Thread thread = new Thread(runnable, name); + thread.setDaemon(true); // Avoid blocking the JVM exit + return thread; + }); + } + + private static HttpTestHandler createServerHandler( + String serverId, + AtomicReference serverResponseLatchRef) { + return (exchange) -> { + String responseBody = "" + SERVER_RESPONSE_COUNTER.getAndIncrement(); + String connectionKey = exchange.getConnectionKey(); + LOGGER.log("Server[%d] has received request (connectionKey=%s)", serverId, connectionKey); + try (exchange) { + + // Participate in the latch count down + CountDownLatch serverResponseLatch = serverResponseLatchRef.get(); + if (serverResponseLatch != null) { + serverResponseLatch.countDown(); + LOGGER.log( + "Server[%s] is waiting for the latch... (connectionKey=%s, responseBody=%s)", + serverId, connectionKey, responseBody); + serverResponseLatch.await(); + } + + // Write the response + LOGGER.log( + "Server[%s] is responding... (connectionKey=%s, responseBody=%s)", + serverId, connectionKey, responseBody); + exchange.getResponseHeaders().addHeader(CONNECTION_KEY_HEADER_NAME, connectionKey); + exchange.getResponseHeaders().addHeader(SERVER_ID_HEADER_NAME, serverId); + byte[] responseBodyBytes = responseBody.getBytes(CHARSET); + exchange.sendResponseHeaders(200, responseBodyBytes.length); + exchange.getResponseBody().write(responseBodyBytes); + + } catch (Exception exception) { + String message = "Server[%s] has failed! (connectionKey=%s, responseBody=%s)" + .formatted(serverId, connectionKey, responseBody); + LOGGER.log(Level.ERROR, message, exception); + if (exception instanceof InterruptedException) { + // Restore the interrupt + Thread.currentThread().interrupt(); + } + throw new RuntimeException(message, exception); + } + }; + } + + @Override + public String toString() { + String version = server.getVersion().toString(); + return secure ? version.replaceFirst("_", "S_") : version; + } + + } + + @AfterAll + static void closeServers() { + Exception[] exceptionRef = {null}; + Stream + .of(PRI_HTTP1, PRI_HTTPS1, PRI_HTTP2, PRI_HTTPS2, SEC_HTTP1, SEC_HTTPS1, SEC_HTTP2, SEC_HTTPS2) + .flatMap(pair -> Stream.of( + pair.server::stop, + () -> { if (pair.executor != null) { pair.executor.shutdownNow(); } })) + .forEach(terminator -> { + try { + terminator.run(); + } catch (Exception exception) { + if (exceptionRef[0] == null) { + exceptionRef[0] = exception; + } else { + exceptionRef[0].addSuppressed(exception); + } + } + }); + if (exceptionRef[0] != null) { + throw new RuntimeException("failed closing one or more server resources", exceptionRef[0]); + } + } + + @AfterEach + void closeClient() { + client.close(); + } + + static ServerRequestPair[] testParallelRequestsToSameServer() { + return new ServerRequestPair[]{ + PRI_HTTP1, + PRI_HTTPS1, + PRI_HTTP2, + PRI_HTTPS2 + }; + } + + @ParameterizedTest + @MethodSource("testParallelRequestsToSameServer") + void testParallelRequestsToSameServer(ServerRequestPair pair) throws Exception { + + // There is no implementation-agnostic reliable way to force admission + // of multiple connections targeting the same server to an HTTP/2 pool. + if (Version.HTTP_2.equals(pair.server.getVersion())) { + return; + } + + // Configure a synchronization point for 4 events: + // + // 1. client --(req1)--> server + // 2. server --(res1)--> client + // 3. client --(req2)--> server + // 4. server --(res2)--> client + // + // This effectively will ensure: + // + // - Server waits for the rendezvous before responding. + // Hence, client won't be able to reuse the connection, but create a new one. + // + // - Client waits for the rendezvous before consuming responses. + CountDownLatch latch = new CountDownLatch(4); + pair.serverResponseLatchRef.set(latch); + + // Fire requests + LOGGER.log("Firing request 1..."); + CompletableFuture> response1Future = + client.sendAsync(pair.request, BodyHandlers.ofString(CHARSET)); + LOGGER.log("Firing request 2..."); + CompletableFuture> response2Future = + client.sendAsync(pair.request, BodyHandlers.ofString(CHARSET)); + + // Release latches to allow the server handlers to proceed + latch.countDown(); + latch.countDown(); + + // Wait for all parties to be ready + LOGGER.log("Client is waiting for the latch..."); + latch.await(); + LOGGER.log("Client is continuing..."); + + // Collect responses + HttpResponse response1 = response1Future.get(); + HttpResponse response2 = response2Future.get(); + + // Verify successful responses + assertEquals(200, response1.statusCode()); + assertEquals(200, response2.statusCode()); + + // Verify that connection keys differ; that is, requests are served through different connections + String connectionKey1 = response1.headers().firstValue(CONNECTION_KEY_HEADER_NAME).get(); + String connectionKey2 = response2.headers().firstValue(CONNECTION_KEY_HEADER_NAME).get(); + assertNotEquals(connectionKey1, connectionKey2); + + // Verify that server IDs match; that is, both requests targeted the same server. + // (Using `parseInt` to validate the content.) + int serverId1 = Integer.parseInt(response1.headers().firstValue(SERVER_ID_HEADER_NAME).get()); + int serverId2 = Integer.parseInt(response2.headers().firstValue(SERVER_ID_HEADER_NAME).get()); + assertEquals(serverId1, serverId2); + + // Verify that response bodies differ. + // (Using `parseInt` to validate the content.) + int body1 = Integer.parseInt(response1.body()); + int body2 = Integer.parseInt(response2.body()); + assertNotEquals(body1, body2); + + // Verify that connection labels differ; that is, requests are served through different connections + String label1 = response1.connectionLabel().orElse(null); + assertNotNull(label1); + LOGGER.log("Connection label 1: %s", label1); + String label2 = response2.connectionLabel().orElse(null); + assertNotNull(label2); + LOGGER.log("Connection label 2: %s", label2); + assertNotEquals(label1, label2); + + } + + static Stream testParallelRequestsToDifferentServers() { + return Stream + .of(PRI_HTTP1, PRI_HTTPS1, PRI_HTTP2, PRI_HTTPS2) + .flatMap(source -> Stream + .of(SEC_HTTP1, SEC_HTTPS1, SEC_HTTP2, SEC_HTTPS2) + .map(target -> Arguments.of(source, target))); + } + + @ParameterizedTest + @MethodSource("testParallelRequestsToDifferentServers") + void testParallelRequestsToDifferentServers(ServerRequestPair pair1, ServerRequestPair pair2) throws Exception { + + // Configure a synchronization point for 4 events: + // + // 1. client --> server1 + // 2. server1 --> client + // 3. client --> server2 + // 4. server2 --> client + // + // This effectively will ensure: + // + // - Server waits for the rendezvous before responding. + // Hence, client won't be able to reuse the connection, but create a new one. + // + // - Client waits for the rendezvous before consuming responses. + CountDownLatch latch = new CountDownLatch(4); + pair1.serverResponseLatchRef.set(latch); + pair2.serverResponseLatchRef.set(latch); + + // Fire requests + LOGGER.log("Firing request 1..."); + CompletableFuture> response1Future = + client.sendAsync(pair1.request, BodyHandlers.ofString(CHARSET)); + LOGGER.log("Firing request 2..."); + CompletableFuture> response2Future = + client.sendAsync(pair2.request, BodyHandlers.ofString(CHARSET)); + + // Release latches to allow the server handlers to proceed + latch.countDown(); + latch.countDown(); + + // Wait for all parties to be ready + LOGGER.log("Client is waiting for the latch..."); + latch.await(); + LOGGER.log("Client is continuing..."); + + // Collect responses + HttpResponse response1 = response1Future.get(); + HttpResponse response2 = response2Future.get(); + + // Verify successful responses + assertEquals(200, response1.statusCode()); + assertEquals(200, response2.statusCode()); + + // Verify that connection keys differ; that is, requests are served through different connections + String connectionKey1 = response1.headers().firstValue(CONNECTION_KEY_HEADER_NAME).get(); + String connectionKey2 = response2.headers().firstValue(CONNECTION_KEY_HEADER_NAME).get(); + assertNotEquals(connectionKey1, connectionKey2); + + // Verify that server IDs differ. + // (Using `parseInt` to validate the content.) + int serverId1 = response1.headers().firstValue(SERVER_ID_HEADER_NAME).map(Integer::parseInt).get(); + int serverId2 = response2.headers().firstValue(SERVER_ID_HEADER_NAME).map(Integer::parseInt).get(); + assertNotEquals(serverId1, serverId2); + + // Verify that response bodies differ. + // (Using `parseInt` to validate the content.) + int body1 = Integer.parseInt(response1.body()); + int body2 = Integer.parseInt(response2.body()); + assertNotEquals(body1, body2); + + // Verify that connection labels differ; that is, requests are served through different connections + String label1 = response1.connectionLabel().orElse(null); + assertNotNull(label1); + LOGGER.log("Connection label 1: %s", label1); + String label2 = response2.connectionLabel().orElse(null); + assertNotNull(label2); + LOGGER.log("Connection label 2: %s", label2); + assertNotEquals(label1, label2); + + } + + static Stream testSerialRequestsToSameServer() { + return Stream.of(PRI_HTTP1, PRI_HTTPS1, PRI_HTTP2, PRI_HTTPS2); + } + + @ParameterizedTest + @MethodSource("testSerialRequestsToSameServer") + void testSerialRequestsToSameServer(ServerRequestPair pair) throws Exception { + + // Disarm the synchronization point + pair.serverResponseLatchRef.set(null); + + // Fire requests + LOGGER.log("Firing request 1..."); + HttpResponse response1 = client.send(pair.request, BodyHandlers.ofString(CHARSET)); + LOGGER.log("Firing request 2..."); + HttpResponse response2 = client.send(pair.request, BodyHandlers.ofString(CHARSET)); + + // Verify successful responses + assertEquals(200, response1.statusCode()); + assertEquals(200, response2.statusCode()); + + // Verify that connection keys match; that is, requests are served through the same connection + String connectionKey1 = response1.headers().firstValue(CONNECTION_KEY_HEADER_NAME).get(); + String connectionKey2 = response2.headers().firstValue(CONNECTION_KEY_HEADER_NAME).get(); + assertEquals(connectionKey1, connectionKey2); + + // Verify that server IDs match. + // (Using `parseInt` to validate the content.) + int serverId1 = response1.headers().firstValue(SERVER_ID_HEADER_NAME).map(Integer::parseInt).get(); + int serverId2 = response2.headers().firstValue(SERVER_ID_HEADER_NAME).map(Integer::parseInt).get(); + assertEquals(serverId1, serverId2); + + // Verify that response bodies differ. + // (Using `parseInt` to validate the content.) + int body1 = Integer.parseInt(response1.body()); + int body2 = Integer.parseInt(response2.body()); + assertNotEquals(body1, body2); + + // Verify that connection labels match; that is, requests are served through the same connection + String label1 = response1.connectionLabel().orElse(null); + assertNotNull(label1); + LOGGER.log("Connection label 1: %s", label1); + String label2 = response2.connectionLabel().orElse(null); + assertNotNull(label2); + LOGGER.log("Connection label 2: %s", label2); + assertEquals(label1, label2); + + } + +} diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java index 9667969ec08..729fdb084e1 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -459,7 +459,7 @@ public class ConnectionPoolTest { InetSocketAddress address, InetSocketAddress proxy, boolean secured) { - super(address, impl); + super(address, impl, "testConn-" + IDS.incrementAndGet()); this.key = ConnectionPool.cacheKey(secured, address, proxy); this.address = address; this.proxy = proxy; From 273a9a61558fdfc422772fa2c6045a4d3c709a41 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 15 Apr 2025 11:49:58 +0000 Subject: [PATCH 183/843] 8354448: [REDO] Remove friends for ObjectMonitor Reviewed-by: kbarrett, shade, dholmes --- src/hotspot/share/runtime/objectMonitor.hpp | 7 ++----- src/hotspot/share/runtime/objectMonitor.inline.hpp | 5 +++++ src/hotspot/share/runtime/synchronizer.cpp | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 729316811c2..c8daeb65b50 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -148,9 +148,6 @@ class ObjectWaiter : public CHeapObj { #define OM_CACHE_LINE_SIZE DEFAULT_CACHE_LINE_SIZE class ObjectMonitor : public CHeapObj { - friend class LightweightSynchronizer; - friend class ObjectSynchronizer; - friend class ObjectWaiter; friend class VMStructs; JVMCI_ONLY(friend class JVMCIVMStructs;) @@ -334,6 +331,7 @@ class ObjectMonitor : public CHeapObj { void add_to_contentions(int value); intx recursions() const { return _recursions; } void set_recursions(size_t recursions); + void increment_recursions(JavaThread* current); // JVM/TI GetObjectMonitorUsage() needs this: int waiters() const; @@ -424,13 +422,12 @@ class ObjectMonitor : public CHeapObj { bool short_fixed_spin(JavaThread* current, int spin_count, bool adapt); void exit_epilog(JavaThread* current, ObjectWaiter* Wakee); + public: // Deflation support bool deflate_monitor(Thread* current); - private: void install_displaced_markword_in_object(const oop obj); // JFR support -public: static bool is_jfr_excluded(const Klass* monitor_klass); }; diff --git a/src/hotspot/share/runtime/objectMonitor.inline.hpp b/src/hotspot/share/runtime/objectMonitor.inline.hpp index 89f6deaab21..7dabc50fca7 100644 --- a/src/hotspot/share/runtime/objectMonitor.inline.hpp +++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp @@ -150,6 +150,11 @@ inline void ObjectMonitor::set_recursions(size_t recursions) { _recursions = checked_cast(recursions); } +inline void ObjectMonitor::increment_recursions(JavaThread* current) { + assert(has_owner(current), "must be the owner"); + _recursions++; +} + // Clear _owner field; current value must match old_value. inline void ObjectMonitor::release_clear_owner(JavaThread* old_owner) { int64_t old_value = owner_id_from(old_owner); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index d608ffbdc02..503b7833351 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -423,7 +423,7 @@ bool ObjectSynchronizer::quick_enter_legacy(oop obj, BasicLock* lock, JavaThread // Case: TLE inimical operations such as nested/recursive synchronization if (m->has_owner(current)) { - m->_recursions++; + m->increment_recursions(current); current->inc_held_monitor_count(); return true; } @@ -440,7 +440,7 @@ bool ObjectSynchronizer::quick_enter_legacy(oop obj, BasicLock* lock, JavaThread lock->set_displaced_header(markWord::unused_mark()); if (!m->has_owner() && m->try_set_owner(current)) { - assert(m->_recursions == 0, "invariant"); + assert(m->recursions() == 0, "invariant"); current->inc_held_monitor_count(); return true; } From 36864a2a08b5b64e63a9265d595ba7fb608994cb Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 15 Apr 2025 11:55:47 +0000 Subject: [PATCH 184/843] 8351491: Add info from release file to hserr file Reviewed-by: dholmes, lucy --- src/hotspot/share/runtime/os.cpp | 50 +++++++++++++++++++++++++ src/hotspot/share/runtime/os.hpp | 5 +++ src/hotspot/share/runtime/threads.cpp | 17 +++++++++ src/hotspot/share/utilities/vmError.cpp | 8 ++++ 4 files changed, 80 insertions(+) diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 99559cee287..e4bab3410c1 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1534,6 +1534,56 @@ bool os::set_boot_path(char fileSep, char pathSep) { return false; } +static char* _image_release_file_content = nullptr; + +void os::read_image_release_file() { + assert(_image_release_file_content == nullptr, "release file content must not be already set"); + const char* home = Arguments::get_java_home(); + stringStream ss; + ss.print("%s/release", home); + + FILE* file = fopen(ss.base(), "rb"); + if (file == nullptr) { + return; + } + fseek(file, 0, SEEK_END); + long sz = ftell(file); + if (sz == -1) { + return; + } + fseek(file, 0, SEEK_SET); + + char* tmp = (char*) os::malloc(sz + 1, mtInternal); + if (tmp == nullptr) { + fclose(file); + return; + } + + size_t elements_read = fread(tmp, 1, sz, file); + if (elements_read < (size_t)sz) { + tmp[elements_read] = '\0'; + } else { + tmp[sz] = '\0'; + } + // issues with \r in line endings on Windows, so better replace those + for (size_t i = 0; i < elements_read; i++) { + if (tmp[i] == '\r') { + tmp[i] = ' '; + } + } + Atomic::release_store(&_image_release_file_content, tmp); + fclose(file); +} + +void os::print_image_release_file(outputStream* st) { + char* ifrc = Atomic::load_acquire(&_image_release_file_content); + if (ifrc != nullptr) { + st->print_cr("%s", ifrc); + } else { + st->print_cr(""); + } +} + bool os::file_exists(const char* filename) { struct stat statbuf; if (filename == nullptr || strlen(filename) == 0) { diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 242959034af..16a74cd7ea9 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -670,6 +670,11 @@ class os: AllStatic { static FILE* fopen(const char* path, const char* mode); static jlong lseek(int fd, jlong offset, int whence); static bool file_exists(const char* file); + + // read/store and print the release file of the image + static void read_image_release_file(); + static void print_image_release_file(outputStream* st); + // This function, on Windows, canonicalizes a given path (see os_windows.cpp for details). // On Posix, this function is a noop: it does not change anything and just returns // the input pointer. diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 1d515c9fe7d..203062582a0 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -425,6 +425,19 @@ void Threads::initialize_jsr292_core_classes(TRAPS) { } } +// One-shot PeriodicTask subclass for reading the release file +class ReadReleaseFileTask : public PeriodicTask { + public: + ReadReleaseFileTask() : PeriodicTask(100) {} + + virtual void task() { + os::read_image_release_file(); + + // Reclaim our storage and disenroll ourself. + delete this; + } +}; + jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { extern void JDK_Version_init(); @@ -580,6 +593,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { return status; } + // Have the WatcherThread read the release file in the background. + ReadReleaseFileTask* read_task = new ReadReleaseFileTask(); + read_task->enroll(); + // Create WatcherThread as soon as we can since we need it in case // of hangs during error reporting. WatcherThread::start(); diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index ccd31269d0d..e1940123d67 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1259,6 +1259,10 @@ void VMError::report(outputStream* st, bool _verbose) { LogConfiguration::describe_current_configuration(st); st->cr(); + STEP_IF("printing release file content", _verbose) + st->print_cr("Release file:"); + os::print_image_release_file(st); + STEP_IF("printing all environment variables", _verbose) os::print_environment_variables(st, env_list); st->cr(); @@ -1439,6 +1443,10 @@ void VMError::print_vm_info(outputStream* st) { LogConfiguration::describe(st); st->cr(); + // STEP("printing release file content") + st->print_cr("Release file:"); + os::print_image_release_file(st); + // STEP("printing all environment variables") os::print_environment_variables(st, env_list); From fc1464727f95508935cfc65d689b74e1709d3649 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 15 Apr 2025 16:06:12 +0000 Subject: [PATCH 185/843] 8354320: Changes to jpackage.md cause pandoc warning Reviewed-by: almatvee, ihse, alanb --- make/autoconf/basic_tools.m4 | 10 +++++++++- src/jdk.jpackage/share/man/jpackage.md | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4 index eac14207b1d..5815c55c962 100644 --- a/make/autoconf/basic_tools.m4 +++ b/make/autoconf/basic_tools.m4 @@ -468,7 +468,15 @@ AC_DEFUN_ONCE([BASIC_SETUP_PANDOC], AC_MSG_CHECKING([if the pandoc smart extension needs to be disabled for markdown]) if $PANDOC --list-extensions | $GREP -q '+smart'; then AC_MSG_RESULT([yes]) - PANDOC_MARKDOWN_FLAG="markdown-smart" + PANDOC_MARKDOWN_FLAG="$PANDOC_MARKDOWN_FLAG-smart" + else + AC_MSG_RESULT([no]) + fi + + AC_MSG_CHECKING([if the pandoc tex_math_dollars extension needs to be disabled for markdown]) + if $PANDOC --list-extensions | $GREP -q '+tex_math_dollars'; then + AC_MSG_RESULT([yes]) + PANDOC_MARKDOWN_FLAG="$PANDOC_MARKDOWN_FLAG-tex_math_dollars" else AC_MSG_RESULT([no]) fi diff --git a/src/jdk.jpackage/share/man/jpackage.md b/src/jdk.jpackage/share/man/jpackage.md index c50370c9641..34e524f9eee 100644 --- a/src/jdk.jpackage/share/man/jpackage.md +++ b/src/jdk.jpackage/share/man/jpackage.md @@ -236,7 +236,7 @@ The `jpackage` tool will take as input a Java application and a Java run-time im will be ignored, and these expandable substrings will be replaced by values calculated by the app launcher. - Prefix the dollar sign character with the backslash character (\) + Prefix the dollar sign character with the backslash character (\\) to prevent substring expansion. `--java-options` *options* From cec48ed270d3bdf704c389a091b42a32c2ed6440 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 15 Apr 2025 16:19:03 +0000 Subject: [PATCH 186/843] 8354542: Clean up x86 stubs after 32-bit x86 removal Reviewed-by: adinn, kvn --- src/hotspot/cpu/x86/methodHandles_x86.cpp | 27 +-- src/hotspot/cpu/x86/methodHandles_x86.hpp | 2 +- src/hotspot/cpu/x86/sharedRuntime_x86.cpp | 9 +- src/hotspot/cpu/x86/stubDeclarations_x86.hpp | 210 +++++++++---------- src/hotspot/cpu/x86/stubRoutines_x86.cpp | 6 - src/hotspot/cpu/x86/stubRoutines_x86.hpp | 31 --- 6 files changed, 109 insertions(+), 176 deletions(-) diff --git a/src/hotspot/cpu/x86/methodHandles_x86.cpp b/src/hotspot/cpu/x86/methodHandles_x86.cpp index 92993dcbf64..ee4dc26ae40 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.cpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp @@ -82,8 +82,8 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, __ verify_oop(obj); __ testptr(obj, obj); __ jcc(Assembler::zero, L_bad); -#define PUSH { __ push(temp); LP64_ONLY( __ push(rscratch1); ) } -#define POP { LP64_ONLY( __ pop(rscratch1); ) __ pop(temp); } +#define PUSH { __ push(temp); __ push(rscratch1); } +#define POP { __ pop(rscratch1); __ pop(temp); } PUSH; __ load_klass(temp, obj, rscratch1); __ cmpptr(temp, ExternalAddress((address) klass_addr), rscratch1); @@ -139,15 +139,9 @@ void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register meth // JVMTI events, such as single-stepping, are implemented partly by avoiding running // compiled code in threads for which the event is enabled. Check here for // interp_only_mode if these events CAN be enabled. -#ifdef _LP64 - Register rthread = r15_thread; -#else - Register rthread = temp; - __ get_thread(rthread); -#endif // interp_only is an int, on little endian it is sufficient to test the byte only // Is a cmpl faster? - __ cmpb(Address(rthread, JavaThread::interp_only_mode_offset()), 0); + __ cmpb(Address(r15_thread, JavaThread::interp_only_mode_offset()), 0); __ jccb(Assembler::zero, run_compiled_code); __ jmp(Address(method, Method::interpreter_entry_offset())); __ BIND(run_compiled_code); @@ -324,7 +318,6 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, assert(is_signature_polymorphic(iid), "expected invoke iid"); Register rbx_method = rbx; // eventual target of this invocation // temps used in this code are not used in *either* compiled or interpreted calling sequences -#ifdef _LP64 Register temp1 = rscratch1; Register temp2 = rscratch2; Register temp3 = rax; @@ -333,19 +326,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5); assert_different_registers(temp2, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5); assert_different_registers(temp3, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5); - } -#else - Register temp1 = (for_compiler_entry ? rsi : rdx); - Register temp2 = rdi; - Register temp3 = rax; - if (for_compiler_entry) { - assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic || iid == vmIntrinsics::_linkToNative ? noreg : rcx), "only valid assignment"); - assert_different_registers(temp1, rcx, rdx); - assert_different_registers(temp2, rcx, rdx); - assert_different_registers(temp3, rcx, rdx); - } -#endif - else { + } else { assert_different_registers(temp1, temp2, temp3, saved_last_sp_register()); // don't trash lastSP } assert_different_registers(temp1, temp2, temp3, receiver_reg); diff --git a/src/hotspot/cpu/x86/methodHandles_x86.hpp b/src/hotspot/cpu/x86/methodHandles_x86.hpp index 6574fec6601..9ffe5e198ac 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.hpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.hpp @@ -60,5 +60,5 @@ public: static Register saved_last_sp_register() { // Should be in sharedRuntime, not here. - return LP64_ONLY(r13) NOT_LP64(rsi); + return r13; } diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86.cpp index 0a277a4eb69..b8a4b829159 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86.cpp @@ -73,21 +73,14 @@ void SharedRuntime::inline_check_hashcode_from_object_header(MacroAssembler* mas } // get hash -#ifdef _LP64 // Read the header and build a mask to get its hash field. // Depend on hash_mask being at most 32 bits and avoid the use of hash_mask_in_place // because it could be larger than 32 bits in a 64-bit vm. See markWord.hpp. __ shrptr(result, markWord::hash_shift); __ andptr(result, markWord::hash_mask); -#else - __ andptr(result, markWord::hash_mask_in_place); -#endif //_LP64 // test if hashCode exists - __ jcc(Assembler::zero, slowCase); -#ifndef _LP64 - __ shrptr(result, markWord::hash_shift); -#endif + __ jccb(Assembler::zero, slowCase); __ ret(0); __ bind(slowCase); } diff --git a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp index 406dbb9aa6d..dcb919ddcd0 100644 --- a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp +++ b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp @@ -34,45 +34,43 @@ do_stub(initial, verify_mxcsr) \ do_arch_entry(x86, initial, verify_mxcsr, verify_mxcsr_entry, \ verify_mxcsr_entry) \ - LP64_ONLY( \ - do_stub(initial, get_previous_sp) \ - do_arch_entry(x86, initial, get_previous_sp, \ - get_previous_sp_entry, \ - get_previous_sp_entry) \ - do_stub(initial, f2i_fixup) \ - do_arch_entry(x86, initial, f2i_fixup, f2i_fixup, f2i_fixup) \ - do_stub(initial, f2l_fixup) \ - do_arch_entry(x86, initial, f2l_fixup, f2l_fixup, f2l_fixup) \ - do_stub(initial, d2i_fixup) \ - do_arch_entry(x86, initial, d2i_fixup, d2i_fixup, d2i_fixup) \ - do_stub(initial, d2l_fixup) \ - do_arch_entry(x86, initial, d2l_fixup, d2l_fixup, d2l_fixup) \ - do_stub(initial, float_sign_mask) \ - do_arch_entry(x86, initial, float_sign_mask, float_sign_mask, \ - float_sign_mask) \ - do_stub(initial, float_sign_flip) \ - do_arch_entry(x86, initial, float_sign_flip, float_sign_flip, \ - float_sign_flip) \ - do_stub(initial, double_sign_mask) \ - do_arch_entry(x86, initial, double_sign_mask, double_sign_mask, \ - double_sign_mask) \ - do_stub(initial, double_sign_flip) \ - do_arch_entry(x86, initial, double_sign_flip, double_sign_flip, \ - double_sign_flip) \ - ) \ + do_stub(initial, get_previous_sp) \ + do_arch_entry(x86, initial, get_previous_sp, \ + get_previous_sp_entry, \ + get_previous_sp_entry) \ + do_stub(initial, f2i_fixup) \ + do_arch_entry(x86, initial, f2i_fixup, f2i_fixup, f2i_fixup) \ + do_stub(initial, f2l_fixup) \ + do_arch_entry(x86, initial, f2l_fixup, f2l_fixup, f2l_fixup) \ + do_stub(initial, d2i_fixup) \ + do_arch_entry(x86, initial, d2i_fixup, d2i_fixup, d2i_fixup) \ + do_stub(initial, d2l_fixup) \ + do_arch_entry(x86, initial, d2l_fixup, d2l_fixup, d2l_fixup) \ + do_stub(initial, float_sign_mask) \ + do_arch_entry(x86, initial, float_sign_mask, float_sign_mask, \ + float_sign_mask) \ + do_stub(initial, float_sign_flip) \ + do_arch_entry(x86, initial, float_sign_flip, float_sign_flip, \ + float_sign_flip) \ + do_stub(initial, double_sign_mask) \ + do_arch_entry(x86, initial, double_sign_mask, double_sign_mask, \ + double_sign_mask) \ + do_stub(initial, double_sign_flip) \ + do_arch_entry(x86, initial, double_sign_flip, double_sign_flip, \ + double_sign_flip) \ #define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(continuation, 1000 LP64_ONLY(+2000)) \ + do_arch_blob(continuation, 3000) \ #define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(compiler, 20000 LP64_ONLY(+89000) WINDOWS_ONLY(+2000)) \ + do_arch_blob(compiler, 109000 WINDOWS_ONLY(+2000)) \ do_stub(compiler, vector_float_sign_mask) \ do_arch_entry(x86, compiler, vector_float_sign_mask, \ vector_float_sign_mask, vector_float_sign_mask) \ @@ -160,90 +158,88 @@ do_arch_entry(x86, compiler, pshuffle_byte_flip_mask, \ pshuffle_byte_flip_mask_addr, \ pshuffle_byte_flip_mask_addr) \ - LP64_ONLY( \ - /* x86_64 exposes these 3 stubs via a generic entry array */ \ - /* oher arches use arch-specific entries */ \ - /* this really needs rationalising */ \ - do_stub(compiler, string_indexof_linear_ll) \ - do_stub(compiler, string_indexof_linear_uu) \ - do_stub(compiler, string_indexof_linear_ul) \ - do_stub(compiler, pshuffle_byte_flip_mask_sha512) \ - do_arch_entry(x86, compiler, pshuffle_byte_flip_mask_sha512, \ - pshuffle_byte_flip_mask_addr_sha512, \ - pshuffle_byte_flip_mask_addr_sha512) \ - do_stub(compiler, compress_perm_table32) \ - do_arch_entry(x86, compiler, compress_perm_table32, \ - compress_perm_table32, compress_perm_table32) \ - do_stub(compiler, compress_perm_table64) \ - do_arch_entry(x86, compiler, compress_perm_table64, \ - compress_perm_table64, compress_perm_table64) \ - do_stub(compiler, expand_perm_table32) \ - do_arch_entry(x86, compiler, expand_perm_table32, \ - expand_perm_table32, expand_perm_table32) \ - do_stub(compiler, expand_perm_table64) \ - do_arch_entry(x86, compiler, expand_perm_table64, \ - expand_perm_table64, expand_perm_table64) \ - do_stub(compiler, avx2_shuffle_base64) \ - do_arch_entry(x86, compiler, avx2_shuffle_base64, \ - avx2_shuffle_base64, base64_avx2_shuffle_addr) \ - do_stub(compiler, avx2_input_mask_base64) \ - do_arch_entry(x86, compiler, avx2_input_mask_base64, \ - avx2_input_mask_base64, \ - base64_avx2_input_mask_addr) \ - do_stub(compiler, avx2_lut_base64) \ - do_arch_entry(x86, compiler, avx2_lut_base64, \ - avx2_lut_base64, base64_avx2_lut_addr) \ - do_stub(compiler, avx2_decode_tables_base64) \ - do_arch_entry(x86, compiler, avx2_decode_tables_base64, \ - avx2_decode_tables_base64, \ - base64_AVX2_decode_tables_addr) \ - do_stub(compiler, avx2_decode_lut_tables_base64) \ - do_arch_entry(x86, compiler, avx2_decode_lut_tables_base64, \ - avx2_decode_lut_tables_base64, \ - base64_AVX2_decode_LUT_tables_addr) \ - do_stub(compiler, shuffle_base64) \ - do_arch_entry(x86, compiler, shuffle_base64, shuffle_base64, \ - base64_shuffle_addr) \ - do_stub(compiler, lookup_lo_base64) \ - do_arch_entry(x86, compiler, lookup_lo_base64, lookup_lo_base64, \ - base64_vbmi_lookup_lo_addr) \ - do_stub(compiler, lookup_hi_base64) \ - do_arch_entry(x86, compiler, lookup_hi_base64, lookup_hi_base64, \ - base64_vbmi_lookup_hi_addr) \ - do_stub(compiler, lookup_lo_base64url) \ - do_arch_entry(x86, compiler, lookup_lo_base64url, \ - lookup_lo_base64url, \ - base64_vbmi_lookup_lo_url_addr) \ - do_stub(compiler, lookup_hi_base64url) \ - do_arch_entry(x86, compiler, lookup_hi_base64url, \ - lookup_hi_base64url, \ - base64_vbmi_lookup_hi_url_addr) \ - do_stub(compiler, pack_vec_base64) \ - do_arch_entry(x86, compiler, pack_vec_base64, pack_vec_base64, \ - base64_vbmi_pack_vec_addr) \ - do_stub(compiler, join_0_1_base64) \ - do_arch_entry(x86, compiler, join_0_1_base64, join_0_1_base64, \ - base64_vbmi_join_0_1_addr) \ - do_stub(compiler, join_1_2_base64) \ - do_arch_entry(x86, compiler, join_1_2_base64, join_1_2_base64, \ - base64_vbmi_join_1_2_addr) \ - do_stub(compiler, join_2_3_base64) \ - do_arch_entry(x86, compiler, join_2_3_base64, join_2_3_base64, \ - base64_vbmi_join_2_3_addr) \ - do_stub(compiler, encoding_table_base64) \ - do_arch_entry(x86, compiler, encoding_table_base64, \ - encoding_table_base64, base64_encoding_table_addr) \ - do_stub(compiler, decoding_table_base64) \ - do_arch_entry(x86, compiler, decoding_table_base64, \ - decoding_table_base64, base64_decoding_table_addr) \ - ) \ + /* x86_64 exposes these 3 stubs via a generic entry array */ \ + /* other arches use arch-specific entries */ \ + /* this really needs rationalising */ \ + do_stub(compiler, string_indexof_linear_ll) \ + do_stub(compiler, string_indexof_linear_uu) \ + do_stub(compiler, string_indexof_linear_ul) \ + do_stub(compiler, pshuffle_byte_flip_mask_sha512) \ + do_arch_entry(x86, compiler, pshuffle_byte_flip_mask_sha512, \ + pshuffle_byte_flip_mask_addr_sha512, \ + pshuffle_byte_flip_mask_addr_sha512) \ + do_stub(compiler, compress_perm_table32) \ + do_arch_entry(x86, compiler, compress_perm_table32, \ + compress_perm_table32, compress_perm_table32) \ + do_stub(compiler, compress_perm_table64) \ + do_arch_entry(x86, compiler, compress_perm_table64, \ + compress_perm_table64, compress_perm_table64) \ + do_stub(compiler, expand_perm_table32) \ + do_arch_entry(x86, compiler, expand_perm_table32, \ + expand_perm_table32, expand_perm_table32) \ + do_stub(compiler, expand_perm_table64) \ + do_arch_entry(x86, compiler, expand_perm_table64, \ + expand_perm_table64, expand_perm_table64) \ + do_stub(compiler, avx2_shuffle_base64) \ + do_arch_entry(x86, compiler, avx2_shuffle_base64, \ + avx2_shuffle_base64, base64_avx2_shuffle_addr) \ + do_stub(compiler, avx2_input_mask_base64) \ + do_arch_entry(x86, compiler, avx2_input_mask_base64, \ + avx2_input_mask_base64, \ + base64_avx2_input_mask_addr) \ + do_stub(compiler, avx2_lut_base64) \ + do_arch_entry(x86, compiler, avx2_lut_base64, \ + avx2_lut_base64, base64_avx2_lut_addr) \ + do_stub(compiler, avx2_decode_tables_base64) \ + do_arch_entry(x86, compiler, avx2_decode_tables_base64, \ + avx2_decode_tables_base64, \ + base64_AVX2_decode_tables_addr) \ + do_stub(compiler, avx2_decode_lut_tables_base64) \ + do_arch_entry(x86, compiler, avx2_decode_lut_tables_base64, \ + avx2_decode_lut_tables_base64, \ + base64_AVX2_decode_LUT_tables_addr) \ + do_stub(compiler, shuffle_base64) \ + do_arch_entry(x86, compiler, shuffle_base64, shuffle_base64, \ + base64_shuffle_addr) \ + do_stub(compiler, lookup_lo_base64) \ + do_arch_entry(x86, compiler, lookup_lo_base64, lookup_lo_base64, \ + base64_vbmi_lookup_lo_addr) \ + do_stub(compiler, lookup_hi_base64) \ + do_arch_entry(x86, compiler, lookup_hi_base64, lookup_hi_base64, \ + base64_vbmi_lookup_hi_addr) \ + do_stub(compiler, lookup_lo_base64url) \ + do_arch_entry(x86, compiler, lookup_lo_base64url, \ + lookup_lo_base64url, \ + base64_vbmi_lookup_lo_url_addr) \ + do_stub(compiler, lookup_hi_base64url) \ + do_arch_entry(x86, compiler, lookup_hi_base64url, \ + lookup_hi_base64url, \ + base64_vbmi_lookup_hi_url_addr) \ + do_stub(compiler, pack_vec_base64) \ + do_arch_entry(x86, compiler, pack_vec_base64, pack_vec_base64, \ + base64_vbmi_pack_vec_addr) \ + do_stub(compiler, join_0_1_base64) \ + do_arch_entry(x86, compiler, join_0_1_base64, join_0_1_base64, \ + base64_vbmi_join_0_1_addr) \ + do_stub(compiler, join_1_2_base64) \ + do_arch_entry(x86, compiler, join_1_2_base64, join_1_2_base64, \ + base64_vbmi_join_1_2_addr) \ + do_stub(compiler, join_2_3_base64) \ + do_arch_entry(x86, compiler, join_2_3_base64, join_2_3_base64, \ + base64_vbmi_join_2_3_addr) \ + do_stub(compiler, encoding_table_base64) \ + do_arch_entry(x86, compiler, encoding_table_base64, \ + encoding_table_base64, base64_encoding_table_addr) \ + do_stub(compiler, decoding_table_base64) \ + do_arch_entry(x86, compiler, decoding_table_base64, \ + decoding_table_base64, base64_decoding_table_addr) \ #define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(final, 11000 LP64_ONLY(+20000) \ - WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \ + do_arch_blob(final, 31000 \ + WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \ #endif // CPU_X86_STUBDECLARATIONS_HPP diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp index 861c1e1216e..9b524ae94cf 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp @@ -46,10 +46,8 @@ STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT) #undef DEFINE_ARCH_ENTRY address StubRoutines::x86::_k256_adr = nullptr; -#ifdef _LP64 address StubRoutines::x86::_k256_W_adr = nullptr; address StubRoutines::x86::_k512_W_addr = nullptr; -#endif const uint64_t StubRoutines::x86::_crc_by128_masks[] = { @@ -146,7 +144,6 @@ const juint StubRoutines::x86::_crc_table[] = 0x2d02ef8dUL }; -#ifdef _LP64 const juint StubRoutines::x86::_crc_table_avx512[] = { 0xe95c1271UL, 0x00000000UL, 0xce3371cbUL, 0x00000000UL, @@ -193,7 +190,6 @@ const juint StubRoutines::x86::_shuf_table_crc32_avx512[] = 0x83828100UL, 0x87868584UL, 0x8b8a8988UL, 0x8f8e8d8cUL, 0x03020100UL, 0x07060504UL, 0x0b0a0908UL, 0x000e0d0cUL }; -#endif // _LP64 const jint StubRoutines::x86::_arrays_hashcode_powers_of_31[] = { @@ -356,7 +352,6 @@ ATTRIBUTE_ALIGNED(64) const juint StubRoutines::x86::_k256[] = 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; -#ifdef _LP64 // used in MacroAssembler::sha256_AVX2 // dynamically built from _k256 ATTRIBUTE_ALIGNED(64) juint StubRoutines::x86::_k256_W[2*sizeof(StubRoutines::x86::_k256)]; @@ -405,4 +400,3 @@ ATTRIBUTE_ALIGNED(64) const julong StubRoutines::x86::_k512_W[] = 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, }; -#endif diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp index aaf84eb8437..c4930e1593c 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp @@ -75,39 +75,16 @@ public: #undef DEFINE_ARCH_ENTRY_GETTER_INIT #undef DEFINE_ARCH_GETTER_ENTRY - -#ifndef _LP64 - - static jint _fpu_cntrl_wrd_std; - static jint _fpu_cntrl_wrd_24; - static jint _fpu_cntrl_wrd_trunc; - - static jint _fpu_subnormal_bias1[3]; - static jint _fpu_subnormal_bias2[3]; - - static address addr_fpu_cntrl_wrd_std() { return (address)&_fpu_cntrl_wrd_std; } - static address addr_fpu_cntrl_wrd_24() { return (address)&_fpu_cntrl_wrd_24; } - static address addr_fpu_cntrl_wrd_trunc() { return (address)&_fpu_cntrl_wrd_trunc; } - static address addr_fpu_subnormal_bias1() { return (address)&_fpu_subnormal_bias1; } - static address addr_fpu_subnormal_bias2() { return (address)&_fpu_subnormal_bias2; } - - static jint fpu_cntrl_wrd_std() { return _fpu_cntrl_wrd_std; } -#endif // !LP64 - private: static jint _mxcsr_std; -#ifdef _LP64 static jint _mxcsr_rz; -#endif // _LP64 // masks and table for CRC32 static const uint64_t _crc_by128_masks[]; static const juint _crc_table[]; -#ifdef _LP64 static const juint _crc_by128_masks_avx512[]; static const juint _crc_table_avx512[]; static const juint _crc32c_table_avx512[]; static const juint _shuf_table_crc32_avx512[]; -#endif // _LP64 // table for CRC32C static juint* _crc32c_table; // table for arrays_hashcode @@ -115,30 +92,22 @@ public: //k256 table for sha256 static const juint _k256[]; static address _k256_adr; -#ifdef _LP64 static juint _k256_W[]; static address _k256_W_adr; static const julong _k512_W[]; static address _k512_W_addr; -#endif public: static address addr_mxcsr_std() { return (address)&_mxcsr_std; } -#ifdef _LP64 static address addr_mxcsr_rz() { return (address)&_mxcsr_rz; } -#endif // _LP64 static address crc_by128_masks_addr() { return (address)_crc_by128_masks; } -#ifdef _LP64 static address crc_by128_masks_avx512_addr() { return (address)_crc_by128_masks_avx512; } static address shuf_table_crc32_avx512_addr() { return (address)_shuf_table_crc32_avx512; } static address crc_table_avx512_addr() { return (address)_crc_table_avx512; } static address crc32c_table_avx512_addr() { return (address)_crc32c_table_avx512; } -#endif // _LP64 static address k256_addr() { return _k256_adr; } -#ifdef _LP64 static address k256_W_addr() { return _k256_W_adr; } static address k512_W_addr() { return _k512_W_addr; } -#endif static address arrays_hashcode_powers_of_31() { return (address)_arrays_hashcode_powers_of_31; } static void generate_CRC32C_table(bool is_pclmulqdq_supported); From 4e3f1848eeb28a78d71c6ffbda31279cee3fc5ea Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Tue, 15 Apr 2025 19:36:10 +0000 Subject: [PATCH 187/843] 8353000: Open source several swing tests batch2 Reviewed-by: azvegint --- .../JavaLAFMenuAcceleratorDelimiter.java | 83 +++++++ .../metal/MetalIconFactory/bug4952462.java | 98 ++++++++ .../MetalSliderUI/4186347/bug4186347.java | 74 ++++++ .../plaf/metal/MetalSliderUI/4186347/duke.gif | Bin 0 -> 1617 bytes .../metal/OceanTheme/4969419/bug4969419.java | 229 ++++++++++++++++++ .../plaf/metal/OceanTheme/4969419/duke.gif | Bin 0 -> 1929 bytes 6 files changed, 484 insertions(+) create mode 100644 test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java create mode 100644 test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java create mode 100644 test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java create mode 100644 test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif create mode 100644 test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java create mode 100644 test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif diff --git a/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java b/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java new file mode 100644 index 00000000000..f9885c98570 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4210461 + * @summary Confirm Metal Look & Feel's MenuItem Accelerator Delimiter + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual JavaLAFMenuAcceleratorDelimiter + */ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +public class JavaLAFMenuAcceleratorDelimiter { + static final String INSTRUCTIONS = """ + A simple check. The visual design specification for JLF/Metal asks for + a "-" to delimit the other two entities in a menu item's accelerator. + The test passes if the delimiter for the accelerator is correct when + opening the example menu. Otherwise, the test fails. + """; + + public static void main(String[] args) throws Exception { + // Set Metal L&F + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("JavaLAFMenuAcceleratorDelimiter Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(JavaLAFMenuAcceleratorDelimiter::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal L&F Accelerator Delimiter Test"); + JPanel menuPanel = new JPanel(); + JMenuBar menuBar = new JMenuBar(); + menuBar.setOpaque(true); + JMenu exampleMenu = new JMenu("Example"); + JMenuItem hiMenuItem = new JMenuItem("Hi There!"); + hiMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, + ActionEvent.CTRL_MASK)); + exampleMenu.add(hiMenuItem); + menuBar.add(exampleMenu); + menuPanel.add(menuBar); + + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(menuPanel, BorderLayout.CENTER); + frame.setSize(250, 150); + return frame; + } +} diff --git a/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java new file mode 100644 index 00000000000..f3562108314 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4952462 + * @summary Ocean: Tests that disabled selected JRadioButton dot is NOT + * painted with the foreground color + * @modules java.desktop/sun.awt + * @library /test/lib + * @key headful + * @run main bug4952462 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; + +import javax.swing.JFrame; +import javax.swing.JRadioButton; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalTheme; + +import jtreg.SkippedException; +import sun.awt.AppContext; + +public class bug4952462 { + private static JFrame frame; + private static JRadioButton rb; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + MetalTheme theme = (MetalTheme) AppContext.getAppContext().get("currentMetalTheme"); + if (theme == null || !"Ocean".equals(theme.getName())) { + throw new SkippedException("Current theme is not Ocean. Test is " + + "only for Metal's Ocean theme. Skipping test."); + } else { + Robot r = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Metal JRadioButton Foreground Color Test"); + frame.getContentPane().setLayout(new FlowLayout()); + rb = new JRadioButton("RadioButton", true); + rb.setEnabled(false); + rb.setForeground(Color.RED); + frame.getContentPane().add(rb); + frame.setSize(250, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + r.waitForIdle(); + r.delay(500); + + SwingUtilities.invokeAndWait(() -> { + Point p = rb.getLocationOnScreen(); + for (int i = 0; i < 50; i++) { + Color c = r.getPixelColor(p.x + 10 + i, p.y + (rb.getHeight() / 2)); + System.out.println(c); + if (c.getRed() > 200 && c.getBlue() < 200 && c.getGreen() < 200) { + throw new RuntimeException("Test failed. Radiobutton is red " + + "and not grey."); + } + } + }); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java b/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java new file mode 100644 index 00000000000..9de9d851805 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4186347 + * @summary Tests changing Slider.horizontalThumbIcon UIResource + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4186347 + */ + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JSlider; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.IconUIResource; + +public class bug4186347 { + static final String INSTRUCTIONS = """ + If the slider's thumb icon is painted correctly + (that is centered vertically relative to slider + channel) then test passed, otherwise it failed. + """; + + public static void main(String[] args) throws Exception { + // Set Metal L&F + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4186347 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4186347::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal JSlider Icon Test"); + String a = System.getProperty("test.src", ".") + + System.getProperty("file.separator") + + "duke.gif"; + Icon icon = new ImageIcon(a); + IconUIResource iconResource = new IconUIResource(icon); + UIDefaults defaults = UIManager.getDefaults(); + defaults.put("Slider.horizontalThumbIcon", iconResource); + JSlider s = new JSlider(); + frame.getContentPane().add(s); + frame.setSize(250, 150); + return frame; + } +} diff --git a/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif b/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif new file mode 100644 index 0000000000000000000000000000000000000000..a02a42fd606741170756cd1a33b48f609692b7f3 GIT binary patch literal 1617 zcmdUu>r)d~7>7?Fz!CwMYgeQ;%S983OoA0jYb}I;F*qYe>gWm@T%>g3RCKjoq7KRm zM%Eift#q|OSSYr!$gu6$c56UMLG9L#8nqu%I@$)QHZs#T)mG92^`GeZupi#DGw<(t zesdNrF3Qzb+|{iet#ekaB`fLq7VR30B``502l!<0YCsi0$>4v z0w56Zi=rFH;ZBrua!%eUxCJ|FXE~O#QWnZWT1XRNB1l4K)M<5EjaGvzaSX>$3`I}` zAOOWN+Ro@qM#4hASR4$xVVKD%ydZFs`Ceq@IGSN#dVeqoF|0HVd3d)QvT-~Q@gOIp zrR{cz2gxBnv|xgBf`CS}Mk7=M1wl;!LF^n%E3%vu!l#;`FHMPG z?#i1zZ+BI~>B`jRW@-KNkGfoGODjrd=HwGMrw&b5g{qHXomJO?tmeuF^H}k>3*)YB zFTWO-F`!s8pf4MG&uKrn=#F>C%FjDe^|e`^^5JejSeX8Ic$Hz>W63GWvxRFE9iOTt z^Uam%@+*I&0R4Ker|vmV3|zYkp1Z0*}z_~j|*(Jg4sVWnaCWb?($o}?o8 zA>|K)?>J&gdgZT(vVT(sXO1(Auo~WBZa7 zXU$FP4jPC5bmYI8pnfYtzRP@neXF|1cDOjX@8-0nNw3z&fsz_SGKqym&N{NI$(B-_ zb+59fLY96#Rw@2uNN?QIW}BIOWm;!=u4;vEV-j+1qz$O>QX=)WtLEmMCl%fO?g`?6Yl_mH8eUMfY% z{RPHHdHJl#+*dKx^x5-|H3iGI$W95w%?xmnj@s(^?w0mt51Fa literal 0 HcmV?d00001 diff --git a/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java b/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java new file mode 100644 index 00000000000..023f17f4c43 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4969419 + * @summary Tests that generated disabled icons have same look with Ocean + * and are updated when theme is switched + * @modules java.desktop/sun.awt + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @key headful + * @run main/manual bug4969419 + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; + +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JToggleButton; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.metal.DefaultMetalTheme; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.MetalTheme; + +import sun.awt.AppContext; + +public class bug4969419 { + static final String INSTRUCTIONS = """ + When the test starts you'll see several components with icons. + Use the bottom combo box and the "Set" button to switch between + the Ocean theme and DefaultMetalTheme. + + 1. Set the Ocean theme. Ensure all the icons are the same + Note that they all are of the same brightness: none of them + can be brighter or darker than the others. + + 2. Switch to DefaultMetalTheme. Ensure all the icons changed + (became slightly darker). + + 3. Switch back to Ocean. Ensure all the icons changed + (became brighter). + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4969419 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4969419::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal Themes Icon Test"); + Container pane = frame.getContentPane(); + + LFSwitch lfswitch = new LFSwitch(pane); + if (!lfswitch.obtainOceanTheme()) { + throw new RuntimeException("No Ocean theme available"); + } + + pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); + + String prefix = System.getProperty("test.src", + System.getProperty("user.dir")) + System.getProperty("file.separator"); + ImageIcon icon = new ImageIcon(prefix + "duke.gif"); + + JPanel panel = new JPanel(); + JButton b = new JButton(icon); + b.setEnabled(false); + + JLabel label = new JLabel(icon, SwingConstants.LEFT); + label.setEnabled(false); + + JTabbedPane tp = new JTabbedPane(); + tp.addTab("", icon, new JPanel()); + tp.addTab("", icon, new JPanel()); + tp.setEnabledAt(0, false); + tp.setEnabledAt(1, false); + + JButton sb = new JButton(icon); + sb.setSelectedIcon(icon); + sb.setSelected(true); + sb.setEnabled(false); + + JToggleButton tb = new JToggleButton(icon); + tb.setEnabled(false); + + JToggleButton stb = new JToggleButton(icon); + stb.setSelectedIcon(icon); + stb.setSelected(true); + stb.setEnabled(false); + + pane.setBackground(Color.white); + panel.setBackground(Color.white); + b.setBackground(Color.white); + label.setBackground(Color.white); + tp.setBackground(Color.white); + sb.setBackground(Color.white); + tb.setBackground(Color.white); + stb.setBackground(Color.white); + + panel.add(b); + panel.add(label); + panel.add(tp); + panel.add(sb); + panel.add(tb); + panel.add(stb); + + pane.add(panel); + pane.add(lfswitch); + frame.setSize(400, 400); + return frame; + } + + static class LFSwitch extends JPanel { + private Component target; + static MetalTheme oceanTheme; + JComboBox lfcombo; + + public LFSwitch(Component target) { + this.target = target; + setLayout(new FlowLayout()); + lfcombo = new JComboBox(lookAndFeels); + add(lfcombo); + JButton setLfBut = new JButton("Set"); + add(setLfBut); + setLfBut.addActionListener(e -> setLf(lfcombo.getSelectedIndex(), + LFSwitch.this.target)); + } + + boolean obtainOceanTheme() { + if (oceanTheme != null) { + return true; + } + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + SwingUtilities.updateComponentTreeUI(this); + } catch (Exception e) { + JOptionPane.showMessageDialog(this, + "Unexpected error: couldn't set Metal", "Error", + JOptionPane.ERROR_MESSAGE); + return false; + } + MetalTheme theme = (MetalTheme) AppContext.getAppContext(). + get("currentMetalTheme"); + if (theme == null || theme.getName() != "Ocean") { + JOptionPane.showMessageDialog(this, + "The Ocean theme is not the default Metal theme,\n" + + "but this test requires it to be default.\n" + + "Therefore simply click PASS"); + return false; + } + oceanTheme = theme; + return true; + } + + void setLf(int idx, final Component root) { + try { + UIManager.setLookAndFeel((LookAndFeel) lfs[idx]); + if (root != null) { + SwingUtilities.updateComponentTreeUI(root); + } + } catch (UnsupportedLookAndFeelException e) { + JOptionPane.showMessageDialog(root, + "The selected look and feel is unsupported on this platform", + "Error", JOptionPane.ERROR_MESSAGE); + } catch (Exception exc) { + JOptionPane.showMessageDialog(root, + "Error setting the selected look and feel", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + + static Object[] lookAndFeels = { + "Metal (Ocean)", "Metal (DefaultMetalTheme)", + }; + static Object[] lfs = { + new MetalLookAndFeel() { + protected void createDefaultTheme() { + setCurrentTheme(oceanTheme); + } + }, + new MetalLookAndFeel() { + protected void createDefaultTheme() { + MetalTheme dt = new DefaultMetalTheme(); + setCurrentTheme(dt); + } + }, + }; + } +} diff --git a/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif b/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed32e0ff79b05c07b82863ce6fb07fa9898adaa2 GIT binary patch literal 1929 zcmWlYe^AtB8pi`HvM4_?{J2I$8$dLc1#@!R2zwgXMWdj^k;9xr+bDW&4{JlE8WpDj z7F-cwwK{H<)?L&#SJz$!;hJ{%BY2FYf)Wp^xl?aq!5Xcdi$c#hV~>m9_n-Hl=Xsy+ z=li^?*Q~;pZ+R1N1J40KRkeWM7ew3~jLM24A{CM-A}~TzqzYpq&od0GC=z71!w_=b z-==B0rt2t*nA}((5YSLs6a*Z@X__WqiSjTW6oLo{5km&|K1mGAimYjhs#wwZtvV8SV~7LCFpgub+-TTAk%UQb0dE_cj+pc?!+0o?qG$?% zVFD)%!w7Z;g)ndE8Uk6Aky=+kLaUQ{UW`XS?Nn*s@SQ{VmFgGdkV{&&98EcEQ5hjc@H$`e)fX zj@&GdchxpMUo|-A^M4iBP3(#Ib53Ap?5{nGT7SBA_V!o!TTzL5R~FUWe)4X?@iTd8 z1;TcF^rQLj?4p0uy?@ikb2eUSXdHVa_jIn=@W%a<6~57D>am6&Z!{lzc=@ZbuGB8` zpU38H8d~@82Da!+qdYG5ls&Cx?~|oPMnbqTHMw%I*KlV~?fc{rSwe29?Om}fsknG# z@n5IwY=4Mx>>0WJLG>=yJX^WbHA30iQ$H!X)3<4K zBe1|sf3NKKTS;)mg{$k(2eDJG^u5=&x{@M!V>EWgzRA((>}?o{WQBehp1mIHU!BGG zYz5_6B(+KIVdCVoum2ItM&gXZd+SB^vQTN=a zeYbbah=i-xCho2{4Pazv_i%2mH`EkM{r8XYDLbdY@(a7Ud}$%!$QrTN_DqwNXA9~g zTGKxKyfto7NDp;5A3O5zgb(hyxjN@OAG!(zy^*Ug4!yjF=Y*8aHA@ovB1({&a4;sR zTf1CVC{>Pgy`m$lG;P1$pC_6F7u%iP+qz0q4{lXT`i9g-ThiYgO^GXC`f?JNo*|@p zr{b%U-tSKw99q0|YJa9{Va?`H{IaNICo>p5lGEY*+IDR4bfIUwq~CTRuC_mGWA%~W zea{@eKJ(Iq^7MvdsPsR%&vt$@4i&s?bPptz#y#!FcRZEaMS0WFTyXMCUEfsNxnJ_9 zPwpt`Er4O>``2G{7=4r1GCSTO8#0xw+{<^L4X(K8y1wKj72KLrYD}Y7SJuY7y==wf z;UkI5?(v?h+4r;vR{P*U`ul~=D@U7K5$eV8c!%rX-38vE>azU80UrhFXCv#d`(ylZS4+i2a^vI91MTIxCx%9gd2&N&D9RC&xcpx8#f=GZv%9;F z#?CEVT%UV$nk;L%RJA+d=f8ZB@U*Xz-TZbG?HKKT(VJZMBH!)$#qRuwbFc%Aljqha zoNBs8od~V$_^vux0ZSk!iP!hI($t35SxY8`FV{pxCjpU}Ova2VIg1&>V)CvvMb_ Date: Tue, 15 Apr 2025 21:25:06 +0000 Subject: [PATCH 188/843] 8354544: Fix bugs in increment and xor APX codegen Reviewed-by: thartmann, jbhateja --- src/hotspot/cpu/x86/x86_64.ad | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 5781ffce4bd..078150c61fb 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -7396,7 +7396,7 @@ instruct addL_mem_imm(memory dst, immL32 src, rFlagsReg cr) ins_pipe(ialu_mem_imm); %} -instruct incL_rReg(rRegI dst, immL1 src, rFlagsReg cr) +instruct incL_rReg(rRegL dst, immL1 src, rFlagsReg cr) %{ predicate(!UseAPX && UseIncDec); match(Set dst (AddL dst src)); @@ -7409,7 +7409,7 @@ instruct incL_rReg(rRegI dst, immL1 src, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct incL_rReg_ndd(rRegI dst, rRegI src, immL1 val, rFlagsReg cr) +instruct incL_rReg_ndd(rRegL dst, rRegI src, immL1 val, rFlagsReg cr) %{ predicate(UseAPX && UseIncDec); match(Set dst (AddL src val)); @@ -7422,7 +7422,7 @@ instruct incL_rReg_ndd(rRegI dst, rRegI src, immL1 val, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct incL_rReg_mem_ndd(rRegI dst, memory src, immL1 val, rFlagsReg cr) +instruct incL_rReg_mem_ndd(rRegL dst, memory src, immL1 val, rFlagsReg cr) %{ predicate(UseAPX && UseIncDec); match(Set dst (AddL (LoadL src) val)); @@ -11345,7 +11345,7 @@ instruct xorL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr ins_cost(150); format %{ "exorq $dst, $src1, $src2\t# long ndd" %} ins_encode %{ - __ exorq($dst$$Register, $src1$$Address, $src1$$Register, false); + __ exorq($dst$$Register, $src1$$Address, $src2$$Register, false); %} ins_pipe(ialu_reg_mem); %} From a2dc9c71e47a1cdf70ab351c557a5f1835eb5f4a Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Tue, 15 Apr 2025 23:48:27 +0000 Subject: [PATCH 189/843] 8352908: Open source several swing tests batch1 Reviewed-by: honkar --- .../javax/swing/JSplitPane/bug4749792.java | 77 ++++++++++++ test/jdk/javax/swing/JToolBar/bug4188825.java | 70 +++++++++++ test/jdk/javax/swing/JToolBar/bug4251592.java | 93 ++++++++++++++ test/jdk/javax/swing/JToolBar/bug5035668.java | 113 ++++++++++++++++++ 4 files changed, 353 insertions(+) create mode 100644 test/jdk/javax/swing/JSplitPane/bug4749792.java create mode 100644 test/jdk/javax/swing/JToolBar/bug4188825.java create mode 100644 test/jdk/javax/swing/JToolBar/bug4251592.java create mode 100644 test/jdk/javax/swing/JToolBar/bug5035668.java diff --git a/test/jdk/javax/swing/JSplitPane/bug4749792.java b/test/jdk/javax/swing/JSplitPane/bug4749792.java new file mode 100644 index 00000000000..1d9823073b7 --- /dev/null +++ b/test/jdk/javax/swing/JSplitPane/bug4749792.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4749792 + * @requires (os.family == "windows") + * @summary Split pane border is not painted properly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4749792 + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSplitPane; + +public class bug4749792 { + static final String INSTRUCTIONS = """ + If the right/bottom edges of JSplitPane's border is missing then the + test fails. If it is visible, then the test passes. + """; + + static JFrame createUI() { + JFrame frame = new JFrame("JSplitPane Border Test"); + frame.setSize(450, 220); + JPanel left = new JPanel(); + JPanel right = new JPanel(); + left.setPreferredSize(new Dimension(200, 200)); + right.setPreferredSize(new Dimension(200, 200)); + JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right); + frame.add(sp); + + JPanel south = new JPanel(); + south.setPreferredSize(new Dimension(20, 20)); + frame.add(south, BorderLayout.SOUTH); + + JPanel east = new JPanel(); + east.setPreferredSize(new Dimension(20, 20)); + frame.add(east, BorderLayout.EAST); + + return frame; + } + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4749792 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4749792::createUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JToolBar/bug4188825.java b/test/jdk/javax/swing/JToolBar/bug4188825.java new file mode 100644 index 00000000000..e5dd6538de4 --- /dev/null +++ b/test/jdk/javax/swing/JToolBar/bug4188825.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4188825 + * @summary Tests if toolbars return to original location when closed + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4188825 + */ + +import java.awt.BorderLayout; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; + +public class bug4188825 { + static final String INSTRUCTIONS = """ + Drag the toolbar out of frame and close it. If it returns to + the original location, then the test succeeded, otherwise it failed. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4188825 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4188825::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Toolbar Drag Test"); + frame.setLayout(new BorderLayout()); + JToolBar tb = new JToolBar(); + tb.setOrientation(JToolBar.VERTICAL); + tb.add(new JButton("a")); + tb.add(new JButton("b")); + tb.add(new JButton("c")); + frame.add(tb, BorderLayout.WEST); + JButton l = new JButton("Get me!!!"); + l.setSize(200, 200); + frame.add(l); + frame.setSize(200, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JToolBar/bug4251592.java b/test/jdk/javax/swing/JToolBar/bug4251592.java new file mode 100644 index 00000000000..add4eb8ec92 --- /dev/null +++ b/test/jdk/javax/swing/JToolBar/bug4251592.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4251592 + * @summary JToolBar should have ability to set custom layout. + * @key headful + * @run main bug4251592 + */ + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; +import javax.swing.SwingUtilities; + +public class bug4251592 { + private static final int OFFSET = 3; + private static volatile Point loc; + private static JFrame frame; + private static JToolBar toolBar; + private static GridLayout customLayout; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Toolbar Layout Save Test"); + toolBar = new JToolBar(); + customLayout = new GridLayout(); + frame.setLayout(new BorderLayout()); + frame.add(toolBar, BorderLayout.NORTH); + + toolBar.setLayout(customLayout); + toolBar.add(new JButton("Button1")); + toolBar.add(new JButton("Button2")); + toolBar.add(new JButton("Button3")); + toolBar.setFloatable(true); + + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> loc = toolBar.getLocationOnScreen()); + + robot.mouseMove(loc.x + OFFSET, loc.y + OFFSET); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(loc.x + OFFSET, loc.y + 50); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (toolBar.getLayout() != customLayout) { + throw new RuntimeException("Custom layout not saved..."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JToolBar/bug5035668.java b/test/jdk/javax/swing/JToolBar/bug5035668.java new file mode 100644 index 00000000000..b0cdef7c7ef --- /dev/null +++ b/test/jdk/javax/swing/JToolBar/bug5035668.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5035668 + * @summary Test that metal ToolBar border correctly sizes the MetalBumps used + * for the grip + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug5035668 + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.ComponentOrientation; +import java.awt.GridLayout; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JToolBar; +import javax.swing.UIManager; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; + +public class bug5035668 { + static final String INSTRUCTIONS = """ + This test is for Metal LaF only. + + All of them have an empty border around their own border. + If you see that in any toolbar the grip (little dotted strip) overlaps + the empty border press Fail. If you see that grips are completely + inside empty borders press Pass. + """; + + public static void main(String[] args) throws Exception { + // Set metal l&f + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4251592 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug5035668::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal JToolBar Border Overlap Test"); + frame.setLayout(new BorderLayout()); + frame.setBackground(Color.white); + + // Horizontal toolbar left-to-right + final JToolBar toolBar = new JToolBar(); + toolBar.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10), + toolBar.getBorder())); + toolBar.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + toolBar.add(new ToolBarButton(toolBar)); + + // Horizontal toolbar right-to-left + JToolBar toolBar2 = new JToolBar(); + toolBar2.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10), + toolBar2.getBorder())); + toolBar2.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + toolBar2.add(new ToolBarButton(toolBar2)); + + JPanel topPanel = new JPanel(new GridLayout(2, 0)); + topPanel.add(toolBar); + topPanel.add(toolBar2); + frame.add(topPanel, BorderLayout.NORTH); + + JToolBar toolBar3 = new JToolBar(); + toolBar3.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10), + toolBar3.getBorder())); + toolBar3.setOrientation(JToolBar.VERTICAL); + toolBar3.add(new ToolBarButton(toolBar3)); + frame.add(toolBar3, BorderLayout.EAST); + + frame.setSize(200, 200); + return frame; + } + + static class ToolBarButton extends JButton { + final JToolBar toolBar; + + public ToolBarButton(JToolBar p_toolBar) { + super("Change toolbar's orientation"); + this.toolBar = p_toolBar; + addActionListener(e -> toolBar.setOrientation(1 - toolBar.getOrientation())); + } + } +} From 5526490743a75786a40754b6805f4381ae2892b5 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 16 Apr 2025 01:57:57 +0000 Subject: [PATCH 190/843] 8354565: jtreg failure handler GatherProcessInfoTimeoutHandler has a leftover call to System.loadLibrary Reviewed-by: alanb, kbarrett --- .../jtreg/GatherProcessInfoTimeoutHandler.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/failure_handler/src/share/classes/jdk/test/failurehandler/jtreg/GatherProcessInfoTimeoutHandler.java b/test/failure_handler/src/share/classes/jdk/test/failurehandler/jtreg/GatherProcessInfoTimeoutHandler.java index 82b0151d86c..63ed7e5f2c7 100644 --- a/test/failure_handler/src/share/classes/jdk/test/failurehandler/jtreg/GatherProcessInfoTimeoutHandler.java +++ b/test/failure_handler/src/share/classes/jdk/test/failurehandler/jtreg/GatherProcessInfoTimeoutHandler.java @@ -36,19 +36,7 @@ import java.nio.file.Path; * A timeout handler for jtreg, which gathers information about the timed out * process and its children. */ -@SuppressWarnings("restricted") public class GatherProcessInfoTimeoutHandler extends TimeoutHandler { - private static final boolean HAS_NATIVE_LIBRARY; - static { - boolean value = true; - try { - System.loadLibrary("timeoutHandler"); - } catch (UnsatisfiedLinkError ignore) { - // not all os need timeoutHandler native-library - value = false; - } - HAS_NATIVE_LIBRARY = value; - } private static final String LOG_FILENAME = "processes.log"; private static final String OUTPUT_FILENAME = "processes.html"; From 55afcb57a5d9dbc7bfad75e35df6b96932f6b074 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 16 Apr 2025 03:58:17 +0000 Subject: [PATCH 191/843] 8352682: Opensource JComponent tests Reviewed-by: jdv, honkar --- .../javax/swing/JComponent/bug4235215.java | 64 +++++++++ .../javax/swing/JComponent/bug4247610.java | 128 ++++++++++++++++++ .../javax/swing/JComponent/bug4254995.java | 60 ++++++++ 3 files changed, 252 insertions(+) create mode 100644 test/jdk/javax/swing/JComponent/bug4235215.java create mode 100644 test/jdk/javax/swing/JComponent/bug4247610.java create mode 100644 test/jdk/javax/swing/JComponent/bug4254995.java diff --git a/test/jdk/javax/swing/JComponent/bug4235215.java b/test/jdk/javax/swing/JComponent/bug4235215.java new file mode 100644 index 00000000000..471f713ee46 --- /dev/null +++ b/test/jdk/javax/swing/JComponent/bug4235215.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4235215 + * @summary Tests that Toolkit.getPrintJob() do not throw NPE + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4235215 + */ + +import java.awt.Toolkit; +import javax.swing.JButton; +import javax.swing.JFrame; + +public class bug4235215 { + + private static final String INSTRUCTIONS = """ + Press "Print Dialog" button. + If you see a print dialog, test passes. + Click "Cancel" button to close it."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4235215 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4235215::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4235215"); + JButton button = new JButton("Print Dialog"); + button.addActionListener(ev -> { + Toolkit.getDefaultToolkit().getPrintJob(frame, "Test Printing", null); + }); + frame.add(button); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JComponent/bug4247610.java b/test/jdk/javax/swing/JComponent/bug4247610.java new file mode 100644 index 00000000000..e5470606f6e --- /dev/null +++ b/test/jdk/javax/swing/JComponent/bug4247610.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4247610 + * @summary Tests an unnecessary repaint issue + * @key headful + * @run main bug4247610 + */ + +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Random; + +public class bug4247610 { + + private static JFrame frame; + private static JButton damager; + private static volatile Point loc; + private static volatile Dimension size; + private static volatile boolean traced; + private static volatile boolean failed; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4247610"); + JDesktopPane pane = new JDesktopPane(); + + JInternalFrame jif = new JInternalFrame( + "Damager", true, true, true, true); + InternalFramePanel ifp = new InternalFramePanel(); + damager = new JButton("Damage!"); + ifp.add(damager); + jif.setContentPane(ifp); + jif.setBounds(0, 0, 300, 300); + jif.setVisible(true); + pane.add(jif); + + jif = new JInternalFrame("Damagee", true, true, true, true); + JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + final JLabel damagee = new JLabel(""); + panel.add(damagee); + jif.setContentPane(panel); + jif.setBounds(60, 220, 300, 100); + jif.setVisible(true); + pane.add(jif); + + final Random random = new Random(); + + damager.addActionListener((e) -> { + System.out.println("trace paints enabled"); + traced = true; + damagee.setText(Integer.toString(random.nextInt())); + }); + frame.setContentPane(pane); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + loc = damager.getLocationOnScreen(); + size = damager.getSize(); + }); + robot.mouseMove(loc.x + size.width / 2, loc.y + size.height / 2); + robot.waitForIdle(); + robot.delay(200); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + if (failed) { + throw new RuntimeException("Failed: unnecessary repaint occured"); + } + } + + + static class InternalFramePanel extends JPanel { + final AtomicInteger repaintCounter = new AtomicInteger(0); + InternalFramePanel() { + super(new FlowLayout()); + setOpaque(true); + } + + public synchronized void paintComponent(Graphics g) { + super.paintComponent(g); + repaintCounter.incrementAndGet(); + System.out.println("repaintCounter " + repaintCounter.intValue()); + if (traced) { + failed = true; + } + } + } +} diff --git a/test/jdk/javax/swing/JComponent/bug4254995.java b/test/jdk/javax/swing/JComponent/bug4254995.java new file mode 100644 index 00000000000..8947558f128 --- /dev/null +++ b/test/jdk/javax/swing/JComponent/bug4254995.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4254995 + * @summary Tests that html in renderer works correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4254995 + */ + +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; + +public class bug4254995 { + + private static final String INSTRUCTIONS = """ + If you see a list containing digits from one to seven, test passes. + Otherwise it fails."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4254995 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4254995::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4254995"); + String[] data = { "1", "2", "3", "4", "5", "6", "7" }; + frame.add(new JScrollPane(new JList(data))); + frame.pack(); + return frame; + } +} From 2be5bc847a444f08a4ebb41b58e8a2bf4553d621 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Wed, 16 Apr 2025 04:48:25 +0000 Subject: [PATCH 192/843] 8354214: Open source Swing tests Batch 2 Reviewed-by: abhiscxk, honkar --- test/jdk/javax/swing/JList/bug4193267.java | 117 +++++++++++++++++++ test/jdk/javax/swing/JList/bug4249161.java | 96 ++++++++++++++++ test/jdk/javax/swing/JList/bug4618767.java | 127 +++++++++++++++++++++ 3 files changed, 340 insertions(+) create mode 100644 test/jdk/javax/swing/JList/bug4193267.java create mode 100644 test/jdk/javax/swing/JList/bug4249161.java create mode 100644 test/jdk/javax/swing/JList/bug4618767.java diff --git a/test/jdk/javax/swing/JList/bug4193267.java b/test/jdk/javax/swing/JList/bug4193267.java new file mode 100644 index 00000000000..cb447644d15 --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4193267.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4193267 + * @summary Tests that JList first and last visible indices are + * updated properly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4193267 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.GridLayout; +import java.util.List; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +public class bug4193267 { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + Resize the frame "JList" with a different ways and scroll the list + (if it possible). The indices of first and last visible elements + should be indicated in the corresponding fields in "Index" frame. + If the indicated indices is not right then test fails. + + Note: + - the first and last visible indices should be -1 if nothing + is visible; + - the first or last visible cells may only be partially visible. + """; + PassFailJFrame.builder() + .title("bug4193267 Instructions") + .instructions(INSTRUCTIONS) + .positionTestUI(WindowLayouts::rightOneRow) + .columns(35) + .testUI(bug4193267::initialize) + .build() + .awaitAndCheck(); + } + + private static List initialize() { + String[] data = {"000000000000000", "111111111111111", + "222222222222222", "333333333333333", + "444444444444444", "555555555555555", + "666666666666666", "777777777777777", + "888888888888888", "999999999999999"}; + + JFrame[] fr = new JFrame[2]; + fr[0] = new JFrame("JList"); + JList lst = new JList(data); + lst.setLayoutOrientation(JList.VERTICAL_WRAP); + lst.setVisibleRowCount(4); + JScrollPane jsp = new JScrollPane(lst); + fr[0].add(jsp); + fr[0].setSize(400, 200); + + JPanel pL = new JPanel(); + pL.setLayout(new GridLayout(2, 1)); + pL.add(new JLabel("First Visible Index")); + pL.add(new JLabel("Last Visible Index")); + + JPanel p = new JPanel(); + p.setLayout(new GridLayout(2, 1)); + JTextField first = new JTextField("0", 2); + first.setEditable(false); + first.setBackground(Color.white); + p.add(first); + JTextField last = new JTextField("9", 2); + last.setEditable(false); + last.setBackground(Color.white); + p.add(last); + + fr[1] = new JFrame("Index"); + fr[1].setSize(200, 200); + fr[1].setLayout(new FlowLayout()); + fr[1].add(pL); + fr[1].add(p); + + jsp.getViewport().addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + first.setText(String.valueOf(lst.getFirstVisibleIndex())); + last.setText(String.valueOf(lst.getLastVisibleIndex())); + } + }); + List frameList = List.of(fr[0], fr[1]); + return frameList; + } +} diff --git a/test/jdk/javax/swing/JList/bug4249161.java b/test/jdk/javax/swing/JList/bug4249161.java new file mode 100644 index 00000000000..09bdd93600f --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4249161.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4249161 + * @summary Tests that JList.setComponentOrientation() works correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4249161 + */ + +import java.awt.BorderLayout; +import java.awt.ComponentOrientation; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; + +public class bug4249161 { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. With a scroll bar, confirm that all words ("one" - "twenty") are + aligned at the left side of a list. + 2. Press "Change!" button. All words on the list should be moved + to the right side. + 3. Press the same button again. All words should be moved to the + left side. + + If all items in a list are moved as soon as "Change!" button is + pressed, test passes. + """; + PassFailJFrame.builder() + .title("bug4249161 Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4249161::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JFrame fr = new JFrame("bug4249161"); + + String[] data = {"one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", + "eleven", "twelve", "thirteen", "fourteen", "fifteen", + "sixteen", "seventeen", "eighteen", "nineteen", "twenty" + }; + final JList list = new JList(data); + list.setSize(200, 200); + list.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + JScrollPane pane = new JScrollPane(list); + fr.add(pane); + + JButton button = new JButton("Change!"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (list.getComponentOrientation() != + ComponentOrientation.RIGHT_TO_LEFT) { + list.setComponentOrientation + (ComponentOrientation.RIGHT_TO_LEFT); + } else { + list.setComponentOrientation + (ComponentOrientation.LEFT_TO_RIGHT); + } + } + }); + fr.add(button, BorderLayout.SOUTH); + fr.setSize(200, 300); + fr.setAlwaysOnTop(true); + return fr; + } +} diff --git a/test/jdk/javax/swing/JList/bug4618767.java b/test/jdk/javax/swing/JList/bug4618767.java new file mode 100644 index 00000000000..f01e20f365c --- /dev/null +++ b/test/jdk/javax/swing/JList/bug4618767.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4618767 + * @summary First letter navigation in JList interferes with mnemonics + * @key headful + * @run main bug4618767 + */ + +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +public class bug4618767 { + private static JFrame f; + private static final JList list = new + JList(new String[] {"one", "two", "three", "four"}); + private static boolean menuSelected; + private static volatile boolean failed; + private static CountDownLatch listGainedFocusLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + try { + createUI(); + runTest(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void createUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4618767"); + JMenu menu = new JMenu("File"); + menu.setMnemonic('F'); + JMenuItem menuItem = new JMenuItem("item"); + menu.add(menuItem); + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + f.setJMenuBar(menuBar); + + menu.addMenuListener(new MenuListener() { + public void menuCanceled(MenuEvent e) {} + public void menuDeselected(MenuEvent e) {} + public void menuSelected(MenuEvent e) { + menuSelected = true; + } + }); + + list.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + listGainedFocusLatch.countDown(); + } + }); + f.add(list); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + } + + private static void runTest() throws Exception { + if (!listGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't gain" + + " focus for list"); + } + Robot robot = new Robot(); + robot.setAutoDelay(200); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_O); + robot.keyRelease(KeyEvent.VK_O); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + + SwingUtilities.invokeAndWait(() -> { + if (menuSelected && list.getSelectedIndex()!= 0) { + failed = true; + } + }); + if (failed) { + throw new RuntimeException("Mnemonics interferes with Jlist" + + " item selection using KeyEvent"); + } + } +} From 9a5c7b3fa90c7f550773e98ee9466ca1665aff4f Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 16 Apr 2025 05:54:21 +0000 Subject: [PATCH 193/843] 8351162: Clean up x86 (Macro)Assembler after 32-bit x86 removal Reviewed-by: kvn, coleenp --- src/hotspot/cpu/x86/assembler_x86.cpp | 249 +---- src/hotspot/cpu/x86/assembler_x86.hpp | 107 +- src/hotspot/cpu/x86/assembler_x86.inline.hpp | 54 - src/hotspot/cpu/x86/macroAssembler_x86.cpp | 921 ++---------------- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 180 +--- .../cpu/x86/macroAssembler_x86_sha.cpp | 28 - ...ssemblerx86.cpp => test_assembler_x86.cpp} | 1 + 7 files changed, 143 insertions(+), 1397 deletions(-) rename test/hotspot/gtest/x86/{test_assemblerx86.cpp => test_assembler_x86.cpp} (99%) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 82a16dc4dd1..6853af9e746 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -24,6 +24,8 @@ #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" #include "gc/shared/cardTableBarrierSet.hpp" #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" @@ -119,8 +121,6 @@ AddressLiteral::AddressLiteral(address target, relocInfo::relocType rtype) { // Implementation of Address -#ifdef _LP64 - Address Address::make_array(ArrayAddress adr) { // Not implementable on 64bit machines // Should have been handled higher up the call chain. @@ -157,30 +157,6 @@ Address::Address(int disp, address loc, relocInfo::relocType rtype) { ShouldNotReachHere(); } } -#else // LP64 - -Address Address::make_array(ArrayAddress adr) { - AddressLiteral base = adr.base(); - Address index = adr.index(); - assert(index._disp == 0, "must not have disp"); // maybe it can? - Address array(index._base, index._index, index._scale, (intptr_t) base.target()); - array._rspec = base._rspec; - return array; -} - -// exceedingly dangerous constructor -Address::Address(address loc, RelocationHolder spec) { - _base = noreg; - _index = noreg; - _scale = no_scale; - _disp = (intptr_t) loc; - _rspec = spec; - _xmmindex = xnoreg; - _isxmmindex = false; -} - -#endif // _LP64 - // Convert the raw encoding form into the form expected by the constructor for @@ -214,7 +190,6 @@ void Assembler::init_attributes(void) { _legacy_mode_dq = (VM_Version::supports_avx512dq() == false); _legacy_mode_vl = (VM_Version::supports_avx512vl() == false); _legacy_mode_vlbw = (VM_Version::supports_avx512vlbw() == false); - NOT_LP64(_is_managed = false;) _attributes = nullptr; } @@ -744,8 +719,8 @@ void Assembler::emit_operand_helper(int reg_enc, int base_enc, int index_enc, assert(inst_mark() != nullptr, "must be inside InstructionMark"); address next_ip = pc() + sizeof(int32_t) + post_addr_length; int64_t adjusted = disp; - // Do rip-rel adjustment for 64bit - LP64_ONLY(adjusted -= (next_ip - inst_mark())); + // Do rip-rel adjustment + adjusted -= (next_ip - inst_mark()); assert(is_simm32(adjusted), "must be 32bit offset (RIP relative address)"); emit_data((int32_t) adjusted, rspec, disp32_operand); @@ -846,7 +821,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case FS_segment: case GS_segment: // Seems dubious - LP64_ONLY(assert(false, "shouldn't have that prefix")); + assert(false, "shouldn't have that prefix"); assert(ip == inst+1, "only one prefix allowed"); goto again_after_prefix; @@ -859,11 +834,9 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case REX_RB: case REX_RX: case REX_RXB: - NOT_LP64(assert(false, "64bit prefixes")); goto again_after_prefix; case REX2: - NOT_LP64(assert(false, "64bit prefixes")); if ((0xFF & *ip++) & REX2BIT_W) { is_64bit = true; } @@ -877,7 +850,6 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case REX_WRB: case REX_WRX: case REX_WRXB: - NOT_LP64(assert(false, "64bit prefixes")); is_64bit = true; goto again_after_prefix; @@ -916,11 +888,9 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case REX_WRB: case REX_WRX: case REX_WRXB: - NOT_LP64(assert(false, "64bit prefix found")); goto again_after_size_prefix2; case REX2: - NOT_LP64(assert(false, "64bit prefix found")); if ((0xFF & *ip++) & REX2BIT_W) { is_64bit = true; } @@ -945,14 +915,9 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case REP8(0xB8): // movl/q r, #32/#64(oop?) if (which == end_pc_operand) return ip + (is_64bit ? 8 : 4); // these asserts are somewhat nonsensical -#ifndef _LP64 - assert(which == imm_operand || which == disp32_operand, - "which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, p2i(ip)); -#else assert(((which == call32_operand || which == imm_operand) && is_64bit) || (which == narrow_oop_operand && !is_64bit), "which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, p2i(ip)); -#endif // _LP64 return ip; case 0x69: // imul r, a, #32 @@ -1113,8 +1078,6 @@ address Assembler::locate_operand(address inst, WhichOperand which) { // to check for them in product version. // Check second byte - NOT_LP64(assert((0xC0 & *ip) == 0xC0, "shouldn't have LDS and LES instructions")); - int vex_opcode; // First byte if ((0xFF & *inst) == VEX_3bytes) { @@ -1216,8 +1179,8 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case REX_WRX: case REX_WRXB: case REX2: - NOT_LP64(assert(false, "found 64bit prefix")); ip++; + // fall-through default: ip++; } @@ -1232,12 +1195,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { } assert(which != call32_operand, "instruction is not a call, jmp, or jcc"); -#ifdef _LP64 assert(which != imm_operand, "instruction is not a movq reg, imm64"); -#else - // assert(which != imm_operand || has_imm32, "instruction has no imm32 field"); - assert(which != imm_operand || has_disp32, "instruction has no imm32 field"); -#endif // LP64 assert(which != disp32_operand || has_disp32, "instruction has no disp32 field"); // parse the output of emit_operand @@ -1292,11 +1250,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { return ip + tail_size; } -#ifdef _LP64 assert(which == narrow_oop_operand && !is_64bit, "instruction is not a movl adr, imm32"); -#else - assert(which == imm_operand, "instruction has only an imm field"); -#endif // LP64 return ip; } @@ -1319,8 +1273,7 @@ void Assembler::check_relocation(RelocationHolder const& rspec, int format) { // assert(format == imm32_operand, "cannot specify a nonzero format"); opnd = locate_operand(inst, call32_operand); } else if (r->is_data()) { - assert(format == imm_operand || format == disp32_operand - LP64_ONLY(|| format == narrow_oop_operand), "format ok"); + assert(format == imm_operand || format == disp32_operand || format == narrow_oop_operand, "format ok"); opnd = locate_operand(inst, (WhichOperand)format); } else { assert(format == imm_operand, "cannot specify a format"); @@ -1830,9 +1783,6 @@ void Assembler::blsrl(Register dst, Address src) { } void Assembler::call(Label& L, relocInfo::relocType rtype) { - // suspect disp32 is always good - int operand = LP64_ONLY(disp32_operand) NOT_LP64(imm_operand); - if (L.is_bound()) { const int long_size = 5; int offs = (int)( target(L) - pc() ); @@ -1840,14 +1790,14 @@ void Assembler::call(Label& L, relocInfo::relocType rtype) { InstructionMark im(this); // 1110 1000 #32-bit disp emit_int8((unsigned char)0xE8); - emit_data(offs - long_size, rtype, operand); + emit_data(offs - long_size, rtype, disp32_operand); } else { InstructionMark im(this); // 1110 1000 #32-bit disp L.add_patch_at(code(), locator()); emit_int8((unsigned char)0xE8); - emit_data(int(0), rtype, operand); + emit_data(int(0), rtype, disp32_operand); } } @@ -1874,8 +1824,7 @@ void Assembler::call_literal(address entry, RelocationHolder const& rspec) { // Technically, should use call32_operand, but this format is // implied by the fact that we're emitting a call instruction. - int operand = LP64_ONLY(disp32_operand) NOT_LP64(call32_operand); - emit_data((int) disp, rspec, operand); + emit_data((int) disp, rspec, disp32_operand); } void Assembler::cdql() { @@ -1887,7 +1836,6 @@ void Assembler::cld() { } void Assembler::cmovl(Condition cc, Register dst, Register src) { - NOT_LP64(guarantee(VM_Version::supports_cmov(), "illegal instruction")); int encode = prefix_and_encode(dst->encoding(), src->encoding(), true /* is_map1 */); emit_opcode_prefix_and_encoding(0x40 | cc, 0xC0, encode); } @@ -1900,7 +1848,6 @@ void Assembler::ecmovl(Condition cc, Register dst, Register src1, Register src2) void Assembler::cmovl(Condition cc, Register dst, Address src) { InstructionMark im(this); - NOT_LP64(guarantee(VM_Version::supports_cmov(), "illegal instruction")); prefix(src, dst, false, true /* is_map1 */); emit_int8((0x40 | cc)); emit_operand(dst, src, 0); @@ -2091,8 +2038,7 @@ void Assembler::crc32(Register crc, Register v, int8_t sizeInBytes) { case 2: case 4: break; - LP64_ONLY(case 8:) - // This instruction is not valid in 32 bits + case 8: // Note: // http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf // @@ -2111,7 +2057,7 @@ void Assembler::crc32(Register crc, Register v, int8_t sizeInBytes) { assert(0, "Unsupported value for a sizeInBytes argument"); break; } - LP64_ONLY(prefix(crc, v, p);) + prefix(crc, v, p); emit_int32(0x0F, 0x38, 0xF0 | w, @@ -2140,15 +2086,14 @@ void Assembler::crc32(Register crc, Address adr, int8_t sizeInBytes) { case 2: case 4: break; - LP64_ONLY(case 8:) - // This instruction is not valid in 32 bits + case 8: p = REX_W; break; default: assert(0, "Unsupported value for a sizeInBytes argument"); break; } - LP64_ONLY(prefix(crc, adr, p);) + prefix(crc, adr, p); emit_int24(0x0F, 0x38, (0xF0 | w)); emit_operand(crc, adr, 0); } @@ -2840,7 +2785,6 @@ void Assembler::leal(Register dst, Address src) { emit_operand(dst, src, 0); } -#ifdef _LP64 void Assembler::lea(Register dst, Label& L) { emit_prefix_and_int8(get_prefixq(Address(), dst), (unsigned char)0x8D); if (!L.is_bound()) { @@ -2858,7 +2802,6 @@ void Assembler::lea(Register dst, Label& L) { emit_int32(disp); } } -#endif void Assembler::lfence() { emit_int24(0x0F, (unsigned char)0xAE, (unsigned char)0xE8); @@ -2916,7 +2859,7 @@ void Assembler::sfence() { } void Assembler::mov(Register dst, Register src) { - LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); + movq(dst, src); } void Assembler::movapd(XMMRegister dst, XMMRegister src) { @@ -2941,7 +2884,6 @@ void Assembler::movlhps(XMMRegister dst, XMMRegister src) { } void Assembler::movb(Register dst, Address src) { - NOT_LP64(assert(dst->has_byte_register(), "must have byte register")); InstructionMark im(this); prefix(src, dst, true); emit_int8((unsigned char)0x8A); @@ -3932,7 +3874,6 @@ void Assembler::movsbl(Register dst, Address src) { // movsxb } void Assembler::movsbl(Register dst, Register src) { // movsxb - NOT_LP64(assert(src->has_byte_register(), "must have byte register")); int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true, true /* is_map1 */); emit_opcode_prefix_and_encoding((unsigned char)0xBE, 0xC0, encode); } @@ -4082,7 +4023,6 @@ void Assembler::movzbl(Register dst, Address src) { // movzxb } void Assembler::movzbl(Register dst, Register src) { // movzxb - NOT_LP64(assert(src->has_byte_register(), "must have byte register")); int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true, true /* is_map1 */); emit_opcode_prefix_and_encoding((unsigned char)0xB6, 0xC0, encode); } @@ -5810,16 +5750,6 @@ void Assembler::popf() { emit_int8((unsigned char)0x9D); } -#ifndef _LP64 // no 32bit push/pop on amd64 -void Assembler::popl(Address dst) { - // NOTE: this will adjust stack by 8byte on 64bits - InstructionMark im(this); - prefix(dst); - emit_int8((unsigned char)0x8F); - emit_operand(rax, dst, 0); -} -#endif - void Assembler::prefetchnta(Address src) { InstructionMark im(this); prefix(src, true /* is_map1 */); @@ -6220,7 +6150,6 @@ void Assembler::evpunpckhqdq(XMMRegister dst, KRegister mask, XMMRegister src1, emit_int16(0x6D, (0xC0 | encode)); } -#ifdef _LP64 void Assembler::push2(Register src1, Register src2, bool with_ppx) { assert(VM_Version::supports_apx_f(), "requires APX"); InstructionAttr attributes(0, /* rex_w */ with_ppx, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); @@ -6282,8 +6211,6 @@ void Assembler::popp(Register dst) { int encode = prefixq_and_encode_rex2(dst->encoding()); emit_int8((unsigned char)0x58 | encode); } -#endif //_LP64 - void Assembler::push(int32_t imm32) { // in 64bits we push 64bits onto the stack but only @@ -6301,16 +6228,6 @@ void Assembler::pushf() { emit_int8((unsigned char)0x9C); } -#ifndef _LP64 // no 32bit push/pop on amd64 -void Assembler::pushl(Address src) { - // Note this will push 64bit on 64bit - InstructionMark im(this); - prefix(src); - emit_int8((unsigned char)0xFF); - emit_operand(rsi, src, 0); -} -#endif - void Assembler::rcll(Register dst, int imm8) { assert(isShiftCount(imm8), "illegal shift count"); int encode = prefix_and_encode(dst->encoding()); @@ -6353,43 +6270,37 @@ void Assembler::rdtsc() { void Assembler::rep_mov() { // REP // MOVSQ - LP64_ONLY(emit_int24((unsigned char)0xF3, REX_W, (unsigned char)0xA5);) - NOT_LP64( emit_int16((unsigned char)0xF3, (unsigned char)0xA5);) + emit_int24((unsigned char)0xF3, REX_W, (unsigned char)0xA5); } // sets rcx bytes with rax, value at [edi] void Assembler::rep_stosb() { // REP // STOSB - LP64_ONLY(emit_int24((unsigned char)0xF3, REX_W, (unsigned char)0xAA);) - NOT_LP64( emit_int16((unsigned char)0xF3, (unsigned char)0xAA);) + emit_int24((unsigned char)0xF3, REX_W, (unsigned char)0xAA); } // sets rcx pointer sized words with rax, value at [edi] // generic void Assembler::rep_stos() { // REP - // LP64:STOSQ, LP32:STOSD - LP64_ONLY(emit_int24((unsigned char)0xF3, REX_W, (unsigned char)0xAB);) - NOT_LP64( emit_int16((unsigned char)0xF3, (unsigned char)0xAB);) + // STOSQ + emit_int24((unsigned char)0xF3, REX_W, (unsigned char)0xAB); } // scans rcx pointer sized words at [edi] for occurrence of rax, // generic void Assembler::repne_scan() { // repne_scan // SCASQ - LP64_ONLY(emit_int24((unsigned char)0xF2, REX_W, (unsigned char)0xAF);) - NOT_LP64( emit_int16((unsigned char)0xF2, (unsigned char)0xAF);) + emit_int24((unsigned char)0xF2, REX_W, (unsigned char)0xAF); } -#ifdef _LP64 // scans rcx 4 byte words at [edi] for occurrence of rax, // generic void Assembler::repne_scanl() { // repne_scan // SCASL emit_int16((unsigned char)0xF2, (unsigned char)0xAF); } -#endif void Assembler::ret(int imm16) { if (imm16 == 0) { @@ -6464,7 +6375,6 @@ void Assembler::erorl(Register dst, Register src, bool no_flags) { emit_int16((unsigned char)0xD3, (0xC8 | encode)); } -#ifdef _LP64 void Assembler::rorq(Register dst) { int encode = prefixq_and_encode(dst->encoding()); emit_int16((unsigned char)0xD3, (0xC8 | encode)); @@ -6527,15 +6437,6 @@ void Assembler::erolq(Register dst, Register src, int imm8, bool no_flags) { } else { emit_int24((unsigned char)0xC1, (0xc0 | encode), imm8); } - } -#endif - -void Assembler::sahf() { -#ifdef _LP64 - // Not supported in 64bit mode - ShouldNotReachHere(); -#endif - emit_int8((unsigned char)0x9E); } void Assembler::sall(Address dst, int imm8) { @@ -6988,7 +6889,6 @@ void Assembler::eshrdl(Register dst, Register src1, Register src2, int8_t imm8, emit_int24(0x2C, (0xC0 | encode), imm8); } -#ifdef _LP64 void Assembler::shldq(Register dst, Register src, int8_t imm8) { int encode = prefixq_and_encode(src->encoding(), dst->encoding(), true /* is_map1 */); emit_opcode_prefix_and_encoding((unsigned char)0xA4, 0xC0, encode, imm8); @@ -7014,7 +6914,6 @@ void Assembler::eshrdq(Register dst, Register src1, Register src2, int8_t imm8, int encode = evex_prefix_and_encode_ndd(src2->encoding(), dst->encoding(), src1->encoding(), VEX_SIMD_NONE, /* MAP4 */VEX_OPCODE_0F_3C, &attributes, no_flags); emit_int24(0x2C, (0xC0 | encode), imm8); } -#endif // copies a single word from [esi] to [edi] void Assembler::smovl() { @@ -7208,7 +7107,6 @@ void Assembler::subss(XMMRegister dst, Address src) { } void Assembler::testb(Register dst, int imm8, bool use_ral) { - NOT_LP64(assert(dst->has_byte_register(), "must have byte register")); if (dst == rax) { if (use_ral) { emit_int8((unsigned char)0xA8); @@ -12872,54 +12770,6 @@ void Assembler::emit_farith(int b1, int b2, int i) { emit_int16(b1, b2 + i); } -#ifndef _LP64 -// 32bit only pieces of the assembler - -void Assembler::emms() { - NOT_LP64(assert(VM_Version::supports_mmx(), "")); - emit_int16(0x0F, 0x77); -} - -void Assembler::vzeroupper() { - vzeroupper_uncached(); -} - -void Assembler::cmp_literal32(Register src1, int32_t imm32, RelocationHolder const& rspec) { - // NO PREFIX AS NEVER 64BIT - InstructionMark im(this); - emit_int16((unsigned char)0x81, (0xF8 | src1->encoding())); - emit_data(imm32, rspec, 0); -} - -void Assembler::cmp_literal32(Address src1, int32_t imm32, RelocationHolder const& rspec) { - // NO PREFIX AS NEVER 64BIT (not even 32bit versions of 64bit regs - InstructionMark im(this); - emit_int8((unsigned char)0x81); - emit_operand(rdi, src1, 4); - emit_data(imm32, rspec, 0); -} - -// The 64-bit (32bit platform) cmpxchg compares the value at adr with the contents of rdx:rax, -// and stores rcx:rbx into adr if so; otherwise, the value at adr is loaded -// into rdx:rax. The ZF is set if the compared values were equal, and cleared otherwise. -void Assembler::cmpxchg8(Address adr) { - InstructionMark im(this); - emit_int16(0x0F, (unsigned char)0xC7); - emit_operand(rcx, adr, 0); -} - -void Assembler::decl(Register dst) { - // Don't use it directly. Use MacroAssembler::decrementl() instead. - emit_int8(0x48 | dst->encoding()); -} - -void Assembler::edecl(Register dst, Register src, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - (void) evex_prefix_and_encode_ndd(0, dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags); - emit_int8(0x48 | src->encoding()); -} -#endif // !_LP64 - // SSE SIMD prefix byte values corresponding to VexSimdPrefix encoding. static int simd_pre[4] = { 0, 0x66, 0xF3, 0xF2 }; // SSE opcode second byte values (first is 0x0F) corresponding to VexOpcode encoding. @@ -13053,7 +12903,7 @@ void Assembler::vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix // is allowed in legacy mode and has resources which will fit in it. // Pure EVEX instructions will have is_evex_instruction set in their definition. if (!attributes->is_legacy_mode()) { - if (UseAVX > 2 && !attributes->is_evex_instruction() && !is_managed()) { + if (UseAVX > 2 && !attributes->is_evex_instruction()) { if ((attributes->get_vector_len() != AVX_512bit) && !is_extended) { attributes->set_is_legacy_mode(); } @@ -13068,7 +12918,6 @@ void Assembler::vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix assert((!is_extended || (!attributes->is_legacy_mode())),"XMM register should be 0-15"); } - clear_managed(); if (UseAVX > 2 && !attributes->is_legacy_mode()) { bool evex_r = (xreg_enc >= 16); @@ -13116,7 +12965,7 @@ int Assembler::vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexS // is allowed in legacy mode and has resources which will fit in it. // Pure EVEX instructions will have is_evex_instruction set in their definition. if (!attributes->is_legacy_mode()) { - if (UseAVX > 2 && !attributes->is_evex_instruction() && !is_managed()) { + if (UseAVX > 2 && !attributes->is_evex_instruction()) { if ((!attributes->uses_vl() || (attributes->get_vector_len() != AVX_512bit)) && !is_extended) { attributes->set_is_legacy_mode(); @@ -13138,7 +12987,6 @@ int Assembler::vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexS assert(((!is_extended) || (!attributes->is_legacy_mode())),"XMM register should be 0-15"); } - clear_managed(); if (UseAVX > 2 && !attributes->is_legacy_mode()) { bool evex_r = (dst_enc >= 16); @@ -14038,55 +13886,6 @@ void Assembler::evcompresspd(XMMRegister dst, KRegister mask, XMMRegister src, b emit_int16((unsigned char)0x8A, (0xC0 | encode)); } -#ifndef _LP64 - -void Assembler::incl(Register dst) { - // Don't use it directly. Use MacroAssembler::incrementl() instead. - emit_int8(0x40 | dst->encoding()); -} - -void Assembler::eincl(Register dst, Register src, bool no_flags) { - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false); - (void) evex_prefix_and_encode_ndd(0, dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags); - emit_int8(0x40 | src->encoding()); -} - -void Assembler::lea(Register dst, Address src) { - leal(dst, src); -} - -void Assembler::mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec) { - InstructionMark im(this); - emit_int8((unsigned char)0xC7); - emit_operand(rax, dst, 4); - emit_data((int)imm32, rspec, 0); -} - -void Assembler::mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec) { - InstructionMark im(this); - int encode = prefix_and_encode(dst->encoding()); - emit_int8((0xB8 | encode)); - emit_data((int)imm32, rspec, 0); -} - -void Assembler::popa() { // 32bit - emit_int8(0x61); -} - -void Assembler::push_literal32(int32_t imm32, RelocationHolder const& rspec) { - InstructionMark im(this); - emit_int8(0x68); - emit_data(imm32, rspec, 0); -} - -void Assembler::pusha() { // 32bit - emit_int8(0x60); -} - -#else // LP64 - -// 64bit only pieces of the assembler - // This should only be used by 64bit instructions that can use rip-relative // it cannot be used by instructions that want an immediate value. @@ -16039,7 +15838,6 @@ void Assembler::rorxq(Register dst, Address src, int imm8) { emit_int8(imm8); } -#ifdef _LP64 void Assembler::salq(Address dst, int imm8) { InstructionMark im(this); assert(isShiftCount(imm8 >> 1), "illegal shift count"); @@ -16194,7 +15992,6 @@ void Assembler::esarq(Register dst, Register src, bool no_flags) { int encode = evex_prefix_and_encode_ndd(0, dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C, &attributes, no_flags); emit_int16((unsigned char)0xD3, (0xF8 | encode)); } -#endif void Assembler::sbbq(Address dst, int32_t imm32) { InstructionMark im(this); @@ -16539,8 +16336,6 @@ void Assembler::exorq(Register dst, Address src1, Register src2, bool no_flags) emit_operand(src2, src1, 0); } -#endif // !LP64 - void InstructionAttr::set_address_attributes(int tuple_type, int input_size_in_bits) { if (VM_Version::supports_evex()) { _tuple_type = tuple_type; diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 33fd0745fb6..6395be02f27 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -35,7 +35,6 @@ class Argument { public: enum { -#ifdef _LP64 #ifdef _WIN64 n_int_register_parameters_c = 4, // rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...) n_float_register_parameters_c = 4, // xmm0 - xmm3 (c_farg0, c_farg1, ... ) @@ -49,16 +48,10 @@ class Argument { #endif // _WIN64 n_int_register_parameters_j = 6, // j_rarg0, j_rarg1, ... n_float_register_parameters_j = 8 // j_farg0, j_farg1, ... -#else - n_register_parameters = 0, // 0 registers used to pass arguments - n_int_register_parameters_j = 0, - n_float_register_parameters_j = 0 -#endif // _LP64 }; }; -#ifdef _LP64 // Symbolically name the register arguments used by the c calling convention. // Windows is different from linux/solaris. So much for standards... @@ -138,15 +131,6 @@ constexpr Register rscratch2 = r11; // volatile constexpr Register r12_heapbase = r12; // callee-saved constexpr Register r15_thread = r15; // callee-saved -#else -// rscratch1 will appear in 32bit code that is dead but of course must compile -// Using noreg ensures if the dead code is incorrectly live and executed it -// will cause an assertion failure -#define rscratch1 noreg -#define rscratch2 noreg - -#endif // _LP64 - // JSR 292 // On x86, the SP does not have to be saved when invoking method handle intrinsics // or compiled lambda forms. We indicate that by setting rbp_mh_SP_save to noreg. @@ -168,7 +152,7 @@ class Address { times_2 = 1, times_4 = 2, times_8 = 3, - times_ptr = LP64_ONLY(times_8) NOT_LP64(times_4) + times_ptr = times_8 }; static ScaleFactor times(int size) { assert(size >= 1 && size <= 8 && is_power_of_2(size), "bad scale size"); @@ -197,7 +181,6 @@ class Address { // Easily misused constructors make them private // %%% can we make these go away? - NOT_LP64(Address(address loc, RelocationHolder spec);) Address(int disp, address loc, relocInfo::relocType rtype); Address(int disp, address loc, RelocationHolder spec); @@ -456,7 +439,7 @@ class InstructionAttr; // 64-bit reflect the fxsave size which is 512 bytes and the new xsave area on EVEX which is another 2176 bytes // See fxsave and xsave(EVEX enabled) documentation for layout -const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY(2688 / wordSize); +const int FPUStateSizeInWords = 2688 / wordSize; // The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction // level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write @@ -628,12 +611,8 @@ class Assembler : public AbstractAssembler { imm_operand = 0, // embedded 32-bit|64-bit immediate operand disp32_operand = 1, // embedded 32-bit displacement or address call32_operand = 2, // embedded 32-bit self-relative displacement -#ifndef _LP64 - _WhichOperand_limit = 3 -#else - narrow_oop_operand = 3, // embedded 32-bit immediate narrow oop + narrow_oop_operand = 3, // embedded 32-bit immediate narrow oop _WhichOperand_limit = 4 -#endif }; // Comparison predicates for integral types & FP types when using SSE @@ -721,7 +700,6 @@ private: bool _legacy_mode_dq; bool _legacy_mode_vl; bool _legacy_mode_vlbw; - NOT_LP64(bool _is_managed;) InstructionAttr *_attributes; void set_attributes(InstructionAttr* attributes); @@ -907,25 +885,13 @@ private: void emit_opcode_prefix_and_encoding(int byte1, int ocp_and_encoding); void emit_opcode_prefix_and_encoding(int byte1, int byte2, int ocp_and_encoding); void emit_opcode_prefix_and_encoding(int byte1, int byte2, int ocp_and_encoding, int byte3); - bool always_reachable(AddressLiteral adr) NOT_LP64( { return true; } ); - bool reachable(AddressLiteral adr) NOT_LP64( { return true; } ); + bool always_reachable(AddressLiteral adr); + bool reachable(AddressLiteral adr); // These are all easily abused and hence protected public: - // 32BIT ONLY SECTION -#ifndef _LP64 - // Make these disappear in 64bit mode since they would never be correct - void cmp_literal32(Register src1, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY - void cmp_literal32(Address src1, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY - - void mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY - void mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY - - void push_literal32(int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY -#else - // 64BIT ONLY SECTION void mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec); // 64BIT ONLY void cmp_narrow_oop(Register src1, int32_t imm32, RelocationHolder const& rspec); @@ -933,7 +899,6 @@ private: void mov_narrow_oop(Register dst, int32_t imm32, RelocationHolder const& rspec); void mov_narrow_oop(Address dst, int32_t imm32, RelocationHolder const& rspec); -#endif // _LP64 protected: // These are unique in that we are ensured by the caller that the 32bit @@ -1017,17 +982,10 @@ private: void init_attributes(void); void clear_attributes(void) { _attributes = nullptr; } - void set_managed(void) { NOT_LP64(_is_managed = true;) } - void clear_managed(void) { NOT_LP64(_is_managed = false;) } - bool is_managed(void) { - NOT_LP64(return _is_managed;) - LP64_ONLY(return false;) } - void lea(Register dst, Address src); void mov(Register dst, Register src); -#ifdef _LP64 // support caching the result of some routines // must be called before pusha(), popa(), vzeroupper() - checked with asserts @@ -1047,7 +1005,6 @@ private: // New Zero Upper setcc instruction. void esetzucc(Condition cc, Register dst); -#endif void vzeroupper_uncached(); void decq(Register dst); void edecq(Register dst, Register src, bool no_flags); @@ -1069,9 +1026,7 @@ private: void rep_stos(); void rep_stosb(); void repne_scan(); -#ifdef _LP64 void repne_scanl(); -#endif // Vanilla instructions in lexical order @@ -1121,7 +1076,6 @@ private: void eincq(Register dst, Register src, bool no_flags); void eincq(Register dst, Address src, bool no_flags); -#ifdef _LP64 //Add Unsigned Integers with Carry Flag void adcxq(Register dst, Register src); void eadcxq(Register dst, Register src1, Register src2); @@ -1129,7 +1083,6 @@ private: //Add Unsigned Integers with Overflow Flag void adoxq(Register dst, Register src); void eadoxq(Register dst, Register src1, Register src2); -#endif void addr_nop_4(); void addr_nop_5(); @@ -1206,10 +1159,8 @@ private: void bsfl(Register dst, Register src); void bsrl(Register dst, Register src); -#ifdef _LP64 void bsfq(Register dst, Register src); void bsrq(Register dst, Register src); -#endif void bswapl(Register reg); @@ -1395,10 +1346,6 @@ private: void emit_farith(int b1, int b2, int i); public: -#ifndef _LP64 - void emms(); -#endif // !_LP64 - // operands that only take the original 32bit registers void emit_operand32(Register reg, Address adr, int post_addr_length); @@ -1417,12 +1364,10 @@ private: void divl(Register src); // Unsigned division void edivl(Register src, bool no_flags); // Unsigned division -#ifdef _LP64 void idivq(Register src); void eidivq(Register src, bool no_flags); void divq(Register src); // Unsigned division void edivq(Register src, bool no_flags); // Unsigned division -#endif void imull(Register src); void eimull(Register src, bool no_flags); @@ -1435,7 +1380,6 @@ private: void imull(Register dst, Address src); void eimull(Register dst, Register src1, Address src2, bool no_flags); -#ifdef _LP64 void imulq(Register dst, Register src); void eimulq(Register dst, Register src, bool no_flags); void eimulq(Register dst, Register src1, Register src2, bool no_flags); @@ -1448,7 +1392,6 @@ private: void eimulq(Register dst, Register src1, Address src2, bool no_flags); void imulq(Register dst); void eimulq(Register dst, bool no_flags); -#endif // jcc is the generic conditional branch generator to run- // time routines, jcc is used for branches to labels. jcc @@ -1500,9 +1443,7 @@ private: void leaq(Register dst, Address src); -#ifdef _LP64 void lea(Register dst, Label& L); -#endif void lfence(); @@ -1514,12 +1455,10 @@ private: void lzcntl(Register dst, Address src); void elzcntl(Register dst, Address src, bool no_flags); -#ifdef _LP64 void lzcntq(Register dst, Register src); void elzcntq(Register dst, Register src, bool no_flags); void lzcntq(Register dst, Address src); void elzcntq(Register dst, Address src, bool no_flags); -#endif enum Membar_mask_bits { StoreStore = 1 << 3, @@ -1679,13 +1618,11 @@ private: void movl(Register dst, Address src); void movl(Address dst, Register src); -#ifdef _LP64 void movq(Register dst, Register src); void movq(Register dst, Address src); void movq(Address dst, Register src); void movq(Address dst, int32_t imm32); void movq(Register dst, int32_t imm32); -#endif // Move Quadword void movq(Address dst, XMMRegister src); @@ -1700,7 +1637,6 @@ private: void vmovw(XMMRegister dst, Register src); void vmovw(Register dst, XMMRegister src); -#ifdef _LP64 void movsbq(Register dst, Address src); void movsbq(Register dst, Register src); @@ -1709,15 +1645,12 @@ private: void movslq(Register dst, Address src); void movslq(Register dst, Register src); -#endif void movswl(Register dst, Address src); void movswl(Register dst, Register src); -#ifdef _LP64 void movswq(Register dst, Address src); void movswq(Register dst, Register src); -#endif void movups(XMMRegister dst, Address src); void vmovups(XMMRegister dst, Address src, int vector_len); @@ -1731,18 +1664,14 @@ private: void movzbl(Register dst, Address src); void movzbl(Register dst, Register src); -#ifdef _LP64 void movzbq(Register dst, Address src); void movzbq(Register dst, Register src); -#endif void movzwl(Register dst, Address src); void movzwl(Register dst, Register src); -#ifdef _LP64 void movzwq(Register dst, Address src); void movzwq(Register dst, Register src); -#endif // Unsigned multiply with RAX destination register void mull(Address src); @@ -1750,13 +1679,11 @@ private: void mull(Register src); void emull(Register src, bool no_flags); -#ifdef _LP64 void mulq(Address src); void emulq(Address src, bool no_flags); void mulq(Register src); void emulq(Register src, bool no_flags); void mulxq(Register dst1, Register dst2, Register src); -#endif // Multiply Scalar Double-Precision Floating-Point Values void mulsd(XMMRegister dst, Address src); @@ -1771,26 +1698,22 @@ private: void negl(Address dst); void enegl(Register dst, Address src, bool no_flags); -#ifdef _LP64 void negq(Register dst); void enegq(Register dst, Register src, bool no_flags); void negq(Address dst); void enegq(Register dst, Address src, bool no_flags); -#endif void nop(uint i = 1); void notl(Register dst); void enotl(Register dst, Register src); -#ifdef _LP64 void notq(Register dst); void enotq(Register dst, Register src); void btsq(Address dst, int imm8); void btrq(Address dst, int imm8); void btq(Register src, int imm8); -#endif void btq(Register dst, Register src); void eorw(Register dst, Register src1, Register src2, bool no_flags); @@ -2009,14 +1932,8 @@ private: // Multiply add accumulate void evpdpwssd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); -#ifndef _LP64 // no 32bit push/pop on amd64 - void popl(Address dst); -#endif - -#ifdef _LP64 void popq(Address dst); void popq(Register dst); -#endif void popcntl(Register dst, Address src); void epopcntl(Register dst, Address src, bool no_flags); @@ -2028,12 +1945,10 @@ private: void evpopcntd(XMMRegister dst, KRegister mask, XMMRegister src, bool merge, int vector_len); void evpopcntq(XMMRegister dst, KRegister mask, XMMRegister src, bool merge, int vector_len); -#ifdef _LP64 void popcntq(Register dst, Address src); void epopcntq(Register dst, Address src, bool no_flags); void popcntq(Register dst, Register src); void epopcntq(Register dst, Register src, bool no_flags); -#endif // Prefetches (SSE, SSE2, 3DNOW only) @@ -2125,10 +2040,6 @@ private: // Vector sum of absolute difference. void vpsadbw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); -#ifndef _LP64 // no 32bit push/pop on amd64 - void pushl(Address src); -#endif - void pushq(Address src); void rcll(Register dst, int imm8); @@ -2160,7 +2071,6 @@ private: void rorl(Register dst, int imm8); void erorl(Register dst, Register src, int imm8, bool no_flags); -#ifdef _LP64 void rolq(Register dst); void erolq(Register dst, Register src, bool no_flags); void rolq(Register dst, int imm8); @@ -2173,9 +2083,6 @@ private: void rorxl(Register dst, Address src, int imm8); void rorxq(Register dst, Register src, int imm8); void rorxq(Register dst, Address src, int imm8); -#endif - - void sahf(); void sall(Register dst, int imm8); void esall(Register dst, Register src, int imm8, bool no_flags); @@ -2195,7 +2102,6 @@ private: void sarl(Register dst); void esarl(Register dst, Register src, bool no_flags); -#ifdef _LP64 void salq(Register dst, int imm8); void esalq(Register dst, Register src, int imm8, bool no_flags); void salq(Register dst); @@ -2213,7 +2119,6 @@ private: void esarq(Register dst, Register src, int imm8, bool no_flags); void sarq(Register dst); void esarq(Register dst, Register src, bool no_flags); -#endif void sbbl(Address dst, int32_t imm32); void sbbl(Register dst, int32_t imm32); @@ -2254,12 +2159,10 @@ private: void eshrdl(Register dst, Register src1, Register src2, bool no_flags); void shrdl(Register dst, Register src, int8_t imm8); void eshrdl(Register dst, Register src1, Register src2, int8_t imm8, bool no_flags); -#ifdef _LP64 void shldq(Register dst, Register src, int8_t imm8); void eshldq(Register dst, Register src1, Register src2, int8_t imm8, bool no_flags); void shrdq(Register dst, Register src, int8_t imm8); void eshrdq(Register dst, Register src1, Register src2, int8_t imm8, bool no_flags); -#endif void shll(Register dst, int imm8); void eshll(Register dst, Register src, int imm8, bool no_flags); diff --git a/src/hotspot/cpu/x86/assembler_x86.inline.hpp b/src/hotspot/cpu/x86/assembler_x86.inline.hpp index f5cc75a55c5..6fae9764306 100644 --- a/src/hotspot/cpu/x86/assembler_x86.inline.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.inline.hpp @@ -25,58 +25,4 @@ #ifndef CPU_X86_ASSEMBLER_X86_INLINE_HPP #define CPU_X86_ASSEMBLER_X86_INLINE_HPP -#include "asm/assembler.inline.hpp" -#include "asm/codeBuffer.hpp" -#include "code/codeCache.hpp" - -#ifndef _LP64 -inline int Assembler::prefix_and_encode(int reg_enc, bool byteinst, bool is_map1) -{ - int opc_prefix = is_map1 ? 0x0F00 : 0; - return opc_prefix | reg_enc; -} - -inline int Assembler::prefixq_and_encode(int reg_enc, bool is_map1) { - int opc_prefix = is_map1 ? 0xF00 : 0; - return opc_prefix | reg_enc; -} - -inline int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte, bool is_map1) { - int opc_prefix = is_map1 ? 0xF00 : 0; - return opc_prefix | (dst_enc << 3 | src_enc); -} - -inline int Assembler::prefixq_and_encode(int dst_enc, int src_enc, bool is_map1) { - int opc_prefix = is_map1 ? 0xF00 : 0; - return opc_prefix | dst_enc << 3 | src_enc; -} - -inline void Assembler::prefix(Register reg) {} -inline void Assembler::prefix(Register dst, Register src, Prefix p) {} -inline void Assembler::prefix(Register dst, Address adr, Prefix p) {} - -inline void Assembler::prefix(Address adr, bool is_map1) { - if (is_map1) { - emit_int8(0x0F); - } -} - -inline void Assembler::prefixq(Address adr) {} - -inline void Assembler::prefix(Address adr, Register reg, bool byteinst, bool is_map1) { - if (is_map1) { - emit_int8(0x0F); - } -} -inline void Assembler::prefixq(Address adr, Register reg, bool is_map1) { - if (is_map1) { - emit_int8(0x0F); - } -} - -inline void Assembler::prefix(Address adr, XMMRegister reg) {} -inline void Assembler::prefixq(Address adr, XMMRegister reg) {} - -#endif // _LP64 - #endif // CPU_X86_ASSEMBLER_X86_INLINE_HPP diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index e5aa7d213e1..6093ad69519 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -93,375 +93,6 @@ static const Assembler::Condition reverse[] = { // Implementation of MacroAssembler -// First all the versions that have distinct versions depending on 32/64 bit -// Unless the difference is trivial (1 line or so). - -#ifndef _LP64 - -// 32bit versions - -Address MacroAssembler::as_Address(AddressLiteral adr) { - return Address(adr.target(), adr.rspec()); -} - -Address MacroAssembler::as_Address(ArrayAddress adr, Register rscratch) { - assert(rscratch == noreg, ""); - return Address::make_array(adr); -} - -void MacroAssembler::call_VM_leaf_base(address entry_point, - int number_of_arguments) { - call(RuntimeAddress(entry_point)); - increment(rsp, number_of_arguments * wordSize); -} - -void MacroAssembler::cmpklass(Address src1, Metadata* obj) { - cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - - -void MacroAssembler::cmpklass(Register src1, Metadata* obj) { - cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::cmpoop(Address src1, jobject obj) { - cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::cmpoop(Register src1, jobject obj, Register rscratch) { - assert(rscratch == noreg, "redundant"); - cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::extend_sign(Register hi, Register lo) { - // According to Intel Doc. AP-526, "Integer Divide", p.18. - if (VM_Version::is_P6() && hi == rdx && lo == rax) { - cdql(); - } else { - movl(hi, lo); - sarl(hi, 31); - } -} - -// 32bit can do a case table jump in one instruction but we no longer allow the base -// to be installed in the Address class -void MacroAssembler::jump(ArrayAddress entry, Register rscratch) { - assert(rscratch == noreg, "not needed"); - jmp(as_Address(entry, noreg)); -} - -// Note: y_lo will be destroyed -void MacroAssembler::lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo) { - // Long compare for Java (semantics as described in JVM spec.) - Label high, low, done; - - cmpl(x_hi, y_hi); - jcc(Assembler::less, low); - jcc(Assembler::greater, high); - // x_hi is the return register - xorl(x_hi, x_hi); - cmpl(x_lo, y_lo); - jcc(Assembler::below, low); - jcc(Assembler::equal, done); - - bind(high); - xorl(x_hi, x_hi); - increment(x_hi); - jmp(done); - - bind(low); - xorl(x_hi, x_hi); - decrementl(x_hi); - - bind(done); -} - -void MacroAssembler::lea(Register dst, AddressLiteral src) { - mov_literal32(dst, (int32_t)src.target(), src.rspec()); -} - -void MacroAssembler::lea(Address dst, AddressLiteral adr, Register rscratch) { - assert(rscratch == noreg, "not needed"); - - // leal(dst, as_Address(adr)); - // see note in movl as to why we must use a move - mov_literal32(dst, (int32_t)adr.target(), adr.rspec()); -} - -void MacroAssembler::leave() { - mov(rsp, rbp); - pop(rbp); -} - -void MacroAssembler::lmul(int x_rsp_offset, int y_rsp_offset) { - // Multiplication of two Java long values stored on the stack - // as illustrated below. Result is in rdx:rax. - // - // rsp ---> [ ?? ] \ \ - // .... | y_rsp_offset | - // [ y_lo ] / (in bytes) | x_rsp_offset - // [ y_hi ] | (in bytes) - // .... | - // [ x_lo ] / - // [ x_hi ] - // .... - // - // Basic idea: lo(result) = lo(x_lo * y_lo) - // hi(result) = hi(x_lo * y_lo) + lo(x_hi * y_lo) + lo(x_lo * y_hi) - Address x_hi(rsp, x_rsp_offset + wordSize); Address x_lo(rsp, x_rsp_offset); - Address y_hi(rsp, y_rsp_offset + wordSize); Address y_lo(rsp, y_rsp_offset); - Label quick; - // load x_hi, y_hi and check if quick - // multiplication is possible - movl(rbx, x_hi); - movl(rcx, y_hi); - movl(rax, rbx); - orl(rbx, rcx); // rbx, = 0 <=> x_hi = 0 and y_hi = 0 - jcc(Assembler::zero, quick); // if rbx, = 0 do quick multiply - // do full multiplication - // 1st step - mull(y_lo); // x_hi * y_lo - movl(rbx, rax); // save lo(x_hi * y_lo) in rbx, - // 2nd step - movl(rax, x_lo); - mull(rcx); // x_lo * y_hi - addl(rbx, rax); // add lo(x_lo * y_hi) to rbx, - // 3rd step - bind(quick); // note: rbx, = 0 if quick multiply! - movl(rax, x_lo); - mull(y_lo); // x_lo * y_lo - addl(rdx, rbx); // correct hi(x_lo * y_lo) -} - -void MacroAssembler::lneg(Register hi, Register lo) { - negl(lo); - adcl(hi, 0); - negl(hi); -} - -void MacroAssembler::lshl(Register hi, Register lo) { - // Java shift left long support (semantics as described in JVM spec., p.305) - // (basic idea for shift counts s >= n: x << s == (x << n) << (s - n)) - // shift value is in rcx ! - assert(hi != rcx, "must not use rcx"); - assert(lo != rcx, "must not use rcx"); - const Register s = rcx; // shift count - const int n = BitsPerWord; - Label L; - andl(s, 0x3f); // s := s & 0x3f (s < 0x40) - cmpl(s, n); // if (s < n) - jcc(Assembler::less, L); // else (s >= n) - movl(hi, lo); // x := x << n - xorl(lo, lo); - // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! - bind(L); // s (mod n) < n - shldl(hi, lo); // x := x << s - shll(lo); -} - - -void MacroAssembler::lshr(Register hi, Register lo, bool sign_extension) { - // Java shift right long support (semantics as described in JVM spec., p.306 & p.310) - // (basic idea for shift counts s >= n: x >> s == (x >> n) >> (s - n)) - assert(hi != rcx, "must not use rcx"); - assert(lo != rcx, "must not use rcx"); - const Register s = rcx; // shift count - const int n = BitsPerWord; - Label L; - andl(s, 0x3f); // s := s & 0x3f (s < 0x40) - cmpl(s, n); // if (s < n) - jcc(Assembler::less, L); // else (s >= n) - movl(lo, hi); // x := x >> n - if (sign_extension) sarl(hi, 31); - else xorl(hi, hi); - // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! - bind(L); // s (mod n) < n - shrdl(lo, hi); // x := x >> s - if (sign_extension) sarl(hi); - else shrl(hi); -} - -void MacroAssembler::movoop(Register dst, jobject obj) { - mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::movoop(Address dst, jobject obj, Register rscratch) { - assert(rscratch == noreg, "redundant"); - mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { - mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::mov_metadata(Address dst, Metadata* obj, Register rscratch) { - assert(rscratch == noreg, "redundant"); - mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::movptr(Register dst, AddressLiteral src) { - if (src.is_lval()) { - mov_literal32(dst, (intptr_t)src.target(), src.rspec()); - } else { - movl(dst, as_Address(src)); - } -} - -void MacroAssembler::movptr(ArrayAddress dst, Register src, Register rscratch) { - assert(rscratch == noreg, "redundant"); - movl(as_Address(dst, noreg), src); -} - -void MacroAssembler::movptr(Register dst, ArrayAddress src) { - movl(dst, as_Address(src, noreg)); -} - -void MacroAssembler::movptr(Address dst, intptr_t src, Register rscratch) { - assert(rscratch == noreg, "redundant"); - movl(dst, src); -} - -void MacroAssembler::pushoop(jobject obj, Register rscratch) { - assert(rscratch == noreg, "redundant"); - push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::pushklass(Metadata* obj, Register rscratch) { - assert(rscratch == noreg, "redundant"); - push_literal32((int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::pushptr(AddressLiteral src, Register rscratch) { - assert(rscratch == noreg, "redundant"); - if (src.is_lval()) { - push_literal32((int32_t)src.target(), src.rspec()); - } else { - pushl(as_Address(src)); - } -} - -static void pass_arg0(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -static void pass_arg1(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -static void pass_arg2(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -static void pass_arg3(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -#ifndef PRODUCT -extern "C" void findpc(intptr_t x); -#endif - -void MacroAssembler::debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg) { - // In order to get locks to work, we need to fake a in_VM state - JavaThread* thread = JavaThread::current(); - JavaThreadState saved_state = thread->thread_state(); - thread->set_thread_state(_thread_in_vm); - if (ShowMessageBoxOnError) { - JavaThread* thread = JavaThread::current(); - JavaThreadState saved_state = thread->thread_state(); - thread->set_thread_state(_thread_in_vm); - if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { - ttyLocker ttyl; - BytecodeCounter::print(); - } - // To see where a verify_oop failed, get $ebx+40/X for this frame. - // This is the value of eip which points to where verify_oop will return. - if (os::message_box(msg, "Execution stopped, print registers?")) { - print_state32(rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax, eip); - BREAKPOINT; - } - } - fatal("DEBUG MESSAGE: %s", msg); -} - -void MacroAssembler::print_state32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip) { - ttyLocker ttyl; - DebuggingContext debugging{}; - tty->print_cr("eip = 0x%08x", eip); -#ifndef PRODUCT - if ((WizardMode || Verbose) && PrintMiscellaneous) { - tty->cr(); - findpc(eip); - tty->cr(); - } -#endif -#define PRINT_REG(rax) \ - { tty->print("%s = ", #rax); os::print_location(tty, rax); } - PRINT_REG(rax); - PRINT_REG(rbx); - PRINT_REG(rcx); - PRINT_REG(rdx); - PRINT_REG(rdi); - PRINT_REG(rsi); - PRINT_REG(rbp); - PRINT_REG(rsp); -#undef PRINT_REG - // Print some words near top of staack. - int* dump_sp = (int*) rsp; - for (int col1 = 0; col1 < 8; col1++) { - tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); - os::print_location(tty, *dump_sp++); - } - for (int row = 0; row < 16; row++) { - tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); - for (int col = 0; col < 8; col++) { - tty->print(" 0x%08x", *dump_sp++); - } - tty->cr(); - } - // Print some instructions around pc: - Disassembler::decode((address)eip-64, (address)eip); - tty->print_cr("--------"); - Disassembler::decode((address)eip, (address)eip+32); -} - -void MacroAssembler::stop(const char* msg) { - // push address of message - ExternalAddress message((address)msg); - pushptr(message.addr(), noreg); - { Label L; call(L, relocInfo::none); bind(L); } // push eip - pusha(); // push registers - call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32))); - hlt(); -} - -void MacroAssembler::warn(const char* msg) { - push_CPU_state(); - - // push address of message - ExternalAddress message((address)msg); - pushptr(message.addr(), noreg); - - call(RuntimeAddress(CAST_FROM_FN_PTR(address, warning))); - addl(rsp, wordSize); // discard argument - pop_CPU_state(); -} - -void MacroAssembler::print_state() { - { Label L; call(L, relocInfo::none); bind(L); } // push eip - pusha(); // push registers - - push_CPU_state(); - call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::print_state32))); - pop_CPU_state(); - - popa(); - addl(rsp, wordSize); -} - -#else // _LP64 - -// 64 bit versions - Address MacroAssembler::as_Address(AddressLiteral adr) { // amd64 always does this as a pc-rel // we can be absolute or disp based on the instruction type @@ -1073,20 +704,16 @@ void MacroAssembler::object_move(OopMap* map, } } -#endif // _LP64 - -// Now versions that are common to 32/64 bit - void MacroAssembler::addptr(Register dst, int32_t imm32) { - LP64_ONLY(addq(dst, imm32)) NOT_LP64(addl(dst, imm32)); + addq(dst, imm32); } void MacroAssembler::addptr(Register dst, Register src) { - LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); + addq(dst, src); } void MacroAssembler::addptr(Address dst, Register src) { - LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); + addq(dst, src); } void MacroAssembler::addsd(XMMRegister dst, AddressLiteral src, Register rscratch) { @@ -1196,10 +823,9 @@ void MacroAssembler::andps(XMMRegister dst, AddressLiteral src, Register rscratc } void MacroAssembler::andptr(Register dst, int32_t imm32) { - LP64_ONLY(andq(dst, imm32)) NOT_LP64(andl(dst, imm32)); + andq(dst, imm32); } -#ifdef _LP64 void MacroAssembler::andq(Register dst, AddressLiteral src, Register rscratch) { assert(rscratch != noreg || always_reachable(src), "missing"); @@ -1210,7 +836,6 @@ void MacroAssembler::andq(Register dst, AddressLiteral src, Register rscratch) { andq(dst, Address(rscratch, 0)); } } -#endif void MacroAssembler::atomic_incl(Address counter_addr) { lock(); @@ -1228,7 +853,6 @@ void MacroAssembler::atomic_incl(AddressLiteral counter_addr, Register rscratch) } } -#ifdef _LP64 void MacroAssembler::atomic_incq(Address counter_addr) { lock(); incrementq(counter_addr); @@ -1244,7 +868,6 @@ void MacroAssembler::atomic_incq(AddressLiteral counter_addr, Register rscratch) atomic_incq(Address(rscratch, 0)); } } -#endif // Writes to stack successive pages until offset reached to check for // stack overflow + shadow pages. This clobbers tmp. @@ -1276,13 +899,11 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) { void MacroAssembler::reserved_stack_check() { // testing if reserved zone needs to be enabled Label no_reserved_zone_enabling; - Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread); - NOT_LP64(get_thread(rsi);) - cmpptr(rsp, Address(thread, JavaThread::reserved_stack_activation_offset())); + cmpptr(rsp, Address(r15_thread, JavaThread::reserved_stack_activation_offset())); jcc(Assembler::below, no_reserved_zone_enabling); - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), thread); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), r15_thread); jump(RuntimeAddress(SharedRuntime::throw_delayed_StackOverflowError_entry())); should_not_reach_here(); @@ -1320,24 +941,19 @@ void MacroAssembler::call(AddressLiteral entry, Register rscratch) { void MacroAssembler::ic_call(address entry, jint method_index) { RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index); -#ifdef _LP64 // Needs full 64-bit immediate for later patching. mov64(rax, (int64_t)Universe::non_oop_word()); -#else - movptr(rax, (intptr_t)Universe::non_oop_word()); -#endif call(AddressLiteral(entry, rh)); } int MacroAssembler::ic_check_size() { - return - LP64_ONLY(UseCompactObjectHeaders ? 17 : 14) NOT_LP64(12); + return UseCompactObjectHeaders ? 17 : 14; } int MacroAssembler::ic_check(int end_alignment) { - Register receiver = LP64_ONLY(j_rarg0) NOT_LP64(rcx); + Register receiver = j_rarg0; Register data = rax; - Register temp = LP64_ONLY(rscratch1) NOT_LP64(rbx); + Register temp = rscratch1; // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed // before the inline cache check, so we don't have to execute any nop instructions when dispatching @@ -1347,13 +963,10 @@ int MacroAssembler::ic_check(int end_alignment) { int uep_offset = offset(); -#ifdef _LP64 if (UseCompactObjectHeaders) { load_narrow_klass_compact(temp, receiver); cmpl(temp, Address(data, CompiledICData::speculated_klass_offset())); - } else -#endif - if (UseCompressedClassPointers) { + } else if (UseCompressedClassPointers) { movl(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); cmpl(temp, Address(data, CompiledICData::speculated_klass_offset())); } else { @@ -1418,7 +1031,7 @@ void MacroAssembler::call_VM(Register oop_result, bind(C); - LP64_ONLY(assert_different_registers(arg_1, c_rarg2)); + assert_different_registers(arg_1, c_rarg2); pass_arg2(this, arg_2); pass_arg1(this, arg_1); @@ -1440,8 +1053,8 @@ void MacroAssembler::call_VM(Register oop_result, bind(C); - LP64_ONLY(assert_different_registers(arg_1, c_rarg2, c_rarg3)); - LP64_ONLY(assert_different_registers(arg_2, c_rarg3)); + assert_different_registers(arg_1, c_rarg2, c_rarg3); + assert_different_registers(arg_2, c_rarg3); pass_arg3(this, arg_3); pass_arg2(this, arg_2); pass_arg1(this, arg_1); @@ -1475,7 +1088,7 @@ void MacroAssembler::call_VM(Register oop_result, Register arg_2, bool check_exceptions) { - LP64_ONLY(assert_different_registers(arg_1, c_rarg2)); + assert_different_registers(arg_1, c_rarg2); pass_arg2(this, arg_2); pass_arg1(this, arg_1); call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); @@ -1488,8 +1101,8 @@ void MacroAssembler::call_VM(Register oop_result, Register arg_2, Register arg_3, bool check_exceptions) { - LP64_ONLY(assert_different_registers(arg_1, c_rarg2, c_rarg3)); - LP64_ONLY(assert_different_registers(arg_2, c_rarg3)); + assert_different_registers(arg_1, c_rarg2, c_rarg3); + assert_different_registers(arg_2, c_rarg3); pass_arg3(this, arg_3); pass_arg2(this, arg_2); pass_arg1(this, arg_1); @@ -1520,7 +1133,7 @@ void MacroAssembler::super_call_VM(Register oop_result, Register arg_2, bool check_exceptions) { - LP64_ONLY(assert_different_registers(arg_1, c_rarg2)); + assert_different_registers(arg_1, c_rarg2); pass_arg2(this, arg_2); pass_arg1(this, arg_1); super_call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); @@ -1533,8 +1146,8 @@ void MacroAssembler::super_call_VM(Register oop_result, Register arg_2, Register arg_3, bool check_exceptions) { - LP64_ONLY(assert_different_registers(arg_1, c_rarg2, c_rarg3)); - LP64_ONLY(assert_different_registers(arg_2, c_rarg3)); + assert_different_registers(arg_1, c_rarg2, c_rarg3); + assert_different_registers(arg_2, c_rarg3); pass_arg3(this, arg_3); pass_arg2(this, arg_2); pass_arg1(this, arg_1); @@ -1645,15 +1258,15 @@ void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0) { void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { - LP64_ONLY(assert_different_registers(arg_0, c_rarg1)); + assert_different_registers(arg_0, c_rarg1); pass_arg1(this, arg_1); pass_arg0(this, arg_0); call_VM_leaf(entry_point, 2); } void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { - LP64_ONLY(assert_different_registers(arg_0, c_rarg1, c_rarg2)); - LP64_ONLY(assert_different_registers(arg_1, c_rarg2)); + assert_different_registers(arg_0, c_rarg1, c_rarg2); + assert_different_registers(arg_1, c_rarg2); pass_arg2(this, arg_2); pass_arg1(this, arg_1); pass_arg0(this, arg_0); @@ -1661,9 +1274,9 @@ void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register } void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) { - LP64_ONLY(assert_different_registers(arg_0, c_rarg1, c_rarg2, c_rarg3)); - LP64_ONLY(assert_different_registers(arg_1, c_rarg2, c_rarg3)); - LP64_ONLY(assert_different_registers(arg_2, c_rarg3)); + assert_different_registers(arg_0, c_rarg1, c_rarg2, c_rarg3); + assert_different_registers(arg_1, c_rarg2, c_rarg3); + assert_different_registers(arg_2, c_rarg3); pass_arg3(this, arg_3); pass_arg2(this, arg_2); pass_arg1(this, arg_1); @@ -1677,15 +1290,15 @@ void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0) { } void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { - LP64_ONLY(assert_different_registers(arg_0, c_rarg1)); + assert_different_registers(arg_0, c_rarg1); pass_arg1(this, arg_1); pass_arg0(this, arg_0); MacroAssembler::call_VM_leaf_base(entry_point, 2); } void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { - LP64_ONLY(assert_different_registers(arg_0, c_rarg1, c_rarg2)); - LP64_ONLY(assert_different_registers(arg_1, c_rarg2)); + assert_different_registers(arg_0, c_rarg1, c_rarg2); + assert_different_registers(arg_1, c_rarg2); pass_arg2(this, arg_2); pass_arg1(this, arg_1); pass_arg0(this, arg_0); @@ -1693,9 +1306,9 @@ void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Reg } void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) { - LP64_ONLY(assert_different_registers(arg_0, c_rarg1, c_rarg2, c_rarg3)); - LP64_ONLY(assert_different_registers(arg_1, c_rarg2, c_rarg3)); - LP64_ONLY(assert_different_registers(arg_2, c_rarg3)); + assert_different_registers(arg_0, c_rarg1, c_rarg2, c_rarg3); + assert_different_registers(arg_1, c_rarg2, c_rarg3); + assert_different_registers(arg_2, c_rarg3); pass_arg3(this, arg_3); pass_arg2(this, arg_2); pass_arg1(this, arg_1); @@ -1808,7 +1421,6 @@ void MacroAssembler::cmp8(AddressLiteral src1, int imm, Register rscratch) { } void MacroAssembler::cmpptr(Register src1, AddressLiteral src2, Register rscratch) { -#ifdef _LP64 assert(rscratch != noreg || always_reachable(src2), "missing"); if (src2.is_lval()) { @@ -1820,26 +1432,13 @@ void MacroAssembler::cmpptr(Register src1, AddressLiteral src2, Register rscratc lea(rscratch, src2); Assembler::cmpq(src1, Address(rscratch, 0)); } -#else - assert(rscratch == noreg, "not needed"); - if (src2.is_lval()) { - cmp_literal32(src1, (int32_t)src2.target(), src2.rspec()); - } else { - cmpl(src1, as_Address(src2)); - } -#endif // _LP64 } void MacroAssembler::cmpptr(Address src1, AddressLiteral src2, Register rscratch) { assert(src2.is_lval(), "not a mem-mem compare"); -#ifdef _LP64 // moves src2's literal address movptr(rscratch, src2); Assembler::cmpq(src1, rscratch); -#else - assert(rscratch == noreg, "not needed"); - cmp_literal32(src1, (int32_t)src2.target(), src2.rspec()); -#endif // _LP64 } void MacroAssembler::cmpoop(Register src1, Register src2) { @@ -1850,12 +1449,10 @@ void MacroAssembler::cmpoop(Register src1, Address src2) { cmpptr(src1, src2); } -#ifdef _LP64 void MacroAssembler::cmpoop(Register src1, jobject src2, Register rscratch) { movoop(rscratch, src2); cmpptr(src1, rscratch); } -#endif void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch) { assert(rscratch != noreg || always_reachable(adr), "missing"); @@ -1871,7 +1468,7 @@ void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr, Registe } void MacroAssembler::cmpxchgptr(Register reg, Address adr) { - LP64_ONLY(cmpxchgq(reg, adr)) NOT_LP64(cmpxchgl(reg, adr)); + cmpxchgq(reg, adr); } void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src, Register rscratch) { @@ -2193,15 +1790,8 @@ void MacroAssembler::ldmxcsr(AddressLiteral src, Register rscratch) { } int MacroAssembler::load_signed_byte(Register dst, Address src) { - int off; - if (LP64_ONLY(true ||) VM_Version::is_P6()) { - off = offset(); - movsbl(dst, src); // movsxb - } else { - off = load_unsigned_byte(dst, src); - shll(dst, 24); - sarl(dst, 24); - } + int off = offset(); + movsbl(dst, src); // movsxb return off; } @@ -2210,33 +1800,19 @@ int MacroAssembler::load_signed_byte(Register dst, Address src) { // manual, which means 16 bits, that usage is found nowhere in HotSpot code. // The term "word" in HotSpot means a 32- or 64-bit machine word. int MacroAssembler::load_signed_short(Register dst, Address src) { - int off; - if (LP64_ONLY(true ||) VM_Version::is_P6()) { - // This is dubious to me since it seems safe to do a signed 16 => 64 bit - // version but this is what 64bit has always done. This seems to imply - // that users are only using 32bits worth. - off = offset(); - movswl(dst, src); // movsxw - } else { - off = load_unsigned_short(dst, src); - shll(dst, 16); - sarl(dst, 16); - } + // This is dubious to me since it seems safe to do a signed 16 => 64 bit + // version but this is what 64bit has always done. This seems to imply + // that users are only using 32bits worth. + int off = offset(); + movswl(dst, src); // movsxw return off; } int MacroAssembler::load_unsigned_byte(Register dst, Address src) { // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, // and "3.9 Partial Register Penalties", p. 22). - int off; - if (LP64_ONLY(true || ) VM_Version::is_P6() || src.uses(dst)) { - off = offset(); - movzbl(dst, src); // movzxb - } else { - xorl(dst, dst); - off = offset(); - movb(dst, src); - } + int off = offset(); + movzbl(dst, src); // movzxb return off; } @@ -2244,29 +1820,14 @@ int MacroAssembler::load_unsigned_byte(Register dst, Address src) { int MacroAssembler::load_unsigned_short(Register dst, Address src) { // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, // and "3.9 Partial Register Penalties", p. 22). - int off; - if (LP64_ONLY(true ||) VM_Version::is_P6() || src.uses(dst)) { - off = offset(); - movzwl(dst, src); // movzxw - } else { - xorl(dst, dst); - off = offset(); - movw(dst, src); - } + int off = offset(); + movzwl(dst, src); // movzxw return off; } void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2) { switch (size_in_bytes) { -#ifndef _LP64 - case 8: - assert(dst2 != noreg, "second dest register required"); - movl(dst, src); - movl(dst2, src.plus_disp(BytesPerInt)); - break; -#else case 8: movq(dst, src); break; -#endif case 4: movl(dst, src); break; case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; @@ -2276,15 +1837,7 @@ void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_ void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2) { switch (size_in_bytes) { -#ifndef _LP64 - case 8: - assert(src2 != noreg, "second source register required"); - movl(dst, src); - movl(dst.plus_disp(BytesPerInt), src2); - break; -#else case 8: movq(dst, src); break; -#endif case 4: movl(dst, src); break; case 2: movw(dst, src); break; case 1: movb(dst, src); break; @@ -2403,16 +1956,15 @@ void MacroAssembler::movflt(XMMRegister dst, AddressLiteral src, Register rscrat } void MacroAssembler::movptr(Register dst, Register src) { - LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); + movq(dst, src); } void MacroAssembler::movptr(Register dst, Address src) { - LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); + movq(dst, src); } // src should NEVER be a real pointer. Use AddressLiteral for true pointers void MacroAssembler::movptr(Register dst, intptr_t src) { -#ifdef _LP64 if (is_uimm32(src)) { movl(dst, checked_cast(src)); } else if (is_simm32(src)) { @@ -2420,17 +1972,14 @@ void MacroAssembler::movptr(Register dst, intptr_t src) { } else { mov64(dst, src); } -#else - movl(dst, src); -#endif } void MacroAssembler::movptr(Address dst, Register src) { - LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); + movq(dst, src); } void MacroAssembler::movptr(Address dst, int32_t src) { - LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); + movslq(dst, src); } void MacroAssembler::movdqu(Address dst, XMMRegister src) { @@ -2808,9 +2357,7 @@ void MacroAssembler::unimplemented(const char* what) { stop(buf); } -#ifdef _LP64 #define XSTATE_BV 0x200 -#endif void MacroAssembler::pop_CPU_state() { pop_FPU_state(); @@ -2818,17 +2365,13 @@ void MacroAssembler::pop_CPU_state() { } void MacroAssembler::pop_FPU_state() { -#ifndef _LP64 - frstor(Address(rsp, 0)); -#else fxrstor(Address(rsp, 0)); -#endif addptr(rsp, FPUStateSizeInWords * wordSize); } void MacroAssembler::pop_IU_state() { popa(); - LP64_ONLY(addq(rsp, 8)); + addq(rsp, 8); popf(); } @@ -2841,19 +2384,14 @@ void MacroAssembler::push_CPU_state() { void MacroAssembler::push_FPU_state() { subptr(rsp, FPUStateSizeInWords * wordSize); -#ifndef _LP64 - fnsave(Address(rsp, 0)); - fwait(); -#else fxsave(Address(rsp, 0)); -#endif // LP64 } void MacroAssembler::push_IU_state() { // Push flags first because pusha kills them pushf(); // Make sure rsp stays 16-byte aligned - LP64_ONLY(subq(rsp, 8)); + subq(rsp, 8); pusha(); } @@ -2963,29 +2501,19 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, } void MacroAssembler::shlptr(Register dst, int imm8) { - LP64_ONLY(shlq(dst, imm8)) NOT_LP64(shll(dst, imm8)); + shlq(dst, imm8); } void MacroAssembler::shrptr(Register dst, int imm8) { - LP64_ONLY(shrq(dst, imm8)) NOT_LP64(shrl(dst, imm8)); + shrq(dst, imm8); } void MacroAssembler::sign_extend_byte(Register reg) { - if (LP64_ONLY(true ||) (VM_Version::is_P6() && reg->has_byte_register())) { - movsbl(reg, reg); // movsxb - } else { - shll(reg, 24); - sarl(reg, 24); - } + movsbl(reg, reg); // movsxb } void MacroAssembler::sign_extend_short(Register reg) { - if (LP64_ONLY(true ||) VM_Version::is_P6()) { - movswl(reg, reg); // movsxw - } else { - shll(reg, 16); - sarl(reg, 16); - } + movswl(reg, reg); // movsxw } void MacroAssembler::testl(Address dst, int32_t imm32) { @@ -3009,8 +2537,6 @@ void MacroAssembler::testl(Register dst, AddressLiteral src) { testl(dst, as_Address(src)); } -#ifdef _LP64 - void MacroAssembler::testq(Address dst, int32_t imm32) { if (imm32 >= 0) { testl(dst, imm32); @@ -3027,8 +2553,6 @@ void MacroAssembler::testq(Register dst, int32_t imm32) { } } -#endif - void MacroAssembler::pcmpeqb(XMMRegister dst, XMMRegister src) { assert(((dst->encoding() < 16 && src->encoding() < 16) || VM_Version::supports_avx512vlbw()),"XMM register should be 0-15"); Assembler::pcmpeqb(dst, src); @@ -3874,16 +3398,16 @@ void MacroAssembler::resolve_global_jobject(Register value, } void MacroAssembler::subptr(Register dst, int32_t imm32) { - LP64_ONLY(subq(dst, imm32)) NOT_LP64(subl(dst, imm32)); + subq(dst, imm32); } // Force generation of a 4 byte immediate value even if it fits into 8bit void MacroAssembler::subptr_imm32(Register dst, int32_t imm32) { - LP64_ONLY(subq_imm32(dst, imm32)) NOT_LP64(subl_imm32(dst, imm32)); + subq_imm32(dst, imm32); } void MacroAssembler::subptr(Register dst, Register src) { - LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); + subq(dst, src); } // C++ bool manipulation @@ -3901,7 +3425,7 @@ void MacroAssembler::testbool(Register dst) { } void MacroAssembler::testptr(Register dst, Register src) { - LP64_ONLY(testq(dst, src)) NOT_LP64(testl(dst, src)); + testq(dst, src); } // Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes. @@ -3917,20 +3441,14 @@ void MacroAssembler::tlab_allocate(Register obj, RegSet MacroAssembler::call_clobbered_gp_registers() { RegSet regs; -#ifdef _LP64 regs += RegSet::of(rax, rcx, rdx); #ifndef _WINDOWS regs += RegSet::of(rsi, rdi); #endif regs += RegSet::range(r8, r11); -#else - regs += RegSet::of(rax, rcx, rdx); -#endif -#ifdef _LP64 if (UseAPX) { regs += RegSet::range(r16, as_Register(Register::number_of_registers - 1)); } -#endif return regs; } @@ -4100,27 +3618,12 @@ void MacroAssembler::zero_memory(Register address, Register length_in_bytes, int shrptr(index, 2); // use 2 instructions to avoid partial flag stall shrptr(index, 1); } -#ifndef _LP64 - // index could have not been a multiple of 8 (i.e., bit 2 was set) - { - Label even; - // note: if index was a multiple of 8, then it cannot - // be 0 now otherwise it must have been 0 before - // => if it is even, we don't need to check for 0 again - jcc(Assembler::carryClear, even); - // clear topmost word (no jump would be needed if conditional assignment worked here) - movptr(Address(address, index, Address::times_8, offset_in_bytes - 0*BytesPerWord), temp); - // index could be 0 now, must check again - jcc(Assembler::zero, done); - bind(even); - } -#endif // !_LP64 + // initialize remaining object fields: index is a multiple of 2 now { Label loop; bind(loop); movptr(Address(address, index, Address::times_8, offset_in_bytes - 1*BytesPerWord), temp); - NOT_LP64(movptr(Address(address, index, Address::times_8, offset_in_bytes - 2*BytesPerWord), temp);) decrement(index); jcc(Assembler::notZero, loop); } @@ -4497,9 +4000,8 @@ void MacroAssembler::check_klass_subtype_slow_path_linear(Register sub_klass, #ifndef PRODUCT uint* pst_counter = &SharedRuntime::_partial_subtype_ctr; ExternalAddress pst_counter_addr((address) pst_counter); - NOT_LP64( incrementl(pst_counter_addr) ); - LP64_ONLY( lea(rcx, pst_counter_addr) ); - LP64_ONLY( incrementl(Address(rcx, 0)) ); + lea(rcx, pst_counter_addr); + incrementl(Address(rcx, 0)); #endif //PRODUCT // We will consult the secondary-super array. @@ -4545,22 +4047,6 @@ void MacroAssembler::check_klass_subtype_slow_path_linear(Register sub_klass, bind(L_fallthrough); } -#ifndef _LP64 - -// 32-bit x86 only: always use the linear search. -void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Register temp2_reg, - Label* L_success, - Label* L_failure, - bool set_cond_codes) { - check_klass_subtype_slow_path_linear - (sub_klass, super_klass, temp_reg, temp2_reg, L_success, L_failure, set_cond_codes); -} - -#else // _LP64 - void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, Register super_klass, Register temp_reg, @@ -5144,8 +4630,6 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass, #undef LOOKUP_SECONDARY_SUPERS_TABLE_REGISTERS -#endif // LP64 - void MacroAssembler::clinit_barrier(Register klass, Label* L_fast_path, Label* L_slow_path) { assert(L_fast_path != nullptr || L_slow_path != nullptr, "at least one is required"); @@ -5200,9 +4684,7 @@ void MacroAssembler::_verify_oop(Register reg, const char* s, const char* file, if (!VerifyOops) return; BLOCK_COMMENT("verify_oop {"); -#ifdef _LP64 push(rscratch1); -#endif push(rax); // save rax push(reg); // pass register argument @@ -5260,9 +4742,7 @@ Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, void MacroAssembler::_verify_oop_addr(Address addr, const char* s, const char* file, int line) { if (!VerifyOops) return; -#ifdef _LP64 push(rscratch1); -#endif push(rax); // save rax, // addr may contain rsp so we will have to adjust it based on the push // we just did (and on 64 bit we do two pushes) @@ -5270,7 +4750,7 @@ void MacroAssembler::_verify_oop_addr(Address addr, const char* s, const char* f // stores rax into addr which is backwards of what was intended. if (addr.uses(rsp)) { lea(rax, addr); - pushptr(Address(rax, LP64_ONLY(2 *) BytesPerWord)); + pushptr(Address(rax, 2 * BytesPerWord)); } else { pushptr(addr); } @@ -5297,27 +4777,23 @@ void MacroAssembler::verify_tlab() { if (UseTLAB && VerifyOops) { Label next, ok; Register t1 = rsi; - Register thread_reg = NOT_LP64(rbx) LP64_ONLY(r15_thread); push(t1); - NOT_LP64(push(thread_reg)); - NOT_LP64(get_thread(thread_reg)); - movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); - cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); + movptr(t1, Address(r15_thread, in_bytes(JavaThread::tlab_top_offset()))); + cmpptr(t1, Address(r15_thread, in_bytes(JavaThread::tlab_start_offset()))); jcc(Assembler::aboveEqual, next); STOP("assert(top >= start)"); should_not_reach_here(); bind(next); - movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); - cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); + movptr(t1, Address(r15_thread, in_bytes(JavaThread::tlab_end_offset()))); + cmpptr(t1, Address(r15_thread, in_bytes(JavaThread::tlab_top_offset()))); jcc(Assembler::aboveEqual, ok); STOP("assert(top <= end)"); should_not_reach_here(); bind(ok); - NOT_LP64(pop(thread_reg)); pop(t1); } #endif @@ -5658,27 +5134,23 @@ void MacroAssembler::load_method_holder(Register holder, Register method) { movptr(holder, Address(holder, ConstantPool::pool_holder_offset())); // InstanceKlass* } -#ifdef _LP64 void MacroAssembler::load_narrow_klass_compact(Register dst, Register src) { assert(UseCompactObjectHeaders, "expect compact object headers"); movq(dst, Address(src, oopDesc::mark_offset_in_bytes())); shrq(dst, markWord::klass_shift); } -#endif void MacroAssembler::load_klass(Register dst, Register src, Register tmp) { assert_different_registers(src, tmp); assert_different_registers(dst, tmp); -#ifdef _LP64 + if (UseCompactObjectHeaders) { load_narrow_klass_compact(dst, src); decode_klass_not_null(dst, tmp); } else if (UseCompressedClassPointers) { movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); decode_klass_not_null(dst, tmp); - } else -#endif - { + } else { movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); } } @@ -5687,17 +5159,15 @@ void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { assert(!UseCompactObjectHeaders, "not with compact headers"); assert_different_registers(src, tmp); assert_different_registers(dst, tmp); -#ifdef _LP64 if (UseCompressedClassPointers) { encode_klass_not_null(src, tmp); movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); - } else -#endif + } else { movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src); + } } void MacroAssembler::cmp_klass(Register klass, Register obj, Register tmp) { -#ifdef _LP64 if (UseCompactObjectHeaders) { assert(tmp != noreg, "need tmp"); assert_different_registers(klass, obj, tmp); @@ -5705,15 +5175,12 @@ void MacroAssembler::cmp_klass(Register klass, Register obj, Register tmp) { cmpl(klass, tmp); } else if (UseCompressedClassPointers) { cmpl(klass, Address(obj, oopDesc::klass_offset_in_bytes())); - } else -#endif - { + } else { cmpptr(klass, Address(obj, oopDesc::klass_offset_in_bytes())); } } void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Register tmp1, Register tmp2) { -#ifdef _LP64 if (UseCompactObjectHeaders) { assert(tmp2 != noreg, "need tmp2"); assert_different_registers(obj1, obj2, tmp1, tmp2); @@ -5723,9 +5190,7 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi } else if (UseCompressedClassPointers) { movl(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); cmpl(tmp1, Address(obj2, oopDesc::klass_offset_in_bytes())); - } else -#endif - { + } else { movptr(tmp1, Address(obj1, oopDesc::klass_offset_in_bytes())); cmpptr(tmp1, Address(obj2, oopDesc::klass_offset_in_bytes())); } @@ -5774,7 +5239,6 @@ void MacroAssembler::store_heap_oop_null(Address dst) { access_store_at(T_OBJECT, IN_HEAP, dst, noreg, noreg, noreg, noreg); } -#ifdef _LP64 void MacroAssembler::store_klass_gap(Register dst, Register src) { assert(!UseCompactObjectHeaders, "Don't use with compact headers"); if (UseCompressedClassPointers) { @@ -6096,8 +5560,6 @@ void MacroAssembler::reinit_heapbase() { } } -#endif // _LP64 - #if COMPILER2_OR_JVMCI // clear memory of size 'cnt' qwords, starting at 'base' using XMM/YMM/ZMM registers @@ -6276,8 +5738,6 @@ void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp, XMMReg cmpptr(cnt, InitArrayShortSize/BytesPerLong); jccb(Assembler::greater, LONG); - NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM - decrement(cnt); jccb(Assembler::negative, DONE); // Zero length @@ -6298,7 +5758,6 @@ void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp, XMMReg } else if (UseXMMForObjInit) { xmm_clear_mem(base, cnt, tmp, xtmp, mask); } else { - NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM rep_stos(); } @@ -6316,7 +5775,7 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned, Label L_exit; Label L_fill_2_bytes, L_fill_4_bytes; -#if defined(COMPILER2) && defined(_LP64) +#if defined(COMPILER2) if(MaxVectorSize >=32 && VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2()) { @@ -6696,7 +6155,6 @@ void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, bind(L_done); } -#ifdef _LP64 /** * Helper for multiply_to_len(). */ @@ -7871,7 +7329,6 @@ void MacroAssembler::mul_add(Register out, Register in, Register offs, pop(tmp2); pop(tmp1); } -#endif /** * Emits code to update CRC-32 with a byte value according to constants in table @@ -8094,7 +7551,6 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, Regi notl(crc); // ~c } -#ifdef _LP64 // Helper function for AVX 512 CRC32 // Fold 512-bit data chunks void MacroAssembler::fold512bit_crc32_avx512(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, @@ -8612,155 +8068,7 @@ void MacroAssembler::crc32c_proc_chunk(uint32_t size, uint32_t const_or_pre_comp bind(L_exit); } -#else -void MacroAssembler::crc32c_ipl_alg4(Register in_out, uint32_t n, - Register tmp1, Register tmp2, Register tmp3, - XMMRegister xtmp1, XMMRegister xtmp2) { - lea(tmp3, ExternalAddress(StubRoutines::crc32c_table_addr())); - if (n > 0) { - addl(tmp3, n * 256 * 8); - } - // Q1 = TABLEExt[n][B & 0xFF]; - movl(tmp1, in_out); - andl(tmp1, 0x000000FF); - shll(tmp1, 3); - addl(tmp1, tmp3); - movq(xtmp1, Address(tmp1, 0)); - // Q2 = TABLEExt[n][B >> 8 & 0xFF]; - movl(tmp2, in_out); - shrl(tmp2, 8); - andl(tmp2, 0x000000FF); - shll(tmp2, 3); - addl(tmp2, tmp3); - movq(xtmp2, Address(tmp2, 0)); - - psllq(xtmp2, 8); - pxor(xtmp1, xtmp2); - - // Q3 = TABLEExt[n][B >> 16 & 0xFF]; - movl(tmp2, in_out); - shrl(tmp2, 16); - andl(tmp2, 0x000000FF); - shll(tmp2, 3); - addl(tmp2, tmp3); - movq(xtmp2, Address(tmp2, 0)); - - psllq(xtmp2, 16); - pxor(xtmp1, xtmp2); - - // Q4 = TABLEExt[n][B >> 24 & 0xFF]; - shrl(in_out, 24); - andl(in_out, 0x000000FF); - shll(in_out, 3); - addl(in_out, tmp3); - movq(xtmp2, Address(in_out, 0)); - - psllq(xtmp2, 24); - pxor(xtmp1, xtmp2); // Result in CXMM - // return Q1 ^ Q2 << 8 ^ Q3 << 16 ^ Q4 << 24; -} - -void MacroAssembler::crc32c_pclmulqdq(XMMRegister w_xtmp1, - Register in_out, - uint32_t const_or_pre_comp_const_index, bool is_pclmulqdq_supported, - XMMRegister w_xtmp2, - Register tmp1, - Register n_tmp2, Register n_tmp3) { - if (is_pclmulqdq_supported) { - movdl(w_xtmp1, in_out); - - movl(tmp1, const_or_pre_comp_const_index); - movdl(w_xtmp2, tmp1); - pclmulqdq(w_xtmp1, w_xtmp2, 0); - // Keep result in XMM since GPR is 32 bit in length - } else { - crc32c_ipl_alg4(in_out, const_or_pre_comp_const_index, tmp1, n_tmp2, n_tmp3, w_xtmp1, w_xtmp2); - } -} - -void MacroAssembler::crc32c_rec_alt2(uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported, Register in_out, Register in1, Register in2, - XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3, - Register tmp1, Register tmp2, - Register n_tmp3) { - crc32c_pclmulqdq(w_xtmp1, in_out, const_or_pre_comp_const_index_u1, is_pclmulqdq_supported, w_xtmp3, tmp1, tmp2, n_tmp3); - crc32c_pclmulqdq(w_xtmp2, in1, const_or_pre_comp_const_index_u2, is_pclmulqdq_supported, w_xtmp3, tmp1, tmp2, n_tmp3); - - psllq(w_xtmp1, 1); - movdl(tmp1, w_xtmp1); - psrlq(w_xtmp1, 32); - movdl(in_out, w_xtmp1); - - xorl(tmp2, tmp2); - crc32(tmp2, tmp1, 4); - xorl(in_out, tmp2); - - psllq(w_xtmp2, 1); - movdl(tmp1, w_xtmp2); - psrlq(w_xtmp2, 32); - movdl(in1, w_xtmp2); - - xorl(tmp2, tmp2); - crc32(tmp2, tmp1, 4); - xorl(in1, tmp2); - xorl(in_out, in1); - xorl(in_out, in2); -} - -void MacroAssembler::crc32c_proc_chunk(uint32_t size, uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported, - Register in_out1, Register in_out2, Register in_out3, - Register tmp1, Register tmp2, Register tmp3, - XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3, - Register tmp4, Register tmp5, - Register n_tmp6) { - Label L_processPartitions; - Label L_processPartition; - Label L_exit; - - bind(L_processPartitions); - cmpl(in_out1, 3 * size); - jcc(Assembler::less, L_exit); - xorl(tmp1, tmp1); - xorl(tmp2, tmp2); - movl(tmp3, in_out2); - addl(tmp3, size); - - bind(L_processPartition); - crc32(in_out3, Address(in_out2, 0), 4); - crc32(tmp1, Address(in_out2, size), 4); - crc32(tmp2, Address(in_out2, size*2), 4); - crc32(in_out3, Address(in_out2, 0+4), 4); - crc32(tmp1, Address(in_out2, size+4), 4); - crc32(tmp2, Address(in_out2, size*2+4), 4); - addl(in_out2, 8); - cmpl(in_out2, tmp3); - jcc(Assembler::less, L_processPartition); - - push(tmp3); - push(in_out1); - push(in_out2); - tmp4 = tmp3; - tmp5 = in_out1; - n_tmp6 = in_out2; - - crc32c_rec_alt2(const_or_pre_comp_const_index_u1, const_or_pre_comp_const_index_u2, is_pclmulqdq_supported, in_out3, tmp1, tmp2, - w_xtmp1, w_xtmp2, w_xtmp3, - tmp4, tmp5, - n_tmp6); - - pop(in_out2); - pop(in_out1); - pop(tmp3); - - addl(in_out2, 2 * size); - subl(in_out1, 3 * size); - jmp(L_processPartitions); - - bind(L_exit); -} -#endif //LP64 - -#ifdef _LP64 // Algorithm 2: Pipelined usage of the CRC32 instruction. // Input: A buffer I of L bytes. // Output: the CRC32C value of the buffer. @@ -8852,84 +8160,6 @@ void MacroAssembler::crc32c_ipl_alg2_alt2(Register in_out, Register in1, Registe BIND(L_exit); } -#else -void MacroAssembler::crc32c_ipl_alg2_alt2(Register in_out, Register in1, Register in2, - Register tmp1, Register tmp2, Register tmp3, - Register tmp4, Register tmp5, Register tmp6, - XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3, - bool is_pclmulqdq_supported) { - uint32_t const_or_pre_comp_const_index[CRC32C_NUM_PRECOMPUTED_CONSTANTS]; - Label L_wordByWord; - Label L_byteByByteProlog; - Label L_byteByByte; - Label L_exit; - - if (is_pclmulqdq_supported) { - const_or_pre_comp_const_index[1] = *(uint32_t *)StubRoutines::crc32c_table_addr(); - const_or_pre_comp_const_index[0] = *((uint32_t *)StubRoutines::crc32c_table_addr() + 1); - - const_or_pre_comp_const_index[3] = *((uint32_t *)StubRoutines::crc32c_table_addr() + 2); - const_or_pre_comp_const_index[2] = *((uint32_t *)StubRoutines::crc32c_table_addr() + 3); - - const_or_pre_comp_const_index[5] = *((uint32_t *)StubRoutines::crc32c_table_addr() + 4); - const_or_pre_comp_const_index[4] = *((uint32_t *)StubRoutines::crc32c_table_addr() + 5); - } else { - const_or_pre_comp_const_index[0] = 1; - const_or_pre_comp_const_index[1] = 0; - - const_or_pre_comp_const_index[2] = 3; - const_or_pre_comp_const_index[3] = 2; - - const_or_pre_comp_const_index[4] = 5; - const_or_pre_comp_const_index[5] = 4; - } - crc32c_proc_chunk(CRC32C_HIGH, const_or_pre_comp_const_index[0], const_or_pre_comp_const_index[1], is_pclmulqdq_supported, - in2, in1, in_out, - tmp1, tmp2, tmp3, - w_xtmp1, w_xtmp2, w_xtmp3, - tmp4, tmp5, - tmp6); - crc32c_proc_chunk(CRC32C_MIDDLE, const_or_pre_comp_const_index[2], const_or_pre_comp_const_index[3], is_pclmulqdq_supported, - in2, in1, in_out, - tmp1, tmp2, tmp3, - w_xtmp1, w_xtmp2, w_xtmp3, - tmp4, tmp5, - tmp6); - crc32c_proc_chunk(CRC32C_LOW, const_or_pre_comp_const_index[4], const_or_pre_comp_const_index[5], is_pclmulqdq_supported, - in2, in1, in_out, - tmp1, tmp2, tmp3, - w_xtmp1, w_xtmp2, w_xtmp3, - tmp4, tmp5, - tmp6); - movl(tmp1, in2); - andl(tmp1, 0x00000007); - negl(tmp1); - addl(tmp1, in2); - addl(tmp1, in1); - - BIND(L_wordByWord); - cmpl(in1, tmp1); - jcc(Assembler::greaterEqual, L_byteByByteProlog); - crc32(in_out, Address(in1,0), 4); - addl(in1, 4); - jmp(L_wordByWord); - - BIND(L_byteByByteProlog); - andl(in2, 0x00000007); - movl(tmp2, 1); - - BIND(L_byteByByte); - cmpl(tmp2, in2); - jccb(Assembler::greater, L_exit); - movb(tmp1, Address(in1, 0)); - crc32(in_out, tmp1, 1); - incl(in1); - incl(tmp2); - jmp(L_byteByByte); - - BIND(L_exit); -} -#endif // LP64 #undef BIND #undef BLOCK_COMMENT @@ -9923,7 +9153,6 @@ void MacroAssembler::fill64(Register dst, int disp, XMMRegister xmm, bool use64b fill64(Address(dst, disp), xmm, use64byteVector); } -#ifdef _LP64 void MacroAssembler::generate_fill_avx3(BasicType type, Register to, Register value, Register count, Register rtmp, XMMRegister xtmp) { Label L_exit; @@ -10100,11 +9329,9 @@ void MacroAssembler::generate_fill_avx3(BasicType type, Register to, Register va } bind(L_exit); } -#endif #endif //COMPILER2_OR_JVMCI -#ifdef _LP64 void MacroAssembler::convert_f2i(Register dst, XMMRegister src) { Label done; cvttss2sil(dst, src); @@ -10268,8 +9495,6 @@ void MacroAssembler::cache_wbsync(bool is_pre) } } -#endif // _LP64 - Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { switch (cond) { // Note some conditions are synonyms for others @@ -10455,7 +9680,6 @@ void MacroAssembler::lightweight_unlock(Register obj, Register reg_rax, Register bind(unlocked); } -#ifdef _LP64 // Saves legacy GPRs state on stack. void MacroAssembler::save_legacy_gprs() { subq(rsp, 16 * wordSize); @@ -10504,4 +9728,3 @@ void MacroAssembler::setcc(Assembler::Condition comparison, Register dst) { movzbl(dst, dst); } } -#endif diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 5e26b79e8ae..bc25138f821 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -140,10 +140,10 @@ class MacroAssembler: public Assembler { // Support for inc/dec with optimal instruction selection depending on value - void increment(Register reg, int value = 1) { LP64_ONLY(incrementq(reg, value)) NOT_LP64(incrementl(reg, value)) ; } - void decrement(Register reg, int value = 1) { LP64_ONLY(decrementq(reg, value)) NOT_LP64(decrementl(reg, value)) ; } - void increment(Address dst, int value = 1) { LP64_ONLY(incrementq(dst, value)) NOT_LP64(incrementl(dst, value)) ; } - void decrement(Address dst, int value = 1) { LP64_ONLY(decrementq(dst, value)) NOT_LP64(decrementl(dst, value)) ; } + void increment(Register reg, int value = 1) { incrementq(reg, value); } + void decrement(Register reg, int value = 1) { decrementq(reg, value); } + void increment(Address dst, int value = 1) { incrementq(dst, value); } + void decrement(Address dst, int value = 1) { decrementq(dst, value); } void decrementl(Address dst, int value = 1); void decrementl(Register reg, int value = 1); @@ -221,7 +221,6 @@ class MacroAssembler: public Assembler { // Normally, JavaThread pointer is available in r15_thread, use that where possible. void get_thread_slow(Register thread); -#ifdef _LP64 // Support for argument shuffling // bias in bytes @@ -237,7 +236,6 @@ class MacroAssembler: public Assembler { VMRegPair dst, bool is_receiver, int* receiver_offset); -#endif // _LP64 // Support for VM calls // @@ -351,9 +349,7 @@ class MacroAssembler: public Assembler { void load_method_holder(Register holder, Register method); // oop manipulations -#ifdef _LP64 void load_narrow_klass_compact(Register dst, Register src); -#endif void load_klass(Register dst, Register src, Register tmp); void store_klass(Register dst, Register src, Register tmp); @@ -379,7 +375,6 @@ class MacroAssembler: public Assembler { // stored using routines that take a jobject. void store_heap_oop_null(Address dst); -#ifdef _LP64 void store_klass_gap(Register dst, Register src); // This dummy is to prevent a call to store_heap_oop from @@ -414,8 +409,6 @@ class MacroAssembler: public Assembler { DEBUG_ONLY(void verify_heapbase(const char* msg);) -#endif // _LP64 - // Int division/remainder for Java // (as idivl, but checks for special case as described in JVM spec.) // returns idivl instruction offset for implicit exception handling @@ -582,7 +575,6 @@ public: Label* L_failure, bool set_cond_codes = false); -#ifdef _LP64 // The 64-bit version, which may do a hashed subclass lookup. void check_klass_subtype_slow_path(Register sub_klass, Register super_klass, @@ -592,7 +584,6 @@ public: Register temp4_reg, Label* L_success, Label* L_failure); -#endif // Three parts of a hashed subclass lookup: a simple linear search, // a table lookup, and a fallback that does linear probing in the @@ -629,7 +620,6 @@ public: Register result, u1 super_klass_slot); -#ifdef _LP64 using Assembler::salq; void salq(Register dest, Register count); using Assembler::rorq; @@ -657,7 +647,6 @@ public: Register temp1, Register temp2, Register temp3); -#endif void repne_scanq(Register addr, Register value, Register count, Register limit, Label* L_success, @@ -766,10 +755,10 @@ public: // Arithmetics - void addptr(Address dst, int32_t src) { LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)) ; } + void addptr(Address dst, int32_t src) { addq(dst, src); } void addptr(Address dst, Register src); - void addptr(Register dst, Address src) { LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); } + void addptr(Register dst, Address src) { addq(dst, src); } void addptr(Register dst, int32_t src); void addptr(Register dst, Register src); void addptr(Register dst, RegisterOrConstant src) { @@ -778,12 +767,10 @@ public: } void andptr(Register dst, int32_t src); - void andptr(Register src1, Register src2) { LP64_ONLY(andq(src1, src2)) NOT_LP64(andl(src1, src2)) ; } + void andptr(Register src1, Register src2) { andq(src1, src2); } -#ifdef _LP64 using Assembler::andq; void andq(Register dst, AddressLiteral src, Register rscratch = noreg); -#endif void cmp8(AddressLiteral src1, int imm, Register rscratch = noreg); @@ -796,12 +783,6 @@ public: void cmp32(Register src1, Address src2); -#ifndef _LP64 - void cmpklass(Address dst, Metadata* obj); - void cmpklass(Register dst, Metadata* obj); - void cmpoop(Address dst, jobject obj); -#endif // _LP64 - void cmpoop(Register src1, Register src2); void cmpoop(Register src1, Address src2); void cmpoop(Register dst, jobject obj, Register rscratch); @@ -811,12 +792,11 @@ public: void cmpptr(Register src1, AddressLiteral src2, Register rscratch = noreg); - void cmpptr(Register src1, Register src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - void cmpptr(Register src1, Address src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - // void cmpptr(Address src1, Register src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } + void cmpptr(Register src1, Register src2) { cmpq(src1, src2); } + void cmpptr(Register src1, Address src2) { cmpq(src1, src2); } - void cmpptr(Register src1, int32_t src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - void cmpptr(Address src1, int32_t src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } + void cmpptr(Register src1, int32_t src2) { cmpq(src1, src2); } + void cmpptr(Address src1, int32_t src2) { cmpq(src1, src2); } // cmp64 to avoild hiding cmpq void cmp64(Register src1, AddressLiteral src, Register rscratch = noreg); @@ -825,26 +805,26 @@ public: void locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch = noreg); - void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); } - void imulptr(Register dst, Register src, int imm32) { LP64_ONLY(imulq(dst, src, imm32)) NOT_LP64(imull(dst, src, imm32)); } + void imulptr(Register dst, Register src) { imulq(dst, src); } + void imulptr(Register dst, Register src, int imm32) { imulq(dst, src, imm32); } - void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); } + void negptr(Register dst) { negq(dst); } - void notptr(Register dst) { LP64_ONLY(notq(dst)) NOT_LP64(notl(dst)); } + void notptr(Register dst) { notq(dst); } void shlptr(Register dst, int32_t shift); - void shlptr(Register dst) { LP64_ONLY(shlq(dst)) NOT_LP64(shll(dst)); } + void shlptr(Register dst) { shlq(dst); } void shrptr(Register dst, int32_t shift); - void shrptr(Register dst) { LP64_ONLY(shrq(dst)) NOT_LP64(shrl(dst)); } + void shrptr(Register dst) { shrq(dst); } - void sarptr(Register dst) { LP64_ONLY(sarq(dst)) NOT_LP64(sarl(dst)); } - void sarptr(Register dst, int32_t src) { LP64_ONLY(sarq(dst, src)) NOT_LP64(sarl(dst, src)); } + void sarptr(Register dst) { sarq(dst); } + void sarptr(Register dst, int32_t src) { sarq(dst, src); } - void subptr(Address dst, int32_t src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } + void subptr(Address dst, int32_t src) { subq(dst, src); } - void subptr(Register dst, Address src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } + void subptr(Register dst, Address src) { subq(dst, src); } void subptr(Register dst, int32_t src); // Force generation of a 4 byte immediate value even if it fits into 8bit void subptr_imm32(Register dst, int32_t src); @@ -854,13 +834,13 @@ public: else subptr(dst, src.as_register()); } - void sbbptr(Address dst, int32_t src) { LP64_ONLY(sbbq(dst, src)) NOT_LP64(sbbl(dst, src)); } - void sbbptr(Register dst, int32_t src) { LP64_ONLY(sbbq(dst, src)) NOT_LP64(sbbl(dst, src)); } + void sbbptr(Address dst, int32_t src) { sbbq(dst, src); } + void sbbptr(Register dst, int32_t src) { sbbq(dst, src); } - void xchgptr(Register src1, Register src2) { LP64_ONLY(xchgq(src1, src2)) NOT_LP64(xchgl(src1, src2)) ; } - void xchgptr(Register src1, Address src2) { LP64_ONLY(xchgq(src1, src2)) NOT_LP64(xchgl(src1, src2)) ; } + void xchgptr(Register src1, Register src2) { xchgq(src1, src2); } + void xchgptr(Register src1, Address src2) { xchgq(src1, src2); } - void xaddptr(Address src1, Register src2) { LP64_ONLY(xaddq(src1, src2)) NOT_LP64(xaddl(src1, src2)) ; } + void xaddptr(Address src1, Register src2) { xaddq(src1, src2); } @@ -870,12 +850,10 @@ public: // Unconditional atomic increment. void atomic_incl(Address counter_addr); void atomic_incl(AddressLiteral counter_addr, Register rscratch = noreg); -#ifdef _LP64 void atomic_incq(Address counter_addr); void atomic_incq(AddressLiteral counter_addr, Register rscratch = noreg); -#endif - void atomic_incptr(AddressLiteral counter_addr, Register rscratch = noreg) { LP64_ONLY(atomic_incq(counter_addr, rscratch)) NOT_LP64(atomic_incl(counter_addr, rscratch)) ; } - void atomic_incptr(Address counter_addr) { LP64_ONLY(atomic_incq(counter_addr)) NOT_LP64(atomic_incl(counter_addr)) ; } + void atomic_incptr(AddressLiteral counter_addr, Register rscratch = noreg) { atomic_incq(counter_addr, rscratch); } + void atomic_incptr(Address counter_addr) { atomic_incq(counter_addr); } using Assembler::lea; void lea(Register dst, AddressLiteral adr); @@ -893,18 +871,18 @@ public: void testq(Address dst, int32_t imm32); void testq(Register dst, int32_t imm32); - void orptr(Register dst, Address src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } - void orptr(Register dst, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } - void orptr(Register dst, int32_t src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } - void orptr(Address dst, int32_t imm32) { LP64_ONLY(orq(dst, imm32)) NOT_LP64(orl(dst, imm32)); } + void orptr(Register dst, Address src) { orq(dst, src); } + void orptr(Register dst, Register src) { orq(dst, src); } + void orptr(Register dst, int32_t src) { orq(dst, src); } + void orptr(Address dst, int32_t imm32) { orq(dst, imm32); } - void testptr(Register src, int32_t imm32) { LP64_ONLY(testq(src, imm32)) NOT_LP64(testl(src, imm32)); } - void testptr(Register src1, Address src2) { LP64_ONLY(testq(src1, src2)) NOT_LP64(testl(src1, src2)); } - void testptr(Address src, int32_t imm32) { LP64_ONLY(testq(src, imm32)) NOT_LP64(testl(src, imm32)); } + void testptr(Register src, int32_t imm32) { testq(src, imm32); } + void testptr(Register src1, Address src2) { testq(src1, src2); } + void testptr(Address src, int32_t imm32) { testq(src, imm32); } void testptr(Register src1, Register src2); - void xorptr(Register dst, Register src) { LP64_ONLY(xorq(dst, src)) NOT_LP64(xorl(dst, src)); } - void xorptr(Register dst, Address src) { LP64_ONLY(xorq(dst, src)) NOT_LP64(xorl(dst, src)); } + void xorptr(Register dst, Register src) { xorq(dst, src); } + void xorptr(Register dst, Address src) { xorq(dst, src); } // Calls @@ -1033,7 +1011,6 @@ public: void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } void ldmxcsr(AddressLiteral src, Register rscratch = noreg); -#ifdef _LP64 private: void sha256_AVX2_one_round_compute( Register reg_old_h, @@ -1083,7 +1060,6 @@ public: Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block, XMMRegister shuf_mask); void sha512_update_ni_x1(Register arg_hash, Register arg_msg, Register ofs, Register limit, bool multi_block); -#endif // _LP64 void fast_md5(Register buf, Address state, Address ofs, Address limit, bool multi_block); @@ -1093,68 +1069,15 @@ public: Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block); -#ifdef _LP64 void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block, XMMRegister shuf_mask); -#else - void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, - XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, - Register buf, Register state, Register ofs, Register limit, Register rsp, - bool multi_block); -#endif void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, Register rdx, Register tmp); -#ifndef _LP64 - private: - // Initialized in macroAssembler_x86_constants.cpp - static address ONES; - static address L_2IL0FLOATPACKET_0; - static address PI4_INV; - static address PI4X3; - static address PI4X4; - - public: - void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, - XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx, Register tmp1); - - void fast_log10(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, - XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx, Register tmp); - - void fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, - XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, - Register rdx, Register tmp); - - void fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, - XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rbx, Register rdx); - - void fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, - XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx, Register tmp); - - void libm_sincos_huge(XMMRegister xmm0, XMMRegister xmm1, Register eax, Register ecx, - Register edx, Register ebx, Register esi, Register edi, - Register ebp, Register esp); - - void libm_reduce_pi04l(Register eax, Register ecx, Register edx, Register ebx, - Register esi, Register edi, Register ebp, Register esp); - - void libm_tancot_huge(XMMRegister xmm0, XMMRegister xmm1, Register eax, Register ecx, - Register edx, Register ebx, Register esi, Register edi, - Register ebp, Register esp); - - void fast_tan(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, - XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx, Register tmp); -#endif // !_LP64 - private: // these are private because users should be doing movflt/movdbl @@ -1921,8 +1844,8 @@ public: void cmov( Condition cc, Register dst, Register src) { cmovptr(cc, dst, src); } - void cmovptr(Condition cc, Register dst, Address src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); } - void cmovptr(Condition cc, Register dst, Register src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); } + void cmovptr(Condition cc, Register dst, Address src) { cmovq(cc, dst, src); } + void cmovptr(Condition cc, Register dst, Register src) { cmovq(cc, dst, src); } void movoop(Register dst, jobject obj); void movoop(Address dst, jobject obj, Register rscratch); @@ -1961,15 +1884,15 @@ public: // Can push value or effective address void pushptr(AddressLiteral src, Register rscratch); - void pushptr(Address src) { LP64_ONLY(pushq(src)) NOT_LP64(pushl(src)); } - void popptr(Address src) { LP64_ONLY(popq(src)) NOT_LP64(popl(src)); } + void pushptr(Address src) { pushq(src); } + void popptr(Address src) { popq(src); } void pushoop(jobject obj, Register rscratch); void pushklass(Metadata* obj, Register rscratch); // sign extend as need a l to ptr sized element - void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); } - void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } + void movl2ptr(Register dst, Address src) { movslq(dst, src); } + void movl2ptr(Register dst, Register src) { movslq(dst, src); } public: @@ -1992,7 +1915,6 @@ public: XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3, XMMRegister tmp4, Register tmp5, Register result, bool ascii); -#ifdef _LP64 void add2_with_carry(Register dest_hi, Register dest_lo, Register src1, Register src2); void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart, Register y, Register y_idx, Register z, @@ -2033,32 +1955,22 @@ public: void vectorized_mismatch(Register obja, Register objb, Register length, Register log2_array_indxscale, Register result, Register tmp1, Register tmp2, XMMRegister vec1, XMMRegister vec2, XMMRegister vec3); -#endif // CRC32 code for java.util.zip.CRC32::updateBytes() intrinsic. void update_byte_crc32(Register crc, Register val, Register table); void kernel_crc32(Register crc, Register buf, Register len, Register table, Register tmp); - -#ifdef _LP64 void kernel_crc32_avx512(Register crc, Register buf, Register len, Register table, Register tmp1, Register tmp2); void kernel_crc32_avx512_256B(Register crc, Register buf, Register len, Register key, Register pos, Register tmp1, Register tmp2, Label& L_barrett, Label& L_16B_reduction_loop, Label& L_get_last_two_xmms, Label& L_128_done, Label& L_cleanup); -#endif // _LP64 // CRC32C code for java.util.zip.CRC32C::updateBytes() intrinsic // Note on a naming convention: // Prefix w = register only used on a Westmere+ architecture // Prefix n = register only used on a Nehalem architecture -#ifdef _LP64 void crc32c_ipl_alg4(Register in_out, uint32_t n, Register tmp1, Register tmp2, Register tmp3); -#else - void crc32c_ipl_alg4(Register in_out, uint32_t n, - Register tmp1, Register tmp2, Register tmp3, - XMMRegister xtmp1, XMMRegister xtmp2); -#endif void crc32c_pclmulqdq(XMMRegister w_xtmp1, Register in_out, uint32_t const_or_pre_comp_const_index, bool is_pclmulqdq_supported, @@ -2083,10 +1995,8 @@ public: // Fold 128-bit data chunk void fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, int offset); void fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, XMMRegister xbuf); -#ifdef _LP64 // Fold 512-bit data chunk void fold512bit_crc32_avx512(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, Register pos, int offset); -#endif // _LP64 // Fold 8-bit data void fold_8bit_crc32(Register crc, Register table, Register tmp); void fold_8bit_crc32(XMMRegister crc, Register table, XMMRegister xtmp, Register tmp); @@ -2120,7 +2030,6 @@ public: void fill64(Register dst, int dis, XMMRegister xmm, bool use64byteVector = false); -#ifdef _LP64 void convert_f2i(Register dst, XMMRegister src); void convert_d2i(Register dst, XMMRegister src); void convert_f2l(Register dst, XMMRegister src); @@ -2135,7 +2044,6 @@ public: void generate_fill_avx3(BasicType type, Register to, Register value, Register count, Register rtmp, XMMRegister xtmp); #endif // COMPILER2_OR_JVMCI -#endif // _LP64 void vallones(XMMRegister dst, int vector_len); @@ -2144,11 +2052,9 @@ public: void lightweight_lock(Register basic_lock, Register obj, Register reg_rax, Register tmp, Label& slow); void lightweight_unlock(Register obj, Register reg_rax, Register tmp, Label& slow); -#ifdef _LP64 void save_legacy_gprs(); void restore_legacy_gprs(); void setcc(Assembler::Condition comparison, Register dst); -#endif }; #endif // CPU_X86_MACROASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp b/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp index e2753b701da..432f9277549 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86_sha.cpp @@ -235,17 +235,10 @@ void MacroAssembler::fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, // and state0 and state1 can never use xmm0 register. // ofs and limit are used for multi-block byte array. // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) -#ifdef _LP64 void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block, XMMRegister shuf_mask) { -#else -void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, - XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, - Register buf, Register state, Register ofs, Register limit, Register rsp, - bool multi_block) { -#endif Label done_hash, loop0; address K256 = StubRoutines::x86::k256_addr(); @@ -260,9 +253,7 @@ void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegiste palignr(state0, state1, 8); pblendw(state1, msgtmp4, 0xF0); -#ifdef _LP64 movdqu(shuf_mask, ExternalAddress(pshuffle_byte_flip_mask)); -#endif lea(rax, ExternalAddress(K256)); bind(loop0); @@ -271,11 +262,7 @@ void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegiste // Rounds 0-3 movdqu(msg, Address(buf, 0)); -#ifdef _LP64 pshufb(msg, shuf_mask); -#else - pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); -#endif movdqa(msgtmp0, msg); paddd(msg, Address(rax, 0)); sha256rnds2(state1, state0); @@ -284,11 +271,7 @@ void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegiste // Rounds 4-7 movdqu(msg, Address(buf, 16)); -#ifdef _LP64 pshufb(msg, shuf_mask); -#else - pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); -#endif movdqa(msgtmp1, msg); paddd(msg, Address(rax, 16)); sha256rnds2(state1, state0); @@ -298,11 +281,7 @@ void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegiste // Rounds 8-11 movdqu(msg, Address(buf, 32)); -#ifdef _LP64 pshufb(msg, shuf_mask); -#else - pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); -#endif movdqa(msgtmp2, msg); paddd(msg, Address(rax, 32)); sha256rnds2(state1, state0); @@ -312,11 +291,7 @@ void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegiste // Rounds 12-15 movdqu(msg, Address(buf, 48)); -#ifdef _LP64 pshufb(msg, shuf_mask); -#else - pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); -#endif movdqa(msgtmp3, msg); paddd(msg, Address(rax, 48)); sha256rnds2(state1, state0); @@ -491,7 +466,6 @@ void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegiste } -#ifdef _LP64 /* The algorithm below is based on Intel publication: "Fast SHA-256 Implementations on Intel(R) Architecture Processors" by Jim Guilford, Kirk Yap and Vinodh Gopal. @@ -1696,5 +1670,3 @@ void MacroAssembler::sha512_update_ni_x1(Register arg_hash, Register arg_msg, Re bind(done_hash); } - -#endif //#ifdef _LP64 diff --git a/test/hotspot/gtest/x86/test_assemblerx86.cpp b/test/hotspot/gtest/x86/test_assembler_x86.cpp similarity index 99% rename from test/hotspot/gtest/x86/test_assemblerx86.cpp rename to test/hotspot/gtest/x86/test_assembler_x86.cpp index eee9fc71488..32315e06fde 100644 --- a/test/hotspot/gtest/x86/test_assemblerx86.cpp +++ b/test/hotspot/gtest/x86/test_assembler_x86.cpp @@ -30,6 +30,7 @@ #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.hpp" +#include "code/codeCache.hpp" #include "memory/resourceArea.hpp" #include "unittest.hpp" From 43b2b0bd1e5e6fad4581957a3072836921ef6683 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 2 Dec 2024 05:21:55 +0000 Subject: [PATCH 194/843] 8343007: Enhance Buffered Image handling Reviewed-by: rhalade, mschoene, jdv, prr --- .../share/native/libawt/java2d/loops/Blit.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libawt/java2d/loops/Blit.c b/src/java.desktop/share/native/libawt/java2d/loops/Blit.c index fee108b833a..8a41584deef 100644 --- a/src/java.desktop/share/native/libawt/java2d/loops/Blit.c +++ b/src/java.desktop/share/native/libawt/java2d/loops/Blit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, 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 @@ -68,14 +68,30 @@ Java_sun_java2d_loops_Blit_Blit return; } + if (width <= 0 || height <= 0) { + return; + } + srcInfo.bounds.x1 = srcx; srcInfo.bounds.y1 = srcy; + if (UNSAFE_TO_ADD(srcx, width) || + UNSAFE_TO_ADD(srcy, height) || + UNSAFE_TO_ADD(dstx, width) || + UNSAFE_TO_ADD(dsty, height)) { + return; + } + srcInfo.bounds.x2 = srcx + width; srcInfo.bounds.y2 = srcy + height; dstInfo.bounds.x1 = dstx; dstInfo.bounds.y1 = dsty; dstInfo.bounds.x2 = dstx + width; dstInfo.bounds.y2 = dsty + height; + if (UNSAFE_TO_SUB(srcx, dstx) || + UNSAFE_TO_SUB(srcy, dsty)) { + return; + } + srcx -= dstx; srcy -= dsty; SurfaceData_IntersectBounds(&dstInfo.bounds, &clipInfo.bounds); From cf871db447660e657a3db82bffae8fce1b7e57a5 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Fri, 13 Dec 2024 04:29:18 +0000 Subject: [PATCH 195/843] 8342562: Enhance Deflater operations Reviewed-by: rhalade, alanb, lancea --- .../java/util/zip/DeflaterOutputStream.java | 40 +++++++++++++++---- .../java/util/zip/GZIPOutputStream.java | 4 +- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java index 3fca6a1b759..85ba968dc9b 100644 --- a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java @@ -57,6 +57,26 @@ import java.io.IOException; * @since 1.1 */ public class DeflaterOutputStream extends FilterOutputStream { + + /* + * The default size of the output buffer + */ + static final int DEFAULT_BUF_SIZE = 512; + + /* + * When calling Deflater.deflate() with Deflater.SYNC_FLUSH or Deflater.FULL_FLUSH, + * the callers are expected to ensure that the size of the buffer is greater than 6. + * This expectation comes from the underlying zlib library which in its zlib.h + * states: + * "If deflate returns with avail_out == 0, this function must be called again + * with the same value of the flush parameter and more output space (updated + * avail_out), until the flush is complete (deflate returns with non-zero + * avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + * avail_out is greater than six when the flush marker begins, in order to avoid + * repeated flush markers upon calling deflate() again when avail_out == 0." + */ + private static final int SYNC_FLUSH_MIN_BUF_SIZE = 7; + /** * Compressor for this stream. */ @@ -152,7 +172,7 @@ public class DeflaterOutputStream extends FilterOutputStream { public DeflaterOutputStream(OutputStream out, Deflater def, boolean syncFlush) { - this(out, def, 512, syncFlush); + this(out, def, DEFAULT_BUF_SIZE, syncFlush); } @@ -171,7 +191,7 @@ public class DeflaterOutputStream extends FilterOutputStream { * @param def the compressor ("deflater") */ public DeflaterOutputStream(OutputStream out, Deflater def) { - this(out, def, 512, false); + this(out, def, DEFAULT_BUF_SIZE, false); } boolean usesDefaultDeflater = false; @@ -195,7 +215,7 @@ public class DeflaterOutputStream extends FilterOutputStream { * @since 1.7 */ public DeflaterOutputStream(OutputStream out, boolean syncFlush) { - this(out, out != null ? new Deflater() : null, 512, syncFlush); + this(out, out != null ? new Deflater() : null, DEFAULT_BUF_SIZE, syncFlush); usesDefaultDeflater = true; } @@ -342,10 +362,16 @@ public class DeflaterOutputStream extends FilterOutputStream { public void flush() throws IOException { if (syncFlush && !def.finished()) { int len = 0; - while ((len = def.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH)) > 0) - { - out.write(buf, 0, len); - if (len < buf.length) + // For SYNC_FLUSH, the Deflater.deflate() expects the callers + // to use a buffer whose length is greater than 6 to avoid + // flush marker (5 bytes) being repeatedly output to the output buffer + // every time it is invoked. + final byte[] flushBuf = buf.length < SYNC_FLUSH_MIN_BUF_SIZE + ? new byte[DEFAULT_BUF_SIZE] + : buf; + while ((len = def.deflate(flushBuf, 0, flushBuf.length, Deflater.SYNC_FLUSH)) > 0) { + out.write(flushBuf, 0, len); + if (len < flushBuf.length) break; } } diff --git a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java index cea0880fca6..12abd53350f 100644 --- a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java @@ -113,7 +113,7 @@ public class GZIPOutputStream extends DeflaterOutputStream { * @throws IOException If an I/O error has occurred. */ public GZIPOutputStream(OutputStream out) throws IOException { - this(out, 512, false); + this(out, DeflaterOutputStream.DEFAULT_BUF_SIZE, false); } /** @@ -135,7 +135,7 @@ public class GZIPOutputStream extends DeflaterOutputStream { public GZIPOutputStream(OutputStream out, boolean syncFlush) throws IOException { - this(out, 512, syncFlush); + this(out, DeflaterOutputStream.DEFAULT_BUF_SIZE, syncFlush); } /** From ef38a04b448f97036c516ba87cb86afcc7559d1f Mon Sep 17 00:00:00 2001 From: Hai-May Chao Date: Thu, 2 Jan 2025 19:03:53 +0000 Subject: [PATCH 196/843] 8337494: Clarify JarInputStream behavior Reviewed-by: jpai, rhalade, lancea --- .../share/classes/java/util/jar/JarFile.java | 3 ++- .../share/classes/java/util/jar/JarInputStream.java | 12 +++++++++++- .../share/classes/java/util/jar/JarVerifier.java | 5 ++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index e7725c8636f..dc2d65bcc99 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -409,7 +409,8 @@ public class JarFile extends ZipFile { jv = new JarVerifier(manEntry.getName(), b); } else { if (JarVerifier.debug != null) { - JarVerifier.debug.println("Multiple MANIFEST.MF found. Treat JAR file as unsigned"); + JarVerifier.debug.println( + JarVerifier.MULTIPLE_MANIFEST_WARNING); } } } diff --git a/src/java.base/share/classes/java/util/jar/JarInputStream.java b/src/java.base/share/classes/java/util/jar/JarInputStream.java index e4ffd09fb1e..5c29d74f92a 100644 --- a/src/java.base/share/classes/java/util/jar/JarInputStream.java +++ b/src/java.base/share/classes/java/util/jar/JarInputStream.java @@ -151,7 +151,17 @@ public class JarInputStream extends ZipInputStream { jv = new JarVerifier(e.getName(), bytes); mev = new ManifestEntryVerifier(man, jv.manifestName); } - return (JarEntry)super.getNextEntry(); + JarEntry nextEntry = (JarEntry)super.getNextEntry(); + if (nextEntry != null && + JarFile.MANIFEST_NAME.equalsIgnoreCase(nextEntry.getName())) { + if (JarVerifier.debug != null) { + JarVerifier.debug.println(JarVerifier.MULTIPLE_MANIFEST_WARNING); + } + + jv = null; + mev = null; + } + return nextEntry; } return e; } diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java index 92cb09448b8..fe58c4dffec 100644 --- a/src/java.base/share/classes/java/util/jar/JarVerifier.java +++ b/src/java.base/share/classes/java/util/jar/JarVerifier.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 @@ -46,6 +46,9 @@ import static sun.security.util.SignatureFileVerifier.isInMetaInf; */ class JarVerifier { + public static final String MULTIPLE_MANIFEST_WARNING = + "WARNING: Multiple MANIFEST.MF found. Treat JAR file as unsigned."; + /* Are we debugging ? */ static final Debug debug = Debug.getInstance("jar"); From e91b3f0c3dddba1ed1e5f2fa87f9cd9d135b4439 Mon Sep 17 00:00:00 2001 From: Jamil Nimeh Date: Wed, 8 Jan 2025 20:39:38 +0000 Subject: [PATCH 197/843] 8337692: Better TLS connection support Co-authored-by: Ferenc Rakoczi Reviewed-by: rhalade, valeriep, pkumaraswamy, mpowers, ahgross, mbalao --- .../com/sun/crypto/provider/RSACipher.java | 67 +++++++---- .../classes/sun/security/rsa/RSAPadding.java | 109 +++++++++++++----- .../classes/sun/security/util/KeyUtil.java | 32 +++-- 3 files changed, 150 insertions(+), 58 deletions(-) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java b/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java index b48917e7557..9f19e1415bd 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java @@ -236,7 +236,8 @@ public final class RSACipher extends CipherSpi { params.getParameterSpec(OAEPParameterSpec.class); init(opmode, key, random, spec); } catch (InvalidParameterSpecException ipse) { - throw new InvalidAlgorithmParameterException("Wrong parameter", ipse); + throw new InvalidAlgorithmParameterException("Wrong parameter", + ipse); } } } @@ -380,7 +381,7 @@ public final class RSACipher extends CipherSpi { byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs); paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false); result = padding.unpad(paddingCopy); - if (result == null && !forTlsPremasterSecret) { + if (!forTlsPremasterSecret && result == null) { throw new BadPaddingException ("Padding error in decryption"); } @@ -400,6 +401,34 @@ public final class RSACipher extends CipherSpi { } } + // TLS master secret decode version of the doFinal() method. + private byte[] doFinalForTls(int clientVersion, int serverVersion) + throws BadPaddingException, IllegalBlockSizeException { + if (bufOfs > buffer.length) { + throw new IllegalBlockSizeException("Data must not be longer " + + "than " + buffer.length + " bytes"); + } + byte[] paddingCopy = null; + byte[] result = null; + try { + byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs); + + paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false); + result = padding.unpadForTls(paddingCopy, clientVersion, + serverVersion); + + return result; + } finally { + Arrays.fill(buffer, 0, bufOfs, (byte)0); + bufOfs = 0; + if (paddingCopy != null + && paddingCopy != buffer // already cleaned + && paddingCopy != result) { // DO NOT CLEAN, THIS IS RESULT + Arrays.fill(paddingCopy, (byte)0); + } + } + } + // see JCE spec protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) { update(in, inOfs, inLen); @@ -469,41 +498,37 @@ public final class RSACipher extends CipherSpi { boolean isTlsRsaPremasterSecret = algorithm.equals("TlsRsaPremasterSecret"); - byte[] encoded; + byte[] encoded = null; update(wrappedKey, 0, wrappedKey.length); - try { - encoded = doFinal(); - } catch (BadPaddingException | IllegalBlockSizeException e) { - // BadPaddingException cannot happen for TLS RSA unwrap. - // In that case, padding error is indicated by returning null. - // IllegalBlockSizeException cannot happen in any case, - // because of the length check above. - throw new InvalidKeyException("Unwrapping failed", e); - } - try { if (isTlsRsaPremasterSecret) { if (!forTlsPremasterSecret) { throw new IllegalStateException( "No TlsRsaPremasterSecretParameterSpec specified"); } - - // polish the TLS premaster secret - encoded = KeyUtil.checkTlsPreMasterSecretKey( - ((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(), - ((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(), - random, encoded, encoded == null); + TlsRsaPremasterSecretParameterSpec parameterSpec = + (TlsRsaPremasterSecretParameterSpec) spec; + encoded = doFinalForTls(parameterSpec.getClientVersion(), + parameterSpec.getServerVersion()); + } else { + encoded = doFinal(); } - return ConstructKeys.constructKey(encoded, algorithm, type); + + } catch (BadPaddingException | IllegalBlockSizeException e) { + // BadPaddingException cannot happen for TLS RSA unwrap. + // Neither padding error nor server version error is indicated + // for TLS, but a fake unwrapped value is returned. + // IllegalBlockSizeException cannot happen in any case, + // because of the length check above. + throw new InvalidKeyException("Unwrapping failed", e); } finally { if (encoded != null) { Arrays.fill(encoded, (byte) 0); } } } - // see JCE spec protected int engineGetKeySize(Key key) throws InvalidKeyException { RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPadding.java b/src/java.base/share/classes/sun/security/rsa/RSAPadding.java index 3fd6aa537ec..919c734eaca 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPadding.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPadding.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 @@ -321,48 +321,103 @@ public final class RSAPadding { * Note that we want to make it a constant-time operation */ private byte[] unpadV15(byte[] padded) { - int k = 0; - boolean bp = false; + int paddedLength = padded.length; - if (padded[k++] != 0) { - bp = true; + if (paddedLength < 2) { + return null; } - if (padded[k++] != type) { - bp = true; - } - int p = 0; - while (k < padded.length) { + + // The following check ensures that the lead byte is zero and + // the second byte is equivalent to the padding type. The + // bp (bad padding) variable throughout this unpadding process will + // be updated and remain 0 if good padding, 1 if bad. + int p0 = padded[0]; + int p1 = padded[1]; + int bp = (-(p0 & 0xff) | ((p1 - type) | (type - p1))) >>> 31; + + int padLen = 0; + int k = 2; + // Walk through the random, nonzero padding bytes. For each padding + // byte bp and padLen will remain zero. When the end-of-padding + // byte (0x00) is reached then padLen will be set to the index of the + // first byte of the message content. + while (k < paddedLength) { int b = padded[k++] & 0xff; - if ((b == 0) && (p == 0)) { - p = k; - } - if ((k == padded.length) && (p == 0)) { - bp = true; - } - if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) && - (p == 0)) { - bp = true; + padLen += (k * (1 - ((-(b | padLen)) >>> 31))); + if (k == paddedLength) { + bp = bp | (1 - ((-padLen) >>> 31)); } + bp = bp | (1 - (-(((type - PAD_BLOCKTYPE_1) & 0xff) | + padLen | (1 - ((b - 0xff) >>> 31))) >>> 31)); } - int n = padded.length - p; - if (n > maxDataSize) { - bp = true; - } + int n = paddedLength - padLen; + // So long as n <= maxDataSize, bp will remain zero + bp = bp | ((maxDataSize - n) >>> 31); // copy useless padding array for a constant-time method - byte[] padding = new byte[p]; - System.arraycopy(padded, 0, padding, 0, p); + byte[] padding = new byte[padLen + 2]; + for (int i = 0; i < padLen; i++) { + padding[i] = padded[i]; + } byte[] data = new byte[n]; - System.arraycopy(padded, p, data, 0, n); + for (int i = 0; i < n; i++) { + data[i] = padded[padLen + i]; + } - if (bp) { + if ((bp | padding[bp]) != 0) { + // using the array padding here hoping that this way + // the compiler does not eliminate the above useless copy return null; } else { return data; } } + public byte[] unpadForTls(byte[] padded, int clientVersion, + int serverVersion) { + int paddedLength = padded.length; + + // bp is positive if the padding is bad and 0 if it is good so far + int bp = (((int) padded[0] | ((int)padded[1] - PAD_BLOCKTYPE_2)) & + 0xFFF); + + int k = 2; + while (k < paddedLength - 49) { + int b = padded[k++] & 0xFF; + bp = bp | (1 - (-b >>> 31)); // if (padded[k] == 0) bp |= 1; + } + bp |= ((int)padded[k++] & 0xFF); + int encodedVersion = ((padded[k] & 0xFF) << 8) | (padded[k + 1] & 0xFF); + + int bv1 = clientVersion - encodedVersion; + bv1 |= -bv1; + int bv3 = serverVersion - encodedVersion; + bv3 |= -bv3; + int bv2 = (0x301 - clientVersion); + + bp |= ((bv1 & (bv2 | bv3)) >>> 28); + + byte[] data = Arrays.copyOfRange(padded, paddedLength - 48, + paddedLength); + if (random == null) { + random = JCAUtil.getSecureRandom(); + } + + byte[] fake = new byte[48]; + random.nextBytes(fake); + + bp = (-bp >> 24); + + // Now bp is 0 if the padding and version number were good and + // -1 otherwise. + for (int i = 0; i < 48; i++) { + data[i] = (byte)((~bp & data[i]) | (bp & fake[i])); + } + + return data; + } + /** * PKCS#1 v2.0 OAEP padding (MGF1). * Paragraph references refer to PKCS#1 v2.1 (June 14, 2002) diff --git a/src/java.base/share/classes/sun/security/util/KeyUtil.java b/src/java.base/share/classes/sun/security/util/KeyUtil.java index 2c9416c0983..95223ec0b12 100644 --- a/src/java.base/share/classes/sun/security/util/KeyUtil.java +++ b/src/java.base/share/classes/sun/security/util/KeyUtil.java @@ -320,19 +320,31 @@ public final class KeyUtil { tmp = encoded; } + // At this point tmp.length is 48 int encodedVersion = ((tmp[0] & 0xFF) << 8) | (tmp[1] & 0xFF); - int check1 = 0; - int check2 = 0; - int check3 = 0; - if (clientVersion != encodedVersion) check1 = 1; - if (clientVersion > 0x0301) check2 = 1; - if (serverVersion != encodedVersion) check3 = 1; - if ((check1 & (check2 | check3)) == 1) { - return replacer; - } else { - return tmp; + + // The following code is a time-constant version of + // if ((clientVersion != encodedVersion) || + // ((clientVersion > 0x301) && (serverVersion != encodedVersion))) { + // return replacer; + // } else { return tmp; } + int check1 = (clientVersion - encodedVersion) | + (encodedVersion - clientVersion); + int check2 = 0x0301 - clientVersion; + int check3 = (serverVersion - encodedVersion) | + (encodedVersion - serverVersion); + + check1 = (check1 & (check2 | check3)) >> 24; + + // Now check1 is either 0 or -1 + check2 = ~check1; + + for (int i = 0; i < 48; i++) { + tmp[i] = (byte) ((tmp[i] & check2) | (replacer[i] & check1)); } + + return tmp; } /** From 38afa4d42ff27f9c9ef18ee1691885ed4cf8dde5 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 20 Jan 2025 12:00:07 +0000 Subject: [PATCH 198/843] 8338430: Improve compiler transformations Co-authored-by: Emanuel Peter Reviewed-by: ahgross, rhalade, thartmann, epeter --- src/hotspot/share/opto/addnode.cpp | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index a097a08607a..143398c57d0 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -1179,6 +1179,14 @@ static bool can_overflow(const TypeInt* t, jint c) { (c > 0 && (java_add(t_hi, c) < t_hi))); } +// Check if addition of a long with type 't' and a constant 'c' can overflow. +static bool can_overflow(const TypeLong* t, jlong c) { + jlong t_lo = t->_lo; + jlong t_hi = t->_hi; + return ((c < 0 && (java_add(t_lo, c) > t_lo)) || + (c > 0 && (java_add(t_hi, c) < t_hi))); +} + // Let = x_operands and = y_operands. // If x == y and neither add(x, x_off) nor add(y, y_off) overflow, return // add(x, op(x_off, y_off)). Otherwise, return nullptr. @@ -1363,6 +1371,31 @@ const Type *MinINode::add_ring( const Type *t0, const Type *t1 ) const { // // Note: we assume that SubL was already replaced by an AddL, and that the stride // has its sign flipped: SubL(limit, stride) -> AddL(limit, -stride). +// +// Proof MaxL collapsed version equivalent to original (MinL version similar): +// is_sub_con ensures that con1, con2 ∈ [min_int, 0[ +// +// Original: +// - AddL2 underflow => x + con2 ∈ ]max_long - min_int, max_long], ALWAYS BAILOUT as x + con1 + con2 surely fails can_overflow (*) +// - AddL2 no underflow => x + con2 ∈ [min_long, max_long] +// - MaxL2 clamp => min_int +// - AddL1 underflow: NOT POSSIBLE: cannot underflow since min_int + con1 ∈ [2 * min_int, min_int] always > min_long +// - AddL1 no underflow => min_int + con1 ∈ [2 * min_int, min_int] +// - MaxL1 clamp => min_int (RESULT 1) +// - MaxL1 no clamp: NOT POSSIBLE: min_int + con1 ∈ [2 * min_int, min_int] always <= min_int, so clamp always taken +// - MaxL2 no clamp => x + con2 ∈ [min_int, max_long] +// - AddL1 underflow: NOT POSSIBLE: cannot underflow since x + con2 + con1 ∈ [2 * min_int, max_long] always > min_long +// - AddL1 no underflow => x + con2 + con1 ∈ [2 * min_int, max_long] +// - MaxL1 clamp => min_int (RESULT 2) +// - MaxL1 no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) +// +// Collapsed: +// - AddL2 (cannot underflow) => con2 + con1 ∈ [2 * min_int, 0] +// - AddL1 underflow: NOT POSSIBLE: would have bailed out at can_overflow (*) +// - AddL1 no underflow => x + con2 + con1 ∈ [min_long, max_long] +// - MaxL clamp => min_int (RESULT 1 and RESULT 2) +// - MaxL no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) +// static Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) { assert(n->Opcode() == Op_MaxL || n->Opcode() == Op_MinL, "sanity"); // Check that the two clamps have the correct values. @@ -1392,6 +1425,10 @@ static Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) { Node* x = add2->in(1); Node* con2 = add2->in(2); if (is_sub_con(con2)) { + // Collapsed graph not equivalent if potential over/underflow -> bailing out (*) + if (can_overflow(phase->type(x)->is_long(), con1->get_long() + con2->get_long())) { + return nullptr; + } Node* new_con = phase->transform(new AddLNode(con1, con2)); Node* new_sub = phase->transform(new AddLNode(x, new_con)); n->set_req_X(1, new_sub, phase); From ed30fce6df57b1cbf7a6efebabc3558550f8ec16 Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Mon, 27 Jan 2025 21:11:23 +0000 Subject: [PATCH 199/843] 8347847: Enhance jar file support Reviewed-by: rhalade, jnibedita, pkumaraswamy, ahgross, hchao, weijun, mullan --- .../security/util/SignatureFileVerifier.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java index 7accd3cbf10..d7e65b6aef0 100644 --- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -518,6 +518,8 @@ public class SignatureFileVerifier { boolean attrsVerified = true; // If only weak algorithms are used. boolean weakAlgs = true; + // If only unsupported algorithms are used. + boolean unsupportedAlgs = true; // If a ATTR_DIGEST entry is found. boolean validEntry = false; @@ -542,6 +544,7 @@ public class SignatureFileVerifier { MessageDigest digest = getDigest(algorithm); if (digest != null) { + unsupportedAlgs = false; ManifestDigester.Entry mde = md.getMainAttsEntry(false); if (mde == null) { throw new SignatureException("Manifest Main Attribute check " + @@ -584,12 +587,22 @@ public class SignatureFileVerifier { } } - // If there were only weak algorithms entries used, throw an exception. - if (validEntry && weakAlgs) { - throw new SignatureException("Manifest Main Attribute check " + - "failed (" + ATTR_DIGEST + "). " + - "Disabled algorithm(s) used: " + - getWeakAlgorithms(ATTR_DIGEST)); + if (validEntry) { + // If there were only weak algorithms entries used, throw an exception. + if (weakAlgs) { + throw new SignatureException( + "Manifest Main Attribute check " + + "failed (" + ATTR_DIGEST + "). " + + "Disabled algorithm(s) used: " + + getWeakAlgorithms(ATTR_DIGEST)); + } + + // If there were only unsupported algorithms entries used, throw an exception. + if (unsupportedAlgs) { + throw new SignatureException( + "Manifest Main Attribute check failed (" + + ATTR_DIGEST + "). Unsupported algorithm(s) used"); + } } // this method returns 'true' if either: From 18d605fadbd57090f5eb02c18e6e8860d9086515 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 16 Apr 2025 08:23:03 +0000 Subject: [PATCH 200/843] 8354629: Test tools/jlink/ClassFileInMetaInfo.java fails on builds with configure option --enable-linkable-runtime Reviewed-by: alanb --- test/jdk/tools/jlink/ClassFileInMetaInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/tools/jlink/ClassFileInMetaInfo.java b/test/jdk/tools/jlink/ClassFileInMetaInfo.java index 028da2cbe50..42b0bd511a2 100644 --- a/test/jdk/tools/jlink/ClassFileInMetaInfo.java +++ b/test/jdk/tools/jlink/ClassFileInMetaInfo.java @@ -29,7 +29,7 @@ * @modules java.base/jdk.internal.module * jdk.jlink * jdk.jartool - * @run junit ClassFileInMetaInfo + * @run junit/othervm ClassFileInMetaInfo */ import java.lang.module.ModuleDescriptor; @@ -117,4 +117,4 @@ class ClassFileInMetaInfo { .shouldContain("contains p") .shouldNotContain("META-INF"); } -} \ No newline at end of file +} From 4c3c2b32a1b9dea6f3e258cf44666932afc179e4 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 16 Apr 2025 08:35:05 +0000 Subject: [PATCH 201/843] 8354576: InetAddress.getLocalHost() on macos may return address of an interface which is not UP - leading to "Network is down" error Reviewed-by: alanb, dfuchs, vyazici --- src/java.base/unix/native/libnet/Inet6AddressImpl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c index bad7872c179..83354356936 100644 --- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,7 +126,7 @@ lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6, int cha while (iter) { if (iter->ifa_addr != NULL) { int family = iter->ifa_addr->sa_family; - if (iter->ifa_name[0] != '\0') { + if (iter->ifa_name[0] != '\0' && (iter->ifa_flags & IFF_UP) == IFF_UP) { jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK; if (family == AF_INET) { addrs4++; @@ -163,7 +163,7 @@ lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6, int cha // Now loop around the ifaddrs iter = ifa; while (iter != NULL) { - if (iter->ifa_addr != NULL) { + if (iter->ifa_addr != NULL && (iter->ifa_flags & IFF_UP) == IFF_UP) { jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK; int family = iter->ifa_addr->sa_family; From cfbbcd78bc7be2c7740de7c0b49180f56f6ccf49 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 16 Apr 2025 09:23:15 +0000 Subject: [PATCH 202/843] 8350595: jshell completion on arrays does not work for clone() Reviewed-by: asotona --- .../jdk/jshell/SourceCodeAnalysisImpl.java | 22 ++++++++++++++----- .../jdk/jshell/CompletionSuggestionTest.java | 5 ++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index d17b13fbd13..7fb354d4d1d 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -54,10 +54,12 @@ import com.sun.tools.javac.api.JavacScope; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.CompletionFailure; +import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; +import com.sun.tools.javac.code.Type.MethodType; import com.sun.tools.javac.parser.Scanner; import com.sun.tools.javac.parser.ScannerFactory; import com.sun.tools.javac.parser.Tokens.Token; @@ -1073,7 +1075,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { if (jlObject != null) { result.addAll(membersOf(at, jlObject)); } - result.add(createArrayLengthSymbol(at, site)); + result.addAll(createArraySymbols(at, site)); if (shouldGenerateDotClassItem) result.add(createDotClassSymbol(at, site)); return result; @@ -1161,11 +1163,21 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { return existing; } - private Element createArrayLengthSymbol(AnalyzeTask at, TypeMirror site) { - Name length = Names.instance(at.getContext()).length; - Type intType = Symtab.instance(at.getContext()).intType; + private List createArraySymbols(AnalyzeTask at, TypeMirror site) { + Symtab syms = Symtab.instance(at.getContext()); + Names names = Names.instance(at.getContext()); + Name length = names.length; + Name clone = names.clone; + Type lengthType = syms.intType; + Type cloneType = new MethodType(com.sun.tools.javac.util.List.nil(), + (Type) site, + com.sun.tools.javac.util.List.nil(), + syms.methodClass); - return new VarSymbol(Flags.PUBLIC | Flags.FINAL, length, intType, ((Type) site).tsym); + return List.of( + new VarSymbol(Flags.PUBLIC | Flags.FINAL, length, lengthType, ((Type) site).tsym), + new MethodSymbol(Flags.PUBLIC | Flags.FINAL, clone, cloneType, ((Type) site).tsym) + ); } private Element createDotClassSymbol(AnalyzeTask at, TypeMirror site) { diff --git a/test/langtools/jdk/jshell/CompletionSuggestionTest.java b/test/langtools/jdk/jshell/CompletionSuggestionTest.java index 8e4be046471..8564c5d1da2 100644 --- a/test/langtools/jdk/jshell/CompletionSuggestionTest.java +++ b/test/langtools/jdk/jshell/CompletionSuggestionTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8131025 8141092 8153761 8145263 8131019 8175886 8176184 8176241 8176110 8177466 8197439 8221759 8234896 8240658 8278039 8286206 8296789 8314662 8326333 + * @bug 8131025 8141092 8153761 8145263 8131019 8175886 8176184 8176241 8176110 8177466 8197439 8221759 8234896 8240658 8278039 8286206 8296789 8314662 8326333 8326333 * @summary Test Completion and Documentation * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -812,13 +812,16 @@ public class CompletionSuggestionTest extends KullaTesting { } //JDK-8326333: verify completion returns sensible output for arrays: + //JDK-8326333: jshell completion on arrays is incomplete public void testArray() { assertEval("String[] strs = null;"); assertCompletion("strs.to|", "toString()"); assertCompletion("strs.le|", "length"); + assertCompletion("strs.cl|", "clone()"); assertEval("int[] ints = null;"); assertCompletion("ints.no|", "notify()", "notifyAll()"); assertCompletion("ints.le|", "length"); + assertCompletion("ints.cl|", "clone()"); assertCompletion("String[].|", "class"); } } From 8c6b611f35af22af5b6c3eb663b30985857c1da3 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 16 Apr 2025 09:52:53 +0000 Subject: [PATCH 203/843] 8353832: Opensource FontClass, Selection and Icon tests Reviewed-by: jdv --- .../FontClass/FontTransformAttributeTest.java | 84 +++++++++++++ .../awt/FontClass/FontUnderscoreTest.java | 77 ++++++++++++ .../jdk/java/awt/Icon/ChildFrameIconTest.java | 76 ++++++++++++ .../jdk/java/awt/Selection/TestClipboard.java | 113 ++++++++++++++++++ 4 files changed, 350 insertions(+) create mode 100644 test/jdk/java/awt/FontClass/FontTransformAttributeTest.java create mode 100644 test/jdk/java/awt/FontClass/FontUnderscoreTest.java create mode 100644 test/jdk/java/awt/Icon/ChildFrameIconTest.java create mode 100644 test/jdk/java/awt/Selection/TestClipboard.java diff --git a/test/jdk/java/awt/FontClass/FontTransformAttributeTest.java b/test/jdk/java/awt/FontClass/FontTransformAttributeTest.java new file mode 100644 index 00000000000..7bbf5d11d28 --- /dev/null +++ b/test/jdk/java/awt/FontClass/FontTransformAttributeTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.font.TextAttribute; +import java.awt.font.TransformAttribute; +import java.awt.geom.AffineTransform; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4650042 + * @summary Draw text using a transform to simulate superscript, it should look like a superscript + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FontTransformAttributeTest + */ + +public class FontTransformAttributeTest extends JPanel { + AttributedCharacterIterator iter; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + This test should display a string ending with the superscripted number '11'. + Pass the test if you see the superscript."""; + + PassFailJFrame.builder() + .title("FontTransformAttributeTest Instruction") + .instructions(INSTRUCTIONS) + .columns(35) + .splitUI(FontTransformAttributeTest::new) + .build() + .awaitAndCheck(); + } + + FontTransformAttributeTest() { + AffineTransform superTransform = AffineTransform.getScaleInstance(0.65, 0.65); + superTransform.translate(0, -7); + TransformAttribute superAttribute = new TransformAttribute(superTransform); + String s = "a big number 7 11"; + AttributedString as = new AttributedString(s); + as.addAttribute(TextAttribute.TRANSFORM, superAttribute, 15, 17); + iter = as.getIterator(); + setBackground(Color.WHITE); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 100); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + Dimension d = getSize(); + g2.drawString(iter, 20, d.height / 2 + 8); + } +} diff --git a/test/jdk/java/awt/FontClass/FontUnderscoreTest.java b/test/jdk/java/awt/FontClass/FontUnderscoreTest.java new file mode 100644 index 00000000000..101a0b49088 --- /dev/null +++ b/test/jdk/java/awt/FontClass/FontUnderscoreTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4248579 + * @summary Make sure the underscore glyph appears in the different strings + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FontUnderscoreTest + */ + +public class FontUnderscoreTest extends JPanel { + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + Make sure all 8 underscore characters appear in each + of the 3 strings. + + Press PASS if all 8 are there, else FAIL."""; + + PassFailJFrame.builder() + .title("FontUnderscoreTest Instruction") + .instructions(INSTRUCTIONS) + .columns(35) + .splitUI(FontUnderscoreTest::new) + .build() + .awaitAndCheck(); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(550, 230); + } + + @Override + public void paint(Graphics g) { + Font f = new Font(Font.SANS_SERIF, Font.PLAIN, 24); + g.setFont(f); + g.drawString ("8 underscore characters appear in each string", 5, 200); + + g.drawString("J_A_V_A_2_j_a_v_a", 25, 50); + + f = new Font(Font.SERIF, Font.PLAIN, 24); + g.setFont(f); + g.drawString("J_A_V_A_2_j_a_v_a", 25, 100); + + f = new Font(Font.MONOSPACED, Font.PLAIN, 24); + g.setFont(f); + g.drawString("J_A_V_A_2_j_a_v_a", 25, 150); + } +} diff --git a/test/jdk/java/awt/Icon/ChildFrameIconTest.java b/test/jdk/java/awt/Icon/ChildFrameIconTest.java new file mode 100644 index 00000000000..6d83fa95acb --- /dev/null +++ b/test/jdk/java/awt/Icon/ChildFrameIconTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +/* + * @test + * @bug 4284610 + * @summary Tests that a child of the non-resizable dialog acquires valid icon. + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ChildFrameIconTest + */ + +public class ChildFrameIconTest { + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + Press "Show Dialog" button to open a dialog with this message: + Do you see a coffee cup icon in the upper left corner ? + + Look at the icon in the upper left corner of the message dialog. + + Press Pass if you see default coffee cup icon else press Fail."""; + + PassFailJFrame.builder() + .title("ChildFrameIconTest Instruction") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ChildFrameIconTest::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame f = new JFrame("ChildFrameIconTest UI"); + JButton b = new JButton("Show Dialog"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String msg = "Do you see a coffee cup icon in the upper left corner ?"; + JDialog dlg = new JDialog(f, "Non-resizable JDialog", false); + dlg.setResizable(false); + JOptionPane.showMessageDialog(dlg, msg); + } + }); + f.add(b); + f.setSize(250, 100); + return f; + } +} diff --git a/test/jdk/java/awt/Selection/TestClipboard.java b/test/jdk/java/awt/Selection/TestClipboard.java new file mode 100644 index 00000000000..ed65d55489c --- /dev/null +++ b/test/jdk/java/awt/Selection/TestClipboard.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import java.io.Serializable; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +/* + * @test + * @bug 4139552 + * @summary Checks to see if 'isDataFlavorSupported' throws exception. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestClipboard + */ + +public class TestClipboard { + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + This test has two steps: + + 1. you need to place some text onto the system clipboard, + for example, + on Windows, you could highlight some text in notepad, and do a Ctrl-C + or select menu Edit->Copy; + + on Linux or Mac, you can do the same with any Terminal or Console or + Text application. + + 2. After you copy to system clipboard, press "Click Me" button. + + Test will fail if any exception is thrown. + + Press Pass if you see "Test Passed" in log area."""; + + PassFailJFrame.builder() + .title("TestClipboard Instruction") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TestClipboard::createUI) + .logArea(4) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame f = new JFrame("ChildFrameIconTest UI"); + JButton b = new JButton("Click Me"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + new MyTest(); + } catch (Exception ex) { + throw new RuntimeException("Exception Thrown : " + ex); + } + } + }); + f.add(b); + f.setSize(200, 100); + return f; + } + + static class MyFlavor extends Object implements Serializable { + // Stub class needed in order to define the data flavor type + } + + static class MyTest { + public MyTest() throws Exception { + // Create an arbitrary dataflavor + DataFlavor myFlavor = new DataFlavor(MyFlavor.class, "TestClipboard"); + // Get the system clipboard + Clipboard theClipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + // Get the current contents of the clipboard + Transferable theTransfer = theClipboard.getContents(this); + + // See if the flavor is supported. This may result in a null + // pointer exception. + theTransfer.isDataFlavorSupported(myFlavor); + PassFailJFrame.log("Test Passed"); + } + } +} From fe3bd5d62fdedb7890bd3d589b04285be79c24ed Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Wed, 16 Apr 2025 09:56:39 +0000 Subject: [PATCH 204/843] 8354667: [TESTBUG] AccessZeroNKlassHitsProtectionZone cds tests require cds Reviewed-by: lmesnik, syan --- .../ErrorHandling/AccessZeroNKlassHitsProtectionZone.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java b/test/hotspot/jtreg/runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java index 189f1c08916..fde81148a02 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java @@ -38,7 +38,7 @@ /* * @test id=no_coh_cds * @summary Test that dereferencing a Klass that is the result of a decode(0) crashes accessing the nKlass guard zone - * @requires vm.bits == 64 & vm.debug == true & vm.flagless + * @requires vm.cds & vm.bits == 64 & vm.debug == true & vm.flagless * @requires os.family != "aix" * @library /test/lib * @modules java.base/jdk.internal.misc @@ -64,7 +64,7 @@ /* * @test id=coh_cds * @summary Test that dereferencing a Klass that is the result of a decode(0) crashes accessing the nKlass guard zone - * @requires vm.bits == 64 & vm.debug == true & vm.flagless + * @requires vm.cds & vm.bits == 64 & vm.debug == true & vm.flagless * @requires os.family != "aix" * @library /test/lib * @modules java.base/jdk.internal.misc From 7ffad35dac1439bc5aa12a6c16b5e8254251170b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Wed, 16 Apr 2025 11:32:47 +0000 Subject: [PATCH 205/843] 8352568: Test gtest/AsyncLogGtest.java failed at droppingMessage_vm Reviewed-by: mbaesken, dholmes --- src/hotspot/share/logging/logAsyncWriter.cpp | 24 ----------- src/hotspot/share/logging/logAsyncWriter.hpp | 10 ----- test/hotspot/gtest/logging/test_asynclog.cpp | 42 +++++++++++++++----- test/hotspot/jtreg/gtest/AsyncLogGtest.java | 4 +- 4 files changed, 34 insertions(+), 46 deletions(-) diff --git a/src/hotspot/share/logging/logAsyncWriter.cpp b/src/hotspot/share/logging/logAsyncWriter.cpp index ea5cc5c96ab..cfb6a991c4c 100644 --- a/src/hotspot/share/logging/logAsyncWriter.cpp +++ b/src/hotspot/share/logging/logAsyncWriter.cpp @@ -354,27 +354,3 @@ void AsyncLogWriter::flush() { _instance->_flush_sem.wait(); } } - -AsyncLogWriter::BufferUpdater::BufferUpdater(size_t newsize) { - ConsumerLocker clocker; - auto p = AsyncLogWriter::_instance; - - _buf1 = p->_buffer; - _buf2 = p->_buffer_staging; - p->_buffer = new Buffer(newsize); - p->_buffer_staging = new Buffer(newsize); -} - -AsyncLogWriter::BufferUpdater::~BufferUpdater() { - AsyncLogWriter::flush(); - auto p = AsyncLogWriter::_instance; - - { - ConsumerLocker clocker; - - delete p->_buffer; - delete p->_buffer_staging; - p->_buffer = _buf1; - p->_buffer_staging = _buf2; - } -} diff --git a/src/hotspot/share/logging/logAsyncWriter.hpp b/src/hotspot/share/logging/logAsyncWriter.hpp index 355d15b904c..5ffd9dc7b33 100644 --- a/src/hotspot/share/logging/logAsyncWriter.hpp +++ b/src/hotspot/share/logging/logAsyncWriter.hpp @@ -199,16 +199,6 @@ class AsyncLogWriter : public NonJavaThread { st->cr(); } - // for testing-only - class BufferUpdater { - Buffer* _buf1; - Buffer* _buf2; - - public: - BufferUpdater(size_t newsize); - ~BufferUpdater(); - }; - static bool is_enqueue_allowed(); public: diff --git a/test/hotspot/gtest/logging/test_asynclog.cpp b/test/hotspot/gtest/logging/test_asynclog.cpp index ebc3e35a4b9..efd4027fa3f 100644 --- a/test/hotspot/gtest/logging/test_asynclog.cpp +++ b/test/hotspot/gtest/logging/test_asynclog.cpp @@ -69,21 +69,22 @@ LOG_LEVEL_LIST log_debug(logging)("log_debug-test"); } - // Caveat: BufferUpdater is not MT-safe. We use it only for testing. - // We would observe missing loglines if we interleaved buffers. - // Emit all logs between constructor and destructor of BufferUpdater. void test_asynclog_drop_messages() { - const size_t sz = 2000; + const size_t sz = AsyncLogBufferSize / 2; + const char* str = "a lot of log..."; + const size_t str_size = strlen(str); - // shrink async buffer. - AsyncLogWriter::BufferUpdater saver(1024); test_asynclog_ls(); // roughly 200 bytes. LogMessage(logging) lm; // write more messages than its capacity in burst - for (size_t i = 0; i < sz; ++i) { - lm.debug("a lot of log..."); + for (size_t i = 0; i < (sz / str_size); ++i) { + lm.debug("%s", str); } + lm.debug("%s", str); + lm.debug("%s", str); + lm.debug("%s", str); + lm.debug("%s", str); lm.flush(); } @@ -244,13 +245,34 @@ TEST_VM_F(AsyncLogTest, logBuffer) { } TEST_VM_F(AsyncLogTest, droppingMessage) { - if (AsyncLogWriter::instance() == nullptr) { + if (AsyncLogWriter::instance() == nullptr) return; + if (LogConfiguration::async_mode() != LogConfiguration::AsyncMode::Drop) { + FAIL() << "This test must be run in drop mode if async UL is activated"; return; } set_log_config(TestLogFileName, "logging=debug"); test_asynclog_drop_messages(); - EXPECT_TRUE(file_contains_substring(TestLogFileName, "messages dropped due to async logging")); + bool messages_dropped = file_contains_substring(TestLogFileName, "messages dropped due to async logging"); + if (!messages_dropped) { + stringStream content; + FILE* fp = os::fopen(TestLogFileName, "r"); + assert(fp != nullptr, "error opening file %s: %s", TestLogFileName, os::strerror(errno)); + { + ResourceMark rm; + char* line = read_line(fp); + while (line != nullptr) { + ResourceMark rm; + content.print_raw(line); + line = read_line(fp); + } + } + + // The thread is null and deattached. + // That means that UL degrades to synchronous logging for this thread, which means that no messages can be dropped. + EXPECT_NE(nullptr, Thread::current_or_null()) << "Thread was null"; + EXPECT_TRUE(messages_dropped) << "Log file content:\n" << content.freeze(); + } } TEST_VM_F(AsyncLogTest, stdoutOutput) { diff --git a/test/hotspot/jtreg/gtest/AsyncLogGtest.java b/test/hotspot/jtreg/gtest/AsyncLogGtest.java index 302730b1515..d2d393c12b7 100644 --- a/test/hotspot/jtreg/gtest/AsyncLogGtest.java +++ b/test/hotspot/jtreg/gtest/AsyncLogGtest.java @@ -35,6 +35,6 @@ * @modules java.base/jdk.internal.misc * java.xml * @requires vm.flagless - * @run main/native GTestWrapper --gtest_filter=AsyncLogTest* -Xlog:async - * @run main/native GTestWrapper --gtest_filter=Log*Test* -Xlog:async + * @run main/native GTestWrapper --gtest_filter=AsyncLogTest* -Xlog:async -XX:AsyncLogBufferSize=100K + * @run main/native GTestWrapper --gtest_filter=Log*Test* -Xlog:async -XX:AsyncLogBufferSize=100K */ From 1ad869f8440cb274e474abd9f89f88db11101071 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 16 Apr 2025 11:43:42 +0000 Subject: [PATCH 206/843] 8322706: AnnotationTypeMismatchException in javac with annotation processing Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Annotate.java | 27 ++-- .../TestAnnotationValuesResolved.java | 152 ++++++++++++++++++ 2 files changed, 168 insertions(+), 11 deletions(-) create mode 100644 test/langtools/tools/javac/annotations/TestAnnotationValuesResolved.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java index 49f5a7472aa..35672b2b1bc 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -187,17 +187,22 @@ public class Annotate { startFlushing(); try { - while (q.nonEmpty()) { - q.next().run(); - } - while (typesQ.nonEmpty()) { - typesQ.next().run(); - } - while (afterTypesQ.nonEmpty()) { - afterTypesQ.next().run(); - } - while (validateQ.nonEmpty()) { - validateQ.next().run(); + while (q.nonEmpty() || + typesQ.nonEmpty() || + afterTypesQ.nonEmpty() || + validateQ.nonEmpty()) { + while (q.nonEmpty()) { + q.next().run(); + } + while (typesQ.nonEmpty()) { + typesQ.next().run(); + } + while (afterTypesQ.nonEmpty()) { + afterTypesQ.next().run(); + } + while (validateQ.nonEmpty()) { + validateQ.next().run(); + } } } finally { doneFlushing(); diff --git a/test/langtools/tools/javac/annotations/TestAnnotationValuesResolved.java b/test/langtools/tools/javac/annotations/TestAnnotationValuesResolved.java new file mode 100644 index 00000000000..b18290b529d --- /dev/null +++ b/test/langtools/tools/javac/annotations/TestAnnotationValuesResolved.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8322706 + * @summary Verify that annotation values are de-proxies after loading from a classfile. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.JavacTask toolbox.ToolBox toolbox.Task + * @run main TestAnnotationValuesResolved + */ + +import com.sun.source.tree.ClassTree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskEvent.Kind; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePathScanner; +import com.sun.source.util.Trees; +import java.nio.file.Files; +import toolbox.*; + +import java.nio.file.Path; +import java.nio.file.Paths; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.util.Elements; +import javax.lang.model.util.SimpleAnnotationValueVisitorPreview; + + +public class TestAnnotationValuesResolved extends TestRunner { + final toolbox.ToolBox tb = new ToolBox(); + + public TestAnnotationValuesResolved() { + super(System.err); + } + + public static void main(String[] args) throws Exception { + new TestAnnotationValuesResolved().runTests(); + } + + protected void runTests() throws Exception { + runTests(m -> new Object[] { Path.of(m.getName()) }); + } + + @Test + public void test(Path base) throws Exception { + Path lib = Paths.get("lib"); + Path libSrc = lib.resolve("src"); + Path libClasses = lib.resolve("classes"); + + tb.writeJavaFiles(libSrc, + """ + package org.example; + + public @interface MyFirstAnnotation { + MySecondAnnotation secondAnnotation() default @MySecondAnnotation; + } + """, + """ + package org.example; + + public @interface MySecondAnnotation { + String[] stringArray() default ""; + } + """ + ); + Files.createDirectories(libClasses); + new toolbox.JavacTask(tb) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run(); + + Path test = Paths.get("test"); + Path testSrc = test.resolve("src"); + Path testClasses = test.resolve("classes"); + tb.writeJavaFiles(testSrc, + """ + package org.example; + + @MyFirstAnnotation + public class AnnotatedClass { + } + """); + Files.createDirectories(testClasses); + new toolbox.JavacTask(tb) + .classpath(libClasses) + .outdir(testClasses) + .files(tb.findJavaFiles(testSrc)) + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void finished(TaskEvent e) { + if (e.getKind() == Kind.ENTER) { + new TreePathScanner<>() { + @Override + public Object visitClass(ClassTree node, Object p) { + Trees trees = Trees.instance(task); + Element el = trees.getElement(getCurrentPath()); + verifyAnnotationValuesResolved(task, el); + return super.visitClass(node, p); + } + }.scan(e.getCompilationUnit(), null); + } + } + }); + }) + .run() + .writeAll(); + } + + private void verifyAnnotationValuesResolved(com.sun.source.util.JavacTask task, + Element forElement) { + Elements elements = task.getElements(); + + class SearchAnnotationValues extends SimpleAnnotationValueVisitorPreview { + @Override + public Object visitAnnotation(AnnotationMirror a, Object p) { + for (AnnotationValue av : elements.getElementValuesWithDefaults(a).values()) { + av.accept(this, null); + } + return super.visitAnnotation(a, p); + } + } + + for (AnnotationMirror mirror : forElement.getAnnotationMirrors()) { + new SearchAnnotationValues().visitAnnotation(mirror, null); + } + } +} From 465c8e658356f658ee04397936f555f6bdffc3c2 Mon Sep 17 00:00:00 2001 From: Ferenc Rakoczi Date: Wed, 16 Apr 2025 12:35:24 +0000 Subject: [PATCH 207/843] 8349721: Add aarch64 intrinsics for ML-KEM Reviewed-by: adinn --- src/hotspot/cpu/aarch64/register_aarch64.cpp | 20 - src/hotspot/cpu/aarch64/register_aarch64.hpp | 93 +- .../cpu/aarch64/stubDeclarations_aarch64.hpp | 2 +- .../cpu/aarch64/stubGenerator_aarch64.cpp | 1561 ++++++++++++++++- .../cpu/aarch64/stubRoutines_aarch64.cpp | 11 + .../cpu/aarch64/stubRoutines_aarch64.hpp | 1 + .../cpu/aarch64/vm_version_aarch64.cpp | 14 +- src/hotspot/share/classfile/vmIntrinsics.cpp | 8 + src/hotspot/share/classfile/vmIntrinsics.hpp | 21 + src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 7 + src/hotspot/share/opto/c2compiler.cpp | 7 + src/hotspot/share/opto/escape.cpp | 7 + src/hotspot/share/opto/library_call.cpp | 256 ++- src/hotspot/share/opto/library_call.hpp | 7 + src/hotspot/share/opto/runtime.cpp | 158 +- src/hotspot/share/opto/runtime.hpp | 46 + src/hotspot/share/runtime/globals.hpp | 2 + .../share/runtime/stubDeclarations.hpp | 15 + .../com/sun/crypto/provider/ML_KEM.java | 434 ++++- .../classes/sun/security/provider/ML_DSA.java | 2 +- 20 files changed, 2523 insertions(+), 149 deletions(-) diff --git a/src/hotspot/cpu/aarch64/register_aarch64.cpp b/src/hotspot/cpu/aarch64/register_aarch64.cpp index 349845154e2..82683daae4f 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.cpp @@ -58,23 +58,3 @@ const char* PRegister::PRegisterImpl::name() const { }; return is_valid() ? names[encoding()] : "pnoreg"; } - -// convenience methods for splitting 8-way vector register sequences -// in half -- needed because vector operations can normally only be -// benefit from 4-way instruction parallelism - -VSeq<4> vs_front(const VSeq<8>& v) { - return VSeq<4>(v.base(), v.delta()); -} - -VSeq<4> vs_back(const VSeq<8>& v) { - return VSeq<4>(v.base() + 4 * v.delta(), v.delta()); -} - -VSeq<4> vs_even(const VSeq<8>& v) { - return VSeq<4>(v.base(), v.delta() * 2); -} - -VSeq<4> vs_odd(const VSeq<8>& v) { - return VSeq<4>(v.base() + 1, v.delta() * 2); -} diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index 45578336cfe..108f0f34140 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -436,19 +436,20 @@ enum RC { rc_bad, rc_int, rc_float, rc_predicate, rc_stack }; // inputs into front and back halves or odd and even halves (see // convenience methods below). +// helper macro for computing register masks +#define VS_MASK_BIT(base, delta, i) (1 << (base + delta * i)) + template class VSeq { static_assert(N >= 2, "vector sequence length must be greater than 1"); - static_assert(N <= 8, "vector sequence length must not exceed 8"); - static_assert((N & (N - 1)) == 0, "vector sequence length must be power of two"); private: int _base; // index of first register in sequence int _delta; // increment to derive successive indices public: VSeq(FloatRegister base_reg, int delta = 1) : VSeq(base_reg->encoding(), delta) { } VSeq(int base, int delta = 1) : _base(base), _delta(delta) { - assert (_base >= 0, "invalid base register"); - assert (_delta >= 0, "invalid register delta"); - assert ((_base + (N - 1) * _delta) < 32, "range exceeded"); + assert (_base >= 0 && _base <= 31, "invalid base register"); + assert ((_base + (N - 1) * _delta) >= 0, "register range underflow"); + assert ((_base + (N - 1) * _delta) < 32, "register range overflow"); } // indexed access to sequence FloatRegister operator [](int i) const { @@ -457,27 +458,89 @@ public: } int mask() const { int m = 0; - int bit = 1 << _base; for (int i = 0; i < N; i++) { - m |= bit << (i * _delta); + m |= VS_MASK_BIT(_base, _delta, i); } return m; } int base() const { return _base; } int delta() const { return _delta; } + bool is_constant() const { return _delta == 0; } }; -// declare convenience methods for splitting vector register sequences - -VSeq<4> vs_front(const VSeq<8>& v); -VSeq<4> vs_back(const VSeq<8>& v); -VSeq<4> vs_even(const VSeq<8>& v); -VSeq<4> vs_odd(const VSeq<8>& v); - -// methods for use in asserts to check VSeq inputs and oupts are +// methods for use in asserts to check VSeq inputs and outputs are // either disjoint or equal template bool vs_disjoint(const VSeq& n, const VSeq& m) { return (n.mask() & m.mask()) == 0; } template bool vs_same(const VSeq& n, const VSeq& m) { return n.mask() == m.mask(); } +// method for use in asserts to check whether registers appearing in +// an output sequence will be written before they are read from an +// input sequence. + +template bool vs_write_before_read(const VSeq& vout, const VSeq& vin) { + int b_in = vin.base(); + int d_in = vin.delta(); + int b_out = vout.base(); + int d_out = vout.delta(); + int bit_in = 1 << b_in; + int bit_out = 1 << b_out; + int mask_read = vin.mask(); // all pending reads + int mask_write = 0; // no writes as yet + + + for (int i = 0; i < N - 1; i++) { + // check whether a pending read clashes with a write + if ((mask_write & mask_read) != 0) { + return true; + } + // remove the pending input (so long as this is a constant + // sequence) + if (d_in != 0) { + mask_read ^= VS_MASK_BIT(b_in, d_in, i); + } + // record the next write + mask_write |= VS_MASK_BIT(b_out, d_out, i); + } + // no write before read + return false; +} + +// convenience methods for splitting 8-way or 4-way vector register +// sequences in half -- needed because vector operations can normally +// benefit from 4-way instruction parallelism or, occasionally, 2-way +// parallelism + +template +VSeq vs_front(const VSeq& v) { + static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even"); + return VSeq(v.base(), v.delta()); +} + +template +VSeq vs_back(const VSeq& v) { + static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even"); + return VSeq(v.base() + N / 2 * v.delta(), v.delta()); +} + +template +VSeq vs_even(const VSeq& v) { + static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even"); + return VSeq(v.base(), v.delta() * 2); +} + +template +VSeq vs_odd(const VSeq& v) { + static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even"); + return VSeq(v.base() + v.delta(), v.delta() * 2); +} + +// convenience method to construct a vector register sequence that +// indexes its elements in reverse order to the original + +template +VSeq vs_reverse(const VSeq& v) { + return VSeq(v.base() + (N - 1) * v.delta(), -v.delta()); +} + #endif // CPU_AARCH64_REGISTER_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp index a893aacaaf2..1107ec0a8f8 100644 --- a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp @@ -44,7 +44,7 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(compiler, 55000 ZGC_ONLY(+5000)) \ + do_arch_blob(compiler, 75000 ZGC_ONLY(+5000)) \ do_stub(compiler, vector_iota_indices) \ do_arch_entry(aarch64, compiler, vector_iota_indices, \ vector_iota_indices, vector_iota_indices) \ diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index f0f145e3d76..467505ed337 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -4651,6 +4651,11 @@ class StubGenerator: public StubCodeGenerator { template void vs_addv(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1, const VSeq& v2) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); + assert(!vs_write_before_read(v, v2), "output overwrites input"); for (int i = 0; i < N; i++) { __ addv(v[i], T, v1[i], v2[i]); } @@ -4659,6 +4664,11 @@ class StubGenerator: public StubCodeGenerator { template void vs_subv(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1, const VSeq& v2) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); + assert(!vs_write_before_read(v, v2), "output overwrites input"); for (int i = 0; i < N; i++) { __ subv(v[i], T, v1[i], v2[i]); } @@ -4667,6 +4677,11 @@ class StubGenerator: public StubCodeGenerator { template void vs_mulv(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1, const VSeq& v2) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); + assert(!vs_write_before_read(v, v2), "output overwrites input"); for (int i = 0; i < N; i++) { __ mulv(v[i], T, v1[i], v2[i]); } @@ -4674,6 +4689,10 @@ class StubGenerator: public StubCodeGenerator { template void vs_negr(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); for (int i = 0; i < N; i++) { __ negr(v[i], T, v1[i]); } @@ -4682,6 +4701,10 @@ class StubGenerator: public StubCodeGenerator { template void vs_sshr(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1, int shift) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); for (int i = 0; i < N; i++) { __ sshr(v[i], T, v1[i], shift); } @@ -4689,6 +4712,11 @@ class StubGenerator: public StubCodeGenerator { template void vs_andr(const VSeq& v, const VSeq& v1, const VSeq& v2) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); + assert(!vs_write_before_read(v, v2), "output overwrites input"); for (int i = 0; i < N; i++) { __ andr(v[i], __ T16B, v1[i], v2[i]); } @@ -4696,18 +4724,51 @@ class StubGenerator: public StubCodeGenerator { template void vs_orr(const VSeq& v, const VSeq& v1, const VSeq& v2) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); + assert(!vs_write_before_read(v, v2), "output overwrites input"); for (int i = 0; i < N; i++) { __ orr(v[i], __ T16B, v1[i], v2[i]); } } template - void vs_notr(const VSeq& v, const VSeq& v1) { + void vs_notr(const VSeq& v, const VSeq& v1) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); for (int i = 0; i < N; i++) { __ notr(v[i], __ T16B, v1[i]); } } + template + void vs_sqdmulh(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1, const VSeq& v2) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); + assert(!vs_write_before_read(v, v2), "output overwrites input"); + for (int i = 0; i < N; i++) { + __ sqdmulh(v[i], T, v1[i], v2[i]); + } + } + + template + void vs_mlsv(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1, VSeq& v2) { + // output must not be constant + assert(N == 1 || !v.is_constant(), "cannot output multiple values to a constant vector"); + // output cannot overwrite pending inputs + assert(!vs_write_before_read(v, v1), "output overwrites input"); + assert(!vs_write_before_read(v, v2), "output overwrites input"); + for (int i = 0; i < N; i++) { + __ mlsv(v[i], T, v1[i], v2[i]); + } + } + // load N/2 successive pairs of quadword values from memory in order // into N successive vector registers of the sequence via the // address supplied in base. @@ -4723,6 +4784,7 @@ class StubGenerator: public StubCodeGenerator { // in base using post-increment addressing template void vs_ldpq_post(const VSeq& v, Register base) { + static_assert((N & (N - 1)) == 0, "sequence length must be even"); for (int i = 0; i < N; i += 2) { __ ldpq(v[i], v[i+1], __ post(base, 32)); } @@ -4733,11 +4795,55 @@ class StubGenerator: public StubCodeGenerator { // supplied in base using post-increment addressing template void vs_stpq_post(const VSeq& v, Register base) { + static_assert((N & (N - 1)) == 0, "sequence length must be even"); for (int i = 0; i < N; i += 2) { __ stpq(v[i], v[i+1], __ post(base, 32)); } } + // load N/2 pairs of quadword values from memory de-interleaved into + // N vector registers 2 at a time via the address supplied in base + // using post-increment addressing. + template + void vs_ld2_post(const VSeq& v, Assembler::SIMD_Arrangement T, Register base) { + static_assert((N & (N - 1)) == 0, "sequence length must be even"); + for (int i = 0; i < N; i += 2) { + __ ld2(v[i], v[i+1], T, __ post(base, 32)); + } + } + + // store N vector registers interleaved into N/2 pairs of quadword + // memory locations via the address supplied in base using + // post-increment addressing. + template + void vs_st2_post(const VSeq& v, Assembler::SIMD_Arrangement T, Register base) { + static_assert((N & (N - 1)) == 0, "sequence length must be even"); + for (int i = 0; i < N; i += 2) { + __ st2(v[i], v[i+1], T, __ post(base, 32)); + } + } + + // load N quadword values from memory de-interleaved into N vector + // registers 3 elements at a time via the address supplied in base. + template + void vs_ld3(const VSeq& v, Assembler::SIMD_Arrangement T, Register base) { + static_assert(N == ((N / 3) * 3), "sequence length must be multiple of 3"); + for (int i = 0; i < N; i += 3) { + __ ld3(v[i], v[i+1], v[i+2], T, base); + } + } + + // load N quadword values from memory de-interleaved into N vector + // registers 3 elements at a time via the address supplied in base + // using post-increment addressing. + template + void vs_ld3_post(const VSeq& v, Assembler::SIMD_Arrangement T, Register base) { + static_assert(N == ((N / 3) * 3), "sequence length must be multiple of 3"); + for (int i = 0; i < N; i += 3) { + __ ld3(v[i], v[i+1], v[i+2], T, __ post(base, 48)); + } + } + // load N/2 pairs of quadword values from memory into N vector // registers via the address supplied in base with each pair indexed // using the the start offset plus the corresponding entry in the @@ -4810,23 +4916,29 @@ class StubGenerator: public StubCodeGenerator { } } - // Helper routines for various flavours of dilithium montgomery - // multiply + // Helper routines for various flavours of Montgomery multiply - // Perform 16 32-bit Montgomery multiplications in parallel - // See the montMul() method of the sun.security.provider.ML_DSA class. + // Perform 16 32-bit (4x4S) or 32 16-bit (4 x 8H) Montgomery + // multiplications in parallel // - // Computes 4x4S results - // a = b * c * 2^-32 mod MONT_Q - // Inputs: vb, vc - 4x4S vector register sequences - // vq - 2x4S constants - // Temps: vtmp - 4x4S vector sequence trashed after call - // Outputs: va - 4x4S vector register sequences + + // See the montMul() method of the sun.security.provider.ML_DSA + // class. + // + // Computes 4x4S results or 8x8H results + // a = b * c * 2^MONT_R_BITS mod MONT_Q + // Inputs: vb, vc - 4x4S or 4x8H vector register sequences + // vq - 2x4S or 2x8H constants + // Temps: vtmp - 4x4S or 4x8H vector sequence trashed after call + // Outputs: va - 4x4S or 4x8H vector register sequences // vb, vc, vtmp and vq must all be disjoint // va must be disjoint from all other inputs/temps or must equal vc - // n.b. MONT_R_BITS is 32, so the right shift by it is implicit. - void dilithium_montmul16(const VSeq<4>& va, const VSeq<4>& vb, const VSeq<4>& vc, - const VSeq<4>& vtmp, const VSeq<2>& vq) { + // va must have a non-zero delta i.e. it must not be a constant vseq. + // n.b. MONT_R_BITS is 16 or 32, so the right shift by it is implicit. + void vs_montmul4(const VSeq<4>& va, const VSeq<4>& vb, const VSeq<4>& vc, + Assembler::SIMD_Arrangement T, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + assert (T == __ T4S || T == __ T8H, "invalid arrangement for montmul"); assert(vs_disjoint(vb, vc), "vb and vc overlap"); assert(vs_disjoint(vb, vq), "vb and vq overlap"); assert(vs_disjoint(vb, vtmp), "vb and vtmp overlap"); @@ -4840,40 +4952,107 @@ class StubGenerator: public StubCodeGenerator { assert(vs_disjoint(va, vb), "va and vb overlap"); assert(vs_disjoint(va, vq), "va and vq overlap"); assert(vs_disjoint(va, vtmp), "va and vtmp overlap"); + assert(!va.is_constant(), "output vector must identify 4 different registers"); // schedule 4 streams of instructions across the vector sequences for (int i = 0; i < 4; i++) { - __ sqdmulh(vtmp[i], __ T4S, vb[i], vc[i]); // aHigh = hi32(2 * b * c) - __ mulv(va[i], __ T4S, vb[i], vc[i]); // aLow = lo32(b * c) + __ sqdmulh(vtmp[i], T, vb[i], vc[i]); // aHigh = hi32(2 * b * c) + __ mulv(va[i], T, vb[i], vc[i]); // aLow = lo32(b * c) } for (int i = 0; i < 4; i++) { - __ mulv(va[i], __ T4S, va[i], vq[0]); // m = aLow * qinv + __ mulv(va[i], T, va[i], vq[0]); // m = aLow * qinv } for (int i = 0; i < 4; i++) { - __ sqdmulh(va[i], __ T4S, va[i], vq[1]); // n = hi32(2 * m * q) + __ sqdmulh(va[i], T, va[i], vq[1]); // n = hi32(2 * m * q) } for (int i = 0; i < 4; i++) { - __ shsubv(va[i], __ T4S, vtmp[i], va[i]); // a = (aHigh - n) / 2 + __ shsubv(va[i], T, vtmp[i], va[i]); // a = (aHigh - n) / 2 } } - // Perform 2x16 32-bit Montgomery multiplications in parallel - // See the montMul() method of the sun.security.provider.ML_DSA class. + // Perform 8 32-bit (4x4S) or 16 16-bit (2 x 8H) Montgomery + // multiplications in parallel // - // Computes 8x4S results - // a = b * c * 2^-32 mod MONT_Q - // Inputs: vb, vc - 8x4S vector register sequences - // vq - 2x4S constants - // Temps: vtmp - 4x4S vector sequence trashed after call - // Outputs: va - 8x4S vector register sequences + + // See the montMul() method of the sun.security.provider.ML_DSA + // class. + // + // Computes 4x4S results or 8x8H results + // a = b * c * 2^MONT_R_BITS mod MONT_Q + // Inputs: vb, vc - 4x4S or 4x8H vector register sequences + // vq - 2x4S or 2x8H constants + // Temps: vtmp - 4x4S or 4x8H vector sequence trashed after call + // Outputs: va - 4x4S or 4x8H vector register sequences // vb, vc, vtmp and vq must all be disjoint // va must be disjoint from all other inputs/temps or must equal vc - // n.b. MONT_R_BITS is 32, so the right shift by it is implicit. - void vs_montmul32(const VSeq<8>& va, const VSeq<8>& vb, const VSeq<8>& vc, - const VSeq<4>& vtmp, const VSeq<2>& vq) { + // va must have a non-zero delta i.e. it must not be a constant vseq. + // n.b. MONT_R_BITS is 16 or 32, so the right shift by it is implicit. + void vs_montmul2(const VSeq<2>& va, const VSeq<2>& vb, const VSeq<2>& vc, + Assembler::SIMD_Arrangement T, + const VSeq<2>& vtmp, const VSeq<2>& vq) { + assert (T == __ T4S || T == __ T8H, "invalid arrangement for montmul"); + assert(vs_disjoint(vb, vc), "vb and vc overlap"); + assert(vs_disjoint(vb, vq), "vb and vq overlap"); + assert(vs_disjoint(vb, vtmp), "vb and vtmp overlap"); + + assert(vs_disjoint(vc, vq), "vc and vq overlap"); + assert(vs_disjoint(vc, vtmp), "vc and vtmp overlap"); + + assert(vs_disjoint(vq, vtmp), "vq and vtmp overlap"); + + assert(vs_disjoint(va, vc) || vs_same(va, vc), "va and vc neither disjoint nor equal"); + assert(vs_disjoint(va, vb), "va and vb overlap"); + assert(vs_disjoint(va, vq), "va and vq overlap"); + assert(vs_disjoint(va, vtmp), "va and vtmp overlap"); + assert(!va.is_constant(), "output vector must identify 2 different registers"); + + // schedule 2 streams of instructions across the vector sequences + for (int i = 0; i < 2; i++) { + __ sqdmulh(vtmp[i], T, vb[i], vc[i]); // aHigh = hi32(2 * b * c) + __ mulv(va[i], T, vb[i], vc[i]); // aLow = lo32(b * c) + } + + for (int i = 0; i < 2; i++) { + __ mulv(va[i], T, va[i], vq[0]); // m = aLow * qinv + } + + for (int i = 0; i < 2; i++) { + __ sqdmulh(va[i], T, va[i], vq[1]); // n = hi32(2 * m * q) + } + + for (int i = 0; i < 2; i++) { + __ shsubv(va[i], T, vtmp[i], va[i]); // a = (aHigh - n) / 2 + } + } + + // Perform 16 16-bit Montgomery multiplications in parallel. + void kyber_montmul16(const VSeq<2>& va, const VSeq<2>& vb, const VSeq<2>& vc, + const VSeq<2>& vtmp, const VSeq<2>& vq) { + // Use the helper routine to schedule a 2x8H Montgomery multiply. + // It will assert that the register use is valid + vs_montmul2(va, vb, vc, __ T8H, vtmp, vq); + } + + // Perform 32 16-bit Montgomery multiplications in parallel. + void kyber_montmul32(const VSeq<4>& va, const VSeq<4>& vb, const VSeq<4>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + // Use the helper routine to schedule a 4x8H Montgomery multiply. + // It will assert that the register use is valid + vs_montmul4(va, vb, vc, __ T8H, vtmp, vq); + } + + // Perform 64 16-bit Montgomery multiplications in parallel. + void kyber_montmul64(const VSeq<8>& va, const VSeq<8>& vb, const VSeq<8>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + // Schedule two successive 4x8H multiplies via the montmul helper + // on the front and back halves of va, vb and vc. The helper will + // assert that the register use has no overlap conflicts on each + // individual call but we also need to ensure that the necessary + // disjoint/equality constraints are met across both calls. + // vb, vc, vtmp and vq must be disjoint. va must either be // disjoint from all other registers or equal vc @@ -4891,8 +5070,8 @@ class StubGenerator: public StubCodeGenerator { assert(vs_disjoint(va, vq), "va and vq overlap"); assert(vs_disjoint(va, vtmp), "va and vtmp overlap"); - // we need to multiply the front and back halves of each sequence - // 4x4S at a time because + // we multiply the front and back halves of each sequence 4 at a + // time because // // 1) we are currently only able to get 4-way instruction // parallelism at best @@ -4901,14 +5080,1236 @@ class StubGenerator: public StubCodeGenerator { // scratch registers to hold intermediate results so vtmp can only // be a VSeq<4> which means we only have 4 scratch slots - dilithium_montmul16(vs_front(va), vs_front(vb), vs_front(vc), vtmp, vq); - dilithium_montmul16(vs_back(va), vs_back(vb), vs_back(vc), vtmp, vq); + vs_montmul4(vs_front(va), vs_front(vb), vs_front(vc), __ T8H, vtmp, vq); + vs_montmul4(vs_back(va), vs_back(vb), vs_back(vc), __ T8H, vtmp, vq); } - // perform combined montmul then add/sub on 4x4S vectors + void kyber_montmul32_sub_add(const VSeq<4>& va0, const VSeq<4>& va1, + const VSeq<4>& vc, + const VSeq<4>& vtmp, + const VSeq<2>& vq) { + // compute a = montmul(a1, c) + kyber_montmul32(vc, va1, vc, vtmp, vq); + // ouptut a1 = a0 - a + vs_subv(va1, __ T8H, va0, vc); + // and a0 = a0 + a + vs_addv(va0, __ T8H, va0, vc); + } - void dilithium_montmul16_sub_add(const VSeq<4>& va0, const VSeq<4>& va1, const VSeq<4>& vc, - const VSeq<4>& vtmp, const VSeq<2>& vq) { + void kyber_sub_add_montmul32(const VSeq<4>& va0, const VSeq<4>& va1, + const VSeq<4>& vb, + const VSeq<4>& vtmp1, + const VSeq<4>& vtmp2, + const VSeq<2>& vq) { + // compute c = a0 - a1 + vs_subv(vtmp1, __ T8H, va0, va1); + // output a0 = a0 + a1 + vs_addv(va0, __ T8H, va0, va1); + // output a1 = b montmul c + kyber_montmul32(va1, vtmp1, vb, vtmp2, vq); + } + + void load64shorts(const VSeq<8>& v, Register shorts) { + vs_ldpq_post(v, shorts); + } + + void load32shorts(const VSeq<4>& v, Register shorts) { + vs_ldpq_post(v, shorts); + } + + void store64shorts(VSeq<8> v, Register tmpAddr) { + vs_stpq_post(v, tmpAddr); + } + + // Kyber NTT function. + // Implements + // static int implKyberNtt(short[] poly, short[] ntt_zetas) {} + // + // coeffs (short[256]) = c_rarg0 + // ntt_zetas (short[256]) = c_rarg1 + address generate_kyberNtt() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::kyberNtt_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + + const Register kyberConsts = r10; + const Register tmpAddr = r11; + + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x8H inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + + __ lea(kyberConsts, ExternalAddress((address) StubRoutines::aarch64::_kyberConsts)); + // load the montmul constants + vs_ldpq(vq, kyberConsts); + + // Each level corresponds to an iteration of the outermost loop of the + // Java method seilerNTT(int[] coeffs). There are some differences + // from what is done in the seilerNTT() method, though: + // 1. The computation is using 16-bit signed values, we do not convert them + // to ints here. + // 2. The zetas are delivered in a bigger array, 128 zetas are stored in + // this array for each level, it is easier that way to fill up the vector + // registers. + // 3. In the seilerNTT() method we use R = 2^20 for the Montgomery + // multiplications (this is because that way there should not be any + // overflow during the inverse NTT computation), here we usr R = 2^16 so + // that we can use the 16-bit arithmetic in the vector unit. + // + // On each level, we fill up the vector registers in such a way that the + // array elements that need to be multiplied by the zetas go into one + // set of vector registers while the corresponding ones that don't need to + // be multiplied, go into another set. + // We can do 32 Montgomery multiplications in parallel, using 12 vector + // registers interleaving the steps of 4 identical computations, + // each done on 8 16-bit values per register. + + // At levels 0-3 the coefficients multiplied by or added/subtracted + // to the zetas occur in discrete blocks whose size is some multiple + // of 32. + + // level 0 + __ add(tmpAddr, coeffs, 256); + load64shorts(vs1, tmpAddr); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 0); + load64shorts(vs1, tmpAddr); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 0); + vs_stpq_post(vs1, tmpAddr); + __ add(tmpAddr, coeffs, 256); + vs_stpq_post(vs3, tmpAddr); + // restore montmul constants + vs_ldpq(vq, kyberConsts); + load64shorts(vs1, tmpAddr); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 128); + load64shorts(vs1, tmpAddr); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 128); + store64shorts(vs1, tmpAddr); + __ add(tmpAddr, coeffs, 384); + store64shorts(vs3, tmpAddr); + + // level 1 + // restore montmul constants + vs_ldpq(vq, kyberConsts); + __ add(tmpAddr, coeffs, 128); + load64shorts(vs1, tmpAddr); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 0); + load64shorts(vs1, tmpAddr); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 0); + store64shorts(vs1, tmpAddr); + store64shorts(vs3, tmpAddr); + vs_ldpq(vq, kyberConsts); + __ add(tmpAddr, coeffs, 384); + load64shorts(vs1, tmpAddr); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 256); + load64shorts(vs1, tmpAddr); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 256); + store64shorts(vs1, tmpAddr); + store64shorts(vs3, tmpAddr); + + // level 2 + vs_ldpq(vq, kyberConsts); + int offsets1[4] = { 0, 32, 128, 160 }; + vs_ldpq_indexed(vs1, coeffs, 64, offsets1); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_ldpq_indexed(vs1, coeffs, 0, offsets1); + // kyber_subv_addv64(); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 0); + vs_stpq_post(vs_front(vs1), tmpAddr); + vs_stpq_post(vs_front(vs3), tmpAddr); + vs_stpq_post(vs_back(vs1), tmpAddr); + vs_stpq_post(vs_back(vs3), tmpAddr); + vs_ldpq(vq, kyberConsts); + vs_ldpq_indexed(vs1, tmpAddr, 64, offsets1); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_ldpq_indexed(vs1, coeffs, 256, offsets1); + // kyber_subv_addv64(); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 256); + vs_stpq_post(vs_front(vs1), tmpAddr); + vs_stpq_post(vs_front(vs3), tmpAddr); + vs_stpq_post(vs_back(vs1), tmpAddr); + vs_stpq_post(vs_back(vs3), tmpAddr); + + // level 3 + vs_ldpq(vq, kyberConsts); + int offsets2[4] = { 0, 64, 128, 192 }; + vs_ldpq_indexed(vs1, coeffs, 32, offsets2); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_ldpq_indexed(vs1, coeffs, 0, offsets2); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + vs_stpq_indexed(vs1, coeffs, 0, offsets2); + vs_stpq_indexed(vs3, coeffs, 32, offsets2); + + vs_ldpq(vq, kyberConsts); + vs_ldpq_indexed(vs1, coeffs, 256 + 32, offsets2); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_ldpq_indexed(vs1, coeffs, 256, offsets2); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + vs_stpq_indexed(vs1, coeffs, 256, offsets2); + vs_stpq_indexed(vs3, coeffs, 256 + 32, offsets2); + + // level 4 + // At level 4 coefficients occur in 8 discrete blocks of size 16 + // so they are loaded using employing an ldr at 8 distinct offsets. + + vs_ldpq(vq, kyberConsts); + int offsets3[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + vs_ldr_indexed(vs1, __ Q, coeffs, 16, offsets3); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_ldr_indexed(vs1, __ Q, coeffs, 0, offsets3); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + vs_str_indexed(vs1, __ Q, coeffs, 0, offsets3); + vs_str_indexed(vs3, __ Q, coeffs, 16, offsets3); + + vs_ldpq(vq, kyberConsts); + vs_ldr_indexed(vs1, __ Q, coeffs, 256 + 16, offsets3); + load64shorts(vs2, zetas); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_ldr_indexed(vs1, __ Q, coeffs, 256, offsets3); + vs_subv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_addv(vs1, __ T8H, vs1, vs2); + vs_str_indexed(vs1, __ Q, coeffs, 256, offsets3); + vs_str_indexed(vs3, __ Q, coeffs, 256 + 16, offsets3); + + // level 5 + // At level 5 related coefficients occur in discrete blocks of size 8 so + // need to be loaded interleaved using an ld2 operation with arrangement 2D. + + vs_ldpq(vq, kyberConsts); + int offsets4[4] = { 0, 32, 64, 96 }; + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 0, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 0, offsets4); + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 128, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 128, offsets4); + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 256, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 256, offsets4); + + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 384, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 384, offsets4); + + // level 6 + // At level 6 related coefficients occur in discrete blocks of size 4 so + // need to be loaded interleaved using an ld2 operation with arrangement 4S. + + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 0, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 0, offsets4); + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 128, offsets4); + // __ ldpq(v18, v19, __ post(zetas, 32)); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 128, offsets4); + + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 256, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 256, offsets4); + + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 384, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_montmul32_sub_add(vs_even(vs1), vs_odd(vs1), vs_front(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 384, offsets4); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // Kyber Inverse NTT function + // Implements + // static int implKyberInverseNtt(short[] poly, short[] zetas) {} + // + // coeffs (short[256]) = c_rarg0 + // ntt_zetas (short[256]) = c_rarg1 + address generate_kyberInverseNtt() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::kyberInverseNtt_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + + const Register kyberConsts = r10; + const Register tmpAddr = r11; + const Register tmpAddr2 = c_rarg2; + + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x8H inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + + __ lea(kyberConsts, + ExternalAddress((address) StubRoutines::aarch64::_kyberConsts)); + + // level 0 + // At level 0 related coefficients occur in discrete blocks of size 4 so + // need to be loaded interleaved using an ld2 operation with arrangement 4S. + + vs_ldpq(vq, kyberConsts); + int offsets4[4] = { 0, 32, 64, 96 }; + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 0, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 0, offsets4); + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 128, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 128, offsets4); + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 256, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 256, offsets4); + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, 384, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, 384, offsets4); + + // level 1 + // At level 1 related coefficients occur in discrete blocks of size 8 so + // need to be loaded interleaved using an ld2 operation with arrangement 2D. + + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 0, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 0, offsets4); + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 128, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 128, offsets4); + + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 256, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 256, offsets4); + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, 384, offsets4); + load32shorts(vs_front(vs2), zetas); + kyber_sub_add_montmul32(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, 384, offsets4); + + // level 2 + // At level 2 coefficients occur in 8 discrete blocks of size 16 + // so they are loaded using employing an ldr at 8 distinct offsets. + + int offsets3[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + vs_ldr_indexed(vs1, __ Q, coeffs, 0, offsets3); + vs_ldr_indexed(vs2, __ Q, coeffs, 16, offsets3); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + vs_str_indexed(vs3, __ Q, coeffs, 0, offsets3); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_str_indexed(vs2, __ Q, coeffs, 16, offsets3); + + vs_ldr_indexed(vs1, __ Q, coeffs, 256, offsets3); + vs_ldr_indexed(vs2, __ Q, coeffs, 256 + 16, offsets3); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + vs_str_indexed(vs3, __ Q, coeffs, 256, offsets3); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_str_indexed(vs2, __ Q, coeffs, 256 + 16, offsets3); + + // Barrett reduction at indexes where overflow may happen + + // load q and the multiplier for the Barrett reduction + __ add(tmpAddr, kyberConsts, 16); + vs_ldpq(vq, tmpAddr); + + VSeq<8> vq1 = VSeq<8>(vq[0], 0); // 2 constant 8 sequences + VSeq<8> vq2 = VSeq<8>(vq[1], 0); // for above two kyber constants + VSeq<8> vq3 = VSeq<8>(v29, 0); // 3rd sequence for const montmul + vs_ldr_indexed(vs1, __ Q, coeffs, 0, offsets3); + vs_sqdmulh(vs2, __ T8H, vs1, vq2); + vs_sshr(vs2, __ T8H, vs2, 11); + vs_mlsv(vs1, __ T8H, vs2, vq1); + vs_str_indexed(vs1, __ Q, coeffs, 0, offsets3); + vs_ldr_indexed(vs1, __ Q, coeffs, 256, offsets3); + vs_sqdmulh(vs2, __ T8H, vs1, vq2); + vs_sshr(vs2, __ T8H, vs2, 11); + vs_mlsv(vs1, __ T8H, vs2, vq1); + vs_str_indexed(vs1, __ Q, coeffs, 256, offsets3); + + // level 3 + // From level 3 upwards coefficients occur in discrete blocks whose size is + // some multiple of 32 so can be loaded using ldpq and suitable indexes. + + int offsets2[4] = { 0, 64, 128, 192 }; + vs_ldpq_indexed(vs1, coeffs, 0, offsets2); + vs_ldpq_indexed(vs2, coeffs, 32, offsets2); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + vs_stpq_indexed(vs3, coeffs, 0, offsets2); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_stpq_indexed(vs2, coeffs, 32, offsets2); + + vs_ldpq_indexed(vs1, coeffs, 256, offsets2); + vs_ldpq_indexed(vs2, coeffs, 256 + 32, offsets2); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + vs_stpq_indexed(vs3, coeffs, 256, offsets2); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_stpq_indexed(vs2, coeffs, 256 + 32, offsets2); + + // level 4 + + int offsets1[4] = { 0, 32, 128, 160 }; + vs_ldpq_indexed(vs1, coeffs, 0, offsets1); + vs_ldpq_indexed(vs2, coeffs, 64, offsets1); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + vs_stpq_indexed(vs3, coeffs, 0, offsets1); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_stpq_indexed(vs2, coeffs, 64, offsets1); + + vs_ldpq_indexed(vs1, coeffs, 256, offsets1); + vs_ldpq_indexed(vs2, coeffs, 256 + 64, offsets1); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + vs_stpq_indexed(vs3, coeffs, 256, offsets1); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + vs_stpq_indexed(vs2, coeffs, 256 + 64, offsets1); + + // level 5 + + __ add(tmpAddr, coeffs, 0); + load64shorts(vs1, tmpAddr); + __ add(tmpAddr, coeffs, 128); + load64shorts(vs2, tmpAddr); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 0); + store64shorts(vs3, tmpAddr); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 128); + store64shorts(vs2, tmpAddr); + + load64shorts(vs1, tmpAddr); + __ add(tmpAddr, coeffs, 384); + load64shorts(vs2, tmpAddr); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 256); + store64shorts(vs3, tmpAddr); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 384); + store64shorts(vs2, tmpAddr); + + // Barrett reduction at indexes where overflow may happen + + // load q and the multiplier for the Barrett reduction + __ add(tmpAddr, kyberConsts, 16); + vs_ldpq(vq, tmpAddr); + + int offsets0[2] = { 0, 256 }; + vs_ldpq_indexed(vs_front(vs1), coeffs, 0, offsets0); + vs_sqdmulh(vs2, __ T8H, vs1, vq2); + vs_sshr(vs2, __ T8H, vs2, 11); + vs_mlsv(vs1, __ T8H, vs2, vq1); + vs_stpq_indexed(vs_front(vs1), coeffs, 0, offsets0); + + // level 6 + + __ add(tmpAddr, coeffs, 0); + load64shorts(vs1, tmpAddr); + __ add(tmpAddr, coeffs, 256); + load64shorts(vs2, tmpAddr); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 0); + store64shorts(vs3, tmpAddr); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 256); + store64shorts(vs2, tmpAddr); + + __ add(tmpAddr, coeffs, 128); + load64shorts(vs1, tmpAddr); + __ add(tmpAddr, coeffs, 384); + load64shorts(vs2, tmpAddr); + vs_addv(vs3, __ T8H, vs1, vs2); // n.b. trashes vq + vs_subv(vs1, __ T8H, vs1, vs2); + __ add(tmpAddr, coeffs, 128); + store64shorts(vs3, tmpAddr); + load64shorts(vs2, zetas); + vs_ldpq(vq, kyberConsts); + kyber_montmul64(vs2, vs1, vs2, vtmp, vq); + __ add(tmpAddr, coeffs, 384); + store64shorts(vs2, tmpAddr); + + // multiply by 2^-n + + // load toMont(2^-n mod q) + __ add(tmpAddr, kyberConsts, 48); + __ ldr(v29, __ Q, tmpAddr); + + vs_ldpq(vq, kyberConsts); + __ add(tmpAddr, coeffs, 0); + load64shorts(vs1, tmpAddr); + kyber_montmul64(vs2, vs1, vq3, vtmp, vq); + __ add(tmpAddr, coeffs, 0); + store64shorts(vs2, tmpAddr); + + // now tmpAddr contains coeffs + 128 because store64shorts adjusted it so + load64shorts(vs1, tmpAddr); + kyber_montmul64(vs2, vs1, vq3, vtmp, vq); + __ add(tmpAddr, coeffs, 128); + store64shorts(vs2, tmpAddr); + + // now tmpAddr contains coeffs + 256 + load64shorts(vs1, tmpAddr); + kyber_montmul64(vs2, vs1, vq3, vtmp, vq); + __ add(tmpAddr, coeffs, 256); + store64shorts(vs2, tmpAddr); + + // now tmpAddr contains coeffs + 384 + load64shorts(vs1, tmpAddr); + kyber_montmul64(vs2, vs1, vq3, vtmp, vq); + __ add(tmpAddr, coeffs, 384); + store64shorts(vs2, tmpAddr); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // Kyber multiply polynomials in the NTT domain. + // Implements + // static int implKyberNttMult( + // short[] result, short[] ntta, short[] nttb, short[] zetas) {} + // + // result (short[256]) = c_rarg0 + // ntta (short[256]) = c_rarg1 + // nttb (short[256]) = c_rarg2 + // zetas (short[128]) = c_rarg3 + address generate_kyberNttMult() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::kyberNttMult_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register result = c_rarg0; + const Register ntta = c_rarg1; + const Register nttb = c_rarg2; + const Register zetas = c_rarg3; + + const Register kyberConsts = r10; + const Register limit = r11; + + VSeq<4> vs1(0), vs2(4); // 4 sets of 8x8H inputs/outputs/tmps + VSeq<4> vs3(16), vs4(20); + VSeq<2> vq(30); // pair of constants for montmul: q, qinv + VSeq<2> vz(28); // pair of zetas + VSeq<4> vc(27, 0); // constant sequence for montmul: montRSquareModQ + + __ lea(kyberConsts, + ExternalAddress((address) StubRoutines::aarch64::_kyberConsts)); + + Label kyberNttMult_loop; + + __ add(limit, result, 512); + + // load q and qinv + vs_ldpq(vq, kyberConsts); + + // load R^2 mod q (to convert back from Montgomery representation) + __ add(kyberConsts, kyberConsts, 64); + __ ldr(v27, __ Q, kyberConsts); + + __ BIND(kyberNttMult_loop); + + // load 16 zetas + vs_ldpq_post(vz, zetas); + + // load 2 sets of 32 coefficients from the two input arrays + // interleaved as shorts. i.e. pairs of shorts adjacent in memory + // are striped across pairs of vector registers + vs_ld2_post(vs_front(vs1), __ T8H, ntta); // x 8H + vs_ld2_post(vs_back(vs1), __ T8H, nttb); // x 8H + vs_ld2_post(vs_front(vs4), __ T8H, ntta); // x 8H + vs_ld2_post(vs_back(vs4), __ T8H, nttb); // x 8H + + // compute 4 montmul cross-products for pairs (a0,a1) and (b0,b1) + // i.e. montmul the first and second halves of vs1 in order and + // then with one sequence reversed storing the two results in vs3 + // + // vs3[0] <- montmul(a0, b0) + // vs3[1] <- montmul(a1, b1) + // vs3[2] <- montmul(a0, b1) + // vs3[3] <- montmul(a1, b0) + kyber_montmul16(vs_front(vs3), vs_front(vs1), vs_back(vs1), vs_front(vs2), vq); + kyber_montmul16(vs_back(vs3), + vs_front(vs1), vs_reverse(vs_back(vs1)), vs_back(vs2), vq); + + // compute 4 montmul cross-products for pairs (a2,a3) and (b2,b3) + // i.e. montmul the first and second halves of vs4 in order and + // then with one sequence reversed storing the two results in vs1 + // + // vs1[0] <- montmul(a2, b2) + // vs1[1] <- montmul(a3, b3) + // vs1[2] <- montmul(a2, b3) + // vs1[3] <- montmul(a3, b2) + kyber_montmul16(vs_front(vs1), vs_front(vs4), vs_back(vs4), vs_front(vs2), vq); + kyber_montmul16(vs_back(vs1), + vs_front(vs4), vs_reverse(vs_back(vs4)), vs_back(vs2), vq); + + // montmul result 2 of each cross-product i.e. (a1*b1, a3*b3) by a zeta. + // We can schedule two montmuls at a time if we use a suitable vector + // sequence . + int delta = vs1[1]->encoding() - vs3[1]->encoding(); + VSeq<2> vs5(vs3[1], delta); + + // vs3[1] <- montmul(montmul(a1, b1), z0) + // vs1[1] <- montmul(montmul(a3, b3), z1) + kyber_montmul16(vs5, vz, vs5, vs_front(vs2), vq); + + // add results in pairs storing in vs3 + // vs3[0] <- montmul(a0, b0) + montmul(montmul(a1, b1), z0); + // vs3[1] <- montmul(a0, b1) + montmul(a1, b0); + vs_addv(vs_front(vs3), __ T8H, vs_even(vs3), vs_odd(vs3)); + + // vs3[2] <- montmul(a2, b2) + montmul(montmul(a3, b3), z1); + // vs3[3] <- montmul(a2, b3) + montmul(a3, b2); + vs_addv(vs_back(vs3), __ T8H, vs_even(vs1), vs_odd(vs1)); + + // vs1 <- montmul(vs3, montRSquareModQ) + kyber_montmul32(vs1, vs3, vc, vs2, vq); + + // store back the two pairs of result vectors de-interleaved as 8H elements + // i.e. storing each pairs of shorts striped across a register pair adjacent + // in memory + vs_st2_post(vs1, __ T8H, result); + + __ cmp(result, limit); + __ br(Assembler::NE, kyberNttMult_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // Kyber add 2 polynomials. + // Implements + // static int implKyberAddPoly(short[] result, short[] a, short[] b) {} + // + // result (short[256]) = c_rarg0 + // a (short[256]) = c_rarg1 + // b (short[256]) = c_rarg2 + address generate_kyberAddPoly_2() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::kyberAddPoly_2_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register result = c_rarg0; + const Register a = c_rarg1; + const Register b = c_rarg2; + + const Register kyberConsts = r11; + + // We sum 256 sets of values in total i.e. 32 x 8H quadwords. + // So, we can load, add and store the data in 3 groups of 11, + // 11 and 10 at a time i.e. we need to map sets of 10 or 11 + // registers. A further constraint is that the mapping needs + // to skip callee saves. So, we allocate the register + // sequences using two 8 sequences, two 2 sequences and two + // single registers. + VSeq<8> vs1_1(0); + VSeq<2> vs1_2(16); + FloatRegister vs1_3 = v28; + VSeq<8> vs2_1(18); + VSeq<2> vs2_2(26); + FloatRegister vs2_3 = v29; + + // two constant vector sequences + VSeq<8> vc_1(31, 0); + VSeq<2> vc_2(31, 0); + + FloatRegister vc_3 = v31; + __ lea(kyberConsts, + ExternalAddress((address) StubRoutines::aarch64::_kyberConsts)); + + __ ldr(vc_3, __ Q, Address(kyberConsts, 16)); // q + for (int i = 0; i < 3; i++) { + // load 80 or 88 values from a into vs1_1/2/3 + vs_ldpq_post(vs1_1, a); + vs_ldpq_post(vs1_2, a); + if (i < 2) { + __ ldr(vs1_3, __ Q, __ post(a, 16)); + } + // load 80 or 88 values from b into vs2_1/2/3 + vs_ldpq_post(vs2_1, b); + vs_ldpq_post(vs2_2, b); + if (i < 2) { + __ ldr(vs2_3, __ Q, __ post(b, 16)); + } + // sum 80 or 88 values across vs1 and vs2 into vs1 + vs_addv(vs1_1, __ T8H, vs1_1, vs2_1); + vs_addv(vs1_2, __ T8H, vs1_2, vs2_2); + if (i < 2) { + __ addv(vs1_3, __ T8H, vs1_3, vs2_3); + } + // add constant to all 80 or 88 results + vs_addv(vs1_1, __ T8H, vs1_1, vc_1); + vs_addv(vs1_2, __ T8H, vs1_2, vc_2); + if (i < 2) { + __ addv(vs1_3, __ T8H, vs1_3, vc_3); + } + // store 80 or 88 values + vs_stpq_post(vs1_1, result); + vs_stpq_post(vs1_2, result); + if (i < 2) { + __ str(vs1_3, __ Q, __ post(result, 16)); + } + } + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // Kyber add 3 polynomials. + // Implements + // static int implKyberAddPoly(short[] result, short[] a, short[] b, short[] c) {} + // + // result (short[256]) = c_rarg0 + // a (short[256]) = c_rarg1 + // b (short[256]) = c_rarg2 + // c (short[256]) = c_rarg3 + address generate_kyberAddPoly_3() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::kyberAddPoly_3_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register result = c_rarg0; + const Register a = c_rarg1; + const Register b = c_rarg2; + const Register c = c_rarg3; + + const Register kyberConsts = r11; + + // As above we sum 256 sets of values in total i.e. 32 x 8H + // quadwords. So, we can load, add and store the data in 3 + // groups of 11, 11 and 10 at a time i.e. we need to map sets + // of 10 or 11 registers. A further constraint is that the + // mapping needs to skip callee saves. So, we allocate the + // register sequences using two 8 sequences, two 2 sequences + // and two single registers. + VSeq<8> vs1_1(0); + VSeq<2> vs1_2(16); + FloatRegister vs1_3 = v28; + VSeq<8> vs2_1(18); + VSeq<2> vs2_2(26); + FloatRegister vs2_3 = v29; + + // two constant vector sequences + VSeq<8> vc_1(31, 0); + VSeq<2> vc_2(31, 0); + + FloatRegister vc_3 = v31; + + __ lea(kyberConsts, + ExternalAddress((address) StubRoutines::aarch64::_kyberConsts)); + + __ ldr(vc_3, __ Q, Address(kyberConsts, 16)); // q + for (int i = 0; i < 3; i++) { + // load 80 or 88 values from a into vs1_1/2/3 + vs_ldpq_post(vs1_1, a); + vs_ldpq_post(vs1_2, a); + if (i < 2) { + __ ldr(vs1_3, __ Q, __ post(a, 16)); + } + // load 80 or 88 values from b into vs2_1/2/3 + vs_ldpq_post(vs2_1, b); + vs_ldpq_post(vs2_2, b); + if (i < 2) { + __ ldr(vs2_3, __ Q, __ post(b, 16)); + } + // sum 80 or 88 values across vs1 and vs2 into vs1 + vs_addv(vs1_1, __ T8H, vs1_1, vs2_1); + vs_addv(vs1_2, __ T8H, vs1_2, vs2_2); + if (i < 2) { + __ addv(vs1_3, __ T8H, vs1_3, vs2_3); + } + // load 80 or 88 values from c into vs2_1/2/3 + vs_ldpq_post(vs2_1, c); + vs_ldpq_post(vs2_2, c); + if (i < 2) { + __ ldr(vs2_3, __ Q, __ post(c, 16)); + } + // sum 80 or 88 values across vs1 and vs2 into vs1 + vs_addv(vs1_1, __ T8H, vs1_1, vs2_1); + vs_addv(vs1_2, __ T8H, vs1_2, vs2_2); + if (i < 2) { + __ addv(vs1_3, __ T8H, vs1_3, vs2_3); + } + // add constant to all 80 or 88 results + vs_addv(vs1_1, __ T8H, vs1_1, vc_1); + vs_addv(vs1_2, __ T8H, vs1_2, vc_2); + if (i < 2) { + __ addv(vs1_3, __ T8H, vs1_3, vc_3); + } + // store 80 or 88 values + vs_stpq_post(vs1_1, result); + vs_stpq_post(vs1_2, result); + if (i < 2) { + __ str(vs1_3, __ Q, __ post(result, 16)); + } + } + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // Kyber parse XOF output to polynomial coefficient candidates + // or decodePoly(12, ...). + // Implements + // static int implKyber12To16( + // byte[] condensed, int index, short[] parsed, int parsedLength) {} + // + // (parsedLength or (parsedLength - 48) must be divisible by 64.) + // + // condensed (byte[]) = c_rarg0 + // condensedIndex = c_rarg1 + // parsed (short[112 or 256]) = c_rarg2 + // parsedLength (112 or 256) = c_rarg3 + address generate_kyber12To16() { + Label L_F00, L_loop, L_end; + + __ BIND(L_F00); + __ emit_int64(0x0f000f000f000f00); + __ emit_int64(0x0f000f000f000f00); + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::kyber12To16_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register condensed = c_rarg0; + const Register condensedOffs = c_rarg1; + const Register parsed = c_rarg2; + const Register parsedLength = c_rarg3; + + const Register tmpAddr = r11; + + // Data is input 96 bytes at a time i.e. in groups of 6 x 16B + // quadwords so we need a 6 vector sequence for the inputs. + // Parsing produces 64 shorts, employing two 8 vector + // sequences to store and combine the intermediate data. + VSeq<6> vin(24); + VSeq<8> va(0), vb(16); + + __ adr(tmpAddr, L_F00); + __ ldr(v31, __ Q, tmpAddr); // 8H times 0x0f00 + __ add(condensed, condensed, condensedOffs); + + __ BIND(L_loop); + // load 96 (6 x 16B) byte values + vs_ld3_post(vin, __ T16B, condensed); + + // The front half of sequence vin (vin[0], vin[1] and vin[2]) + // holds 48 (16x3) contiguous bytes from memory striped + // horizontally across each of the 16 byte lanes. Equivalently, + // that is 16 pairs of 12-bit integers. Likewise the back half + // holds the next 48 bytes in the same arrangement. + + // Each vector in the front half can also be viewed as a vertical + // strip across the 16 pairs of 12 bit integers. Each byte in + // vin[0] stores the low 8 bits of the first int in a pair. Each + // byte in vin[1] stores the high 4 bits of the first int and the + // low 4 bits of the second int. Each byte in vin[2] stores the + // high 8 bits of the second int. Likewise the vectors in second + // half. + + // Converting the data to 16-bit shorts requires first of all + // expanding each of the 6 x 16B vectors into 6 corresponding + // pairs of 8H vectors. Mask, shift and add operations on the + // resulting vector pairs can be used to combine 4 and 8 bit + // parts of related 8H vector elements. + // + // The middle vectors (vin[2] and vin[5]) are actually expanded + // twice, one copy manipulated to provide the lower 4 bits + // belonging to the first short in a pair and another copy + // manipulated to provide the higher 4 bits belonging to the + // second short in a pair. This is why the the vector sequences va + // and vb used to hold the expanded 8H elements are of length 8. + + // Expand vin[0] into va[0:1], and vin[1] into va[2:3] and va[4:5] + // n.b. target elements 2 and 3 duplicate elements 4 and 5 + __ ushll(va[0], __ T8H, vin[0], __ T8B, 0); + __ ushll2(va[1], __ T8H, vin[0], __ T16B, 0); + __ ushll(va[2], __ T8H, vin[1], __ T8B, 0); + __ ushll2(va[3], __ T8H, vin[1], __ T16B, 0); + __ ushll(va[4], __ T8H, vin[1], __ T8B, 0); + __ ushll2(va[5], __ T8H, vin[1], __ T16B, 0); + + // likewise expand vin[3] into vb[0:1], and vin[4] into vb[2:3] + // and vb[4:5] + __ ushll(vb[0], __ T8H, vin[3], __ T8B, 0); + __ ushll2(vb[1], __ T8H, vin[3], __ T16B, 0); + __ ushll(vb[2], __ T8H, vin[4], __ T8B, 0); + __ ushll2(vb[3], __ T8H, vin[4], __ T16B, 0); + __ ushll(vb[4], __ T8H, vin[4], __ T8B, 0); + __ ushll2(vb[5], __ T8H, vin[4], __ T16B, 0); + + // shift lo byte of copy 1 of the middle stripe into the high byte + __ shl(va[2], __ T8H, va[2], 8); + __ shl(va[3], __ T8H, va[3], 8); + __ shl(vb[2], __ T8H, vb[2], 8); + __ shl(vb[3], __ T8H, vb[3], 8); + + // expand vin[2] into va[6:7] and vin[5] into vb[6:7] but this + // time pre-shifted by 4 to ensure top bits of input 12-bit int + // are in bit positions [4..11]. + __ ushll(va[6], __ T8H, vin[2], __ T8B, 4); + __ ushll2(va[7], __ T8H, vin[2], __ T16B, 4); + __ ushll(vb[6], __ T8H, vin[5], __ T8B, 4); + __ ushll2(vb[7], __ T8H, vin[5], __ T16B, 4); + + // mask hi 4 bits of the 1st 12-bit int in a pair from copy1 and + // shift lo 4 bits of the 2nd 12-bit int in a pair to the bottom of + // copy2 + __ andr(va[2], __ T16B, va[2], v31); + __ andr(va[3], __ T16B, va[3], v31); + __ ushr(va[4], __ T8H, va[4], 4); + __ ushr(va[5], __ T8H, va[5], 4); + __ andr(vb[2], __ T16B, vb[2], v31); + __ andr(vb[3], __ T16B, vb[3], v31); + __ ushr(vb[4], __ T8H, vb[4], 4); + __ ushr(vb[5], __ T8H, vb[5], 4); + + // sum hi 4 bits and lo 8 bits of the 1st 12-bit int in each pair and + // hi 8 bits plus lo 4 bits of the 2nd 12-bit int in each pair + // n.b. the ordering ensures: i) inputs are consumed before they + // are overwritten ii) the order of 16-bit results across successive + // pairs of vectors in va and then vb reflects the order of the + // corresponding 12-bit inputs + __ addv(va[0], __ T8H, va[0], va[2]); + __ addv(va[2], __ T8H, va[1], va[3]); + __ addv(va[1], __ T8H, va[4], va[6]); + __ addv(va[3], __ T8H, va[5], va[7]); + __ addv(vb[0], __ T8H, vb[0], vb[2]); + __ addv(vb[2], __ T8H, vb[1], vb[3]); + __ addv(vb[1], __ T8H, vb[4], vb[6]); + __ addv(vb[3], __ T8H, vb[5], vb[7]); + + // store 64 results interleaved as shorts + vs_st2_post(vs_front(va), __ T8H, parsed); + vs_st2_post(vs_front(vb), __ T8H, parsed); + + __ sub(parsedLength, parsedLength, 64); + __ cmp(parsedLength, (u1)64); + __ br(Assembler::GE, L_loop); + __ cbz(parsedLength, L_end); + + // if anything is left it should be a final 72 bytes of input + // i.e. a final 48 12-bit values. so we handle this by loading + // 48 bytes into all 16B lanes of front(vin) and only 24 + // bytes into the lower 8B lane of back(vin) + vs_ld3_post(vs_front(vin), __ T16B, condensed); + vs_ld3(vs_back(vin), __ T8B, condensed); + + // Expand vin[0] into va[0:1], and vin[1] into va[2:3] and va[4:5] + // n.b. target elements 2 and 3 of va duplicate elements 4 and + // 5 and target element 2 of vb duplicates element 4. + __ ushll(va[0], __ T8H, vin[0], __ T8B, 0); + __ ushll2(va[1], __ T8H, vin[0], __ T16B, 0); + __ ushll(va[2], __ T8H, vin[1], __ T8B, 0); + __ ushll2(va[3], __ T8H, vin[1], __ T16B, 0); + __ ushll(va[4], __ T8H, vin[1], __ T8B, 0); + __ ushll2(va[5], __ T8H, vin[1], __ T16B, 0); + + // This time expand just the lower 8 lanes + __ ushll(vb[0], __ T8H, vin[3], __ T8B, 0); + __ ushll(vb[2], __ T8H, vin[4], __ T8B, 0); + __ ushll(vb[4], __ T8H, vin[4], __ T8B, 0); + + // shift lo byte of copy 1 of the middle stripe into the high byte + __ shl(va[2], __ T8H, va[2], 8); + __ shl(va[3], __ T8H, va[3], 8); + __ shl(vb[2], __ T8H, vb[2], 8); + + // expand vin[2] into va[6:7] and lower 8 lanes of vin[5] into + // vb[6] pre-shifted by 4 to ensure top bits of the input 12-bit + // int are in bit positions [4..11]. + __ ushll(va[6], __ T8H, vin[2], __ T8B, 4); + __ ushll2(va[7], __ T8H, vin[2], __ T16B, 4); + __ ushll(vb[6], __ T8H, vin[5], __ T8B, 4); + + // mask hi 4 bits of each 1st 12-bit int in pair from copy1 and + // shift lo 4 bits of each 2nd 12-bit int in pair to bottom of + // copy2 + __ andr(va[2], __ T16B, va[2], v31); + __ andr(va[3], __ T16B, va[3], v31); + __ ushr(va[4], __ T8H, va[4], 4); + __ ushr(va[5], __ T8H, va[5], 4); + __ andr(vb[2], __ T16B, vb[2], v31); + __ ushr(vb[4], __ T8H, vb[4], 4); + + + + // sum hi 4 bits and lo 8 bits of each 1st 12-bit int in pair and + // hi 8 bits plus lo 4 bits of each 2nd 12-bit int in pair + + // n.b. ordering ensures: i) inputs are consumed before they are + // overwritten ii) order of 16-bit results across succsessive + // pairs of vectors in va and then lower half of vb reflects order + // of corresponding 12-bit inputs + __ addv(va[0], __ T8H, va[0], va[2]); + __ addv(va[2], __ T8H, va[1], va[3]); + __ addv(va[1], __ T8H, va[4], va[6]); + __ addv(va[3], __ T8H, va[5], va[7]); + __ addv(vb[0], __ T8H, vb[0], vb[2]); + __ addv(vb[1], __ T8H, vb[4], vb[6]); + + // store 48 results interleaved as shorts + vs_st2_post(vs_front(va), __ T8H, parsed); + vs_st2_post(vs_front(vs_front(vb)), __ T8H, parsed); + + __ BIND(L_end); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // Kyber Barrett reduce function. + // Implements + // static int implKyberBarrettReduce(short[] coeffs) {} + // + // coeffs (short[256]) = c_rarg0 + address generate_kyberBarrettReduce() { + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::kyberBarrettReduce_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + __ enter(); + + const Register coeffs = c_rarg0; + + const Register kyberConsts = r10; + const Register result = r11; + + // As above we process 256 sets of values in total i.e. 32 x + // 8H quadwords. So, we can load, add and store the data in 3 + // groups of 11, 11 and 10 at a time i.e. we need to map sets + // of 10 or 11 registers. A further constraint is that the + // mapping needs to skip callee saves. So, we allocate the + // register sequences using two 8 sequences, two 2 sequences + // and two single registers. + VSeq<8> vs1_1(0); + VSeq<2> vs1_2(16); + FloatRegister vs1_3 = v28; + VSeq<8> vs2_1(18); + VSeq<2> vs2_2(26); + FloatRegister vs2_3 = v29; + + // we also need a pair of corresponding constant sequences + + VSeq<8> vc1_1(30, 0); + VSeq<2> vc1_2(30, 0); + FloatRegister vc1_3 = v30; // for kyber_q + + VSeq<8> vc2_1(31, 0); + VSeq<2> vc2_2(31, 0); + FloatRegister vc2_3 = v31; // for kyberBarrettMultiplier + + __ add(result, coeffs, 0); + __ lea(kyberConsts, + ExternalAddress((address) StubRoutines::aarch64::_kyberConsts)); + + // load q and the multiplier for the Barrett reduction + __ add(kyberConsts, kyberConsts, 16); + __ ldpq(vc1_3, vc2_3, kyberConsts); + + for (int i = 0; i < 3; i++) { + // load 80 or 88 coefficients + vs_ldpq_post(vs1_1, coeffs); + vs_ldpq_post(vs1_2, coeffs); + if (i < 2) { + __ ldr(vs1_3, __ Q, __ post(coeffs, 16)); + } + + // vs2 <- (2 * vs1 * kyberBarrettMultiplier) >> 16 + vs_sqdmulh(vs2_1, __ T8H, vs1_1, vc2_1); + vs_sqdmulh(vs2_2, __ T8H, vs1_2, vc2_2); + if (i < 2) { + __ sqdmulh(vs2_3, __ T8H, vs1_3, vc2_3); + } + + // vs2 <- (vs1 * kyberBarrettMultiplier) >> 26 + vs_sshr(vs2_1, __ T8H, vs2_1, 11); + vs_sshr(vs2_2, __ T8H, vs2_2, 11); + if (i < 2) { + __ sshr(vs2_3, __ T8H, vs2_3, 11); + } + + // vs1 <- vs1 - vs2 * kyber_q + vs_mlsv(vs1_1, __ T8H, vs2_1, vc1_1); + vs_mlsv(vs1_2, __ T8H, vs2_2, vc1_2); + if (i < 2) { + __ mlsv(vs1_3, __ T8H, vs2_3, vc1_3); + } + + vs_stpq_post(vs1_1, result); + vs_stpq_post(vs1_2, result); + if (i < 2) { + __ str(vs1_3, __ Q, __ post(result, 16)); + } + } + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + + // Dilithium-specific montmul helper routines that generate parallel + // code for, respectively, a single 4x4s vector sequence montmul or + // two such multiplies in a row. + + // Perform 16 32-bit Montgomery multiplications in parallel + void dilithium_montmul16(const VSeq<4>& va, const VSeq<4>& vb, const VSeq<4>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + // Use the helper routine to schedule a 4x4S Montgomery multiply. + // It will assert that the register use is valid + vs_montmul4(va, vb, vc, __ T4S, vtmp, vq); + } + + // Perform 2x16 32-bit Montgomery multiplications in parallel + void dilithium_montmul32(const VSeq<8>& va, const VSeq<8>& vb, const VSeq<8>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + // Schedule two successive 4x4S multiplies via the montmul helper + // on the front and back halves of va, vb and vc. The helper will + // assert that the register use has no overlap conflicts on each + // individual call but we also need to ensure that the necessary + // disjoint/equality constraints are met across both calls. + + // vb, vc, vtmp and vq must be disjoint. va must either be + // disjoint from all other registers or equal vc + + assert(vs_disjoint(vb, vc), "vb and vc overlap"); + assert(vs_disjoint(vb, vq), "vb and vq overlap"); + assert(vs_disjoint(vb, vtmp), "vb and vtmp overlap"); + + assert(vs_disjoint(vc, vq), "vc and vq overlap"); + assert(vs_disjoint(vc, vtmp), "vc and vtmp overlap"); + + assert(vs_disjoint(vq, vtmp), "vq and vtmp overlap"); + + assert(vs_disjoint(va, vc) || vs_same(va, vc), "va and vc neither disjoint nor equal"); + assert(vs_disjoint(va, vb), "va and vb overlap"); + assert(vs_disjoint(va, vq), "va and vq overlap"); + assert(vs_disjoint(va, vtmp), "va and vtmp overlap"); + + // We multiply the front and back halves of each sequence 4 at a + // time because + // + // 1) we are currently only able to get 4-way instruction + // parallelism at best + // + // 2) we need registers for the constants in vq and temporary + // scratch registers to hold intermediate results so vtmp can only + // be a VSeq<4> which means we only have 4 scratch slots. + + vs_montmul4(vs_front(va), vs_front(vb), vs_front(vc), __ T4S, vtmp, vq); + vs_montmul4(vs_back(va), vs_back(vb), vs_back(vc), __ T4S, vtmp, vq); + } + + // Perform combined montmul then add/sub on 4x4S vectors. + void dilithium_montmul16_sub_add( + const VSeq<4>& va0, const VSeq<4>& va1, const VSeq<4>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { // compute a = montmul(a1, c) dilithium_montmul16(vc, va1, vc, vtmp, vq); // ouptut a1 = a0 - a @@ -4917,10 +6318,10 @@ class StubGenerator: public StubCodeGenerator { vs_addv(va0, __ T4S, va0, vc); } - // perform combined add/sub then montul on 4x4S vectors - - void dilithium_sub_add_montmul16(const VSeq<4>& va0, const VSeq<4>& va1, const VSeq<4>& vb, - const VSeq<4>& vtmp1, const VSeq<4>& vtmp2, const VSeq<2>& vq) { + // Perform combined add/sub then montul on 4x4S vectors. + void dilithium_sub_add_montmul16( + const VSeq<4>& va0, const VSeq<4>& va1, const VSeq<4>& vb, + const VSeq<4>& vtmp1, const VSeq<4>& vtmp2, const VSeq<2>& vq) { // compute c = a0 - a1 vs_subv(vtmp1, __ T4S, va0, va1); // output a0 = a0 + a1 @@ -4963,10 +6364,10 @@ class StubGenerator: public StubCodeGenerator { offsets[3] = 192; } - // for levels 1 - 4 we simply load 2 x 4 adjacent values at a + // For levels 1 - 4 we simply load 2 x 4 adjacent values at a // time at 4 different offsets and multiply them in order by the // next set of input values. So we employ indexed load and store - // pair instructions with arrangement 4S + // pair instructions with arrangement 4S. for (int i = 0; i < 4; i++) { // reload q and qinv vs_ldpq(vq, dilithiumConsts); // qInv, q @@ -4975,7 +6376,7 @@ class StubGenerator: public StubCodeGenerator { // load next 8x4S inputs == b vs_ldpq_post(vs2, zetas); // compute a == c2 * b mod MONT_Q - vs_montmul32(vs2, vs1, vs2, vtmp, vq); + dilithium_montmul32(vs2, vs1, vs2, vtmp, vq); // load 8x4s coefficients via first start pos == c1 vs_ldpq_indexed(vs1, coeffs, c1Start, offsets); // compute a1 = c1 + a @@ -5029,20 +6430,21 @@ class StubGenerator: public StubCodeGenerator { VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 VSeq<2> vq(30); // n.b. constants overlap vs3 - int offsets[4] = {0, 32, 64, 96}; - int offsets1[8] = {16, 48, 80, 112, 144, 176, 208, 240 }; + int offsets[4] = { 0, 32, 64, 96}; + int offsets1[8] = { 16, 48, 80, 112, 144, 176, 208, 240 }; int offsets2[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; __ add(result, coeffs, 0); - __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + __ lea(dilithiumConsts, + ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); - // Each level represents one iteration of the outer for loop of the Java version + // Each level represents one iteration of the outer for loop of the Java version. // level 0-4 dilithiumNttLevel0_4(dilithiumConsts, coeffs, zetas); // level 5 - // at level 5 the coefficients we need to combine with the zetas + // At level 5 the coefficients we need to combine with the zetas // are grouped in memory in blocks of size 4. So, for both sets of // coefficients we load 4 adjacent values at 8 different offsets // using an indexed ldr with register variant Q and multiply them @@ -5056,7 +6458,7 @@ class StubGenerator: public StubCodeGenerator { // load next 32 (8x4S) inputs = b vs_ldpq_post(vs2, zetas); // a = b montul c1 - vs_montmul32(vs2, vs1, vs2, vtmp, vq); + dilithium_montmul32(vs2, vs1, vs2, vtmp, vq); // load 32 (8x4S) coefficients via second offsets = c2 vs_ldr_indexed(vs1, __ Q, coeffs, i, offsets2); // add/sub with result of multiply @@ -5068,7 +6470,7 @@ class StubGenerator: public StubCodeGenerator { } // level 6 - // at level 6 the coefficients we need to combine with the zetas + // At level 6 the coefficients we need to combine with the zetas // are grouped in memory in pairs, the first two being montmul // inputs and the second add/sub inputs. We can still implement // the montmul+sub+add using 4-way parallelism but only if we @@ -5096,7 +6498,7 @@ class StubGenerator: public StubCodeGenerator { } // level 7 - // at level 7 the coefficients we need to combine with the zetas + // At level 7 the coefficients we need to combine with the zetas // occur singly with montmul inputs alterating with add/sub // inputs. Once again we can use 4-way parallelism to combine 16 // zetas at a time. However, we have to load 8 adjacent values at @@ -5168,10 +6570,10 @@ class StubGenerator: public StubCodeGenerator { offsets[3] = 96; } - // for levels 3 - 7 we simply load 2 x 4 adjacent values at a + // For levels 3 - 7 we simply load 2 x 4 adjacent values at a // time at 4 different offsets and multiply them in order by the // next set of input values. So we employ indexed load and store - // pair instructions with arrangement 4S + // pair instructions with arrangement 4S. for (int i = 0; i < 4; i++) { // load v1 32 (8x4S) coefficients relative to first start index vs_ldpq_indexed(vs1, coeffs, c1Start, offsets); @@ -5188,7 +6590,7 @@ class StubGenerator: public StubCodeGenerator { // load b next 32 (8x4S) inputs vs_ldpq_post(vs2, zetas); // a = a1 montmul b - vs_montmul32(vs2, vs1, vs2, vtmp, vq); + dilithium_montmul32(vs2, vs1, vs2, vtmp, vq); // save a relative to second start index vs_stpq_indexed(vs2, coeffs, c2Start, offsets); @@ -5239,16 +6641,16 @@ class StubGenerator: public StubCodeGenerator { int offsets2[8] = { 16, 48, 80, 112, 144, 176, 208, 240 }; __ add(result, coeffs, 0); - __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + __ lea(dilithiumConsts, + ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); // Each level represents one iteration of the outer for loop of the Java version - // level0 // level 0 // At level 0 we need to interleave adjacent quartets of // coefficients before we multiply and add/sub by the next 16 // zetas just as we did for level 7 in the multiply code. So we - // load and store the values using an ld2/st2 with arrangement 4S + // load and store the values using an ld2/st2 with arrangement 4S. for (int i = 0; i < 1024; i += 128) { // load constants q, qinv // n.b. this can be moved out of the loop as they do not get @@ -5270,7 +6672,7 @@ class StubGenerator: public StubCodeGenerator { // At level 1 we need to interleave pairs of adjacent pairs of // coefficients before we multiply by the next 16 zetas just as we // did for level 6 in the multiply code. So we load and store the - // values an ld2/st2 with arrangement 2D + // values an ld2/st2 with arrangement 2D. for (int i = 0; i < 1024; i += 128) { // a0/a1 load interleaved 32 (8x2D) coefficients vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, i, offsets); @@ -5306,7 +6708,7 @@ class StubGenerator: public StubCodeGenerator { // reload constants q, qinv -- they were clobbered earlier vs_ldpq(vq, dilithiumConsts); // qInv, q // compute a1 = b montmul c - vs_montmul32(vs2, vs1, vs2, vtmp, vq); + dilithium_montmul32(vs2, vs1, vs2, vtmp, vq); // store a1 32 (8x4S) coefficients via second offsets vs_str_indexed(vs2, __ Q, coeffs, i, offsets2); } @@ -5319,7 +6721,6 @@ class StubGenerator: public StubCodeGenerator { __ ret(lr); return start; - } // Dilithium multiply polynomials in the NTT domain. @@ -5353,7 +6754,8 @@ class StubGenerator: public StubCodeGenerator { VSeq<2> vq(30); // n.b. constants overlap vs3 VSeq<8> vrsquare(29, 0); // for montmul by constant RSQUARE - __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + __ lea(dilithiumConsts, + ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); // load constants q, qinv vs_ldpq(vq, dilithiumConsts); // qInv, q @@ -5370,9 +6772,9 @@ class StubGenerator: public StubCodeGenerator { // c load 32 (8x4S) next inputs from poly2 vs_ldpq_post(vs2, poly2); // compute a = b montmul c - vs_montmul32(vs2, vs1, vs2, vtmp, vq); + dilithium_montmul32(vs2, vs1, vs2, vtmp, vq); // compute a = rsquare montmul a - vs_montmul32(vs2, vrsquare, vs2, vtmp, vq); + dilithium_montmul32(vs2, vrsquare, vs2, vtmp, vq); // save a 32 (8x4S) results vs_stpq_post(vs2, result); @@ -5385,7 +6787,6 @@ class StubGenerator: public StubCodeGenerator { __ ret(lr); return start; - } // Dilithium Motgomery multiply an array by a constant. @@ -5413,13 +6814,14 @@ class StubGenerator: public StubCodeGenerator { const Register len = r12; VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs - VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 VSeq<2> vq(30); // n.b. constants overlap vs3 VSeq<8> vconst(29, 0); // for montmul by constant // results track inputs __ add(result, coeffs, 0); - __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + __ lea(dilithiumConsts, + ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); // load constants q, qinv -- they do not get clobbered by first two loops vs_ldpq(vq, dilithiumConsts); // qInv, q @@ -5433,7 +6835,7 @@ class StubGenerator: public StubCodeGenerator { // load next 32 inputs vs_ldpq_post(vs2, coeffs); // mont mul by constant - vs_montmul32(vs2, vconst, vs2, vtmp, vq); + dilithium_montmul32(vs2, vconst, vs2, vtmp, vq); // write next 32 results vs_stpq_post(vs2, result); @@ -5446,7 +6848,6 @@ class StubGenerator: public StubCodeGenerator { __ ret(lr); return start; - } // Dilithium decompose poly. @@ -5477,9 +6878,12 @@ class StubGenerator: public StubCodeGenerator { const Register dilithiumConsts = r10; const Register tmp = r11; - VSeq<4> vs1(0), vs2(4), vs3(8); // 6 independent sets of 4x4s values + // 6 independent sets of 4x4s values + VSeq<4> vs1(0), vs2(4), vs3(8); VSeq<4> vs4(12), vs5(16), vtmp(20); - VSeq<4> one(25, 0); // 7 constants for cross-multiplying + + // 7 constants for cross-multiplying + VSeq<4> one(25, 0); VSeq<4> qminus1(26, 0); VSeq<4> g2(27, 0); VSeq<4> twog2(28, 0); @@ -5489,7 +6893,8 @@ class StubGenerator: public StubCodeGenerator { __ enter(); - __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + __ lea(dilithiumConsts, + ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); // save callee-saved registers __ stpd(v8, v9, __ pre(sp, -64)); @@ -5586,7 +6991,6 @@ class StubGenerator: public StubCodeGenerator { __ st4(vs3[0], vs3[1], vs3[2], vs3[3], __ T4S, __ post(lowPart, 64)); __ st4(vs1[0], vs1[1], vs1[2], vs1[3], __ T4S, __ post(highPart, 64)); - __ sub(len, len, 64); __ cmp(len, (u1)64); __ br(Assembler::GE, L_loop); @@ -5602,7 +7006,6 @@ class StubGenerator: public StubCodeGenerator { __ ret(lr); return start; - } /** @@ -10003,6 +11406,16 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_chacha20Block = generate_chacha20Block_qrpar(); } + if (UseKyberIntrinsics) { + StubRoutines::_kyberNtt = generate_kyberNtt(); + StubRoutines::_kyberInverseNtt = generate_kyberInverseNtt(); + StubRoutines::_kyberNttMult = generate_kyberNttMult(); + StubRoutines::_kyberAddPoly_2 = generate_kyberAddPoly_2(); + StubRoutines::_kyberAddPoly_3 = generate_kyberAddPoly_3(); + StubRoutines::_kyber12To16 = generate_kyber12To16(); + StubRoutines::_kyberBarrettReduce = generate_kyberBarrettReduce(); + } + if (UseDilithiumIntrinsics) { StubRoutines::_dilithiumAlmostNtt = generate_dilithiumAlmostNtt(); StubRoutines::_dilithiumAlmostInverseNtt = generate_dilithiumAlmostInverseNtt(); diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index 536583ff40c..fab76c41303 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -48,6 +48,17 @@ STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT) bool StubRoutines::aarch64::_completed = false; +ATTRIBUTE_ALIGNED(64) uint16_t StubRoutines::aarch64::_kyberConsts[] = +{ + // Because we sometimes load these in pairs, montQInvModR, kyber_q + // and kyberBarrettMultiplier should stay together and in this order. + 0xF301, 0xF301, 0xF301, 0xF301, 0xF301, 0xF301, 0xF301, 0xF301, // montQInvModR + 0x0D01, 0x0D01, 0x0D01, 0x0D01, 0x0D01, 0x0D01, 0x0D01, 0x0D01, // kyber_q + 0x4EBF, 0x4EBF, 0x4EBF, 0x4EBF, 0x4EBF, 0x4EBF, 0x4EBF, 0x4EBF, // kyberBarrettMultiplier + 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, // toMont((kyber_n / 2)^-1 (mod kyber_q)) + 0x0549, 0x0549, 0x0549, 0x0549, 0x0549, 0x0549, 0x0549, 0x0549 // montRSquareModQ +}; + ATTRIBUTE_ALIGNED(64) uint32_t StubRoutines::aarch64::_dilithiumConsts[] = { 58728449, 58728449, 58728449, 58728449, // montQInvModR diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index 857bb2ff10a..4c942b9f8d8 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -110,6 +110,7 @@ private: } private: + static uint16_t _kyberConsts[]; static uint32_t _dilithiumConsts[]; static juint _crc_table[]; static jubyte _adler_table[]; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 0f04fee7922..6bf300ced42 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -414,13 +414,24 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } + if (_features & CPU_ASIMD) { + if (FLAG_IS_DEFAULT(UseKyberIntrinsics)) { + UseKyberIntrinsics = true; + } + } else if (UseKyberIntrinsics) { + if (!FLAG_IS_DEFAULT(UseKyberIntrinsics)) { + warning("Kyber intrinsics require ASIMD instructions"); + } + FLAG_SET_DEFAULT(UseKyberIntrinsics, false); + } + if (_features & CPU_ASIMD) { if (FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { UseDilithiumIntrinsics = true; } } else if (UseDilithiumIntrinsics) { if (!FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { - warning("Dilithium intrinsic requires ASIMD instructions"); + warning("Dilithium intrinsics require ASIMD instructions"); } FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false); } @@ -703,6 +714,7 @@ void VM_Version::initialize_cpu_information(void) { get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len); desc_len = (int)strlen(_cpu_desc); snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _features_string); + fprintf(stderr, "_features_string = \"%s\"", _features_string); _initialized = true; } diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 8011b059697..e23720f3ae0 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -488,6 +488,14 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_chacha20Block: if (!UseChaCha20Intrinsics) return true; break; + case vmIntrinsics::_kyberNtt: + case vmIntrinsics::_kyberInverseNtt: + case vmIntrinsics::_kyberNttMult: + case vmIntrinsics::_kyberAddPoly_2: + case vmIntrinsics::_kyberAddPoly_3: + case vmIntrinsics::_kyber12To16: + case vmIntrinsics::_kyberBarrettReduce: + if (!UseKyberIntrinsics) return true; case vmIntrinsics::_dilithiumAlmostNtt: case vmIntrinsics::_dilithiumAlmostInverseNtt: case vmIntrinsics::_dilithiumNttMult: diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 49446b53b98..68de40f1788 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -569,6 +569,27 @@ class methodHandle; do_name(chacha20Block_name, "implChaCha20Block") \ do_signature(chacha20Block_signature, "([I[B)I") \ \ + /* support for com.sun.crypto.provider.ML_KEM */ \ + do_class(com_sun_crypto_provider_ML_KEM, "com/sun/crypto/provider/ML_KEM") \ + do_signature(SaSaSaSaI_signature, "([S[S[S[S)I") \ + do_signature(BaISaII_signature, "([BI[SI)I") \ + do_signature(SaSaSaI_signature, "([S[S[S)I") \ + do_signature(SaSaI_signature, "([S[S)I") \ + do_signature(SaI_signature, "([S)I") \ + do_name(kyberAddPoly_name, "implKyberAddPoly") \ + do_intrinsic(_kyberNtt, com_sun_crypto_provider_ML_KEM, kyberNtt_name, SaSaI_signature, F_S) \ + do_name(kyberNtt_name, "implKyberNtt") \ + do_intrinsic(_kyberInverseNtt, com_sun_crypto_provider_ML_KEM, kyberInverseNtt_name, SaSaI_signature, F_S) \ + do_name(kyberInverseNtt_name, "implKyberInverseNtt") \ + do_intrinsic(_kyberNttMult, com_sun_crypto_provider_ML_KEM, kyberNttMult_name, SaSaSaSaI_signature, F_S) \ + do_name(kyberNttMult_name, "implKyberNttMult") \ + do_intrinsic(_kyberAddPoly_2, com_sun_crypto_provider_ML_KEM, kyberAddPoly_name, SaSaSaI_signature, F_S) \ + do_intrinsic(_kyberAddPoly_3, com_sun_crypto_provider_ML_KEM, kyberAddPoly_name, SaSaSaSaI_signature, F_S) \ + do_intrinsic(_kyber12To16, com_sun_crypto_provider_ML_KEM, kyber12To16_name, BaISaII_signature, F_S) \ + do_name(kyber12To16_name, "implKyber12To16") \ + do_intrinsic(_kyberBarrettReduce, com_sun_crypto_provider_ML_KEM, kyberBarrettReduce_name, SaI_signature, F_S) \ + do_name(kyberBarrettReduce_name, "implKyberBarrettReduce") \ + \ /* support for sun.security.provider.ML_DSA */ \ do_class(sun_security_provider_ML_DSA, "sun/security/provider/ML_DSA") \ do_signature(IaII_signature, "([II)I") \ diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 3cbb1512cd0..4fe2b286e15 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -395,6 +395,13 @@ static_field(StubRoutines, _sha3_implCompress, address) \ static_field(StubRoutines, _double_keccak, address) \ static_field(StubRoutines, _sha3_implCompressMB, address) \ + static_field(StubRoutines, _kyberNtt, address) \ + static_field(StubRoutines, _kyberInverseNtt, address) \ + static_field(StubRoutines, _kyberNttMult, address) \ + static_field(StubRoutines, _kyberAddPoly_2, address) \ + static_field(StubRoutines, _kyberAddPoly_3, address) \ + static_field(StubRoutines, _kyber12To16, address) \ + static_field(StubRoutines, _kyberBarrettReduce, address) \ static_field(StubRoutines, _dilithiumAlmostNtt, address) \ static_field(StubRoutines, _dilithiumAlmostInverseNtt, address) \ static_field(StubRoutines, _dilithiumNttMult, address) \ diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index 3effa8eee04..f39937b9cdd 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -792,6 +792,13 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_vectorizedMismatch: case vmIntrinsics::_ghash_processBlocks: case vmIntrinsics::_chacha20Block: + case vmIntrinsics::_kyberNtt: + case vmIntrinsics::_kyberInverseNtt: + case vmIntrinsics::_kyberNttMult: + case vmIntrinsics::_kyberAddPoly_2: + case vmIntrinsics::_kyberAddPoly_3: + case vmIntrinsics::_kyber12To16: + case vmIntrinsics::_kyberBarrettReduce: case vmIntrinsics::_dilithiumAlmostNtt: case vmIntrinsics::_dilithiumAlmostInverseNtt: case vmIntrinsics::_dilithiumNttMult: diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 23cf8a67be7..decc43a212a 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2192,6 +2192,13 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "intpoly_assign") == 0 || strcmp(call->as_CallLeaf()->_name, "ghash_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "chacha20Block") == 0 || + strcmp(call->as_CallLeaf()->_name, "kyberNtt") == 0 || + strcmp(call->as_CallLeaf()->_name, "kyberInverseNtt") == 0 || + strcmp(call->as_CallLeaf()->_name, "kyberNttMult") == 0 || + strcmp(call->as_CallLeaf()->_name, "kyberAddPoly_2") == 0 || + strcmp(call->as_CallLeaf()->_name, "kyberAddPoly_3") == 0 || + strcmp(call->as_CallLeaf()->_name, "kyber12To16") == 0 || + strcmp(call->as_CallLeaf()->_name, "kyberBarrettReduce") == 0 || strcmp(call->as_CallLeaf()->_name, "dilithiumAlmostNtt") == 0 || strcmp(call->as_CallLeaf()->_name, "dilithiumAlmostInverseNtt") == 0 || strcmp(call->as_CallLeaf()->_name, "dilithiumNttMult") == 0 || diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 783631bf08d..017564173a8 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -626,6 +626,20 @@ bool LibraryCallKit::try_to_inline(int predicate) { return inline_ghash_processBlocks(); case vmIntrinsics::_chacha20Block: return inline_chacha20Block(); + case vmIntrinsics::_kyberNtt: + return inline_kyberNtt(); + case vmIntrinsics::_kyberInverseNtt: + return inline_kyberInverseNtt(); + case vmIntrinsics::_kyberNttMult: + return inline_kyberNttMult(); + case vmIntrinsics::_kyberAddPoly_2: + return inline_kyberAddPoly_2(); + case vmIntrinsics::_kyberAddPoly_3: + return inline_kyberAddPoly_3(); + case vmIntrinsics::_kyber12To16: + return inline_kyber12To16(); + case vmIntrinsics::_kyberBarrettReduce: + return inline_kyberBarrettReduce(); case vmIntrinsics::_dilithiumAlmostNtt: return inline_dilithiumAlmostNtt(); case vmIntrinsics::_dilithiumAlmostInverseNtt: @@ -7640,6 +7654,245 @@ bool LibraryCallKit::inline_chacha20Block() { return true; } +//------------------------------inline_kyberNtt +bool LibraryCallKit::inline_kyberNtt() { + address stubAddr; + const char *stubName; + assert(UseKyberIntrinsics, "need Kyber intrinsics support"); + assert(callee()->signature()->size() == 2, "kyberNtt has 2 parameters"); + + stubAddr = StubRoutines::kyberNtt(); + stubName = "kyberNtt"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* ntt_zetas = argument(1); + + coeffs = must_be_not_null(coeffs, true); + ntt_zetas = must_be_not_null(ntt_zetas, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_SHORT); + assert(coeffs_start, "coeffs is null"); + Node* ntt_zetas_start = array_element_address(ntt_zetas, intcon(0), T_SHORT); + assert(ntt_zetas_start, "ntt_zetas is null"); + Node* kyberNtt = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::kyberNtt_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, ntt_zetas_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(kyberNtt, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_kyberInverseNtt +bool LibraryCallKit::inline_kyberInverseNtt() { + address stubAddr; + const char *stubName; + assert(UseKyberIntrinsics, "need Kyber intrinsics support"); + assert(callee()->signature()->size() == 2, "kyberInverseNtt has 2 parameters"); + + stubAddr = StubRoutines::kyberInverseNtt(); + stubName = "kyberInverseNtt"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* zetas = argument(1); + + coeffs = must_be_not_null(coeffs, true); + zetas = must_be_not_null(zetas, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_SHORT); + assert(coeffs_start, "coeffs is null"); + Node* zetas_start = array_element_address(zetas, intcon(0), T_SHORT); + assert(zetas_start, "inverseNtt_zetas is null"); + Node* kyberInverseNtt = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::kyberInverseNtt_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, zetas_start); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(kyberInverseNtt, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_kyberNttMult +bool LibraryCallKit::inline_kyberNttMult() { + address stubAddr; + const char *stubName; + assert(UseKyberIntrinsics, "need Kyber intrinsics support"); + assert(callee()->signature()->size() == 4, "kyberNttMult has 4 parameters"); + + stubAddr = StubRoutines::kyberNttMult(); + stubName = "kyberNttMult"; + if (!stubAddr) return false; + + Node* result = argument(0); + Node* ntta = argument(1); + Node* nttb = argument(2); + Node* zetas = argument(3); + + result = must_be_not_null(result, true); + ntta = must_be_not_null(ntta, true); + nttb = must_be_not_null(nttb, true); + zetas = must_be_not_null(zetas, true); + Node* result_start = array_element_address(result, intcon(0), T_SHORT); + assert(result_start, "result is null"); + Node* ntta_start = array_element_address(ntta, intcon(0), T_SHORT); + assert(ntta_start, "ntta is null"); + Node* nttb_start = array_element_address(nttb, intcon(0), T_SHORT); + assert(nttb_start, "nttb is null"); + Node* zetas_start = array_element_address(zetas, intcon(0), T_SHORT); + assert(zetas_start, "nttMult_zetas is null"); + Node* kyberNttMult = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::kyberNttMult_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + result_start, ntta_start, nttb_start, + zetas_start); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(kyberNttMult, TypeFunc::Parms)); + set_result(retvalue); + + return true; +} + +//------------------------------inline_kyberAddPoly_2 +bool LibraryCallKit::inline_kyberAddPoly_2() { + address stubAddr; + const char *stubName; + assert(UseKyberIntrinsics, "need Kyber intrinsics support"); + assert(callee()->signature()->size() == 3, "kyberAddPoly_2 has 3 parameters"); + + stubAddr = StubRoutines::kyberAddPoly_2(); + stubName = "kyberAddPoly_2"; + if (!stubAddr) return false; + + Node* result = argument(0); + Node* a = argument(1); + Node* b = argument(2); + + result = must_be_not_null(result, true); + a = must_be_not_null(a, true); + b = must_be_not_null(b, true); + + Node* result_start = array_element_address(result, intcon(0), T_SHORT); + assert(result_start, "result is null"); + Node* a_start = array_element_address(a, intcon(0), T_SHORT); + assert(a_start, "a is null"); + Node* b_start = array_element_address(b, intcon(0), T_SHORT); + assert(b_start, "b is null"); + Node* kyberAddPoly_2 = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::kyberAddPoly_2_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + result_start, a_start, b_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(kyberAddPoly_2, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_kyberAddPoly_3 +bool LibraryCallKit::inline_kyberAddPoly_3() { + address stubAddr; + const char *stubName; + assert(UseKyberIntrinsics, "need Kyber intrinsics support"); + assert(callee()->signature()->size() == 4, "kyberAddPoly_3 has 4 parameters"); + + stubAddr = StubRoutines::kyberAddPoly_3(); + stubName = "kyberAddPoly_3"; + if (!stubAddr) return false; + + Node* result = argument(0); + Node* a = argument(1); + Node* b = argument(2); + Node* c = argument(3); + + result = must_be_not_null(result, true); + a = must_be_not_null(a, true); + b = must_be_not_null(b, true); + c = must_be_not_null(c, true); + + Node* result_start = array_element_address(result, intcon(0), T_SHORT); + assert(result_start, "result is null"); + Node* a_start = array_element_address(a, intcon(0), T_SHORT); + assert(a_start, "a is null"); + Node* b_start = array_element_address(b, intcon(0), T_SHORT); + assert(b_start, "b is null"); + Node* c_start = array_element_address(c, intcon(0), T_SHORT); + assert(c_start, "c is null"); + Node* kyberAddPoly_3 = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::kyberAddPoly_3_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + result_start, a_start, b_start, c_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(kyberAddPoly_3, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_kyber12To16 +bool LibraryCallKit::inline_kyber12To16() { + address stubAddr; + const char *stubName; + assert(UseKyberIntrinsics, "need Kyber intrinsics support"); + assert(callee()->signature()->size() == 4, "kyber12To16 has 4 parameters"); + + stubAddr = StubRoutines::kyber12To16(); + stubName = "kyber12To16"; + if (!stubAddr) return false; + + Node* condensed = argument(0); + Node* condensedOffs = argument(1); + Node* parsed = argument(2); + Node* parsedLength = argument(3); + + condensed = must_be_not_null(condensed, true); + parsed = must_be_not_null(parsed, true); + + Node* condensed_start = array_element_address(condensed, intcon(0), T_BYTE); + assert(condensed_start, "condensed is null"); + Node* parsed_start = array_element_address(parsed, intcon(0), T_SHORT); + assert(parsed_start, "parsed is null"); + Node* kyber12To16 = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::kyber12To16_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + condensed_start, condensedOffs, parsed_start, parsedLength); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(kyber12To16, TypeFunc::Parms)); + set_result(retvalue); + return true; + +} + +//------------------------------inline_kyberBarrettReduce +bool LibraryCallKit::inline_kyberBarrettReduce() { + address stubAddr; + const char *stubName; + assert(UseKyberIntrinsics, "need Kyber intrinsics support"); + assert(callee()->signature()->size() == 1, "kyberBarrettReduce has 1 parameters"); + + stubAddr = StubRoutines::kyberBarrettReduce(); + stubName = "kyberBarrettReduce"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + + coeffs = must_be_not_null(coeffs, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_SHORT); + assert(coeffs_start, "coeffs is null"); + Node* kyberBarrettReduce = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::kyberBarrettReduce_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(kyberBarrettReduce, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + //------------------------------inline_dilithiumAlmostNtt bool LibraryCallKit::inline_dilithiumAlmostNtt() { address stubAddr; @@ -7696,7 +7949,6 @@ bool LibraryCallKit::inline_dilithiumAlmostInverseNtt() { OptoRuntime::dilithiumAlmostInverseNtt_Type(), stubAddr, stubName, TypePtr::BOTTOM, coeffs_start, zetas_start); - // return an int Node* retvalue = _gvn.transform(new ProjNode(dilithiumAlmostInverseNtt, TypeFunc::Parms)); set_result(retvalue); @@ -7717,10 +7969,12 @@ bool LibraryCallKit::inline_dilithiumNttMult() { Node* result = argument(0); Node* ntta = argument(1); Node* nttb = argument(2); + Node* zetas = argument(3); result = must_be_not_null(result, true); ntta = must_be_not_null(ntta, true); nttb = must_be_not_null(nttb, true); + zetas = must_be_not_null(zetas, true); Node* result_start = array_element_address(result, intcon(0), T_INT); assert(result_start, "result is null"); diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index ad1ce71c374..cb755267ec5 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -314,6 +314,13 @@ class LibraryCallKit : public GraphKit { Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); bool inline_ghash_processBlocks(); bool inline_chacha20Block(); + bool inline_kyberNtt(); + bool inline_kyberInverseNtt(); + bool inline_kyberNttMult(); + bool inline_kyberAddPoly_2(); + bool inline_kyberAddPoly_3(); + bool inline_kyber12To16(); + bool inline_kyberBarrettReduce(); bool inline_dilithiumAlmostNtt(); bool inline_dilithiumAlmostInverseNtt(); bool inline_dilithiumNttMult(); diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index e32cedf6cee..74d7eb42ebc 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -242,13 +242,18 @@ const TypeFunc* OptoRuntime::_bigIntegerShift_Type = nullptr; const TypeFunc* OptoRuntime::_vectorizedMismatch_Type = nullptr; const TypeFunc* OptoRuntime::_ghash_processBlocks_Type = nullptr; const TypeFunc* OptoRuntime::_chacha20Block_Type = nullptr; - +const TypeFunc* OptoRuntime::_kyberNtt_Type = nullptr; +const TypeFunc* OptoRuntime::_kyberInverseNtt_Type = nullptr; +const TypeFunc* OptoRuntime::_kyberNttMult_Type = nullptr; +const TypeFunc* OptoRuntime::_kyberAddPoly_2_Type = nullptr; +const TypeFunc* OptoRuntime::_kyberAddPoly_3_Type = nullptr; +const TypeFunc* OptoRuntime::_kyber12To16_Type = nullptr; +const TypeFunc* OptoRuntime::_kyberBarrettReduce_Type = nullptr; const TypeFunc* OptoRuntime::_dilithiumAlmostNtt_Type = nullptr; const TypeFunc* OptoRuntime::_dilithiumAlmostInverseNtt_Type = nullptr; const TypeFunc* OptoRuntime::_dilithiumNttMult_Type = nullptr; const TypeFunc* OptoRuntime::_dilithiumMontMulByConstant_Type = nullptr; const TypeFunc* OptoRuntime::_dilithiumDecomposePoly_Type = nullptr; - const TypeFunc* OptoRuntime::_base64_encodeBlock_Type = nullptr; const TypeFunc* OptoRuntime::_base64_decodeBlock_Type = nullptr; const TypeFunc* OptoRuntime::_string_IndexOf_Type = nullptr; @@ -1409,6 +1414,146 @@ static const TypeFunc* make_chacha20Block_Type() { return TypeFunc::make(domain, range); } +// Kyber NTT function +static const TypeFunc* make_kyberNtt_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypePtr::NOTNULL; // NTT zetas + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Kyber inverse NTT function +static const TypeFunc* make_kyberInverseNtt_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypePtr::NOTNULL; // inverse NTT zetas + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Kyber NTT multiply function +static const TypeFunc* make_kyberNttMult_Type() { + int argcnt = 4; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // result + fields[argp++] = TypePtr::NOTNULL; // ntta + fields[argp++] = TypePtr::NOTNULL; // nttb + fields[argp++] = TypePtr::NOTNULL; // NTT multiply zetas + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} +// Kyber add 2 polynomials function +static const TypeFunc* make_kyberAddPoly_2_Type() { + int argcnt = 3; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // result + fields[argp++] = TypePtr::NOTNULL; // a + fields[argp++] = TypePtr::NOTNULL; // b + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + + +// Kyber add 3 polynomials function +static const TypeFunc* make_kyberAddPoly_3_Type() { + int argcnt = 4; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // result + fields[argp++] = TypePtr::NOTNULL; // a + fields[argp++] = TypePtr::NOTNULL; // b + fields[argp++] = TypePtr::NOTNULL; // c + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + + +// Kyber XOF output parsing into polynomial coefficients candidates +// or decompress(12,...) function +static const TypeFunc* make_kyber12To16_Type() { + int argcnt = 4; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // condensed + fields[argp++] = TypeInt::INT; // condensedOffs + fields[argp++] = TypePtr::NOTNULL; // parsed + fields[argp++] = TypeInt::INT; // parsedLength + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Kyber Barrett reduce function +static const TypeFunc* make_kyberBarrettReduce_Type() { + int argcnt = 1; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + // Dilithium NTT function except for the final "normalization" to |coeff| < Q static const TypeFunc* make_dilithiumAlmostNtt_Type() { int argcnt = 2; @@ -2120,13 +2265,18 @@ void OptoRuntime::initialize_types() { _vectorizedMismatch_Type = make_vectorizedMismatch_Type(); _ghash_processBlocks_Type = make_ghash_processBlocks_Type(); _chacha20Block_Type = make_chacha20Block_Type(); - + _kyberNtt_Type = make_kyberNtt_Type(); + _kyberInverseNtt_Type = make_kyberInverseNtt_Type(); + _kyberNttMult_Type = make_kyberNttMult_Type(); + _kyberAddPoly_2_Type = make_kyberAddPoly_2_Type(); + _kyberAddPoly_3_Type = make_kyberAddPoly_3_Type(); + _kyber12To16_Type = make_kyber12To16_Type(); + _kyberBarrettReduce_Type = make_kyberBarrettReduce_Type(); _dilithiumAlmostNtt_Type = make_dilithiumAlmostNtt_Type(); _dilithiumAlmostInverseNtt_Type = make_dilithiumAlmostInverseNtt_Type(); _dilithiumNttMult_Type = make_dilithiumNttMult_Type(); _dilithiumMontMulByConstant_Type = make_dilithiumMontMulByConstant_Type(); _dilithiumDecomposePoly_Type = make_dilithiumDecomposePoly_Type(); - _base64_encodeBlock_Type = make_base64_encodeBlock_Type(); _base64_decodeBlock_Type = make_base64_decodeBlock_Type(); _string_IndexOf_Type = make_string_IndexOf_Type(); diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index 96b7e9297d6..fd7fc796aa4 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -180,6 +180,13 @@ class OptoRuntime : public AllStatic { static const TypeFunc* _vectorizedMismatch_Type; static const TypeFunc* _ghash_processBlocks_Type; static const TypeFunc* _chacha20Block_Type; + static const TypeFunc* _kyberNtt_Type; + static const TypeFunc* _kyberInverseNtt_Type; + static const TypeFunc* _kyberNttMult_Type; + static const TypeFunc* _kyberAddPoly_2_Type; + static const TypeFunc* _kyberAddPoly_3_Type; + static const TypeFunc* _kyber12To16_Type; + static const TypeFunc* _kyberBarrettReduce_Type; static const TypeFunc* _dilithiumAlmostNtt_Type; static const TypeFunc* _dilithiumAlmostInverseNtt_Type; static const TypeFunc* _dilithiumNttMult_Type; @@ -468,6 +475,10 @@ private: return _unsafe_setmemory_Type; } +// static const TypeFunc* digestBase_implCompress_Type(bool is_sha3); +// static const TypeFunc* digestBase_implCompressMB_Type(bool is_sha3); +// static const TypeFunc* double_keccak_Type(); + static inline const TypeFunc* array_fill_Type() { assert(_array_fill_Type != nullptr, "should be initialized"); return _array_fill_Type; @@ -584,6 +595,41 @@ private: return _chacha20Block_Type; } + static const TypeFunc* kyberNtt_Type() { + assert(_kyberNtt_Type != nullptr, "should be initialized"); + return _kyberNtt_Type; + } + + static const TypeFunc* kyberInverseNtt_Type() { + assert(_kyberInverseNtt_Type != nullptr, "should be initialized"); + return _kyberInverseNtt_Type; + } + + static const TypeFunc* kyberNttMult_Type() { + assert(_kyberNttMult_Type != nullptr, "should be initialized"); + return _kyberNttMult_Type; + } + + static const TypeFunc* kyberAddPoly_2_Type() { + assert(_kyberAddPoly_2_Type != nullptr, "should be initialized"); + return _kyberAddPoly_2_Type; + } + + static const TypeFunc* kyberAddPoly_3_Type() { + assert(_kyberAddPoly_3_Type != nullptr, "should be initialized"); + return _kyberAddPoly_3_Type; + } + + static const TypeFunc* kyber12To16_Type() { + assert(_kyber12To16_Type != nullptr, "should be initialized"); + return _kyber12To16_Type; + } + + static const TypeFunc* kyberBarrettReduce_Type() { + assert(_kyberBarrettReduce_Type != nullptr, "should be initialized"); + return _kyberBarrettReduce_Type; + } + static inline const TypeFunc* dilithiumAlmostNtt_Type() { assert(_dilithiumAlmostNtt_Type != nullptr, "should be initialized"); return _dilithiumAlmostNtt_Type; diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 9edd95b9cdc..29f0948276a 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -325,6 +325,8 @@ const int ObjectAlignmentInBytes = 8; product(bool, UseChaCha20Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for the vectorized version of ChaCha20") \ \ + product(bool, UseKyberIntrinsics, false, DIAGNOSTIC, \ + "Use intrinsics for the vectorized version of Kyber") \ product(bool, UseDilithiumIntrinsics, false, DIAGNOSTIC, \ "Use intrinsics for the vectorized version of Dilithium") \ \ diff --git a/src/hotspot/share/runtime/stubDeclarations.hpp b/src/hotspot/share/runtime/stubDeclarations.hpp index c061d0b5daf..46feaaf0175 100644 --- a/src/hotspot/share/runtime/stubDeclarations.hpp +++ b/src/hotspot/share/runtime/stubDeclarations.hpp @@ -678,6 +678,21 @@ ghash_processBlocks) \ do_stub(compiler, chacha20Block) \ do_entry(compiler, chacha20Block, chacha20Block, chacha20Block) \ + do_stub(compiler, kyberNtt) \ + do_entry(compiler, kyberNtt, kyberNtt, kyberNtt) \ + do_stub(compiler, kyberInverseNtt) \ + do_entry(compiler, kyberInverseNtt, kyberInverseNtt, kyberInverseNtt) \ + do_stub(compiler, kyberNttMult) \ + do_entry(compiler, kyberNttMult, kyberNttMult, kyberNttMult) \ + do_stub(compiler, kyberAddPoly_2) \ + do_entry(compiler, kyberAddPoly_2, kyberAddPoly_2, kyberAddPoly_2) \ + do_stub(compiler, kyberAddPoly_3) \ + do_entry(compiler, kyberAddPoly_3, kyberAddPoly_3, kyberAddPoly_3) \ + do_stub(compiler, kyber12To16) \ + do_entry(compiler, kyber12To16, kyber12To16, kyber12To16) \ + do_stub(compiler, kyberBarrettReduce) \ + do_entry(compiler, kyberBarrettReduce, kyberBarrettReduce, \ + kyberBarrettReduce) \ do_stub(compiler, dilithiumAlmostNtt) \ do_entry(compiler, dilithiumAlmostNtt, \ dilithiumAlmostNtt, dilithiumAlmostNtt) \ diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java index 9808a013303..b45b655e1f3 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java @@ -28,6 +28,7 @@ package com.sun.crypto.provider; import java.security.*; import java.util.Arrays; import javax.crypto.DecapsulateException; +import jdk.internal.vm.annotation.IntrinsicCandidate; import sun.security.provider.SHA3.SHAKE256; import sun.security.provider.SHA3Parallel.Shake128Parallel; @@ -71,6 +72,268 @@ public final class ML_KEM { -1599, -709, -789, -1317, -57, 1049, -584 }; + private static final short[] montZetasForVectorNttArr = new short[]{ + // level 0 + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + -758, -758, -758, -758, -758, -758, -758, -758, + // level 1 + -359, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + // level 2 + 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, + 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, + 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, + 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, + 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, + 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, + 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, + 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, + 287, 287, 287, 287, 287, 287, 287, 287, + 287, 287, 287, 287, 287, 287, 287, 287, + 287, 287, 287, 287, 287, 287, 287, 287, + 287, 287, 287, 287, 287, 287, 287, 287, + 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, + // level 3 + -171, -171, -171, -171, -171, -171, -171, -171, + -171, -171, -171, -171, -171, -171, -171, -171, + 622, 622, 622, 622, 622, 622, 622, 622, + 622, 622, 622, 622, 622, 622, 622, 622, + 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, + 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, + 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, + 962, 962, 962, 962, 962, 962, 962, 962, + 962, 962, 962, 962, 962, 962, 962, 962, + -1202, -1202, -1202, -1202, -1202, -1202, -1202, -1202, + -1202, -1202, -1202, -1202, -1202, -1202, -1202, -1202, + -1474, -1474, -1474, -1474, -1474, -1474, -1474, -1474, + -1474, -1474, -1474, -1474, -1474, -1474, -1474, -1474, + 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, + 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, + // level 4 + 573, 573, 573, 573, 573, 573, 573, 573, + -1325, -1325, -1325, -1325, -1325, -1325, -1325, -1325, + 264, 264, 264, 264, 264, 264, 264, 264, + 383, 383, 383, 383, 383, 383, 383, 383, + -829, -829, -829, -829, -829, -829, -829, -829, + 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, + -1602, -1602, -1602, -1602, -1602, -1602, -1602, -1602, + -130, -130, -130, -130, -130, -130, -130, -130, + -681, -681, -681, -681, -681, -681, -681, -681, + 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, + 732, 732, 732, 732, 732, 732, 732, 732, + 608, 608, 608, 608, 608, 608, 608, 608, + -1542, -1542, -1542, -1542, -1542, -1542, -1542, -1542, + 411, 411, 411, 411, 411, 411, 411, 411, + -205, -205, -205, -205, -205, -205, -205, -205, + -1571, -1571, -1571, -1571, -1571, -1571, -1571, -1571, + // level 5 + 1223, 1223, 1223, 1223, 652, 652, 652, 652, + -552, -552, -552, -552, 1015, 1015, 1015, 1015, + -1293, -1293, -1293, -1293, 1491, 1491, 1491, 1491, + -282, -282, -282, -282, -1544, -1544, -1544, -1544, + 516, 516, 516, 516, -8, -8, -8, -8, + -320, -320, -320, -320, -666, -666, -666, -666, + 1711, 1711, 1711, 1711, -1162, -1162, -1162, -1162, + 126, 126, 126, 126, 1469, 1469, 1469, 1469, + -853, -853, -853, -853, -90, -90, -90, -90, + -271, -271, -271, -271, 830, 830, 830, 830, + 107, 107, 107, 107, -1421, -1421, -1421, -1421, + -247, -247, -247, -247, -951, -951, -951, -951, + -398, -398, -398, -398, 961, 961, 961, 961, + -1508, -1508, -1508, -1508, -725, -725, -725, -725, + 448, 448, 448, 448, -1065, -1065, -1065, -1065, + 677, 677, 677, 677, -1275, -1275, -1275, -1275, + // level 6 + -1103, -1103, 430, 430, 555, 555, 843, 843, + -1251, -1251, 871, 871, 1550, 1550, 105, 105, + 422, 422, 587, 587, 177, 177, -235, -235, + -291, -291, -460, -460, 1574, 1574, 1653, 1653, + -246, -246, 778, 778, 1159, 1159, -147, -147, + -777, -777, 1483, 1483, -602, -602, 1119, 1119, + -1590, -1590, 644, 644, -872, -872, 349, 349, + 418, 418, 329, 329, -156, -156, -75, -75, + 817, 817, 1097, 1097, 603, 603, 610, 610, + 1322, 1322, -1285, -1285, -1465, -1465, 384, 384, + -1215, -1215, -136, -136, 1218, 1218, -1335, -1335, + -874, -874, 220, 220, -1187, -1187, 1670, 1670, + -1185, -1185, -1530, -1530, -1278, -1278, 794, 794, + -1510, -1510, -854, -854, -870, -870, 478, 478, + -108, -108, -308, -308, 996, 996, 991, 991, + 958, 958, -1460, -1460, 1522, 1522, 1628, 1628 + }; + private static final int[] MONT_ZETAS_FOR_INVERSE_NTT = new int[]{ + 584, -1049, 57, 1317, 789, 709, 1599, -1601, + -990, 604, 348, 857, 612, 474, 1177, -1014, + -88, -982, -191, 668, 1386, 486, -1153, -534, + 514, 137, 586, -1178, 227, 339, -907, 244, + 1200, -833, 1394, -30, 1074, 636, -317, -1192, + -1259, -355, -425, -884, -977, 1430, 868, 607, + 184, 1448, 702, 1327, 431, 497, 595, -94, + 1649, -1497, -620, 42, -172, 1107, -222, 1003, + 426, -845, 395, -510, 1613, 825, 1269, -290, + -1429, 623, -567, 1617, 36, 1007, 1440, 332, + -201, 1313, -1382, -744, 669, -1538, 128, -1598, + 1401, 1183, -553, 714, 405, -1155, -445, 406, + -1496, -49, 82, 1369, 259, 1604, 373, 909, + -1249, -1000, -25, -52, 530, -895, 1226, 819, + -185, 281, -742, 1253, 417, 1400, 35, -593, + 97, -1263, 551, -585, 969, -914, -1188 + }; + + private static final short[] montZetasForVectorInverseNttArr = new short[]{ + // level 0 + -1628, -1628, -1522, -1522, 1460, 1460, -958, -958, + -991, -991, -996, -996, 308, 308, 108, 108, + -478, -478, 870, 870, 854, 854, 1510, 1510, + -794, -794, 1278, 1278, 1530, 1530, 1185, 1185, + 1659, 1659, 1187, 1187, -220, -220, 874, 874, + 1335, 1335, -1218, -1218, 136, 136, 1215, 1215, + -384, -384, 1465, 1465, 1285, 1285, -1322, -1322, + -610, -610, -603, -603, -1097, -1097, -817, -817, + 75, 75, 156, 156, -329, -329, -418, -418, + -349, -349, 872, 872, -644, -644, 1590, 1590, + -1119, -1119, 602, 602, -1483, -1483, 777, 777, + 147, 147, -1159, -1159, -778, -778, 246, 246, + -1653, -1653, -1574, -1574, 460, 460, 291, 291, + 235, 235, -177, -177, -587, -587, -422, -422, + -105, -105, -1550, -1550, -871, -871, 1251, 1251, + -843, -843, -555, -555, -430, -430, 1103, 1103, + // level 1 + 1275, 1275, 1275, 1275, -677, -677, -677, -677, + 1065, 1065, 1065, 1065, -448, -448, -448, -448, + 725, 725, 725, 725, 1508, 1508, 1508, 1508, + -961, -961, -961, -961, 398, 398, 398, 398, + 951, 951, 951, 951, 247, 247, 247, 247, + 1421, 1421, 1421, 1421, -107, -107, -107, -107, + -830, -830, -830, -830, 271, 271, 271, 271, + 90, 90, 90, 90, 853, 853, 853, 853, + -1469, -1469, -1469, -1469, -126, -126, -126, -126, + 1162, 1162, 1162, 1162, 1618, 1618, 1618, 1618, + 666, 666, 666, 666, 320, 320, 320, 320, + 8, 8, 8, 8, -516, -516, -516, -516, + 1544, 1544, 1544, 1544, 282, 282, 282, 282, + -1491, -1491, -1491, -1491, 1293, 1293, 1293, 1293, + -1015, -1015, -1015, -1015, 552, 552, 552, 552, + -652, -652, -652, -652, -1223, -1223, -1223, -1223, + // level 2 + 1571, 1571, 1571, 1571, 1571, 1571, 1571, 1571, + 205, 205, 205, 205, 205, 205, 205, 205, + -411, -411, -411, -411, -411, -411, -411, -411, + 1542, 1542, 1542, 1542, 1542, 1542, 1542, 1542, + -608, -608, -608, -608, -608, -608, -608, -608, + -732, -732, -732, -732, -732, -732, -732, -732, + -1017, -1017, -1017, -1017, -1017, -1017, -1017, -1017, + 681, 681, 681, 681, 681, 681, 681, 681, + 130, 130, 130, 130, 130, 130, 130, 130, + 1602, 1602, 1602, 1602, 1602, 1602, 1602, 1602, + -1458, -1458, -1458, -1458, -1458, -1458, -1458, -1458, + 829, 829, 829, 829, 829, 829, 829, 829, + -383, -383, -383, -383, -383, -383, -383, -383, + -264, -264, -264, -264, -264, -264, -264, -264, + 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, + -573, -573, -573, -573, -573, -573, -573, -573, + // level 3 + -1468, -1468, -1468, -1468, -1468, -1468, -1468, -1468, + -1468, -1468, -1468, -1468, -1468, -1468, -1468, -1468, + 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, + 1474, 1474, 1474, 1474, 1474, 1474, 1474, 1474, + 1202, 1202, 1202, 1202, 1202, 1202, 1202, 1202, + 1202, 1202, 1202, 1202, 1202, 1202, 1202, 1202, + -962, -962, -962, -962, -962, -962, -962, -962, + -962, -962, -962, -962, -962, -962, -962, -962, + -182, -182, -182, -182, -182, -182, -182, -182, + -182, -182, -182, -182, -182, -182, -182, -182, + -1577, -1577, -1577, -1577, -1577, -1577, -1577, -1577, + -1577, -1577, -1577, -1577, -1577, -1577, -1577, -1577, + -622, -622, -622, -622, -622, -622, -622, -622, + -622, -622, -622, -622, -622, -622, -622, -622, + 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, + // level 4 + -202, -202, -202, -202, -202, -202, -202, -202, + -202, -202, -202, -202, -202, -202, -202, -202, + -202, -202, -202, -202, -202, -202, -202, -202, + -202, -202, -202, -202, -202, -202, -202, -202, + -287, -287, -287, -287, -287, -287, -287, -287, + -287, -287, -287, -287, -287, -287, -287, -287, + -287, -287, -287, -287, -287, -287, -287, -287, + -287, -287, -287, -287, -287, -287, -287, -287, + -1422, -1422, -1422, -1422, -1422, -1422, -1422, -1422, + -1422, -1422, -1422, -1422, -1422, -1422, -1422, -1422, + -1422, -1422, -1422, -1422, -1422, -1422, -1422, -1422, + -1422, -1422, -1422, -1422, -1422, -1422, -1422, -1422, + -1493, -1493, -1493, -1493, -1493, -1493, -1493, -1493, + -1493, -1493, -1493, -1493, -1493, -1493, -1493, -1493, + -1493, -1493, -1493, -1493, -1493, -1493, -1493, -1493, + -1493, -1493, -1493, -1493, -1493, -1493, -1493, -1493, + // level 5 + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 1517, 1517, 1517, 1517, 1517, 1517, 1517, 1517, + 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 359, + // level 6 + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758 + }; + private static final int[] MONT_ZETAS_FOR_NTT_MULT = new int[]{ -1003, 1003, 222, -222, -1107, 1107, 172, -172, -42, 42, 620, -620, 1497, -1497, -1649, 1649, @@ -89,6 +352,24 @@ public final class ML_KEM { 1601, -1601, -1599, 1599, -709, 709, -789, 789, -1317, 1317, -57, 57, 1049, -1049, -584, 584 }; + private static final short[] montZetasForVectorNttMultArr = new short[]{ + -1103, 1103, 430, -430, 555, -555, 843, -843, + -1251, 1251, 871, -871, 1550, -1550, 105, -105, + 422, -422, 587, -587, 177, -177, -235, 235, + -291, 291, -460, 460, 1574, -1574, 1653, -1653, + -246, 246, 778, -778, 1159, -1159, -147, 147, + -777, 777, 1483, -1483, -602, 602, 1119, -1119, + -1590, 1590, 644, -644, -872, 872, 349, -349, + 418, -418, 329, -329, -156, 156, -75, 75, + 817, -817, 1097, -1097, 603, -603, 610, -610, + 1322, -1322, -1285, 1285, -1465, 1465, 384, -384, + -1215, 1215, -136, 136, 1218, -1218, -1335, 1335, + -874, 874, 220, -220, -1187, 1187, 1670, 1659, + -1185, 1185, -1530, 1530, -1278, 1278, 794, -794, + -1510, 1510, -854, 854, -870, 870, 478, -478, + -108, 108, -308, 308, 996, -996, 991, -991, + 958, -958, -1460, 1460, 1522, -1522, 1628, -1628 + }; private final int mlKem_k; private final int mlKem_eta1; @@ -261,7 +542,7 @@ public final class ML_KEM { try { mlKemH = MessageDigest.getInstance(HASH_H_NAME); mlKemG = MessageDigest.getInstance(HASH_G_NAME); - } catch (NoSuchAlgorithmException e){ + } catch (NoSuchAlgorithmException e) { // This should never happen. throw new RuntimeException(e); } @@ -527,7 +808,7 @@ public final class ML_KEM { for (int i = 0; i < mlKem_k; i++) { for (int j = 0; j < mlKem_k; j++) { - xofBufArr[parInd] = seedBuf.clone(); + System.arraycopy(seedBuf, 0, xofBufArr[parInd], 0, seedBuf.length); if (transposed) { xofBufArr[parInd][rhoLen] = (byte) i; xofBufArr[parInd][rhoLen + 1] = (byte) j; @@ -707,9 +988,13 @@ public final class ML_KEM { return vector; } - // The elements of poly should be in the range [-ML_KEM_Q, ML_KEM_Q] - // The elements of poly at return will be in the range of [0, ML_KEM_Q] - private void mlKemNTT(short[] poly) { + @IntrinsicCandidate + static int implKyberNtt(short[] poly, short[] ntt_zetas) { + implKyberNttJava(poly); + return 1; + } + + static void implKyberNttJava(short[] poly) { int[] coeffs = new int[ML_KEM_N]; for (int m = 0; m < ML_KEM_N; m++) { coeffs[m] = poly[m]; @@ -718,12 +1003,23 @@ public final class ML_KEM { for (int m = 0; m < ML_KEM_N; m++) { poly[m] = (short) coeffs[m]; } + } + + // The elements of poly should be in the range [-mlKem_q, mlKem_q] + // The elements of poly at return will be in the range of [0, mlKem_q] + private void mlKemNTT(short[] poly) { + assert poly.length == ML_KEM_N; + implKyberNtt(poly, montZetasForVectorNttArr); mlKemBarrettReduce(poly); } - // Works in place, but also returns its (modified) input so that it can - // be used in expressions - private short[] mlKemInverseNTT(short[] poly) { + @IntrinsicCandidate + static int implKyberInverseNtt(short[] poly, short[] zetas) { + implKyberInverseNttJava(poly); + return 1; + } + + static void implKyberInverseNttJava(short[] poly) { int[] coeffs = new int[ML_KEM_N]; for (int m = 0; m < ML_KEM_N; m++) { coeffs[m] = poly[m]; @@ -732,6 +1028,13 @@ public final class ML_KEM { for (int m = 0; m < ML_KEM_N; m++) { poly[m] = (short) coeffs[m]; } + } + + // Works in place, but also returns its (modified) input so that it can + // be used in expressions + private short[] mlKemInverseNTT(short[] poly) { + assert poly.length == ML_KEM_N; + implKyberInverseNtt(poly, montZetasForVectorInverseNttArr); return poly; } @@ -822,11 +1125,16 @@ public final class ML_KEM { return result; } - // Multiplies two polynomials represented in the NTT domain. - // The result is a representation of the product still in the NTT domain. - // The coefficients in the result are in the range (-ML_KEM_Q, ML_KEM_Q). - private void nttMult(short[] result, short[] ntta, short[] nttb) { + @IntrinsicCandidate + static int implKyberNttMult(short[] result, short[] ntta, short[] nttb, + short[] zetas) { + implKyberNttMultJava(result, ntta, nttb); + return 1; + } + + static void implKyberNttMultJava(short[] result, short[] ntta, short[] nttb) { for (int m = 0; m < ML_KEM_N / 2; m++) { + int a0 = ntta[2 * m]; int a1 = ntta[2 * m + 1]; int b0 = nttb[2 * m]; @@ -839,6 +1147,15 @@ public final class ML_KEM { } } + // Multiplies two polynomials represented in the NTT domain. + // The result is a representation of the product still in the NTT domain. + // The coefficients in the result are in the range (-mlKem_q, mlKem_q). + private void nttMult(short[] result, short[] ntta, short[] nttb) { + assert (result.length == ML_KEM_N) && (ntta.length == ML_KEM_N) && + (nttb.length == ML_KEM_N); + implKyberNttMult(result, ntta, nttb, montZetasForVectorNttMultArr); + } + // Adds the vector of polynomials b to a in place, i.e. a will hold // the result. It also returns (the modified) a so that it can be used // in an expression. @@ -853,15 +1170,41 @@ public final class ML_KEM { return a; } + @IntrinsicCandidate + static int implKyberAddPoly(short[] result, short[] a, short[] b) { + implKyberAddPolyJava(result, a, b); + return 1; + } + + static void implKyberAddPolyJava(short[] result, short[] a, short[] b) { + for (int m = 0; m < ML_KEM_N; m++) { + int r = a[m] + b[m] + ML_KEM_Q; // This makes r > - ML_KEM_Q + a[m] = (short) r; + } + mlKemBarrettReduce(a); + } + // Adds the polynomial b to a in place, i.e. (the modified) a will hold // the result. // The coefficients are supposed be greater than -ML_KEM_Q in a and // greater than -ML_KEM_Q and less than ML_KEM_Q in b. // The coefficients in the result are greater than -ML_KEM_Q. - private void mlKemAddPoly(short[] a, short[] b) { + private short[] mlKemAddPoly(short[] a, short[] b) { + assert (a.length == ML_KEM_N) && (b.length == ML_KEM_N); + implKyberAddPoly(a, a, b); + return a; + } + + @IntrinsicCandidate + static int implKyberAddPoly(short[] result, short[] a, short[] b, short[] c) { + implKyberAddPolyJava(result, a, b, c); + return 1; + } + + static void implKyberAddPolyJava(short[] result, short[] a, short[] b, short[] c) { for (int m = 0; m < ML_KEM_N; m++) { - int r = a[m] + b[m] + ML_KEM_Q; // This makes r > -ML_KEM_Q - a[m] = (short) r; + int r = a[m] + b[m] + c[m] + 2 * ML_KEM_Q; // This makes r > - ML_KEM_Q + result[m] = (short) r; } } @@ -871,10 +1214,9 @@ public final class ML_KEM { // greater than -ML_KEM_Q and less than ML_KEM_Q. // The coefficients in the result are nonnegative and less than ML_KEM_Q. private short[] mlKemAddPoly(short[] a, short[] b, short[] c) { - for (int m = 0; m < ML_KEM_N; m++) { - int r = a[m] + b[m] + c[m] + 2 * ML_KEM_Q; // This makes r > - ML_KEM_Q - a[m] = (short) r; - } + assert (a.length == ML_KEM_N) && (b.length == ML_KEM_N) && + (c.length == ML_KEM_N); + implKyberAddPoly(a, a, b, c); mlKemBarrettReduce(a); return a; } @@ -997,15 +1339,13 @@ public final class ML_KEM { return result; } - // The intrinsic implementations assume that the input and output buffers - // are such that condensed can be read in 192-byte chunks and - // parsed can be written in 128 shorts chunks. In other words, - // if (i - 1) * 128 < parsedLengths <= i * 128 then - // parsed.size should be at least i * 128 and - // condensed.size should be at least index + i * 192 - private void twelve2Sixteen(byte[] condensed, int index, - short[] parsed, int parsedLength) { + @IntrinsicCandidate + private static int implKyber12To16(byte[] condensed, int index, short[] parsed, int parsedLength) { + implKyber12To16Java(condensed, index, parsed, parsedLength); + return 1; + } + private static void implKyber12To16Java(byte[] condensed, int index, short[] parsed, int parsedLength) { for (int i = 0; i < parsedLength * 3 / 2; i += 3) { parsed[(i / 3) * 2] = (short) ((condensed[i + index] & 0xff) + 256 * (condensed[i + index + 1] & 0xf)); @@ -1014,6 +1354,25 @@ public final class ML_KEM { } } + // The intrinsic implementations assume that the input and output buffers + // are such that condensed can be read in 96-byte chunks and + // parsed can be written in 64 shorts chunks except for the last chunk + // that can be either 48 or 64 shorts. In other words, + // if (i - 1) * 64 < parsedLengths <= i * 64 then + // parsed.length should be either i * 64 or (i-1) * 64 + 48 and + // condensed.length should be at least index + i * 96. + private void twelve2Sixteen(byte[] condensed, int index, + short[] parsed, int parsedLength) { + int i = parsedLength / 64; + int remainder = parsedLength - i * 64; + if (remainder != 0) { + i++; + } + assert ((remainder == 0) || (remainder == 48)) && + (index + i * 96 <= condensed.length); + implKyber12To16(condensed, index, parsed, parsedLength); + } + private static void decodePoly5(byte[] condensed, int index, short[] parsed) { int j = index; for (int i = 0; i < ML_KEM_N; i += 8) { @@ -1152,6 +1511,19 @@ public final class ML_KEM { return result; } + @IntrinsicCandidate + static int implKyberBarrettReduce(short[] coeffs) { + implKyberBarrettReduceJava(coeffs); + return 1; + } + + static void implKyberBarrettReduceJava(short[] poly) { + for (int m = 0; m < ML_KEM_N; m++) { + int tmp = ((int) poly[m] * BARRETT_MULTIPLIER) >> BARRETT_SHIFT; + poly[m] = (short) (poly[m] - tmp * ML_KEM_Q); + } + } + // The input elements can have any short value. // Modifies poly such that upon return poly[i] will be // in the range [0, ML_KEM_Q] and will be congruent with the original @@ -1161,11 +1533,9 @@ public final class ML_KEM { // That means that if the original poly[i] > -ML_KEM_Q then at return it // will be in the range [0, ML_KEM_Q), i.e. it will be the canonical // representative of its residue class. - private void mlKemBarrettReduce(short[] poly) { - for (int m = 0; m < ML_KEM_N; m++) { - int tmp = ((int) poly[m] * BARRETT_MULTIPLIER) >> BARRETT_SHIFT; - poly[m] = (short) (poly[m] - tmp * ML_KEM_Q); - } + private static void mlKemBarrettReduce(short[] poly) { + assert poly.length == ML_KEM_N; + implKyberBarrettReduce(poly); } // Precondition: -(2^MONT_R_BITS -1) * MONT_Q <= b * c < (2^MONT_R_BITS - 1) * MONT_Q diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA.java b/src/java.base/share/classes/sun/security/provider/ML_DSA.java index 238b5e9d46a..ff25eb527ef 100644 --- a/src/java.base/share/classes/sun/security/provider/ML_DSA.java +++ b/src/java.base/share/classes/sun/security/provider/ML_DSA.java @@ -1554,7 +1554,7 @@ public class ML_DSA { // precondition: -2^31 * MONT_Q <= a, b < 2^31, -2^31 < a * b < 2^31 * MONT_Q // computes a * b * 2^-32 mod MONT_Q // the result is greater than -MONT_Q and less than MONT_Q - // see e.g. Algorithm 3 in https://eprint.iacr.org/2018/039.pdf + // See e.g. Algorithm 3 in https://eprint.iacr.org/2018/039.pdf private static int montMul(int b, int c) { long a = (long) b * (long) c; int aHigh = (int) (a >> MONT_R_BITS); From c3de94cee12471a11c457c11dd55c547633de5cb Mon Sep 17 00:00:00 2001 From: KIRIYAMA Takuya Date: Wed, 16 Apr 2025 15:42:40 +0000 Subject: [PATCH 208/843] 8352942: jdk/jfr/startupargs/TestMemoryOptions.java fails with 32-bit build Reviewed-by: phh --- test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java b/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java index 6827c663ee3..100b0d74a07 100644 --- a/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java +++ b/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java @@ -485,6 +485,7 @@ public class TestMemoryOptions { if (flightRecorderOptions != null) { pb = ProcessTools.createTestJavaProcessBuilder("--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + "-Xmx256m", flightRecorderOptions, "-XX:StartFlightRecording", SUT.class.getName(), @@ -493,6 +494,7 @@ public class TestMemoryOptions { // default, no FlightRecorderOptions passed pb = ProcessTools.createTestJavaProcessBuilder("--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", + "-Xmx256m", "-XX:StartFlightRecording", SUT.class.getName(), tc.getTestName()); From 84458ec18ce33295636f7b26b8e3ff25ecb349f2 Mon Sep 17 00:00:00 2001 From: Rohitash Kumar Date: Wed, 16 Apr 2025 16:08:31 +0000 Subject: [PATCH 209/843] 8353013: java.net.URI.create(String) may have low performance to scan the host/domain name from URI string when the hostname starts with number Reviewed-by: michaelm, xpeng --- src/java.base/share/classes/java/net/URI.java | 15 ++++- test/jdk/java/net/URI/Test.java | 38 +++++++++++- .../net/URIAuthorityParsingBenchmark.java | 62 +++++++++++++++++++ 3 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/net/URIAuthorityParsingBenchmark.java diff --git a/src/java.base/share/classes/java/net/URI.java b/src/java.base/share/classes/java/net/URI.java index 2e6f2409bf4..cd116f3877b 100644 --- a/src/java.base/share/classes/java/net/URI.java +++ b/src/java.base/share/classes/java/net/URI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3426,6 +3426,19 @@ public final class URI int p = start; int q = scan(p, n, L_DIGIT, H_DIGIT); if (q <= p) return q; + + // Handle leading zeros + int i = p, j; + while ((j = scan(i, q, '0')) > i) i = j; + + // Calculate the number of significant digits (after leading zeros) + int significantDigitsNum = q - i; + + if (significantDigitsNum < 3) return q; // definitely < 255 + + // If more than 3 significant digits, it's definitely > 255 + if (significantDigitsNum > 3) return p; + if (Integer.parseInt(input, p, q, 10) > 255) return p; return q; } diff --git a/test/jdk/java/net/URI/Test.java b/test/jdk/java/net/URI/Test.java index 00d473f87be..95dd49ea34f 100644 --- a/test/jdk/java/net/URI/Test.java +++ b/test/jdk/java/net/URI/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* @test * @summary Unit test for java.net.URI * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800 - * 7171415 6339649 6933879 8037396 8272072 8051627 8297687 + * 7171415 6339649 6933879 8037396 8272072 8051627 8297687 8353013 * @author Mark Reinhold */ @@ -1620,6 +1620,7 @@ public class Test { b8051627(); b8272072(); b8297687(); + b8353013(); } private static void b8297687() { @@ -1786,6 +1787,39 @@ public class Test { } } + // 8353013 - Increase test coverage for cases where the authority component of a hierarchical + // URI has a host component that starts with a number. + private static void b8353013() { + testCreate("https://0.0.0.1").s("https").h("0.0.0.1").p("").z(); + testCreate("https://00.0.0.2").s("https").h("00.0.0.2").p("").z(); + testCreate("https://000.0.0.3").s("https").h("000.0.0.3").p("").z(); + testCreate("https://0000.0.0.4").s("https").h("0000.0.0.4").p("").z(); + + testCreate("https://00000.0.0.5").s("https").h("00000.0.0.5").p("").z(); + testCreate("https://00001.0.0.6").s("https").h("00001.0.0.6").p("").z(); + + testCreate("https://01.0.0.1").s("https").h("01.0.0.1").p("").z(); + + testCreate("https://111111.2.3.com").s("https").h("111111.2.3.com").p("").z(); + + testCreate("https://1.example.com").s("https").h("1.example.com").p("").z(); + testCreate("https://12.example.com").s("https").h("12.example.com").p("").z(); + testCreate("https://123.example.com").s("https").h("123.example.com").p("").z(); + testCreate("https://1234.example.com").s("https").h("1234.example.com").p("").z(); + testCreate("https://12345.example.com").s("https").h("12345.example.com").p("").z(); + + testCreate("https://98765432101.example.com").s("https").h("98765432101.example.com").p("").z(); + testCreate("https://98765432101.www.example.com/").s("https").h("98765432101.www.example.com").p("/").z(); + testCreate("https://98765432101.www.example.com").s("https").h("98765432101.www.example.com").p("").z(); + + testCreate("https://9223372036854775808.example.com").s("https").h("9223372036854775808.example.com").p("").z(); + testCreate("https://9223372036854775808.www.example.com").s("https").h("9223372036854775808.www.example.com").p("").z(); + testCreate("https://9223372036854775808.xyz.abc.com").s("https").h("9223372036854775808.xyz.abc.com").p("").z(); + testCreate("https://9223372036854775808.xyz.abc.pqr.com").s("https").h("9223372036854775808.xyz.abc.pqr.com").p("").z(); + + testCreate("https://256.example.com").s("https").h("256.example.com").p("").z(); + } + public static void main(String[] args) throws Exception { switch (args.length) { diff --git a/test/micro/org/openjdk/bench/java/net/URIAuthorityParsingBenchmark.java b/test/micro/org/openjdk/bench/java/net/URIAuthorityParsingBenchmark.java new file mode 100644 index 00000000000..8e75b9e35ac --- /dev/null +++ b/test/micro/org/openjdk/bench/java/net/URIAuthorityParsingBenchmark.java @@ -0,0 +1,62 @@ +/* + * 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. + */ +package org.openjdk.bench.java.net; + +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.net.URI; +import java.util.concurrent.TimeUnit; + +/** + * Tests Java.net.URI.create performance on various URI types. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 3) +public class URIAuthorityParsingBenchmark { + + @Param({ + "https://98765432101.abc.xyz.com", + "https://ABCDEFGHIJK.abc.xyz.com" + }) + private String uri; + + @Benchmark + public void create(Blackhole blackhole) { + blackhole.consume(URI.create(uri)); + } + +} From 7a107e2fc4b0ea5c6d82fd047a631aff37bf3e74 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Wed, 16 Apr 2025 16:28:12 +0000 Subject: [PATCH 210/843] 8351603: Change to GCC 14.2.0 for building on Linux at Oracle 8344272: gcc devkit doesn't have lto-plugin where needed Reviewed-by: ihse, erikj --- doc/building.html | 4 ++-- doc/building.md | 4 ++-- make/conf/jib-profiles.js | 10 +++++----- make/devkit/Tools.gmk | 42 +++++++++++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/doc/building.html b/doc/building.html index 7157848f561..95cda58e828 100644 --- a/doc/building.html +++ b/doc/building.html @@ -586,7 +586,7 @@ to compile successfully without issues.

Linux -gcc 13.2.0 +gcc 14.2.0 macOS @@ -604,7 +604,7 @@ standard for C, and C++14 for C++.

The minimum accepted version of gcc is 10.0. Older versions will not be accepted by configure.

The JDK is currently known to compile successfully with gcc version -13.2 or newer.

+14.2 or newer.

In general, any version between these two should be usable.

clang

The minimum accepted version of clang is 13. Older versions will not diff --git a/doc/building.md b/doc/building.md index 04db6e94d1c..914473916b4 100644 --- a/doc/building.md +++ b/doc/building.md @@ -392,7 +392,7 @@ issues. | Operating system | Toolchain version | | ------------------ | ------------------------------------------- | -| Linux | gcc 13.2.0 | +| Linux | gcc 14.2.0 | | macOS | Apple Xcode 14.3.1 (using clang 14.0.3) | | Windows | Microsoft Visual Studio 2022 version 17.6.5 | @@ -404,7 +404,7 @@ C, and C++14 for C++. The minimum accepted version of gcc is 10.0. Older versions will not be accepted by `configure`. -The JDK is currently known to compile successfully with gcc version 13.2 or +The JDK is currently known to compile successfully with gcc version 14.2 or newer. In general, any version between these two should be usable. diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 02474f3dccb..aa4d846280e 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1088,14 +1088,14 @@ var getJibProfilesProfiles = function (input, common, data) { var getJibProfilesDependencies = function (input, common) { var devkit_platform_revisions = { - linux_x64: "gcc13.2.0-OL6.4+1.0", + linux_x64: "gcc14.2.0-OL6.4+1.0", macosx: "Xcode14.3.1+1.0", windows_x64: "VS2022-17.6.5+1.0", - linux_aarch64: "gcc13.2.0-OL7.6+1.0", + linux_aarch64: "gcc14.2.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", - linux_ppc64le: "gcc13.2.0-Fedora_41+1.0", - linux_s390x: "gcc13.2.0-Fedora_41+1.0", - linux_riscv64: "gcc13.2.0-Fedora_41+1.0" + linux_ppc64le: "gcc14.2.0-Fedora_41+1.0", + linux_s390x: "gcc14.2.0-Fedora_41+1.0", + linux_riscv64: "gcc14.2.0-Fedora_41+1.0" }; var devkit_platform = (input.target_cpu == "x86" diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 249eaa66247..f4323f58638 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -92,8 +92,18 @@ endif # Define external dependencies # Latest that could be made to work. -GCC_VER := 13.2.0 -ifeq ($(GCC_VER), 13.2.0) +GCC_VER := 14.2.0 +ifeq ($(GCC_VER), 14.2.0) + gcc_ver := gcc-14.2.0 + binutils_ver := binutils-2.43 + ccache_ver := ccache-4.10.2 + CCACHE_CMAKE_BASED := 1 + mpfr_ver := mpfr-4.2.1 + gmp_ver := gmp-6.3.0 + mpc_ver := mpc-1.3.1 + gdb_ver := gdb-15.2 + REQUIRED_MIN_MAKE_MAJOR_VERSION := 4 +else ifeq ($(GCC_VER), 13.2.0) gcc_ver := gcc-13.2.0 binutils_ver := binutils-2.41 ccache_ver := ccache-3.7.12 @@ -262,10 +272,18 @@ define Download # Allow override $(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1))))) $(1)_DIR = $(abspath $(SRCDIR)/$$($(1)_DIRNAME)) - $(1)_CFG = $$($(1)_DIR)/configure + ifeq ($$($(1)_CMAKE_BASED),) + $(1)_CFG = $$($(1)_DIR)/configure + $(1)_SRC_MARKER = $$($(1)_DIR)/configure + $(1)_CONFIG = $(CONFIG) + else + $(1)_CFG = cmake + $(1)_SRC_MARKER = $$($(1)_DIR)/CMakeLists.txt + $(1)_CONFIG = $$(CMAKE_CONFIG) $$($(1)_DIR) + endif $(1)_FILE = $(DOWNLOAD)/$(notdir $($(1))) - $$($(1)_CFG) : $$($(1)_FILE) + $$($(1)_SRC_MARKER) : $$($(1)_FILE) mkdir -p $$(SRCDIR) tar -C $$(SRCDIR) -xf $$< $$(foreach p,$$(abspath $$(wildcard patches/$$(ARCH)-$$(notdir $$($(1)_DIR)).patch)), \ @@ -365,6 +383,8 @@ CONFIG = --target=$(TARGET) \ --host=$(HOST) --build=$(BUILD) \ --prefix=$(PREFIX) +CMAKE_CONFIG = -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$(PREFIX) + PATHEXT = $(PREFIX)/bin: PATHPRE = PATH=$(PATHEXT)$(PATH) @@ -576,6 +596,8 @@ ifeq ($(HOST), $(TARGET)) $(PATHPRE) $(ENVS) CFLAGS="$(CFLAGS)" $(GDB_CFG) \ $(CONFIG) \ --with-sysroot=$(SYSROOT) \ + --with-mpfr=$(PREFIX) \ + --with-gmp=$(PREFIX) \ ) > $(@D)/log.config 2>&1 @echo 'done' @@ -591,13 +613,13 @@ endif ################################################################################ # very straightforward. just build a ccache. it is only for host. $(BUILDDIR)/$(ccache_ver)/Makefile \ - : $(CCACHE_CFG) + : $(CCACHE_SRC_MARKER) $(info Configuring $@. Log in $(@D)/log.config) @mkdir -p $(@D) @( \ cd $(@D) ; \ $(PATHPRE) $(ENVS) $(CCACHE_CFG) \ - $(CONFIG) \ + $(CCACHE_CONFIG) \ ) > $(@D)/log.config 2>&1 @echo 'done' @@ -703,6 +725,14 @@ ifeq ($(TARGET), $(HOST)) ld.gold nm objcopy objdump ranlib readelf size strings strip) endif +# Add link to work around "plugin needed to handle lto object" (JDK-8344272) +$(PREFIX)/lib/bfd-plugins/liblto_plugin.so: $(PREFIX)/libexec/gcc/$(TARGET)/$(GCC_VER)/liblto_plugin.so + @echo 'Creating missing $(@F) soft link' + @mkdir -p $(@D) + ln -s $$(realpath -s --relative-to=$(@D) $<) $@ + +missing-links += $(PREFIX)/lib/bfd-plugins/liblto_plugin.so + ################################################################################ bfdlib : $(bfdlib) From d80db00f8221b95ab767bb84d06b83a83ba4cd4c Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Wed, 16 Apr 2025 17:19:47 +0000 Subject: [PATCH 211/843] 8354873: javax/swing/plaf/metal/MetalIconFactory/bug4952462.java failing on CI Reviewed-by: honkar --- .../metal/MetalIconFactory/bug4952462.java | 64 ++++++++----------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java index f3562108314..65c5c510fc3 100644 --- a/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java +++ b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java @@ -29,7 +29,7 @@ * @modules java.desktop/sun.awt * @library /test/lib * @key headful - * @run main bug4952462 + * @run main/othervm -Dsun.java2d.uiScale=1 bug4952462 */ import java.awt.Color; @@ -41,10 +41,8 @@ import javax.swing.JFrame; import javax.swing.JRadioButton; import javax.swing.SwingUtilities; import javax.swing.UIManager; -import javax.swing.plaf.metal.MetalTheme; - -import jtreg.SkippedException; -import sun.awt.AppContext; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.OceanTheme; public class bug4952462 { private static JFrame frame; @@ -52,41 +50,35 @@ public class bug4952462 { public static void main(String[] args) throws Exception { try { + MetalLookAndFeel.setCurrentTheme(new OceanTheme()); UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + Robot r = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Metal JRadioButton Foreground Color Test"); + frame.getContentPane().setLayout(new FlowLayout()); + rb = new JRadioButton("RadioButton", true); + rb.setEnabled(false); + rb.setForeground(Color.RED); + frame.getContentPane().add(rb); + frame.setSize(250, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); - MetalTheme theme = (MetalTheme) AppContext.getAppContext().get("currentMetalTheme"); - if (theme == null || !"Ocean".equals(theme.getName())) { - throw new SkippedException("Current theme is not Ocean. Test is " + - "only for Metal's Ocean theme. Skipping test."); - } else { - Robot r = new Robot(); - SwingUtilities.invokeAndWait(() -> { - frame = new JFrame("Metal JRadioButton Foreground Color Test"); - frame.getContentPane().setLayout(new FlowLayout()); - rb = new JRadioButton("RadioButton", true); - rb.setEnabled(false); - rb.setForeground(Color.RED); - frame.getContentPane().add(rb); - frame.setSize(250, 100); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - }); + r.waitForIdle(); + r.delay(500); - r.waitForIdle(); - r.delay(500); - - SwingUtilities.invokeAndWait(() -> { - Point p = rb.getLocationOnScreen(); - for (int i = 0; i < 50; i++) { - Color c = r.getPixelColor(p.x + 10 + i, p.y + (rb.getHeight() / 2)); - System.out.println(c); - if (c.getRed() > 200 && c.getBlue() < 200 && c.getGreen() < 200) { - throw new RuntimeException("Test failed. Radiobutton is red " + - "and not grey."); - } + SwingUtilities.invokeAndWait(() -> { + Point p = rb.getLocationOnScreen(); + for (int i = 0; i < 50; i++) { + Color c = r.getPixelColor(p.x + 10 + i, p.y + (rb.getHeight() / 2)); + System.out.println(c); + if (c.getRed() > 200 && c.getBlue() < 80 && c.getGreen() < 80) { + throw new RuntimeException("Test failed. Radiobutton is red " + + "and not grey."); } - }); - } + } + }); } finally { SwingUtilities.invokeAndWait(() -> { if (frame != null) { From e433fa2719917cff6cb373e9a60981a7418e2f4f Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 16 Apr 2025 17:52:53 +0000 Subject: [PATCH 212/843] 8352001: AOT cache should not contain classes injected into built-in class loaders Reviewed-by: ccheung, matsaave --- src/hotspot/share/cds/aotClassLocation.cpp | 31 ++++ src/hotspot/share/cds/aotClassLocation.hpp | 5 + src/hotspot/share/classfile/classLoader.cpp | 14 ++ src/hotspot/share/classfile/classLoader.hpp | 1 + .../share/classfile/classLoaderExt.cpp | 10 +- .../share/classfile/classLoaderExt.hpp | 2 +- src/hotspot/share/utilities/zipLibrary.cpp | 9 + src/hotspot/share/utilities/zipLibrary.hpp | 3 +- src/java.base/share/native/libzip/zip_util.c | 4 +- src/java.base/share/native/libzip/zip_util.h | 4 +- .../aotClassLinking/FakeCodeLocation.java | 170 ++++++++++++++++++ 11 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java diff --git a/src/hotspot/share/cds/aotClassLocation.cpp b/src/hotspot/share/cds/aotClassLocation.cpp index 656d7551b03..8471d04b572 100644 --- a/src/hotspot/share/cds/aotClassLocation.cpp +++ b/src/hotspot/share/cds/aotClassLocation.cpp @@ -47,6 +47,7 @@ #include #include +Array* AOTClassLocationConfig::_dumptime_jar_files = nullptr; AOTClassLocationConfig* AOTClassLocationConfig::_dumptime_instance = nullptr; const AOTClassLocationConfig* AOTClassLocationConfig::_runtime_instance = nullptr; @@ -479,6 +480,13 @@ void AOTClassLocationConfig::dumptime_init_helper(TRAPS) { _class_locations->at_put(i, tmp_array.at(i)); } + _dumptime_jar_files = MetadataFactory::new_array(ClassLoaderData::the_null_class_loader_data(), + tmp_array.length(), CHECK); + for (int i = 1; i < tmp_array.length(); i++) { + ClassPathZipEntry* jar_file = ClassLoader::create_class_path_zip_entry(tmp_array.at(i)->path()); + _dumptime_jar_files->at_put(i, jar_file); // may be null if the path is not a valid JAR file + } + const char* lcp = find_lcp(all_css.boot_and_app_cp(), _dumptime_lcp_len); if (_dumptime_lcp_len > 0) { os::free((void*)lcp); @@ -693,6 +701,29 @@ void AOTClassLocationConfig::check_nonempty_dirs() const { } } +// It's possible to use reflection+setAccessible to call into ClassLoader::defineClass() to +// pretend that a dynamically generated class comes from a JAR file in the classpath. +// Detect such classes so that they can be excluded from the archive. +bool AOTClassLocationConfig::is_valid_classpath_index(int classpath_index, InstanceKlass* ik) { + if (1 <= classpath_index && classpath_index < length()) { + ClassPathZipEntry *zip = _dumptime_jar_files->at(classpath_index); + if (zip != nullptr) { + JavaThread* current = JavaThread::current(); + ResourceMark rm(current); + const char* const class_name = ik->name()->as_C_string(); + const char* const file_name = ClassLoader::file_name_for_class_name(class_name, + ik->name()->utf8_length()); + if (!zip->has_entry(current, file_name)) { + log_warning(cds)("class %s cannot be archived because it was not defined from %s as claimed", + class_name, zip->name()); + return false; + } + } + } + + return true; +} + AOTClassLocationConfig* AOTClassLocationConfig::write_to_archive() const { Array* archived_copy = ArchiveBuilder::new_ro_array(_class_locations->length()); for (int i = 0; i < _class_locations->length(); i++) { diff --git a/src/hotspot/share/cds/aotClassLocation.hpp b/src/hotspot/share/cds/aotClassLocation.hpp index cb53e9c96e9..47f4dc86c98 100644 --- a/src/hotspot/share/cds/aotClassLocation.hpp +++ b/src/hotspot/share/cds/aotClassLocation.hpp @@ -34,6 +34,7 @@ class AllClassLocationStreams; class ClassLocationStream; +class ClassPathZipEntry; class LogStream; // An AOTClassLocation is a location where the application is configured to load Java classes @@ -139,6 +140,8 @@ class AOTClassLocationConfig : public CHeapObj { static const AOTClassLocationConfig* _runtime_instance; Array* _class_locations; // jrt -> -Xbootclasspath/a -> -classpath -> --module_path + static Array* _dumptime_jar_files; + int _boot_classpath_end; int _app_classpath_end; int _module_end; @@ -263,6 +266,8 @@ public: // Functions used only during runtime bool validate(bool has_aot_linked_classes, bool* has_extra_module_paths) const; + + bool is_valid_classpath_index(int classpath_index, InstanceKlass* ik); }; diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 3ca1ec237e8..a7d6cc39614 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -305,6 +305,20 @@ ClassPathZipEntry::~ClassPathZipEntry() { FREE_C_HEAP_ARRAY(char, _zip_name); } +bool ClassPathZipEntry::has_entry(JavaThread* current, const char* name) { + ThreadToNativeFromVM ttn(current); + // check whether zip archive contains name + jint name_len; + jint filesize; + jzentry* entry = ZipLibrary::find_entry(_zip, name, &filesize, &name_len); + if (entry == nullptr) { + return false; + } else { + ZipLibrary::free_entry(_zip, entry); + return true; + } +} + u1* ClassPathZipEntry::open_entry(JavaThread* current, const char* name, jint* filesize, bool nul_terminate) { // enable call to C land ThreadToNativeFromVM ttn(current); diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 7827b6066e5..d762e6caca7 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -93,6 +93,7 @@ class ClassPathZipEntry: public ClassPathEntry { const char* name() const { return _zip_name; } ClassPathZipEntry(jzfile* zip, const char* zip_name); virtual ~ClassPathZipEntry(); + bool has_entry(JavaThread* current, const char* name); u1* open_entry(JavaThread* current, const char* name, jint* filesize, bool nul_terminate); ClassFileStream* open_stream(JavaThread* current, const char* name); }; diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp index 3a6fd0d933c..fb635133537 100644 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ b/src/hotspot/share/classfile/classLoaderExt.cpp @@ -67,7 +67,7 @@ int ClassLoaderExt::compare_module_names(const char** p1, const char** p2) { return strcmp(*p1, *p2); } -void ClassLoaderExt::record_result(const s2 classpath_index, InstanceKlass* result, bool redefined) { +void ClassLoaderExt::record_result(s2 classpath_index, InstanceKlass* result, bool redefined) { assert(CDSConfig::is_dumping_archive(), "sanity"); // We need to remember where the class comes from during dumping. @@ -80,9 +80,17 @@ void ClassLoaderExt::record_result(const s2 classpath_index, InstanceKlass* resu classloader_type = ClassLoader::PLATFORM_LOADER; AOTClassLocationConfig::dumptime_set_has_platform_classes(); } + + if (CDSConfig::is_dumping_preimage_static_archive() || CDSConfig::is_dumping_dynamic_archive()) { + if (!AOTClassLocationConfig::dumptime()->is_valid_classpath_index(classpath_index, result)) { + classpath_index = -1; + } + } + AOTClassLocationConfig::dumptime_update_max_used_index(classpath_index); result->set_shared_classpath_index(classpath_index); result->set_shared_class_loader_type(classloader_type); + #if INCLUDE_CDS_JAVA_HEAP if (CDSConfig::is_dumping_heap() && AllowArchivingWithJavaAgent && classloader_type == ClassLoader::BOOT_LOADER && classpath_index < 0 && redefined) { diff --git a/src/hotspot/share/classfile/classLoaderExt.hpp b/src/hotspot/share/classfile/classLoaderExt.hpp index 86bd5cce7ba..f4a1cf1a9c7 100644 --- a/src/hotspot/share/classfile/classLoaderExt.hpp +++ b/src/hotspot/share/classfile/classLoaderExt.hpp @@ -40,7 +40,7 @@ public: static void append_boot_classpath(ClassPathEntry* new_entry); static int compare_module_names(const char** p1, const char** p2); - static void record_result(const s2 classpath_index, InstanceKlass* result, bool redefined); + static void record_result(s2 classpath_index, InstanceKlass* result, bool redefined); #endif // INCLUDE_CDS }; diff --git a/src/hotspot/share/utilities/zipLibrary.cpp b/src/hotspot/share/utilities/zipLibrary.cpp index f56e311ec2e..ae68fb9ef77 100644 --- a/src/hotspot/share/utilities/zipLibrary.cpp +++ b/src/hotspot/share/utilities/zipLibrary.cpp @@ -35,6 +35,7 @@ typedef void**(*ZIP_Open_t)(const char* name, char** pmsg); typedef void(*ZIP_Close_t)(jzfile* zip); typedef jzentry* (*ZIP_FindEntry_t)(jzfile* zip, const char* name, jint* sizeP, jint* nameLen); typedef jboolean(*ZIP_ReadEntry_t)(jzfile* zip, jzentry* entry, unsigned char* buf, char* namebuf); +typedef void(*ZIP_FreeEntry_t)(jzfile *zip, jzentry *entry); typedef jint(*ZIP_CRC32_t)(jint crc, const jbyte* buf, jint len); typedef const char* (*ZIP_GZip_InitParams_t)(size_t, size_t*, size_t*, int); typedef size_t(*ZIP_GZip_Fully_t)(char*, size_t, char*, size_t, char*, size_t, int, char*, char const**); @@ -43,6 +44,7 @@ static ZIP_Open_t ZIP_Open = nullptr; static ZIP_Close_t ZIP_Close = nullptr; static ZIP_FindEntry_t ZIP_FindEntry = nullptr; static ZIP_ReadEntry_t ZIP_ReadEntry = nullptr; +static ZIP_FreeEntry_t ZIP_FreeEntry = nullptr; static ZIP_CRC32_t ZIP_CRC32 = nullptr; static ZIP_GZip_InitParams_t ZIP_GZip_InitParams = nullptr; static ZIP_GZip_Fully_t ZIP_GZip_Fully = nullptr; @@ -79,6 +81,7 @@ static void store_function_pointers(const char* path, bool vm_exit_on_failure) { ZIP_Close = CAST_TO_FN_PTR(ZIP_Close_t, dll_lookup("ZIP_Close", path, vm_exit_on_failure)); ZIP_FindEntry = CAST_TO_FN_PTR(ZIP_FindEntry_t, dll_lookup("ZIP_FindEntry", path, vm_exit_on_failure)); ZIP_ReadEntry = CAST_TO_FN_PTR(ZIP_ReadEntry_t, dll_lookup("ZIP_ReadEntry", path, vm_exit_on_failure)); + ZIP_FreeEntry = CAST_TO_FN_PTR(ZIP_FreeEntry_t, dll_lookup("ZIP_FreeEntry", path, vm_exit_on_failure)); ZIP_CRC32 = CAST_TO_FN_PTR(ZIP_CRC32_t, dll_lookup("ZIP_CRC32", path, vm_exit_on_failure)); // The following entry points are most likely optional from a zip library implementation perspective. // Hence no vm_exit on a resolution failure. Further refactorings should investigate this, @@ -176,6 +179,12 @@ jboolean ZipLibrary::read_entry(jzfile* zip, jzentry* entry, unsigned char* buf, return ZIP_ReadEntry(zip, entry, buf, namebuf); } +void ZipLibrary::free_entry(jzfile* zip, jzentry* entry) { + initialize(); + assert(ZIP_FreeEntry != nullptr, "invariant"); + ZIP_FreeEntry(zip, entry); +} + jint ZipLibrary::crc32(jint crc, const jbyte* buf, jint len) { initialize(); assert(ZIP_CRC32 != nullptr, "invariant"); diff --git a/src/hotspot/share/utilities/zipLibrary.hpp b/src/hotspot/share/utilities/zipLibrary.hpp index 73745aca2e2..90f55c24c19 100644 --- a/src/hotspot/share/utilities/zipLibrary.hpp +++ b/src/hotspot/share/utilities/zipLibrary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ class ZipLibrary : AllStatic { static void close(jzfile* zip); static jzentry* find_entry(jzfile* zip, const char* name, jint* sizeP, jint* nameLen); static jboolean read_entry(jzfile* zip, jzentry* entry, unsigned char* buf, char* namebuf); + static void free_entry(jzfile* zip, jzentry* entry); static jint crc32(jint crc, const jbyte* buf, jint len); static const char* init_params(size_t block_size, size_t* needed_out_size, size_t* needed_tmp_size, int level); static size_t compress(char* in, size_t in_size, char* out, size_t out_size, char* tmp, size_t tmp_size, int level, char* buf, const char** pmsg); diff --git a/src/java.base/share/native/libzip/zip_util.c b/src/java.base/share/native/libzip/zip_util.c index c327d337659..86223f22a43 100644 --- a/src/java.base/share/native/libzip/zip_util.c +++ b/src/java.base/share/native/libzip/zip_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1116,7 +1116,7 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint) * jzentry for each zip. This optimizes a common access pattern. */ -void +JNIEXPORT void ZIP_FreeEntry(jzfile *jz, jzentry *ze) { jzentry *last; diff --git a/src/java.base/share/native/libzip/zip_util.h b/src/java.base/share/native/libzip/zip_util.h index eef52b38b05..9825202fc7b 100644 --- a/src/java.base/share/native/libzip/zip_util.h +++ b/src/java.base/share/native/libzip/zip_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -276,7 +276,7 @@ void ZIP_Unlock(jzfile *zip); jint ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len); -void +JNIEXPORT void ZIP_FreeEntry(jzfile *zip, jzentry *ze); jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry); jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java new file mode 100644 index 00000000000..5bec6623a08 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/FakeCodeLocation.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test Do not cache classes that are loaded from a fake location. + * @bug 8352001 + * @requires vm.cds.supports.aot.class.linking + * @comment work around JDK-8345635 + * @requires !vm.jvmci.enabled + * @library /test/jdk/lib/testlibrary /test/lib + * @build FakeCodeLocation + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar FakeCodeLocationApp + * @run driver jdk.test.lib.helpers.ClassFileInstaller ClassNotInJar1 ClassNotInJar2 + * @run driver FakeCodeLocation + */ + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.InaccessibleObjectException; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.ProtectionDomain; + +import jdk.test.lib.cds.CDSAppTester; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.StringArrayUtils; + +public class FakeCodeLocation { + static final String appJar = "app.jar"; + static final String mainClass = FakeCodeLocationApp.class.getName(); + + public static void main(String[] args) throws Exception { + (new Tester(false)).run(new String[] {"STATIC"}); + (new Tester(true )).run(new String[] {"STATIC"}); + (new Tester(false)).run(new String[] {"AOT"}); + (new Tester(true )).run(new String[] {"AOT"}); + } + + static class Tester extends CDSAppTester { + boolean addOpen;; + public Tester(boolean addOpen) { + super(mainClass); + this.addOpen = addOpen; + } + + @Override + public String classpath(RunMode runMode) { + return appJar; + } + + @Override + public String[] vmArgs(RunMode runMode) { + String[] args = new String[] { + "-Xlog:cds", + "-Xlog:cds+class=debug", + "-Xlog:class+load", + }; + if (addOpen) { + args = StringArrayUtils.concat(args, "--add-opens", "java.base/java.lang=ALL-UNNAMED", "-XX:-AOTClassLinking"); + } + return args; + } + + @Override + public String[] appCommandLine(RunMode runMode) { + return new String[] { + mainClass, + addOpen ? "hasAddedOpen" : "hasNotAddedOpen", + }; + } + + @Override + public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception { + if (isDumping(runMode)) { + out.shouldMatch("cds,class.* FakeCodeLocationApp"); + out.shouldNotMatch("cds,class.* ClassNotInJar1"); + out.shouldNotMatch("cds,class.* ClassNotInJar2"); + } + + if (runMode.isProductionRun()) { + out.shouldMatch("class,load.* FakeCodeLocationApp .*source: shared objects file"); + out.shouldNotMatch("class,load.* ClassNotInJar1 .*source: shared objects file"); + out.shouldNotMatch("class,load.* ClassNotInJar2 .*source: shared objects file"); + } + } + } +} + +class FakeCodeLocationApp { + static boolean hasAddedOpen; + + public static void main(String args[]) throws Exception { + hasAddedOpen = args[0].equals("hasAddedOpen"); + testWithLookup(); + testWithSetAccessible(); + } + + // Define a class using Lookup.defineClass(). The ClassFileParser should see "__JVM_DefineClass__" + // as the source location, so this class will be excluded, as the location is not supported. + static void testWithLookup() throws Exception { + byte[] data = Files.readAllBytes(Paths.get("ClassNotInJar1.class")); + Class c = MethodHandles.lookup().defineClass(data); + System.out.println(c.getProtectionDomain()); + System.out.println(c.getProtectionDomain().getCodeSource()); + } + + // Use setAccessible to call into ClassLoader.defineClass(). In this case, the ClassFileParser + // sees "app.jar" as the source location, but the app.jar doesn't contain this class file, so we + // should exclude this class. + static void testWithSetAccessible() throws Exception { + Method m = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class); + System.out.println(m); + try { + m.setAccessible(true); + if (!hasAddedOpen) { + throw new RuntimeException("setAccessible() should have failed because '--add-opens java.base/java.lang=ALL-UNNAMED' was not specified"); + } + } catch (InaccessibleObjectException t) { + if (hasAddedOpen) { + throw new RuntimeException("setAccessible() failed even though '--add-opens java.base/java.lang=ALL-UNNAMED' was specified"); + } else { + System.out.println("\n\nExpected: " + t); + t.printStackTrace(System.out); + return; + } + } + + ProtectionDomain pd = FakeCodeLocationApp.class.getProtectionDomain(); + ClassLoader appLoader = FakeCodeLocationApp.class.getClassLoader(); + byte[] data = Files.readAllBytes(Paths.get("ClassNotInJar2.class")); + Class c = null; + try { + c = (Class)m.invoke(appLoader, "ClassNotInJar2", data, 0, data.length, pd); + } catch (Throwable t) { + System.out.println(t); + t.printStackTrace(System.out); + return; + } + + System.out.println(c); + System.out.println(c.getProtectionDomain()); + System.out.println(c.getProtectionDomain().getCodeSource()); + } +} + +class ClassNotInJar1 {} + +class ClassNotInJar2 {} From 98dac46aac2cea9790c1275208cc4c92e8e9a98a Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 16 Apr 2025 18:05:07 +0000 Subject: [PATCH 213/843] 8353589: Open source a few Swing menu-related tests Reviewed-by: jdv, honkar --- .../javax/swing/JPopupMenu/bug4119993.java | 112 ++++++++++++++++++ .../javax/swing/JPopupMenu/bug4187004.java | 97 +++++++++++++++ .../javax/swing/JPopupMenu/bug4530303.java | 85 +++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4119993.java create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4187004.java create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4530303.java diff --git a/test/jdk/javax/swing/JPopupMenu/bug4119993.java b/test/jdk/javax/swing/JPopupMenu/bug4119993.java new file mode 100644 index 00000000000..1fe72ea29d6 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4119993.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4119993 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Check that mouse button 3 is reserved for popup invocation not selection. + * @run main/manual bug4119993 + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.border.BevelBorder; + +/* + * This is a sort of negative test. Mouse Button 3 is not supposed to cause selections. + * If it did, then it would not be useable to invoke popup menus. + * So this popup menu test .. does not popup menus. + */ + +public class bug4119993 { + + static final String INSTRUCTIONS = """ + + The test window contains a text area, a table, and a list. +

+ For each component, try to select text/cells/rows/items as appropriate + using the RIGHT mouse button (Mouse Button 3). +

+ If the selection changes, then press FAIL. +

+ If the selection does not change, press PASS + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4119993::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("bug4119993"); + JPanel p = new JPanel(); + p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); + frame.add(p); + + String text = "This is some text that you should try to select using the right mouse button"; + JTextArea area = new JTextArea(text, 5, 40); + JScrollPane scrollpane0 = new JScrollPane(area); + scrollpane0.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane0.setPreferredSize(new Dimension(430, 200)); + p.add(scrollpane0); + + String[][] data = new String[5][5]; + String[] cols = new String[5]; + for (int r = 0; r < 5; r ++) { + cols[r] = "col " + r; + for (int c = 0; c < 5; c ++) { + data[r][c] = "(" + r + "," + c + ")"; + } + } + + JTable tableView = new JTable(data, cols); + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + p.add(scrollpane); + + String[] s = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; + JList listView = new JList(s); + JScrollPane scrollpane2 = new JScrollPane(listView); + scrollpane2.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane2.setPreferredSize(new Dimension(430, 200)); + p.add(scrollpane2); + + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4187004.java b/test/jdk/javax/swing/JPopupMenu/bug4187004.java new file mode 100644 index 00000000000..40a6633c130 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4187004.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4187004 + @summary test that title/label is show on menu for Motif L&F + @key headful +*/ + +import java.awt.Dimension; +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4187004 { + + static volatile JPopupMenu m; + static volatile Dimension d1, d2; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug4187004::createUI); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + d1 = m.getSize(); + SwingUtilities.invokeAndWait(bug4187004::hideMenu); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(bug4187004::updateUI); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(bug4187004::showMenu); + robot.waitForIdle(); + robot.delay(1000); + d2 = m.getSize(); + } finally { + SwingUtilities.invokeAndWait(bug4187004::hideMenu); + } + System.out.println(d1); + System.out.println(d2); + if (d1.width <= d2.width) { + throw new RuntimeException("Menu not updated"); + } + } + + static void createUI() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + m = new JPopupMenu("One really long menu title"); + m.add("Item 1"); + m.add("Item 2"); + m.add("Item 3"); + m.add("Item 4"); + m.pack(); + m.setVisible(true); + } + + static void hideMenu() { + m.setVisible(false); + } + + static void showMenu() { + m.setVisible(true); + } + + static void updateUI() { + m.setLabel("short"); + m.pack(); + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4530303.java b/test/jdk/javax/swing/JPopupMenu/bug4530303.java new file mode 100644 index 00000000000..c99dacc7cff --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4530303.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4530303 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Tests JPopupMenu.pack() + * @run main/manual bug4530303 + */ + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +public class bug4530303 { + + static final String INSTRUCTIONS = """ + The test window has a menu bar. + Open the menu "Menu" and place the mouse pointer over the first menu item, "Point here". + The second menu item, "Ghost", should be replaced with another item, "Fixed!". + If the item just disappears and no new item appears in the empty space, the test FAILS. + """; + + static volatile JMenu menu; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4530303::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("bug4530303"); + menu = new JMenu("Menu"); + JMenuItem item = new JMenuItem("Point here"); + item.addMouseListener(new MenuBuilder()); + menu.add(item); + menu.add(new JMenuItem("Ghost")); + + JMenuBar mbar = new JMenuBar(); + mbar.add(menu); + frame.setJMenuBar(mbar); + frame.setSize(300, 300); + return frame; + } + + static class MenuBuilder extends MouseAdapter { + public void mouseEntered(MouseEvent ev) { + menu.remove(1); + menu.add(new JMenuItem("Fixed!")); + + JPopupMenu pm = menu.getPopupMenu(); + pm.pack(); + pm.paintImmediately(pm.getBounds()); + } + } +} From 0c34bf047615ad57c91cd49844f9d34f9a8329a2 Mon Sep 17 00:00:00 2001 From: Volodymyr Paprotski Date: Wed, 16 Apr 2025 19:57:42 +0000 Subject: [PATCH 214/843] 8354471: Assertion failure with -XX:-EnableX86ECoreOpts Reviewed-by: sviswanathan, jbhateja --- .../x86/stubGenerator_x86_64_poly_mont.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp index a897fe2e694..d142414be5e 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_poly_mont.cpp @@ -564,7 +564,16 @@ address StubGenerator::generate_intpoly_montgomeryMult_P256() { address start = __ pc(); __ enter(); - if (EnableX86ECoreOpts && UseAVX > 1) { + if (VM_Version::supports_avx512ifma() && VM_Version::supports_avx512vlbw()) { + // Register Map + const Register aLimbs = c_rarg0; // rdi | rcx + const Register bLimbs = c_rarg1; // rsi | rdx + const Register rLimbs = c_rarg2; // rdx | r8 + const Register tmp = r9; + + montgomeryMultiply(aLimbs, bLimbs, rLimbs, tmp, _masm); + } else { + assert(VM_Version::supports_avxifma(), "Require AVX_IFMA support"); __ push(r12); __ push(r13); __ push(r14); @@ -607,14 +616,6 @@ address StubGenerator::generate_intpoly_montgomeryMult_P256() { __ pop(r14); __ pop(r13); __ pop(r12); - } else { - // Register Map - const Register aLimbs = c_rarg0; // rdi | rcx - const Register bLimbs = c_rarg1; // rsi | rdx - const Register rLimbs = c_rarg2; // rdx | r8 - const Register tmp = r9; - - montgomeryMultiply(aLimbs, bLimbs, rLimbs, tmp, _masm); } __ leave(); From a2d7f441b8616e0cd8c231f3358b1b508e76686d Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Wed, 16 Apr 2025 20:11:26 +0000 Subject: [PATCH 215/843] 8295651: JFR: 'jfr scrub' should summarize what was removed Reviewed-by: mgronlun --- .../jdk/jfr/consumer/RecordedObject.java | 10 +++- .../jdk/jfr/consumer/RecordingFile.java | 9 +++- .../classes/jdk/jfr/internal/LongMap.java | 15 +++++- .../jfr/internal/consumer/JdkJfrConsumer.java | 6 ++- .../internal/consumer/filter/ChunkWriter.java | 48 ++++++++++++++++++- .../jdk/jfr/internal/tool/Command.java | 4 ++ .../classes/jdk/jfr/internal/tool/Scrub.java | 24 ++++++++-- .../jdk/jfr/internal/tool/Summary.java | 2 +- test/jdk/jdk/jfr/tool/TestScrub.java | 33 +++++++++++-- 9 files changed, 136 insertions(+), 15 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index 21bd30a8248..8d4a69a92d7 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ package jdk.jfr.consumer; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.nio.file.Path; import java.time.Duration; import java.time.Instant; import java.time.OffsetDateTime; @@ -35,6 +36,7 @@ import java.time.temporal.ChronoUnit; import java.util.Comparator; import java.util.List; import java.util.Objects; +import java.util.function.Predicate; import jdk.jfr.Configuration; import jdk.jfr.EventType; @@ -46,6 +48,7 @@ import jdk.jfr.internal.Type; import jdk.jfr.internal.consumer.JdkJfrConsumer; import jdk.jfr.internal.consumer.ObjectContext; import jdk.jfr.internal.consumer.ObjectFactory; +import jdk.jfr.internal.consumer.filter.ChunkWriter.RemovedEvents; import jdk.jfr.internal.tool.PrettyWriter; /** @@ -148,6 +151,11 @@ public sealed class RecordedObject List configurations) { return new MetadataEvent(previous, current, configurations); } + + @Override + public List write(RecordingFile file, Path output, Predicate filter) throws IOException { + return file.write(output, filter, true); + } }; JdkJfrConsumer.setAccess(access); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java index 0e51da04119..a3880da33fa 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java @@ -46,6 +46,7 @@ import jdk.jfr.internal.consumer.ChunkParser; import jdk.jfr.internal.consumer.ParserState; import jdk.jfr.internal.consumer.RecordingInput; import jdk.jfr.internal.consumer.filter.ChunkWriter; +import jdk.jfr.internal.consumer.filter.ChunkWriter.RemovedEvents; /** * A recording file. @@ -229,12 +230,18 @@ public final class RecordingFile implements Closeable { public void write(Path destination, Predicate filter) throws IOException { Objects.requireNonNull(destination, "destination"); Objects.requireNonNull(filter, "filter"); - try (ChunkWriter cw = new ChunkWriter(file.toPath(), destination, filter)) { + write(destination, filter, false); + } + + // package private + List write(Path destination, Predicate filter, boolean collectResults) throws IOException { + try (ChunkWriter cw = new ChunkWriter(file.toPath(), destination, filter, collectResults)) { try (RecordingFile rf = new RecordingFile(cw)) { while (rf.hasMoreEvents()) { rf.readEvent(); } } + return cw.getRemovedEventTypes(); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/LongMap.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/LongMap.java index 3a3539df4b1..dfb549b5778 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/LongMap.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/LongMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,9 @@ package jdk.jfr.internal; +import java.util.ArrayList; import java.util.BitSet; +import java.util.List; import java.util.function.Consumer; import java.util.function.LongConsumer; @@ -265,4 +267,15 @@ public final class LongMap { } return sb.toString(); } + + public List values() { + List list = new ArrayList<>(count); + for (int i = 0; i < keys.length; i++) { + T o = objects[i]; + if (o != null) { + list.add(o); + } + } + return list; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java index cc5dc4f5d74..9690cc1684b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/JdkJfrConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,10 @@ package jdk.jfr.internal.consumer; import java.io.IOException; +import java.nio.file.Path; import java.util.Comparator; import java.util.List; +import java.util.function.Predicate; import jdk.jfr.Configuration; import jdk.jfr.EventType; @@ -43,6 +45,7 @@ import jdk.jfr.consumer.RecordedThread; import jdk.jfr.consumer.RecordedThreadGroup; import jdk.jfr.consumer.RecordingFile; import jdk.jfr.internal.Type; +import jdk.jfr.internal.consumer.filter.ChunkWriter.RemovedEvents;; /* * Purpose of this class is to give package private access to @@ -105,4 +108,5 @@ public abstract class JdkJfrConsumer { public abstract MetadataEvent newMetadataEvent(List previous, List current, List configuration); + public abstract List write(RecordingFile file, Path output, Predicate filter) throws IOException; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java index 5e3940e7d11..06a415c3561 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java @@ -32,6 +32,7 @@ import java.util.ArrayDeque; import java.util.Deque; import java.util.Map; import java.util.HashMap; +import java.util.List; import java.util.function.Predicate; import jdk.jfr.consumer.RecordedEvent; @@ -51,6 +52,28 @@ import jdk.jfr.internal.consumer.Reference; * All positional values are relative to file start, not the chunk. */ public final class ChunkWriter implements Closeable { + public static class RemovedEvents implements Comparable { + public final String name; + private long count; + private long removed; + + private RemovedEvents(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String share() { + return removed + "/" + count; + } + + @Override + public int compareTo(RemovedEvents that) { + return this.getName().compareTo(that.getName()); + } + } private LongMap pools = new LongMap<>(); private final Deque checkpoints = new ArrayDeque<>(); private final Path destination; @@ -58,16 +81,19 @@ public final class ChunkWriter implements Closeable { private final RecordingOutput output; private final Predicate filter; private final Map waste = new HashMap<>(); + private final LongMap removedEvents = new LongMap<>(); + private final boolean collectResults; private long chunkStartPosition; private boolean chunkComplete; private long lastCheckpoint; - public ChunkWriter(Path source, Path destination, Predicate filter) throws IOException { + public ChunkWriter(Path source, Path destination, Predicate filter, boolean collectResults) throws IOException { this.destination = destination; this.output = new RecordingOutput(destination.toFile()); this.input = new RecordingInput(source.toFile()); this.filter = filter; + this.collectResults = collectResults; } Constants getPool(Type type) { @@ -87,7 +113,25 @@ public final class ChunkWriter implements Closeable { } public boolean accept(RecordedEvent event) { - return filter.test(event); + if (!collectResults) { + return filter.test(event); + } + long id = event.getEventType().getId(); + RemovedEvents r = removedEvents.get(id); + if (r == null) { + r = new RemovedEvents(event.getEventType().getName()); + removedEvents.put(id, r); + } + r.count++; + if (filter.test(event)) { + return true; + } + r.removed++; + return false; + } + + public List getRemovedEventTypes() { + return removedEvents.values().stream().filter(r -> r.removed > 0).sorted().toList(); } public void touch(Object object) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java index 38c6bb4285e..066b528d950 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java @@ -318,6 +318,10 @@ abstract class Command { System.out.println(text); } + protected final void printf(String text, Object ... args) { + System.out.printf(text, args); + } + public static void checkCommonError(Deque options, String typo, String correct) throws UserSyntaxException { if (typo.equals(options.peek())) { throw new UserSyntaxException("unknown option " + typo + ", did you mean " + correct + "?"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Scrub.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Scrub.java index a17662af88d..8a02ded1125 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Scrub.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Scrub.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,8 @@ import java.util.function.Predicate; import jdk.jfr.EventType; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.internal.consumer.JdkJfrConsumer; +import jdk.jfr.internal.consumer.filter.ChunkWriter.RemovedEvents; import jdk.jfr.internal.util.UserDataException; import jdk.jfr.internal.util.UserSyntaxException; @@ -141,12 +143,26 @@ final class Scrub extends Command { try (RecordingFile rf = new RecordingFile(input)) { List types = rf.readEventTypes(); Predicate filter = createFilter(options, types); - rf.write(output, filter); + List result = JdkJfrConsumer.instance().write(rf, output, filter); + println("Scrubbed recording file written to:"); + println(output.toRealPath().toString()); + if (result.isEmpty()) { + println("No events removed."); + return; + } + int maxName = 0; + int maxShare = 0; + for (RemovedEvents re : result) { + maxName = Math.max(maxName, re.getName().length()); + maxShare = Math.max(maxShare, re.share().length()); + } + println("Removed events:"); + for (RemovedEvents re : result) { + printf("%-" + maxName + "s %" + maxShare + "s\n", re.getName(), re.share()); + } } catch (IOException ioe) { couldNotReadError(input, ioe); } - println("Scrubbed recording file written to:"); - println(output.toAbsolutePath().toString()); } private Predicate createFilter(Deque options, List types) throws UserSyntaxException, UserDataException { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java index 08ab475fa68..31b8d807ba0 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java @@ -152,7 +152,7 @@ final class Summary extends Command { println(typeHeader + " ".repeat(minWidth - typeHeader.length()) + header); println("=".repeat(minWidth + header.length())); for (Statistics s : statsList) { - System.out.printf(" %-" + minWidth + "s%10d %12d\n", s.name, s.count, s.size); + printf(" %-" + minWidth + "s%10d %12d\n", s.name, s.count, s.size); } } } diff --git a/test/jdk/jdk/jfr/tool/TestScrub.java b/test/jdk/jdk/jfr/tool/TestScrub.java index 43b9fca7ee4..23a87452ff9 100644 --- a/test/jdk/jdk/jfr/tool/TestScrub.java +++ b/test/jdk/jdk/jfr/tool/TestScrub.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,9 +69,16 @@ public class TestScrub { try (Recording r = new Recording()) { r.start(); - emit(100, "India", TigerEvent.class); - emit(100, "Namibia", ZebraEvent.class); - emit(10000, "Lake Tanganyika", TigerfishEvent.class); + emit(50, "India", TigerEvent.class); + emit(50, "Namibia", ZebraEvent.class); + emit(5000, "Lake Tanganyika", TigerfishEvent.class); + // Force rotation + try (Recording s = new Recording()) { + s.start(); + } + emit(50, "India", TigerEvent.class); + emit(50, "Namibia", ZebraEvent.class); + emit(5000, "Lake Tanganyika", TigerfishEvent.class); r.stop(); r.dump(file); } @@ -89,6 +96,7 @@ public class TestScrub { testThreadInclude(file); testMissingEventType(file); + testSummary(file); } private static void testInputOutput(Path file) throws Throwable { @@ -275,6 +283,23 @@ public class TestScrub { Files.delete(output); } + + private static void testSummary(Path file) throws Throwable { + String inputFile = file.toAbsolutePath().toString(); + + String removedZebras = Path.of("removed-zebras.jfr").toAbsolutePath().toString(); + var outp = ExecuteHelper.jfr("scrub", "--exclude-events", "Zebra", inputFile, removedZebras); + outp.shouldContain("Removed events:"); + outp.shouldContain("example.Zebra 100/100"); + outp.shouldNotContain("Tiger"); + outp.shouldNotContain("No events removed"); + + String noneRemoved = Path.of("none-removed.jfr").toAbsolutePath().toString(); + outp = ExecuteHelper.jfr("scrub", "--exclude-events", "jdk.JVMInformation", inputFile, noneRemoved); + outp.shouldContain("No events removed"); + outp.shouldNotContain("jdk.JVMInformation"); + } + private static void assertNotThread(RecordedEvent event, String... threadNames) { String s = event.getThread().getJavaName(); for (String threadName : threadNames) { From db2dffb6e5fed3773080581350f7f5c0bcff8f35 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Wed, 16 Apr 2025 23:04:37 +0000 Subject: [PATCH 216/843] 8354559: gc/g1/TestAllocationFailure.java doesn't need WB API Reviewed-by: ayang, kbarrett --- test/hotspot/jtreg/gc/g1/TestAllocationFailure.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java b/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java index cd4c991de26..a0aabf359b4 100644 --- a/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java +++ b/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,10 +31,7 @@ package gc.g1; * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * gc.g1.TestAllocationFailure + * @run driver gc.g1.TestAllocationFailure */ import jdk.test.lib.process.OutputAnalyzer; From 07aad68c17ba8d95aee914f3bd9705301477acf6 Mon Sep 17 00:00:00 2001 From: Anjian-Wen Date: Thu, 17 Apr 2025 02:16:24 +0000 Subject: [PATCH 217/843] 8329887: RISC-V: C2: Support Zvbb Vector And-Not instruction Reviewed-by: fyang, fjiang --- src/hotspot/cpu/riscv/riscv_v.ad | 68 +++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 10 +++ .../AllBitsSetVectorMatchRuleTest.java | 64 ++++++++++++++++- 3 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 1e99b2ece29..9b135215b3d 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -1117,6 +1117,74 @@ instruct vxor_regL_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{ ins_pipe(pipe_slow); %} +// ------------------------------ Vector and not ----------------------------------- + +// vector and not + +instruct vand_notI(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{ + predicate(UseZvbb); + predicate(Matcher::vector_element_basic_type(n) == T_INT || + Matcher::vector_element_basic_type(n) == T_BYTE || + Matcher::vector_element_basic_type(n) == T_SHORT); + match(Set dst (AndV src1 (XorV src2 (Replicate m1)))); + format %{ "vand_notI $dst, $src1, $src2" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vandn_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vand_notL(vReg dst, vReg src1, vReg src2, immL_M1 m1) %{ + predicate(UseZvbb); + predicate(Matcher::vector_element_basic_type(n) == T_LONG); + match(Set dst (AndV src1 (XorV src2 (Replicate m1)))); + format %{ "vand_notL $dst, $src1, $src2" %} + ins_encode %{ + __ vsetvli_helper(T_LONG, Matcher::vector_length(this)); + __ vandn_vv(as_VectorRegister($dst$$reg), + as_VectorRegister($src1$$reg), + as_VectorRegister($src2$$reg)); + %} + ins_pipe(pipe_slow); +%} + +instruct vand_notI_masked(vReg dst_src1, vReg src2, immI_M1 m1, vRegMask_V0 v0) %{ + predicate(UseZvbb); + predicate(Matcher::vector_element_basic_type(n) == T_INT || + Matcher::vector_element_basic_type(n) == T_BYTE || + Matcher::vector_element_basic_type(n) == T_SHORT); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (Replicate m1))) v0)); + format %{ "vand_notI_masked $dst_src1, $dst_src1, $src2, $v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + __ vsetvli_helper(bt, Matcher::vector_length(this)); + __ vandn_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), + Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vand_notL_masked(vReg dst_src1, vReg src2, immL_M1 m1, vRegMask_V0 v0) %{ + predicate(UseZvbb); + predicate(Matcher::vector_element_basic_type(n) == T_LONG); + match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (Replicate m1))) v0)); + format %{ "vand_notL_masked $dst_src1, $dst_src1, $src2, $v0" %} + ins_encode %{ + __ vsetvli_helper(T_LONG, Matcher::vector_length(this)); + __ vandn_vv(as_VectorRegister($dst_src1$$reg), + as_VectorRegister($dst_src1$$reg), + as_VectorRegister($src2$$reg), + Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + // ------------------------------ Vector not ----------------------------------- // vector not diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 57e4d413fea..6d58b35f53c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -2116,6 +2116,16 @@ public class IRNode { machOnlyNameRegex(VAND_NOT_L, "vand_notL"); } + public static final String VAND_NOT_I_MASKED = PREFIX + "VAND_NOT_I_MASKED" + POSTFIX; + static { + machOnlyNameRegex(VAND_NOT_I_MASKED, "vand_notI_masked"); + } + + public static final String VAND_NOT_L_MASKED = PREFIX + "VAND_NOT_L_MASKED" + POSTFIX; + static { + machOnlyNameRegex(VAND_NOT_L_MASKED, "vand_notL_masked"); + } + public static final String VECTOR_BLEND_B = VECTOR_PREFIX + "VECTOR_BLEND_B" + POSTFIX; static { vectorNode(VECTOR_BLEND_B, "VectorBlend", TYPE_BYTE); diff --git a/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java b/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java index e490174e380..f33dd24e726 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java @@ -42,7 +42,7 @@ import jdk.test.lib.Utils; * @key randomness * @library /test/lib / * @requires vm.compiler2.enabled - * @requires vm.cpu.features ~= ".*asimd.*" + * @requires (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*asimd.*") | (os.simpleArch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") * @summary AArch64: [vector] Make all bits set vector sharable for match rules * @modules jdk.incubator.vector * @@ -59,6 +59,9 @@ public class AllBitsSetVectorMatchRuleTest { private static int[] ia; private static int[] ib; private static int[] ir; + private static long[] la; + private static long[] lb; + private static long[] lr; private static boolean[] ma; private static boolean[] mb; private static boolean[] mc; @@ -68,6 +71,9 @@ public class AllBitsSetVectorMatchRuleTest { ia = new int[LENGTH]; ib = new int[LENGTH]; ir = new int[LENGTH]; + la = new long[LENGTH]; + lb = new long[LENGTH]; + lr = new long[LENGTH]; ma = new boolean[LENGTH]; mb = new boolean[LENGTH]; mc = new boolean[LENGTH]; @@ -76,6 +82,8 @@ public class AllBitsSetVectorMatchRuleTest { for (int i = 0; i < LENGTH; i++) { ia[i] = RD.nextInt(25); ib[i] = RD.nextInt(25); + la[i] = RD.nextLong(25); + lb[i] = RD.nextLong(25); ma[i] = RD.nextBoolean(); mb[i] = RD.nextBoolean(); mc[i] = RD.nextBoolean(); @@ -98,8 +106,58 @@ public class AllBitsSetVectorMatchRuleTest { @Test @Warmup(10000) - @IR(counts = { IRNode.VAND_NOT_L, " >= 1" }, applyIf = {"UseSVE", "0"}) - @IR(counts = { IRNode.VMASK_AND_NOT_L, " >= 1" }, applyIf = {"UseSVE", "> 0"}) + @IR(counts = { IRNode.VAND_NOT_L, " >= 1" }) + public static void testVectorVAndNotL() { + LongVector av = LongVector.fromArray(L_SPECIES, la, 0); + LongVector bv = LongVector.fromArray(L_SPECIES, lb, 0); + av.not().lanewise(VectorOperators.AND_NOT, bv).intoArray(lr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals((~la[i]) & (~lb[i]), lr[i]); + } + } + + @Test + @Warmup(10000) + @IR(counts = { IRNode.VAND_NOT_I_MASKED, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "> 0"}) + @IR(counts = { IRNode.VAND_NOT_I_MASKED, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testVectorVAndNotIMasked() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); + IntVector bv = IntVector.fromArray(I_SPECIES, ib, 0); + av.not().lanewise(VectorOperators.AND_NOT, bv, avm).intoArray(ir, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + if (ma[i] == true) { + Asserts.assertEquals((~ia[i]) & (~ib[i]), ir[i]); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = { IRNode.VAND_NOT_L_MASKED, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "> 0"}) + @IR(counts = { IRNode.VAND_NOT_L_MASKED, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) + public static void testVectorVAndNotLMasked() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + LongVector av = LongVector.fromArray(L_SPECIES, la, 0); + LongVector bv = LongVector.fromArray(L_SPECIES, lb, 0); + av.not().lanewise(VectorOperators.AND_NOT, bv, avm).intoArray(lr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + if (ma[i] == true) { + Asserts.assertEquals((~la[i]) & (~lb[i]), lr[i]); + } + } + } + + @Test + @Warmup(10000) + @IR(counts = { IRNode.VAND_NOT_L, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "0"}) + @IR(counts = { IRNode.VMASK_AND_NOT_L, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "> 0"}) public static void testAllBitsSetMask() { VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); From a71f621a3248320e8a7a78f1652a7750271ed4ef Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 17 Apr 2025 03:10:58 +0000 Subject: [PATCH 218/843] 8353694: Resolved Class/Field/Method CP entries missing from AOT Configuration Reviewed-by: shade, vlivanov --- src/hotspot/share/cds/archiveUtils.inline.hpp | 2 +- src/hotspot/share/cds/finalImageRecipes.cpp | 167 ++++++++++++------ src/hotspot/share/cds/finalImageRecipes.hpp | 19 +- src/hotspot/share/runtime/mutexLocker.cpp | 2 + src/hotspot/share/runtime/mutexLocker.hpp | 1 + 5 files changed, 127 insertions(+), 64 deletions(-) diff --git a/src/hotspot/share/cds/archiveUtils.inline.hpp b/src/hotspot/share/cds/archiveUtils.inline.hpp index 9388bca18c7..72de48743f3 100644 --- a/src/hotspot/share/cds/archiveUtils.inline.hpp +++ b/src/hotspot/share/cds/archiveUtils.inline.hpp @@ -78,7 +78,7 @@ Array* ArchiveUtils::archive_ptr_array(GrowableArray* tmp_array) { Array* archived_array = ArchiveBuilder::new_ro_array(tmp_array->length()); for (int i = 0; i < tmp_array->length(); i++) { T ptr = tmp_array->at(i); - if (!builder->is_in_buffer_space(ptr)) { + if (ptr != nullptr && !builder->is_in_buffer_space(ptr)) { if (is_dynamic_dump && MetaspaceShared::is_in_shared_metaspace(ptr)) { // We have a pointer that lives in the dynamic archive but points into // the static archive. diff --git a/src/hotspot/share/cds/finalImageRecipes.cpp b/src/hotspot/share/cds/finalImageRecipes.cpp index bdfd261355b..f0ce8ceb020 100644 --- a/src/hotspot/share/cds/finalImageRecipes.cpp +++ b/src/hotspot/share/cds/finalImageRecipes.cpp @@ -36,6 +36,7 @@ #include "memory/resourceArea.hpp" #include "oops/constantPool.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/mutexLocker.hpp" static FinalImageRecipes* _final_image_recipes = nullptr; @@ -43,56 +44,126 @@ void* FinalImageRecipes::operator new(size_t size) throw() { return ArchiveBuilder::current()->ro_region_alloc(size); } -void FinalImageRecipes::record_recipes_impl() { - assert(CDSConfig::is_dumping_preimage_static_archive(), "must be"); +void FinalImageRecipes::record_all_classes() { + _all_klasses = ArchiveUtils::archive_array(ArchiveBuilder::current()->klasses()); + ArchivePtrMarker::mark_pointer(&_all_klasses); +} + +void FinalImageRecipes::record_recipes_for_constantpool() { ResourceMark rm; + + // The recipes are recorded regardless of CDSConfig::is_dumping_{invokedynamic,dynamic_proxies,reflection_data}(). + // If some of these options are not enabled, the corresponding recipes will be + // ignored during the final image assembly. + + GrowableArray*> tmp_cp_recipes; + GrowableArray tmp_cp_flags; + GrowableArray* klasses = ArchiveBuilder::current()->klasses(); - - // Record the indys that have been resolved in the training run. These indys will be - // resolved during the final image assembly. - - GrowableArray tmp_indy_klasses; - GrowableArray*> tmp_indy_cp_indices; - int total_indys_to_resolve = 0; for (int i = 0; i < klasses->length(); i++) { + GrowableArray cp_indices; + int flags = 0; + Klass* k = klasses->at(i); if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); - GrowableArray indices; + ConstantPool* cp = ik->constants(); + ConstantPoolCache* cp_cache = cp->cache(); - if (ik->constants()->cache() != nullptr) { - Array* tmp_indy_entries = ik->constants()->cache()->resolved_indy_entries(); - if (tmp_indy_entries != nullptr) { - for (int i = 0; i < tmp_indy_entries->length(); i++) { - ResolvedIndyEntry* rie = tmp_indy_entries->adr_at(i); - int cp_index = rie->constant_pool_index(); - if (rie->is_resolved()) { - indices.append(cp_index); - } + for (int cp_index = 1; cp_index < cp->length(); cp_index++) { // Index 0 is unused + if (cp->tag_at(cp_index).value() == JVM_CONSTANT_Class) { + Klass* k = cp->resolved_klass_at(cp_index); + if (k->is_instance_klass()) { + cp_indices.append(cp_index); + flags |= HAS_CLASS; } } } - if (indices.length() > 0) { - tmp_indy_klasses.append(ArchiveBuilder::current()->get_buffered_addr(ik)); - tmp_indy_cp_indices.append(ArchiveUtils::archive_array(&indices)); - total_indys_to_resolve += indices.length(); + if (cp_cache != nullptr) { + Array* field_entries = cp_cache->resolved_field_entries(); + if (field_entries != nullptr) { + for (int i = 0; i < field_entries->length(); i++) { + ResolvedFieldEntry* rfe = field_entries->adr_at(i); + if (rfe->is_resolved(Bytecodes::_getfield) || + rfe->is_resolved(Bytecodes::_putfield)) { + cp_indices.append(rfe->constant_pool_index()); + flags |= HAS_FIELD_AND_METHOD; + } + } + } + + Array* method_entries = cp_cache->resolved_method_entries(); + if (method_entries != nullptr) { + for (int i = 0; i < method_entries->length(); i++) { + ResolvedMethodEntry* rme = method_entries->adr_at(i); + if (rme->is_resolved(Bytecodes::_invokevirtual) || + rme->is_resolved(Bytecodes::_invokespecial) || + rme->is_resolved(Bytecodes::_invokeinterface) || + rme->is_resolved(Bytecodes::_invokestatic) || + rme->is_resolved(Bytecodes::_invokehandle)) { + cp_indices.append(rme->constant_pool_index()); + flags |= HAS_FIELD_AND_METHOD; + } + } + } + + Array* indy_entries = cp_cache->resolved_indy_entries(); + if (indy_entries != nullptr) { + for (int i = 0; i < indy_entries->length(); i++) { + ResolvedIndyEntry* rie = indy_entries->adr_at(i); + int cp_index = rie->constant_pool_index(); + if (rie->is_resolved()) { + cp_indices.append(cp_index); + flags |= HAS_INDY; + } + } + } + } + } + + if (cp_indices.length() > 0) { + tmp_cp_recipes.append(ArchiveUtils::archive_array(&cp_indices)); + } else { + tmp_cp_recipes.append(nullptr); + } + tmp_cp_flags.append(flags); + } + + _cp_recipes = ArchiveUtils::archive_array(&tmp_cp_recipes); + ArchivePtrMarker::mark_pointer(&_cp_recipes); + + _cp_flags = ArchiveUtils::archive_array(&tmp_cp_flags); + ArchivePtrMarker::mark_pointer(&_cp_flags); +} + +void FinalImageRecipes::apply_recipes_for_constantpool(JavaThread* current) { + assert(CDSConfig::is_dumping_final_static_archive(), "must be"); + + for (int i = 0; i < _all_klasses->length(); i++) { + Array* cp_indices = _cp_recipes->at(i); + int flags = _cp_flags->at(i); + if (cp_indices != nullptr) { + InstanceKlass* ik = InstanceKlass::cast(_all_klasses->at(i)); + if (ik->is_loaded()) { + ResourceMark rm(current); + ConstantPool* cp = ik->constants(); + GrowableArray preresolve_list(cp->length(), cp->length(), false); + for (int j = 0; j < cp_indices->length(); j++) { + preresolve_list.at_put(cp_indices->at(j), true); + } + if ((flags & HAS_CLASS) != 0) { + AOTConstantPoolResolver::preresolve_class_cp_entries(current, ik, &preresolve_list); + } + if ((flags & HAS_FIELD_AND_METHOD) != 0) { + AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(current, ik, &preresolve_list); + } + if ((flags & HAS_INDY) != 0) { + AOTConstantPoolResolver::preresolve_indy_cp_entries(current, ik, &preresolve_list); + } } } } - - _all_klasses = ArchiveUtils::archive_array(klasses); - ArchivePtrMarker::mark_pointer(&_all_klasses); - - assert(tmp_indy_klasses.length() == tmp_indy_cp_indices.length(), "must be"); - if (tmp_indy_klasses.length() > 0) { - _indy_klasses = ArchiveUtils::archive_array(&tmp_indy_klasses); - _indy_cp_indices = ArchiveUtils::archive_array(&tmp_indy_cp_indices); - - ArchivePtrMarker::mark_pointer(&_indy_klasses); - ArchivePtrMarker::mark_pointer(&_indy_cp_indices); - } - log_info(cds)("%d indies in %d classes will be resolved in final CDS image", total_indys_to_resolve, tmp_indy_klasses.length()); } void FinalImageRecipes::load_all_classes(TRAPS) { @@ -122,27 +193,11 @@ void FinalImageRecipes::load_all_classes(TRAPS) { } } -void FinalImageRecipes::apply_recipes_for_invokedynamic(TRAPS) { - assert(CDSConfig::is_dumping_final_static_archive(), "must be"); - - if (CDSConfig::is_dumping_invokedynamic() && _indy_klasses != nullptr) { - assert(_indy_cp_indices != nullptr, "must be"); - for (int i = 0; i < _indy_klasses->length(); i++) { - InstanceKlass* ik = _indy_klasses->at(i); - ConstantPool* cp = ik->constants(); - Array* cp_indices = _indy_cp_indices->at(i); - GrowableArray preresolve_list(cp->length(), cp->length(), false); - for (int j = 0; j < cp_indices->length(); j++) { - preresolve_list.at_put(cp_indices->at(j), true); - } - AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list); - } - } -} - void FinalImageRecipes::record_recipes() { + assert(CDSConfig::is_dumping_preimage_static_archive(), "must be"); _final_image_recipes = new FinalImageRecipes(); - _final_image_recipes->record_recipes_impl(); + _final_image_recipes->record_all_classes(); + _final_image_recipes->record_recipes_for_constantpool(); } void FinalImageRecipes::apply_recipes(TRAPS) { @@ -163,7 +218,7 @@ void FinalImageRecipes::apply_recipes(TRAPS) { void FinalImageRecipes::apply_recipes_impl(TRAPS) { load_all_classes(CHECK); - apply_recipes_for_invokedynamic(CHECK); + apply_recipes_for_constantpool(THREAD); } void FinalImageRecipes::serialize(SerializeClosure* soc) { diff --git a/src/hotspot/share/cds/finalImageRecipes.hpp b/src/hotspot/share/cds/finalImageRecipes.hpp index f07d9787af9..3af1e70772c 100644 --- a/src/hotspot/share/cds/finalImageRecipes.hpp +++ b/src/hotspot/share/cds/finalImageRecipes.hpp @@ -42,26 +42,31 @@ template class Array; // - The list of all classes that are stored in the AOTConfiguration file. // - The list of all classes that require AOT resolution of invokedynamic call sites. class FinalImageRecipes { + static constexpr int HAS_CLASS = 0x1; + static constexpr int HAS_FIELD_AND_METHOD = 0x2; + static constexpr int HAS_INDY = 0x4; + // A list of all the archived classes from the preimage. We want to transfer all of these // into the final image. Array* _all_klasses; - // The classes who have resolved at least one indy CP entry during the training run. - // _indy_cp_indices[i] is a list of all resolved CP entries for _indy_klasses[i]. - Array* _indy_klasses; - Array*>* _indy_cp_indices; + // For each klass k _all_klasses->at(i), _cp_recipes->at(i) lists all the {klass,field,method,indy} + // cp indices that were resolved for k during the training run. + Array*>* _cp_recipes; + Array* _cp_flags; - FinalImageRecipes() : _indy_klasses(nullptr), _indy_cp_indices(nullptr) {} + FinalImageRecipes() : _all_klasses(nullptr), _cp_recipes(nullptr), _cp_flags(nullptr) {} void* operator new(size_t size) throw(); // Called when dumping preimage - void record_recipes_impl(); + void record_all_classes(); + void record_recipes_for_constantpool(); // Called when dumping final image void apply_recipes_impl(TRAPS); void load_all_classes(TRAPS); - void apply_recipes_for_invokedynamic(TRAPS); + void apply_recipes_for_constantpool(JavaThread* current); public: static void serialize(SerializeClosure* soc); diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 3db53d038b6..faed0d5f952 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -147,6 +147,7 @@ Mutex* ClassListFile_lock = nullptr; Mutex* UnregisteredClassesTable_lock= nullptr; Mutex* LambdaFormInvokers_lock = nullptr; Mutex* ScratchObjects_lock = nullptr; +Mutex* FinalImageRecipes_lock = nullptr; #endif // INCLUDE_CDS Mutex* Bootclasspath_lock = nullptr; @@ -299,6 +300,7 @@ void mutex_init() { MUTEX_DEFN(UnregisteredClassesTable_lock , PaddedMutex , nosafepoint-1); MUTEX_DEFN(LambdaFormInvokers_lock , PaddedMutex , safepoint); MUTEX_DEFN(ScratchObjects_lock , PaddedMutex , nosafepoint-1); // Holds DumpTimeTable_lock + MUTEX_DEFN(FinalImageRecipes_lock , PaddedMutex , nosafepoint); #endif // INCLUDE_CDS MUTEX_DEFN(Bootclasspath_lock , PaddedMutex , nosafepoint); diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index bd2073dfe88..3bd01b575c4 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -129,6 +129,7 @@ extern Mutex* ClassListFile_lock; // ClassListWriter() extern Mutex* UnregisteredClassesTable_lock; // UnregisteredClassesTableTable extern Mutex* LambdaFormInvokers_lock; // Protecting LambdaFormInvokers::_lambdaform_lines extern Mutex* ScratchObjects_lock; // Protecting _scratch_xxx_table in heapShared.cpp +extern Mutex* FinalImageRecipes_lock; // Protecting the tables used by FinalImageRecipes. #endif // INCLUDE_CDS #if INCLUDE_JFR extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table From 055b750d999e52569094bffa7dc0364a50771853 Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Thu, 17 Apr 2025 06:08:36 +0000 Subject: [PATCH 219/843] 8354543: Set more meaningful names for "get_vm_result" and "get_vm_result_2" Reviewed-by: shade, coleenp --- .../cpu/aarch64/c1_Runtime1_aarch64.cpp | 12 +++--- .../cpu/aarch64/macroAssembler_aarch64.cpp | 14 +++---- .../cpu/aarch64/macroAssembler_aarch64.hpp | 4 +- .../cpu/aarch64/sharedRuntime_aarch64.cpp | 4 +- .../templateInterpreterGenerator_aarch64.cpp | 4 +- .../cpu/aarch64/templateTable_aarch64.cpp | 8 ++-- src/hotspot/cpu/arm/c1_Runtime1_arm.cpp | 4 +- src/hotspot/cpu/arm/macroAssembler_arm.cpp | 14 +++---- src/hotspot/cpu/arm/macroAssembler_arm.hpp | 4 +- src/hotspot/cpu/arm/sharedRuntime_arm.cpp | 4 +- .../arm/templateInterpreterGenerator_arm.cpp | 4 +- src/hotspot/cpu/arm/templateTable_arm.cpp | 8 ++-- src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp | 8 ++-- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 22 +++++------ src/hotspot/cpu/ppc/macroAssembler_ppc.hpp | 4 +- src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 4 +- .../ppc/templateInterpreterGenerator_ppc.cpp | 4 +- src/hotspot/cpu/ppc/templateTable_ppc_64.cpp | 6 +-- src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 12 +++--- .../cpu/riscv/macroAssembler_riscv.cpp | 14 +++---- .../cpu/riscv/macroAssembler_riscv.hpp | 4 +- src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 4 +- .../templateInterpreterGenerator_riscv.cpp | 4 +- src/hotspot/cpu/riscv/templateTable_riscv.cpp | 8 ++-- src/hotspot/cpu/s390/c1_Runtime1_s390.cpp | 12 +++--- src/hotspot/cpu/s390/macroAssembler_s390.cpp | 16 ++++---- src/hotspot/cpu/s390/macroAssembler_s390.hpp | 4 +- src/hotspot/cpu/s390/sharedRuntime_s390.cpp | 4 +- .../templateInterpreterGenerator_s390.cpp | 2 +- src/hotspot/cpu/s390/templateTable_s390.cpp | 6 +-- src/hotspot/cpu/x86/c1_Runtime1_x86.cpp | 12 +++--- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 14 +++---- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 4 +- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 4 +- .../x86/templateInterpreterGenerator_x86.cpp | 4 +- src/hotspot/cpu/x86/templateTable_x86.cpp | 8 ++-- src/hotspot/share/c1/c1_Runtime1.cpp | 10 ++--- .../share/interpreter/interpreterRuntime.cpp | 38 +++++++++---------- .../interpreter/zero/bytecodeInterpreter.cpp | 34 ++++++++--------- .../leakprofiler/checkpoint/rootResolver.cpp | 2 +- src/hotspot/share/jvmci/jvmciRuntime.cpp | 20 +++++----- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 +- src/hotspot/share/opto/generateOptoStub.cpp | 2 +- src/hotspot/share/opto/runtime.cpp | 20 +++++----- src/hotspot/share/runtime/javaCalls.cpp | 6 +-- src/hotspot/share/runtime/javaThread.cpp | 6 +-- src/hotspot/share/runtime/javaThread.hpp | 14 +++---- src/hotspot/share/runtime/sharedRuntime.cpp | 14 +++---- src/hotspot/share/runtime/vmStructs.cpp | 4 +- 49 files changed, 215 insertions(+), 225 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index 063918ee20b..a6aab24349a 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -91,10 +91,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre // exception pending => remove activation and forward to exception handler // make sure that the vm_results are cleared if (oop_result1->is_valid()) { - str(zr, Address(rthread, JavaThread::vm_result_offset())); + str(zr, Address(rthread, JavaThread::vm_result_oop_offset())); } if (metadata_result->is_valid()) { - str(zr, Address(rthread, JavaThread::vm_result_2_offset())); + str(zr, Address(rthread, JavaThread::vm_result_metadata_offset())); } if (frame_size() == no_frame_size) { leave(); @@ -108,10 +108,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre } // get oop results if there are any and reset the values in the thread if (oop_result1->is_valid()) { - get_vm_result(oop_result1, rthread); + get_vm_result_oop(oop_result1, rthread); } if (metadata_result->is_valid()) { - get_vm_result_2(metadata_result, rthread); + get_vm_result_metadata(metadata_result, rthread); } return call_offset; } @@ -406,8 +406,8 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ authenticate_return_address(exception_pc); // make sure that the vm_results are cleared (may be unnecessary) - __ str(zr, Address(rthread, JavaThread::vm_result_offset())); - __ str(zr, Address(rthread, JavaThread::vm_result_2_offset())); + __ str(zr, Address(rthread, JavaThread::vm_result_oop_offset())); + __ str(zr, Address(rthread, JavaThread::vm_result_metadata_offset())); break; case C1StubId::handle_exception_nofpu_id: case C1StubId::handle_exception_id: diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index b6472b1b948..1e226c70420 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -849,7 +849,7 @@ void MacroAssembler::call_VM_base(Register oop_result, // get oop result if there is one and reset the value in the thread if (oop_result->is_valid()) { - get_vm_result(oop_result, java_thread); + get_vm_result_oop(oop_result, java_thread); } } @@ -1145,15 +1145,15 @@ void MacroAssembler::call_VM(Register oop_result, } -void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) { - ldr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); - str(zr, Address(java_thread, JavaThread::vm_result_offset())); +void MacroAssembler::get_vm_result_oop(Register oop_result, Register java_thread) { + ldr(oop_result, Address(java_thread, JavaThread::vm_result_oop_offset())); + str(zr, Address(java_thread, JavaThread::vm_result_oop_offset())); verify_oop_msg(oop_result, "broken oop in call_VM_base"); } -void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) { - ldr(metadata_result, Address(java_thread, JavaThread::vm_result_2_offset())); - str(zr, Address(java_thread, JavaThread::vm_result_2_offset())); +void MacroAssembler::get_vm_result_metadata(Register metadata_result, Register java_thread) { + ldr(metadata_result, Address(java_thread, JavaThread::vm_result_metadata_offset())); + str(zr, Address(java_thread, JavaThread::vm_result_metadata_offset())); } void MacroAssembler::align(int modulus) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index bd537af59e4..11d1985e50b 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -823,8 +823,8 @@ public: Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - void get_vm_result (Register oop_result, Register thread); - void get_vm_result_2(Register metadata_result, Register thread); + void get_vm_result_oop(Register oop_result, Register thread); + void get_vm_result_metadata(Register metadata_result, Register thread); // These always tightly bind to MacroAssembler::call_VM_base // bypassing the virtual implementation diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index b0b29987601..967984b8821 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -2783,7 +2783,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti __ cbnz(rscratch1, pending); // get the returned Method* - __ get_vm_result_2(rmethod, rthread); + __ get_vm_result_metadata(rmethod, rthread); __ str(rmethod, Address(sp, reg_save.reg_offset_in_bytes(rmethod))); // r0 is where we want to jump, overwrite rscratch1 which is saved and scratch @@ -2802,7 +2802,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // exception pending => remove activation and forward to exception handler - __ str(zr, Address(rthread, JavaThread::vm_result_offset())); + __ str(zr, Address(rthread, JavaThread::vm_result_oop_offset())); __ ldr(r0, Address(rthread, Thread::pending_exception_offset())); __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 80c9437de6b..2db3b435abb 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1978,11 +1978,11 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // preserve exception over this code sequence __ pop_ptr(r0); - __ str(r0, Address(rthread, JavaThread::vm_result_offset())); + __ str(r0, Address(rthread, JavaThread::vm_result_oop_offset())); // remove the activation (without doing throws on illegalMonitorExceptions) __ remove_activation(vtos, false, true, false); // restore exception - __ get_vm_result(r0, rthread); + __ get_vm_result_oop(r0, rthread); // In between activations - previous activation type unknown yet // compute continuation point - the continuation point expects the diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index e50810486c8..2cc9b39983a 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -484,7 +484,7 @@ void TemplateTable::condy_helper(Label& Done) __ mov(rarg, (int) bytecode()); __ call_VM(obj, entry, rarg); - __ get_vm_result_2(flags, rthread); + __ get_vm_result_metadata(flags, rthread); // VMr = obj = base address to find primitive value to push // VMr2 = flags = (tos, off) using format of CPCE::_flags @@ -3723,8 +3723,7 @@ void TemplateTable::checkcast() __ push(atos); // save receiver for result, and for GC call_VM(r0, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(r0, rthread); + __ get_vm_result_metadata(r0, rthread); __ pop(r3); // restore receiver __ b(resolved); @@ -3777,8 +3776,7 @@ void TemplateTable::instanceof() { __ push(atos); // save receiver for result, and for GC call_VM(r0, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(r0, rthread); + __ get_vm_result_metadata(r0, rthread); __ pop(r3); // restore receiver __ verify_oop(r3); __ load_klass(r3, r3); diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp index 949e985ab1e..021b47148fa 100644 --- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp +++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp @@ -70,11 +70,11 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre if (oop_result1->is_valid()) { assert_different_registers(oop_result1, R3, Rtemp); - get_vm_result(oop_result1, Rtemp); + get_vm_result_oop(oop_result1, Rtemp); } if (metadata_result->is_valid()) { assert_different_registers(metadata_result, R3, Rtemp); - get_vm_result_2(metadata_result, Rtemp); + get_vm_result_metadata(metadata_result, Rtemp); } // Check for pending exception diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index 638b3a5404c..3dcde7d898d 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -424,7 +424,7 @@ void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, in // get oop result if there is one and reset the value in the thread if (oop_result->is_valid()) { - get_vm_result(oop_result, tmp); + get_vm_result_oop(oop_result, tmp); } } @@ -528,17 +528,17 @@ void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1, Register call_VM_leaf_helper(entry_point, 4); } -void MacroAssembler::get_vm_result(Register oop_result, Register tmp) { +void MacroAssembler::get_vm_result_oop(Register oop_result, Register tmp) { assert_different_registers(oop_result, tmp); - ldr(oop_result, Address(Rthread, JavaThread::vm_result_offset())); - str(zero_register(tmp), Address(Rthread, JavaThread::vm_result_offset())); + ldr(oop_result, Address(Rthread, JavaThread::vm_result_oop_offset())); + str(zero_register(tmp), Address(Rthread, JavaThread::vm_result_oop_offset())); verify_oop(oop_result); } -void MacroAssembler::get_vm_result_2(Register metadata_result, Register tmp) { +void MacroAssembler::get_vm_result_metadata(Register metadata_result, Register tmp) { assert_different_registers(metadata_result, tmp); - ldr(metadata_result, Address(Rthread, JavaThread::vm_result_2_offset())); - str(zero_register(tmp), Address(Rthread, JavaThread::vm_result_2_offset())); + ldr(metadata_result, Address(Rthread, JavaThread::vm_result_metadata_offset())); + str(zero_register(tmp), Address(Rthread, JavaThread::vm_result_metadata_offset())); } void MacroAssembler::add_rc(Register dst, Register arg1, RegisterOrConstant arg2) { diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp index 621f0101432..d60b38e42db 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp @@ -257,8 +257,8 @@ public: void call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3); void call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4); - void get_vm_result(Register oop_result, Register tmp); - void get_vm_result_2(Register metadata_result, Register tmp); + void get_vm_result_oop(Register oop_result, Register tmp); + void get_vm_result_metadata(Register metadata_result, Register tmp); // Always sets/resets sp, which default to SP if (last_sp == noreg) // Optionally sets/resets fp (use noreg to avoid setting it) diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index c63d72920a5..6dde82daaf9 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -1717,7 +1717,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // Overwrite saved register values // Place metadata result of VM call into Rmethod - __ get_vm_result_2(R1, Rtemp); + __ get_vm_result_metadata(R1, Rtemp); __ str(R1, Address(SP, RegisterSaver::Rmethod_offset * wordSize)); // Place target address (VM call result) into Rtemp @@ -1730,7 +1730,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti RegisterSaver::restore_live_registers(masm); const Register Rzero = __ zero_register(Rtemp); - __ str(Rzero, Address(Rthread, JavaThread::vm_result_2_offset())); + __ str(Rzero, Address(Rthread, JavaThread::vm_result_metadata_offset())); __ mov(Rexception_pc, LR); __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp); diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp index da226c09f3c..30d88a4db91 100644 --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -1467,11 +1467,11 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // preserve exception over this code sequence __ pop_ptr(R0_tos); - __ str(R0_tos, Address(Rthread, JavaThread::vm_result_offset())); + __ str(R0_tos, Address(Rthread, JavaThread::vm_result_oop_offset())); // remove the activation (without doing throws on illegalMonitorExceptions) __ remove_activation(vtos, Rexception_pc, false, true, false); // restore exception - __ get_vm_result(Rexception_obj, Rtemp); + __ get_vm_result_oop(Rexception_obj, Rtemp); // In between activations - previous activation type unknown yet // compute continuation point - the continuation point expects diff --git a/src/hotspot/cpu/arm/templateTable_arm.cpp b/src/hotspot/cpu/arm/templateTable_arm.cpp index bbe5713090a..50e3761dcb9 100644 --- a/src/hotspot/cpu/arm/templateTable_arm.cpp +++ b/src/hotspot/cpu/arm/templateTable_arm.cpp @@ -538,7 +538,7 @@ void TemplateTable::condy_helper(Label& Done) __ mov(rtmp, (int) bytecode()); __ call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rtmp); - __ get_vm_result_2(flags, rtmp); + __ get_vm_result_metadata(flags, rtmp); // VMr = obj = base address to find primitive value to push // VMr2 = flags = (tos, off) using format of CPCE::_flags @@ -4143,8 +4143,7 @@ void TemplateTable::checkcast() { __ push(atos); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(Rsuper, Robj); + __ get_vm_result_metadata(Rsuper, Robj); __ pop_ptr(Robj); __ b(resolved); @@ -4214,8 +4213,7 @@ void TemplateTable::instanceof() { __ push(atos); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(Rsuper, Robj); + __ get_vm_result_metadata(Rsuper, Robj); __ pop_ptr(Robj); __ b(resolved); diff --git a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp index 11c01dcdc60..79b129c08ae 100644 --- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp @@ -82,10 +82,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, if (oop_result1->is_valid() || metadata_result->is_valid()) { li(R0, 0); if (oop_result1->is_valid()) { - std(R0, in_bytes(JavaThread::vm_result_offset()), R16_thread); + std(R0, in_bytes(JavaThread::vm_result_oop_offset()), R16_thread); } if (metadata_result->is_valid()) { - std(R0, in_bytes(JavaThread::vm_result_2_offset()), R16_thread); + std(R0, in_bytes(JavaThread::vm_result_metadata_offset()), R16_thread); } } @@ -112,10 +112,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, // Get oop results if there are any and reset the values in the thread. if (oop_result1->is_valid()) { - get_vm_result(oop_result1); + get_vm_result_oop(oop_result1); } if (metadata_result->is_valid()) { - get_vm_result_2(metadata_result); + get_vm_result_metadata(metadata_result); } return (int)(return_pc - code_section()->start()); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 40019ef9f4b..f82395b14fb 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -1337,7 +1337,7 @@ void MacroAssembler::call_VM_base(Register oop_result, // Get oop result if there is one and reset the value in the thread. if (oop_result->is_valid()) { - get_vm_result(oop_result); + get_vm_result_oop(oop_result); } _last_calls_return_pc = return_pc; @@ -3425,34 +3425,34 @@ void MacroAssembler::set_top_ijava_frame_at_SP_as_last_Java_frame(Register sp, R set_last_Java_frame(/*sp=*/sp, /*pc=*/tmp1); } -void MacroAssembler::get_vm_result(Register oop_result) { +void MacroAssembler::get_vm_result_oop(Register oop_result) { // Read: // R16_thread - // R16_thread->in_bytes(JavaThread::vm_result_offset()) + // R16_thread->in_bytes(JavaThread::vm_result_oop_offset()) // // Updated: // oop_result - // R16_thread->in_bytes(JavaThread::vm_result_offset()) + // R16_thread->in_bytes(JavaThread::vm_result_oop_offset()) - ld(oop_result, in_bytes(JavaThread::vm_result_offset()), R16_thread); + ld(oop_result, in_bytes(JavaThread::vm_result_oop_offset()), R16_thread); li(R0, 0); - std(R0, in_bytes(JavaThread::vm_result_offset()), R16_thread); + std(R0, in_bytes(JavaThread::vm_result_oop_offset()), R16_thread); verify_oop(oop_result, FILE_AND_LINE); } -void MacroAssembler::get_vm_result_2(Register metadata_result) { +void MacroAssembler::get_vm_result_metadata(Register metadata_result) { // Read: // R16_thread - // R16_thread->in_bytes(JavaThread::vm_result_2_offset()) + // R16_thread->in_bytes(JavaThread::vm_result_metadata_offset()) // // Updated: // metadata_result - // R16_thread->in_bytes(JavaThread::vm_result_2_offset()) + // R16_thread->in_bytes(JavaThread::vm_result_metadata_offset()) - ld(metadata_result, in_bytes(JavaThread::vm_result_2_offset()), R16_thread); + ld(metadata_result, in_bytes(JavaThread::vm_result_metadata_offset()), R16_thread); li(R0, 0); - std(R0, in_bytes(JavaThread::vm_result_2_offset()), R16_thread); + std(R0, in_bytes(JavaThread::vm_result_metadata_offset()), R16_thread); } Register MacroAssembler::encode_klass_not_null(Register dst, Register src) { diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp index b709cf16713..7e2925ace26 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp @@ -745,8 +745,8 @@ class MacroAssembler: public Assembler { void set_top_ijava_frame_at_SP_as_last_Java_frame(Register sp, Register tmp1, Label* jpc = nullptr); // Read vm result from thread: oop_result = R16_thread->result; - void get_vm_result (Register oop_result); - void get_vm_result_2(Register metadata_result); + void get_vm_result_oop(Register oop_result); + void get_vm_result_metadata(Register metadata_result); static bool needs_explicit_null_check(intptr_t offset); static bool uses_implicit_null_check(void* address); diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 0d0e004c923..5a94d469434 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -3404,7 +3404,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti RegisterSaver::restore_live_registers_and_pop_frame(masm, frame_size_in_bytes, /*restore_ctr*/ false); // Get the returned method. - __ get_vm_result_2(R19_method); + __ get_vm_result_metadata(R19_method); __ bctr(); @@ -3418,7 +3418,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti __ li(R11_scratch1, 0); __ ld(R3_ARG1, thread_(pending_exception)); - __ std(R11_scratch1, in_bytes(JavaThread::vm_result_offset()), R16_thread); + __ std(R11_scratch1, in_bytes(JavaThread::vm_result_oop_offset()), R16_thread); __ b64_patchable(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); // ------------- diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp index b1ad3cd48bc..a8f5dbda484 100644 --- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp @@ -2160,12 +2160,12 @@ void TemplateInterpreterGenerator::generate_throw_exception() { { __ pop_ptr(Rexception); __ verify_oop(Rexception); - __ std(Rexception, in_bytes(JavaThread::vm_result_offset()), R16_thread); + __ std(Rexception, in_bytes(JavaThread::vm_result_oop_offset()), R16_thread); __ unlock_if_synchronized_method(vtos, /* throw_monitor_exception */ false, true); __ notify_method_exit(false, vtos, InterpreterMacroAssembler::SkipNotifyJVMTI, false); - __ get_vm_result(Rexception); + __ get_vm_result_oop(Rexception); // We are done with this activation frame; find out where to go next. // The continuation point will be an exception handler, which expects diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index 934bb1bd529..8be6080e3d1 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -386,7 +386,7 @@ void TemplateTable::condy_helper(Label& Done) { const Register rarg = R4_ARG2; __ li(rarg, (int)bytecode()); call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg); - __ get_vm_result_2(flags); + __ get_vm_result_metadata(flags); // VMr = obj = base address to find primitive value to push // VMr2 = flags = (tos, off) using format of CPCE::_flags @@ -3964,7 +3964,7 @@ void TemplateTable::checkcast() { // Call into the VM to "quicken" instanceof. __ push_ptr(); // for GC call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ get_vm_result_2(RspecifiedKlass); + __ get_vm_result_metadata(RspecifiedKlass); __ pop_ptr(); // Restore receiver. __ b(Lresolved); @@ -4026,7 +4026,7 @@ void TemplateTable::instanceof() { // Call into the VM to "quicken" instanceof. __ push_ptr(); // for GC call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ get_vm_result_2(RspecifiedKlass); + __ get_vm_result_metadata(RspecifiedKlass); __ pop_ptr(); // Restore receiver. __ b(Lresolved); diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp index 0f1f1dd891c..849417725a7 100644 --- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -89,10 +89,10 @@ int StubAssembler::call_RT(Register oop_result, Register metadata_result, addres // exception pending => remove activation and forward to exception handler // make sure that the vm_results are cleared if (oop_result->is_valid()) { - sd(zr, Address(xthread, JavaThread::vm_result_offset())); + sd(zr, Address(xthread, JavaThread::vm_result_oop_offset())); } if (metadata_result->is_valid()) { - sd(zr, Address(xthread, JavaThread::vm_result_2_offset())); + sd(zr, Address(xthread, JavaThread::vm_result_metadata_offset())); } if (frame_size() == no_frame_size) { leave(); @@ -106,10 +106,10 @@ int StubAssembler::call_RT(Register oop_result, Register metadata_result, addres } // get oop results if there are any and reset the values in the thread if (oop_result->is_valid()) { - get_vm_result(oop_result, xthread); + get_vm_result_oop(oop_result, xthread); } if (metadata_result->is_valid()) { - get_vm_result_2(metadata_result, xthread); + get_vm_result_metadata(metadata_result, xthread); } return call_offset; } @@ -427,8 +427,8 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ ld(exception_pc, Address(fp, frame::return_addr_offset * BytesPerWord)); // make sure that the vm_results are cleared (may be unnecessary) - __ sd(zr, Address(xthread, JavaThread::vm_result_offset())); - __ sd(zr, Address(xthread, JavaThread::vm_result_2_offset())); + __ sd(zr, Address(xthread, JavaThread::vm_result_oop_offset())); + __ sd(zr, Address(xthread, JavaThread::vm_result_metadata_offset())); break; case C1StubId::handle_exception_nofpu_id: case C1StubId::handle_exception_id: diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 71481565fc7..b5c311c341d 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -498,19 +498,19 @@ void MacroAssembler::call_VM_base(Register oop_result, // get oop result if there is one and reset the value in the thread if (oop_result->is_valid()) { - get_vm_result(oop_result, java_thread); + get_vm_result_oop(oop_result, java_thread); } } -void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) { - ld(oop_result, Address(java_thread, JavaThread::vm_result_offset())); - sd(zr, Address(java_thread, JavaThread::vm_result_offset())); +void MacroAssembler::get_vm_result_oop(Register oop_result, Register java_thread) { + ld(oop_result, Address(java_thread, JavaThread::vm_result_oop_offset())); + sd(zr, Address(java_thread, JavaThread::vm_result_oop_offset())); verify_oop_msg(oop_result, "broken oop in call_VM_base"); } -void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) { - ld(metadata_result, Address(java_thread, JavaThread::vm_result_2_offset())); - sd(zr, Address(java_thread, JavaThread::vm_result_2_offset())); +void MacroAssembler::get_vm_result_metadata(Register metadata_result, Register java_thread) { + ld(metadata_result, Address(java_thread, JavaThread::vm_result_metadata_offset())); + sd(zr, Address(java_thread, JavaThread::vm_result_metadata_offset())); } void MacroAssembler::clinit_barrier(Register klass, Register tmp, Label* L_fast_path, Label* L_slow_path) { diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index e145639bbe7..b390fb236c2 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -122,8 +122,8 @@ class MacroAssembler: public Assembler { Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - void get_vm_result(Register oop_result, Register java_thread); - void get_vm_result_2(Register metadata_result, Register java_thread); + void get_vm_result_oop(Register oop_result, Register java_thread); + void get_vm_result_metadata(Register metadata_result, Register java_thread); // These always tightly bind to MacroAssembler::call_VM_leaf_base // bypassing the virtual implementation diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 49e630bbfdf..10790841490 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -2646,7 +2646,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti __ bnez(t1, pending); // get the returned Method* - __ get_vm_result_2(xmethod, xthread); + __ get_vm_result_metadata(xmethod, xthread); __ sd(xmethod, Address(sp, reg_saver.reg_offset_in_bytes(xmethod))); // x10 is where we want to jump, overwrite t1 which is saved and temporary @@ -2664,7 +2664,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // exception pending => remove activation and forward to exception handler - __ sd(zr, Address(xthread, JavaThread::vm_result_offset())); + __ sd(zr, Address(xthread, JavaThread::vm_result_oop_offset())); __ ld(x10, Address(xthread, Thread::pending_exception_offset())); __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index e96bd2e1f2a..72e1180164b 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1725,11 +1725,11 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // preserve exception over this code sequence __ pop_ptr(x10); - __ sd(x10, Address(xthread, JavaThread::vm_result_offset())); + __ sd(x10, Address(xthread, JavaThread::vm_result_oop_offset())); // remove the activation (without doing throws on illegalMonitorExceptions) __ remove_activation(vtos, false, true, false); // restore exception - __ get_vm_result(x10, xthread); + __ get_vm_result_oop(x10, xthread); // In between activations - previous activation type unknown yet // compute continuation point - the continuation point expects the diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp index 216cfdeed79..a035326be01 100644 --- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp @@ -460,7 +460,7 @@ void TemplateTable::condy_helper(Label& Done) { __ mv(rarg, (int) bytecode()); __ call_VM(obj, entry, rarg); - __ get_vm_result_2(flags, xthread); + __ get_vm_result_metadata(flags, xthread); // VMr = obj = base address to find primitive value to push // VMr2 = flags = (tos, off) using format of CPCE::_flags @@ -3657,8 +3657,7 @@ void TemplateTable::checkcast() { __ push(atos); // save receiver for result, and for GC call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(x10, xthread); + __ get_vm_result_metadata(x10, xthread); __ pop_reg(x13); // restore receiver __ j(resolved); @@ -3712,8 +3711,7 @@ void TemplateTable::instanceof() { __ push(atos); // save receiver for result, and for GC call_VM(x10, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(x10, xthread); + __ get_vm_result_metadata(x10, xthread); __ pop_reg(x13); // restore receiver __ verify_oop(x13); __ load_klass(x13, x13); diff --git a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp index b5d804d283e..db04703ceb0 100644 --- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp +++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp @@ -86,10 +86,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre // Make sure that the vm_results are cleared. if (oop_result1->is_valid()) { - clear_mem(Address(Z_thread, JavaThread::vm_result_offset()), sizeof(jlong)); + clear_mem(Address(Z_thread, JavaThread::vm_result_oop_offset()), sizeof(jlong)); } if (metadata_result->is_valid()) { - clear_mem(Address(Z_thread, JavaThread::vm_result_2_offset()), sizeof(jlong)); + clear_mem(Address(Z_thread, JavaThread::vm_result_metadata_offset()), sizeof(jlong)); } if (frame_size() == no_frame_size) { // Pop the stub frame. @@ -109,10 +109,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre // Get oop results if there are any and reset the values in the thread. if (oop_result1->is_valid()) { - get_vm_result(oop_result1); + get_vm_result_oop(oop_result1); } if (metadata_result->is_valid()) { - get_vm_result_2(metadata_result); + get_vm_result_metadata(metadata_result); } return call_offset; @@ -886,8 +886,8 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) DEBUG_ONLY(__ z_lay(reg_fp, Address(Z_SP, frame_size_in_bytes));) // Make sure that the vm_results are cleared (may be unnecessary). - __ clear_mem(Address(Z_thread, JavaThread::vm_result_offset()), sizeof(oop)); - __ clear_mem(Address(Z_thread, JavaThread::vm_result_2_offset()), sizeof(Metadata*)); + __ clear_mem(Address(Z_thread, JavaThread::vm_result_oop_offset()), sizeof(oop)); + __ clear_mem(Address(Z_thread, JavaThread::vm_result_metadata_offset()), sizeof(Metadata*)); break; } case C1StubId::handle_exception_nofpu_id: diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 54370a4959b..88aedd1b5c0 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -2304,7 +2304,7 @@ void MacroAssembler::call_VM_base(Register oop_result, // Get oop result if there is one and reset the value in the thread. if (oop_result->is_valid()) { - get_vm_result(oop_result); + get_vm_result_oop(oop_result); } _last_calls_return_pc = return_pc; // Wipe out other (error handling) calls. @@ -4067,22 +4067,22 @@ void MacroAssembler::set_thread_state(JavaThreadState new_state) { store_const(Address(Z_thread, JavaThread::thread_state_offset()), new_state, Z_R0, false); } -void MacroAssembler::get_vm_result(Register oop_result) { - z_lg(oop_result, Address(Z_thread, JavaThread::vm_result_offset())); - clear_mem(Address(Z_thread, JavaThread::vm_result_offset()), sizeof(void*)); +void MacroAssembler::get_vm_result_oop(Register oop_result) { + z_lg(oop_result, Address(Z_thread, JavaThread::vm_result_oop_offset())); + clear_mem(Address(Z_thread, JavaThread::vm_result_oop_offset()), sizeof(void*)); verify_oop(oop_result, FILE_AND_LINE); } -void MacroAssembler::get_vm_result_2(Register result) { - z_lg(result, Address(Z_thread, JavaThread::vm_result_2_offset())); - clear_mem(Address(Z_thread, JavaThread::vm_result_2_offset()), sizeof(void*)); +void MacroAssembler::get_vm_result_metadata(Register result) { + z_lg(result, Address(Z_thread, JavaThread::vm_result_metadata_offset())); + clear_mem(Address(Z_thread, JavaThread::vm_result_metadata_offset()), sizeof(void*)); } // We require that C code which does not return a value in vm_result will // leave it undisturbed. void MacroAssembler::set_vm_result(Register oop_result) { - z_stg(oop_result, Address(Z_thread, JavaThread::vm_result_offset())); + z_stg(oop_result, Address(Z_thread, JavaThread::vm_result_oop_offset())); } // Explicit null checks (used for method handle code). diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp index 3f7744588d6..4aa7bb56f3a 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp @@ -816,8 +816,8 @@ class MacroAssembler: public Assembler { void set_thread_state(JavaThreadState new_state); // Read vm result from thread. - void get_vm_result (Register oop_result); - void get_vm_result_2(Register result); + void get_vm_result_oop (Register oop_result); + void get_vm_result_metadata(Register result); // Vm result is currently getting hijacked to for oop preservation. void set_vm_result(Register oop_result); diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index 7b6735eabcc..f4487ccabec 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -3043,7 +3043,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti RegisterSaver::restore_live_registers(masm, RegisterSaver::all_registers); // get the returned method - __ get_vm_result_2(Z_method); + __ get_vm_result_metadata(Z_method); // We are back to the original state on entry and ready to go. __ z_br(Z_R1_scratch); @@ -3057,7 +3057,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // exception pending => remove activation and forward to exception handler __ z_lgr(Z_R2, Z_R0); // pending_exception - __ clear_mem(Address(Z_thread, JavaThread::vm_result_offset()), sizeof(jlong)); + __ clear_mem(Address(Z_thread, JavaThread::vm_result_oop_offset()), sizeof(jlong)); __ load_const_optimized(Z_R1_scratch, StubRoutines::forward_exception_entry()); __ z_br(Z_R1_scratch); diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index 841f4f9ca4b..a52d20e32a3 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -2228,7 +2228,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ remove_activation(vtos, noreg/*ret.pc already loaded*/, false/*throw exc*/, true/*install exc*/, false/*notify jvmti*/); __ z_lg(Z_fp, _z_abi(callers_sp), Z_SP); // Restore frame pointer. - __ get_vm_result(Z_ARG1); // Restore exception. + __ get_vm_result_oop(Z_ARG1); // Restore exception. __ verify_oop(Z_ARG1); __ z_lgr(Z_ARG2, return_pc); // Restore return address. diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp index e6c0c7781a3..4262c77ecd7 100644 --- a/src/hotspot/cpu/s390/templateTable_s390.cpp +++ b/src/hotspot/cpu/s390/templateTable_s390.cpp @@ -540,7 +540,7 @@ void TemplateTable::condy_helper(Label& Done) { const Register rarg = Z_ARG2; __ load_const_optimized(rarg, (int)bytecode()); call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg); - __ get_vm_result_2(flags); + __ get_vm_result_metadata(flags); // VMr = obj = base address to find primitive value to push // VMr2 = flags = (tos, off) using format of CPCE::_flags @@ -4063,7 +4063,7 @@ void TemplateTable::checkcast() { __ push(atos); // Save receiver for result, and for GC. call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ get_vm_result_2(Z_tos); + __ get_vm_result_metadata(Z_tos); Register receiver = Z_ARG4; Register klass = Z_tos; @@ -4135,7 +4135,7 @@ void TemplateTable::instanceof() { __ push(atos); // Save receiver for result, and for GC. call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ get_vm_result_2(Z_tos); + __ get_vm_result_metadata(Z_tos); Register receiver = Z_tmp_2; Register klass = Z_tos; diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index db6614686a2..726574e69e8 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -103,10 +103,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre movptr(rax, Address(thread, Thread::pending_exception_offset())); // make sure that the vm_results are cleared if (oop_result1->is_valid()) { - movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); + movptr(Address(thread, JavaThread::vm_result_oop_offset()), NULL_WORD); } if (metadata_result->is_valid()) { - movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); + movptr(Address(thread, JavaThread::vm_result_metadata_offset()), NULL_WORD); } if (frame_size() == no_frame_size) { leave(); @@ -120,10 +120,10 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre } // get oop results if there are any and reset the values in the thread if (oop_result1->is_valid()) { - get_vm_result(oop_result1); + get_vm_result_oop(oop_result1); } if (metadata_result->is_valid()) { - get_vm_result_2(metadata_result); + get_vm_result_metadata(metadata_result); } assert(call_offset >= 0, "Should be set"); @@ -532,8 +532,8 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm) __ movptr(exception_pc, Address(rbp, 1*BytesPerWord)); // make sure that the vm_results are cleared (may be unnecessary) - __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); - __ movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); + __ movptr(Address(thread, JavaThread::vm_result_oop_offset()), NULL_WORD); + __ movptr(Address(thread, JavaThread::vm_result_metadata_offset()), NULL_WORD); break; case C1StubId::handle_exception_nofpu_id: case C1StubId::handle_exception_id: diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 6093ad69519..25de76a7e40 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1226,7 +1226,7 @@ void MacroAssembler::call_VM_base(Register oop_result, // get oop result if there is one and reset the value in the thread if (oop_result->is_valid()) { - get_vm_result(oop_result); + get_vm_result_oop(oop_result); } } @@ -1316,15 +1316,15 @@ void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Reg MacroAssembler::call_VM_leaf_base(entry_point, 4); } -void MacroAssembler::get_vm_result(Register oop_result) { - movptr(oop_result, Address(r15_thread, JavaThread::vm_result_offset())); - movptr(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); +void MacroAssembler::get_vm_result_oop(Register oop_result) { + movptr(oop_result, Address(r15_thread, JavaThread::vm_result_oop_offset())); + movptr(Address(r15_thread, JavaThread::vm_result_oop_offset()), NULL_WORD); verify_oop_msg(oop_result, "broken oop in call_VM_base"); } -void MacroAssembler::get_vm_result_2(Register metadata_result) { - movptr(metadata_result, Address(r15_thread, JavaThread::vm_result_2_offset())); - movptr(Address(r15_thread, JavaThread::vm_result_2_offset()), NULL_WORD); +void MacroAssembler::get_vm_result_metadata(Register metadata_result) { + movptr(metadata_result, Address(r15_thread, JavaThread::vm_result_metadata_offset())); + movptr(Address(r15_thread, JavaThread::vm_result_metadata_offset()), NULL_WORD); } void MacroAssembler::check_and_handle_earlyret() { diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index bc25138f821..efd1a4c154f 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -282,8 +282,8 @@ class MacroAssembler: public Assembler { Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - void get_vm_result (Register oop_result); - void get_vm_result_2(Register metadata_result); + void get_vm_result_oop(Register oop_result); + void get_vm_result_metadata(Register metadata_result); // These always tightly bind to MacroAssembler::call_VM_base // bypassing the virtual implementation diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 09c102aa5d1..621340964ac 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -3233,7 +3233,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti __ jcc(Assembler::notEqual, pending); // get the returned Method* - __ get_vm_result_2(rbx); + __ get_vm_result_metadata(rbx); __ movptr(Address(rsp, RegisterSaver::rbx_offset_in_bytes()), rbx); __ movptr(Address(rsp, RegisterSaver::rax_offset_in_bytes()), rax); @@ -3252,7 +3252,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti // exception pending => remove activation and forward to exception handler - __ movptr(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::vm_result_oop_offset()), NULL_WORD); __ movptr(rax, Address(r15_thread, Thread::pending_exception_offset())); __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index bdc2ca908bd..45e30a8b4fb 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -1543,11 +1543,11 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // preserve exception over this code sequence __ pop_ptr(rax); - __ movptr(Address(thread, JavaThread::vm_result_offset()), rax); + __ movptr(Address(thread, JavaThread::vm_result_oop_offset()), rax); // remove the activation (without doing throws on illegalMonitorExceptions) __ remove_activation(vtos, rdx, false, true, false); // restore exception - __ get_vm_result(rax); + __ get_vm_result_oop(rax); // In between activations - previous activation type unknown yet // compute continuation point - the continuation point expects the diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp index 226b8b1c655..43da80f4082 100644 --- a/src/hotspot/cpu/x86/templateTable_x86.cpp +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp @@ -470,7 +470,7 @@ void TemplateTable::condy_helper(Label& Done) { const Register rarg = c_rarg1; __ movl(rarg, (int)bytecode()); call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg); - __ get_vm_result_2(flags); + __ get_vm_result_metadata(flags); // VMr = obj = base address to find primitive value to push // VMr2 = flags = (tos, off) using format of CPCE::_flags __ movl(off, flags); @@ -3680,8 +3680,7 @@ void TemplateTable::checkcast() { __ push(atos); // save receiver for result, and for GC call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(rax); + __ get_vm_result_metadata(rax); __ pop_ptr(rdx); // restore receiver __ jmpb(resolved); @@ -3737,8 +3736,7 @@ void TemplateTable::instanceof() { __ push(atos); // save receiver for result, and for GC call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - // vm_result_2 has metadata result - __ get_vm_result_2(rax); + __ get_vm_result_metadata(rax); __ pop_ptr(rdx); // restore receiver __ verify_oop(rdx); diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index d7a9c8d56d4..9d4b35024ed 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -370,7 +370,7 @@ JRT_ENTRY(void, Runtime1::new_instance(JavaThread* current, Klass* klass)) h->initialize(CHECK); // allocate instance and return via TLS oop obj = h->allocate_instance(CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END @@ -386,7 +386,7 @@ JRT_ENTRY(void, Runtime1::new_type_array(JavaThread* current, Klass* klass, jint assert(klass->is_klass(), "not a class"); BasicType elt_type = TypeArrayKlass::cast(klass)->element_type(); oop obj = oopFactory::new_typeArray(elt_type, length, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); // This is pretty rare but this runtime patch is stressful to deoptimization // if we deoptimize here so force a deopt to stress the path. if (DeoptimizeALot) { @@ -409,7 +409,7 @@ JRT_ENTRY(void, Runtime1::new_object_array(JavaThread* current, Klass* array_kla Handle holder(current, array_klass->klass_holder()); // keep the klass alive Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); // This is pretty rare but this runtime patch is stressful to deoptimization // if we deoptimize here so force a deopt to stress the path. if (DeoptimizeALot) { @@ -428,7 +428,7 @@ JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* current, Klass* klass, int assert(rank >= 1, "rank must be nonzero"); Handle holder(current, klass->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END @@ -642,7 +642,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c } } - current->set_vm_result(exception()); + current->set_vm_result_oop(exception()); // Set flag if return address is a method handle call site. current->set_is_method_handle_return(nm->is_method_handle_return(pc)); diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 52eab4f796e..0f16b17e99e 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -150,7 +150,7 @@ JRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* current, bool wide)) assert (tag.is_unresolved_klass() || tag.is_klass(), "wrong ldc call"); Klass* klass = pool->klass_at(cp_index, CHECK); oop java_class = klass->java_mirror(); - current->set_vm_result(java_class); + current->set_vm_result_oop(java_class); JRT_END JRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* current, Bytecodes::Code bytecode)) { @@ -193,14 +193,14 @@ JRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* current, Bytecodes:: } } #endif - current->set_vm_result(result); + current->set_vm_result_oop(result); if (!is_fast_aldc) { // Tell the interpreter how to unbox the primitive. guarantee(java_lang_boxing_object::is_instance(result, type), ""); int offset = java_lang_boxing_object::value_offset(type); intptr_t flags = ((as_TosState(type) << ConstantPoolCache::tos_state_shift) | (offset & ConstantPoolCache::field_index_mask)); - current->set_vm_result_2((Metadata*)flags); + current->set_vm_result_metadata((Metadata*)flags); } } JRT_END @@ -220,20 +220,20 @@ JRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* current, ConstantPool* pool klass->initialize(CHECK); oop obj = klass->allocate_instance(CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END JRT_ENTRY(void, InterpreterRuntime::newarray(JavaThread* current, BasicType type, jint size)) oop obj = oopFactory::new_typeArray(type, size, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END JRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* current, ConstantPool* pool, int index, jint size)) Klass* klass = pool->klass_at(index, CHECK); objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END @@ -261,7 +261,7 @@ JRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* current, jint* fi dims[index] = first_size_address[n]; } oop obj = ArrayKlass::cast(klass)->multi_allocate(nof_dims, dims, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END @@ -283,7 +283,7 @@ JRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* current)) // thread quicken the bytecode before we get here. // assert( cpool->tag_at(which).is_unresolved_klass(), "should only come here to quicken bytecodes" ); Klass* klass = cpool->klass_at(which, CHECK); - current->set_vm_result_2(klass); + current->set_vm_result_metadata(klass); JRT_END @@ -383,7 +383,7 @@ JRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* current, char* } // create exception Handle exception = Exceptions::new_exception(current, s, message); - current->set_vm_result(exception()); + current->set_vm_result_oop(exception()); JRT_END @@ -402,7 +402,7 @@ JRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* current, } // create exception, with klass name as detail message Handle exception = Exceptions::new_exception(current, s, klass_name); - current->set_vm_result(exception()); + current->set_vm_result_oop(exception()); JRT_END JRT_ENTRY(void, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException(JavaThread* current, arrayOopDesc* a, jint index)) @@ -461,7 +461,7 @@ JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea // Allocation of scalar replaced object used in this frame // failed. Unconditionally pop the frame. current->dec_frames_to_pop_failed_realloc(); - current->set_vm_result(h_exception()); + current->set_vm_result_oop(h_exception()); // If the method is synchronized we already unlocked the monitor // during deoptimization so the interpreter needs to skip it when // the frame is popped. @@ -476,7 +476,7 @@ JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea if (current->do_not_unlock_if_synchronized()) { ResourceMark rm; assert(current_bci == 0, "bci isn't zero for do_not_unlock_if_synchronized"); - current->set_vm_result(exception); + current->set_vm_result_oop(exception); return Interpreter::remove_activation_entry(); } @@ -577,7 +577,7 @@ JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea JvmtiExport::notice_unwind_due_to_exception(current, h_method(), handler_pc, h_exception(), (handler_pc != nullptr)); } - current->set_vm_result(h_exception()); + current->set_vm_result_oop(h_exception()); return continuation; JRT_END @@ -765,11 +765,11 @@ JRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThre // method will be called during an exception unwind. assert(!HAS_PENDING_EXCEPTION, "no pending exception"); - Handle exception(current, current->vm_result()); + Handle exception(current, current->vm_result_oop()); assert(exception() != nullptr, "vm result should be set"); - current->set_vm_result(nullptr); // clear vm result before continuing (may cause memory leaks and assert failures) + current->set_vm_result_oop(nullptr); // clear vm result before continuing (may cause memory leaks and assert failures) exception = get_preinitialized_exception(vmClasses::IllegalMonitorStateException_klass(), CATCH); - current->set_vm_result(exception()); + current->set_vm_result_oop(exception()); JRT_END @@ -1474,7 +1474,7 @@ JRT_END #if INCLUDE_JVMTI // This is a support of the JVMTI PopFrame interface. // Make sure it is an invokestatic of a polymorphic intrinsic that has a member_name argument -// and return it as a vm_result so that it can be reloaded in the list of invokestatic parameters. +// and return it as a vm_result_oop so that it can be reloaded in the list of invokestatic parameters. // The member_name argument is a saved reference (in local#0) to the member_name. // For backward compatibility with some JDK versions (7, 8) it can also be a direct method handle. // FIXME: remove DMH case after j.l.i.InvokerBytecodeGenerator code shape is updated. @@ -1495,9 +1495,9 @@ JRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* current, // FIXME: remove after j.l.i.InvokerBytecodeGenerator code shape is updated. member_name_oop = java_lang_invoke_DirectMethodHandle::member(member_name_oop); } - current->set_vm_result(member_name_oop); + current->set_vm_result_oop(member_name_oop); } else { - current->set_vm_result(nullptr); + current->set_vm_result_oop(nullptr); } JRT_END #endif // INCLUDE_JVMTI diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp index 43b618dcc1e..401953a170f 100644 --- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp @@ -2033,8 +2033,8 @@ run: // Must prevent reordering of stores for object initialization // with stores that publish the new object. OrderAccess::storestore(); - SET_STACK_OBJECT(THREAD->vm_result(), 0); - THREAD->set_vm_result(nullptr); + SET_STACK_OBJECT(THREAD->vm_result_oop(), 0); + THREAD->set_vm_result_oop(nullptr); UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1); } CASE(_anewarray): { @@ -2045,8 +2045,8 @@ run: // Must prevent reordering of stores for object initialization // with stores that publish the new object. OrderAccess::storestore(); - SET_STACK_OBJECT(THREAD->vm_result(), -1); - THREAD->set_vm_result(nullptr); + SET_STACK_OBJECT(THREAD->vm_result_oop(), -1); + THREAD->set_vm_result_oop(nullptr); UPDATE_PC_AND_CONTINUE(3); } CASE(_multianewarray): { @@ -2062,8 +2062,8 @@ run: // Must prevent reordering of stores for object initialization // with stores that publish the new object. OrderAccess::storestore(); - SET_STACK_OBJECT(THREAD->vm_result(), -dims); - THREAD->set_vm_result(nullptr); + SET_STACK_OBJECT(THREAD->vm_result_oop(), -dims); + THREAD->set_vm_result_oop(nullptr); UPDATE_PC_AND_TOS_AND_CONTINUE(4, -(dims-1)); } CASE(_checkcast): @@ -2144,8 +2144,8 @@ run: oop result = constants->resolved_reference_at(index); if (result == nullptr) { CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); - SET_STACK_OBJECT(THREAD->vm_result(), 0); - THREAD->set_vm_result(nullptr); + SET_STACK_OBJECT(THREAD->vm_result_oop(), 0); + THREAD->set_vm_result_oop(nullptr); } else { VERIFY_OOP(result); SET_STACK_OBJECT(result, 0); @@ -2161,15 +2161,15 @@ run: case JVM_CONSTANT_UnresolvedClass: case JVM_CONSTANT_UnresolvedClassInError: CALL_VM(InterpreterRuntime::ldc(THREAD, wide), handle_exception); - SET_STACK_OBJECT(THREAD->vm_result(), 0); - THREAD->set_vm_result(nullptr); + SET_STACK_OBJECT(THREAD->vm_result_oop(), 0); + THREAD->set_vm_result_oop(nullptr); break; case JVM_CONSTANT_Dynamic: case JVM_CONSTANT_DynamicInError: { CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); - oop result = THREAD->vm_result(); + oop result = THREAD->vm_result_oop(); VERIFY_OOP(result); jvalue value; @@ -2211,7 +2211,7 @@ run: case JVM_CONSTANT_DynamicInError: { CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); - oop result = THREAD->vm_result(); + oop result = THREAD->vm_result_oop(); VERIFY_OOP(result); jvalue value; @@ -2250,7 +2250,7 @@ run: if (result == nullptr) { CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); - result = THREAD->vm_result(); + result = THREAD->vm_result_oop(); } if (result == Universe::the_null_sentinel()) result = nullptr; @@ -2518,8 +2518,8 @@ run: // Must prevent reordering of stores for object initialization // with stores that publish the new object. OrderAccess::storestore(); - SET_STACK_OBJECT(THREAD->vm_result(), -1); - THREAD->set_vm_result(nullptr); + SET_STACK_OBJECT(THREAD->vm_result_oop(), -1); + THREAD->set_vm_result_oop(nullptr); UPDATE_PC_AND_CONTINUE(2); } @@ -2959,8 +2959,8 @@ run: CALL_VM(continuation_bci = (intptr_t)InterpreterRuntime::exception_handler_for_exception(THREAD, except_oop()), handle_exception); - except_oop = Handle(THREAD, THREAD->vm_result()); - THREAD->set_vm_result(nullptr); + except_oop = Handle(THREAD, THREAD->vm_result_oop()); + THREAD->set_vm_result_oop(nullptr); if (continuation_bci >= 0) { // Place exception on top of stack SET_STACK_OBJECT(except_oop(), 0); diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp index d1ae48e4a75..cf94293f0a3 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp @@ -277,7 +277,7 @@ bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) { // around using this function /* * // can't reach these oop* from the outside - f->do_oop((oop*) &_vm_result); + f->do_oop((oop*) &_vm_result_oop); f->do_oop((oop*) &_exception_oop); f->do_oop((oop*) &_pending_async_exception); */ diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 8e885e5f7f9..6f1fa52576e 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -96,7 +96,7 @@ static void deopt_caller() { // call is of the variety where allocation failure returns null without an // exception, the following action is taken: // 1. The pending OutOfMemoryError is cleared -// 2. null is written to JavaThread::_vm_result +// 2. null is written to JavaThread::_vm_result_oop class RetryableAllocationMark { private: InternalOOMEMark _iom; @@ -107,7 +107,7 @@ class RetryableAllocationMark { if (THREAD != nullptr) { if (HAS_PENDING_EXCEPTION) { oop ex = PENDING_EXCEPTION; - THREAD->set_vm_result(nullptr); + THREAD->set_vm_result_oop(nullptr); if (ex->is_a(vmClasses::OutOfMemoryError_klass())) { CLEAR_PENDING_EXCEPTION; } @@ -127,12 +127,12 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance_or_null(JavaThread* current, Kl if (!h->is_initialized()) { // Cannot re-execute class initialization without side effects // so return without attempting the initialization - current->set_vm_result(nullptr); + current->set_vm_result_oop(nullptr); return; } // allocate instance and return via TLS oop obj = h->allocate_instance(CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); } JRT_BLOCK_END; SharedRuntime::on_slowpath_allocation_exit(current); @@ -166,7 +166,7 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_or_null(JavaThread* current, Klass deopt_caller(); } } - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_BLOCK_END; SharedRuntime::on_slowpath_allocation_exit(current); JRT_END @@ -177,13 +177,13 @@ JRT_ENTRY(void, JVMCIRuntime::new_multi_array_or_null(JavaThread* current, Klass Handle holder(current, klass->klass_holder()); // keep the klass alive RetryableAllocationMark ram(current); oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array_or_null(JavaThread* current, oopDesc* element_mirror, jint length)) RetryableAllocationMark ram(current); oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance_or_null(JavaThread* current, oopDesc* type_mirror)) @@ -201,12 +201,12 @@ JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance_or_null(JavaThread* current, if (!klass->is_initialized()) { // Cannot re-execute class initialization without side effects // so return without attempting the initialization - current->set_vm_result(nullptr); + current->set_vm_result_oop(nullptr); return; } oop obj = klass->allocate_instance(CHECK); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END extern void vm_exit(int code); @@ -533,7 +533,7 @@ JRT_ENTRY(jlong, JVMCIRuntime::invoke_static_method_one_arg(JavaThread* current, if (return_type == T_VOID) { return 0; } else if (return_type == T_OBJECT || return_type == T_ARRAY) { - current->set_vm_result(result.get_oop()); + current->set_vm_result_oop(result.get_oop()); return 0; } else { jvalue *value = (jvalue *) result.get_value_addr(); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 4fe2b286e15..8ca13a3a6c3 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -227,7 +227,7 @@ nonstatic_field(JavaThread, _scopedValueCache, OopHandle) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ nonstatic_field(JavaThread, _monitor_owner_id, int64_t) \ - nonstatic_field(JavaThread, _vm_result, oop) \ + nonstatic_field(JavaThread, _vm_result_oop, oop) \ nonstatic_field(JavaThread, _stack_overflow_state._stack_overflow_limit, address) \ volatile_nonstatic_field(JavaThread, _exception_oop, oop) \ volatile_nonstatic_field(JavaThread, _exception_pc, address) \ diff --git a/src/hotspot/share/opto/generateOptoStub.cpp b/src/hotspot/share/opto/generateOptoStub.cpp index b13504ab10e..77633857cdf 100644 --- a/src/hotspot/share/opto/generateOptoStub.cpp +++ b/src/hotspot/share/opto/generateOptoStub.cpp @@ -228,7 +228,7 @@ void GraphKit::gen_stub(address C_function, Node* target = map()->in(TypeFunc::Parms); // Runtime call returning oop in TLS? Fetch it out if( pass_tls ) { - Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset())); + Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_oop_offset())); Node* vm_result = make_load(nullptr, adr, TypeOopPtr::BOTTOM, T_OBJECT, MemNode::unordered); map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result // clear thread-local-storage(tls) diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 74d7eb42ebc..6d24fb26cd2 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -347,7 +347,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* curr // Scavenge and allocate an instance. Handle holder(current, klass->klass_holder()); // keep the klass alive oop result = InstanceKlass::cast(klass)->allocate_instance(THREAD); - current->set_vm_result(result); + current->set_vm_result_oop(result); // Pass oops back through thread local storage. Our apparent type to Java // is that we return an oop, but we can block on exit from this routine and @@ -393,7 +393,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaT // a GC can trash the oop in C's return register. The generated stub will // fetch the oop from TLS after any possible GC. deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION); - current->set_vm_result(result); + current->set_vm_result_oop(result); JRT_BLOCK_END; // inform GC that we won't do card marks for initializing writes. @@ -421,14 +421,14 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len // a GC can trash the oop in C's return register. The generated stub will // fetch the oop from TLS after any possible GC. deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION); - current->set_vm_result(result); + current->set_vm_result_oop(result); JRT_BLOCK_END; // inform GC that we won't do card marks for initializing writes. SharedRuntime::on_slowpath_allocation_exit(current); - oop result = current->vm_result(); + oop result = current->vm_result_oop(); if ((len > 0) && (result != nullptr) && is_deoptimized_caller_frame(current)) { // Zero array here if the caller is deoptimized. @@ -465,7 +465,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int l Handle holder(current, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD); deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END // multianewarray for 3 dimensions @@ -482,7 +482,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int l Handle holder(current, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD); deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END // multianewarray for 4 dimensions @@ -500,7 +500,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int l Handle holder(current, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD); deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END // multianewarray for 5 dimensions @@ -519,7 +519,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray5_C(Klass* elem_type, int len1, int l Handle holder(current, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD); deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* dims, JavaThread* current)) @@ -537,7 +537,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* d Handle holder(current, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD); deoptimize_caller_frame(current, HAS_PENDING_EXCEPTION); - current->set_vm_result(obj); + current->set_vm_result_oop(obj); JRT_END JRT_BLOCK_ENTRY(void, OptoRuntime::monitor_notify_C(oopDesc* obj, JavaThread* current)) @@ -2012,7 +2012,7 @@ address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address r } #endif - thread->set_vm_result(exception); + thread->set_vm_result_oop(exception); // Frame not compiled (handles deoptimization blob) return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc); } diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp index e9b0a11917a..012cea19bb0 100644 --- a/src/hotspot/share/runtime/javaCalls.cpp +++ b/src/hotspot/share/runtime/javaCalls.cpp @@ -427,7 +427,7 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC result = link.result(); // circumvent MS C++ 5.0 compiler bug (result is clobbered across call) // Preserve oop return value across possible gc points if (oop_result_flag) { - thread->set_vm_result(result->get_oop()); + thread->set_vm_result_oop(result->get_oop()); } } } // Exit JavaCallWrapper (can block - potential return oop must be preserved) @@ -438,8 +438,8 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC // Restore possible oop return if (oop_result_flag) { - result->set_oop(thread->vm_result()); - thread->set_vm_result(nullptr); + result->set_oop(thread->vm_result_oop()); + thread->set_vm_result_oop(nullptr); } } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index b5c7709ac88..e4f377a1217 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -423,8 +423,8 @@ JavaThread::JavaThread(MemTag mem_tag) : _vframe_array_last(nullptr), _jvmti_deferred_updates(nullptr), _callee_target(nullptr), - _vm_result(nullptr), - _vm_result_2(nullptr), + _vm_result_oop(nullptr), + _vm_result_metadata(nullptr), _current_pending_monitor(nullptr), _current_pending_monitor_is_from_java(true), @@ -1412,7 +1412,7 @@ void JavaThread::oops_do_no_frames(OopClosure* f, NMethodClosure* cf) { // Traverse instance variables at the end since the GC may be moving things // around using this function - f->do_oop((oop*) &_vm_result); + f->do_oop((oop*) &_vm_result_oop); f->do_oop((oop*) &_exception_oop); #if INCLUDE_JVMCI f->do_oop((oop*) &_jvmci_reserved_oop0); diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 25d3b7906e6..01da26a97e8 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -145,8 +145,8 @@ class JavaThread: public Thread { Method* _callee_target; // Used to pass back results to the interpreter or generated code running Java code. - oop _vm_result; // oop result is GC-preserved - Metadata* _vm_result_2; // non-oop result + oop _vm_result_oop; // oop result is GC-preserved + Metadata* _vm_result_metadata; // non-oop result // See ReduceInitialCardMarks: this holds the precise space interval of // the most recent slow path allocation for which compiled code has @@ -784,10 +784,10 @@ private: void set_callee_target (Method* x) { _callee_target = x; } // Oop results of vm runtime calls - oop vm_result() const { return _vm_result; } - void set_vm_result (oop x) { _vm_result = x; } + oop vm_result_oop() const { return _vm_result_oop; } + void set_vm_result_oop(oop x) { _vm_result_oop = x; } - void set_vm_result_2 (Metadata* x) { _vm_result_2 = x; } + void set_vm_result_metadata(Metadata* x) { _vm_result_metadata = x; } MemRegion deferred_card_mark() const { return _deferred_card_mark; } void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } @@ -853,8 +853,8 @@ private: return byte_offset_of(JavaThread, _anchor); } static ByteSize callee_target_offset() { return byte_offset_of(JavaThread, _callee_target); } - static ByteSize vm_result_offset() { return byte_offset_of(JavaThread, _vm_result); } - static ByteSize vm_result_2_offset() { return byte_offset_of(JavaThread, _vm_result_2); } + static ByteSize vm_result_oop_offset() { return byte_offset_of(JavaThread, _vm_result_oop); } + static ByteSize vm_result_metadata_offset() { return byte_offset_of(JavaThread, _vm_result_metadata); } static ByteSize thread_state_offset() { return byte_offset_of(JavaThread, _thread_state); } static ByteSize saved_exception_pc_offset() { return byte_offset_of(JavaThread, _saved_exception_pc); } static ByteSize osthread_offset() { return byte_offset_of(JavaThread, _osthread); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 2f29ce9b1fc..3695d9dfe76 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1439,7 +1439,7 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method_ic_miss(JavaThread* JRT_BLOCK callee_method = SharedRuntime::handle_ic_miss_helper(CHECK_NULL); // Return Method* through TLS - current->set_vm_result_2(callee_method()); + current->set_vm_result_metadata(callee_method()); JRT_BLOCK_END // return compiled code entry point after potential safepoints return get_resolved_entry(current, callee_method); @@ -1470,7 +1470,7 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* current) caller_frame.is_upcall_stub_frame()) { Method* callee = current->callee_target(); guarantee(callee != nullptr && callee->is_method(), "bad handshake"); - current->set_vm_result_2(callee); + current->set_vm_result_metadata(callee); current->set_callee_target(nullptr); if (caller_frame.is_entry_frame() && VM_Version::supports_fast_class_init_checks()) { // Bypass class initialization checks in c2i when caller is in native. @@ -1492,7 +1492,7 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* current) JRT_BLOCK // Force resolving of caller (if we called from compiled frame) callee_method = SharedRuntime::reresolve_call_site(CHECK_NULL); - current->set_vm_result_2(callee_method()); + current->set_vm_result_metadata(callee_method()); JRT_BLOCK_END // return compiled code entry point after potential safepoints return get_resolved_entry(current, callee_method); @@ -1550,7 +1550,7 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_static_call_C(JavaThread* curren bool enter_special = false; JRT_BLOCK callee_method = SharedRuntime::resolve_helper(false, false, CHECK_NULL); - current->set_vm_result_2(callee_method()); + current->set_vm_result_metadata(callee_method()); JRT_BLOCK_END // return compiled code entry point after potential safepoints return get_resolved_entry(current, callee_method); @@ -1561,7 +1561,7 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_virtual_call_C(JavaThread* curre methodHandle callee_method; JRT_BLOCK callee_method = SharedRuntime::resolve_helper(true, false, CHECK_NULL); - current->set_vm_result_2(callee_method()); + current->set_vm_result_metadata(callee_method()); JRT_BLOCK_END // return compiled code entry point after potential safepoints return get_resolved_entry(current, callee_method); @@ -1574,7 +1574,7 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_opt_virtual_call_C(JavaThread* c methodHandle callee_method; JRT_BLOCK callee_method = SharedRuntime::resolve_helper(true, true, CHECK_NULL); - current->set_vm_result_2(callee_method()); + current->set_vm_result_metadata(callee_method()); JRT_BLOCK_END // return compiled code entry point after potential safepoints return get_resolved_entry(current, callee_method); @@ -3168,7 +3168,7 @@ void SharedRuntime::on_slowpath_allocation_exit(JavaThread* current) { // this object in the future without emitting card-marks, so // GC may take any compensating steps. - oop new_obj = current->vm_result(); + oop new_obj = current->vm_result_oop(); if (new_obj == nullptr) return; BarrierSet *bs = BarrierSet::barrier_set(); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index c95dd709c84..f865380fdb7 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -604,10 +604,8 @@ nonstatic_field(JavaThread, _threadObj, OopHandle) \ nonstatic_field(JavaThread, _vthread, OopHandle) \ nonstatic_field(JavaThread, _jvmti_vthread, OopHandle) \ - nonstatic_field(JavaThread, _scopedValueCache, OopHandle) \ + nonstatic_field(JavaThread, _scopedValueCache, OopHandle) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ - nonstatic_field(JavaThread, _vm_result, oop) \ - nonstatic_field(JavaThread, _vm_result_2, Metadata*) \ volatile_nonstatic_field(JavaThread, _current_pending_monitor, ObjectMonitor*) \ nonstatic_field(JavaThread, _current_pending_monitor_is_from_java, bool) \ volatile_nonstatic_field(JavaThread, _current_waiting_monitor, ObjectMonitor*) \ From af7a19a8cfba8d7016de94d6ffc86d201ab4a884 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 17 Apr 2025 06:34:43 +0000 Subject: [PATCH 220/843] 8354802: MAX_SECS definition is unused in os_linux Reviewed-by: kbarrett, dholmes --- src/hotspot/os/linux/os_linux.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 4e26797cd5b..1afece719cb 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -139,8 +139,6 @@ #define MAX_PATH (2 * K) -#define MAX_SECS 100000000 - // for timer info max values which include all bits #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) From 3d0feba00a1c1ef7627880859a093bb00eb8fc4c Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Thu, 17 Apr 2025 06:39:50 +0000 Subject: [PATCH 221/843] 8352865: Open source several AWT TextComponent tests - Batch 2 Reviewed-by: prr, serb, jdv --- test/jdk/ProblemList.txt | 2 + .../AltPlusNumberKeyCombinationsTest.java | 74 ++++++++ .../CorrectTextComponentSelectionTest.java | 139 +++++++++++++++ .../TextComponent/SelectionAndCaretColor.java | 162 ++++++++++++++++++ .../java/awt/TextComponent/SelectionTest.java | 73 ++++++++ 5 files changed, 450 insertions(+) create mode 100644 test/jdk/java/awt/TextComponent/AltPlusNumberKeyCombinationsTest.java create mode 100644 test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java create mode 100644 test/jdk/java/awt/TextComponent/SelectionAndCaretColor.java create mode 100644 test/jdk/java/awt/TextComponent/SelectionTest.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 4ff6ea1fe74..a0d9f6586ba 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -799,6 +799,8 @@ java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all java/awt/print/PageFormat/Orient.java 8016055 macosx-all java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 8024986 macosx-all,linux-all +java/awt/TextComponent/CorrectTextComponentSelectionTest.java 8237220 macosx-all +java/awt/TextComponent/SelectionAndCaretColor.java 7017622 linux-all java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter.java 8254841 macosx-all java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.java 8256289 windows-x64 java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all diff --git a/test/jdk/java/awt/TextComponent/AltPlusNumberKeyCombinationsTest.java b/test/jdk/java/awt/TextComponent/AltPlusNumberKeyCombinationsTest.java new file mode 100644 index 00000000000..27599b0a91c --- /dev/null +++ b/test/jdk/java/awt/TextComponent/AltPlusNumberKeyCombinationsTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4737679 4623376 4501485 4740906 4708221 + * @requires (os.family == "windows") + * @summary Alt+Left/right/up/down generate characters in JTextArea + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AltPlusNumberKeyCombinationsTest + */ + +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.TextField; + +public class AltPlusNumberKeyCombinationsTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + [WINDOWS PLATFORM ONLY] + Please do the following steps for both TextField and TextArea: + 1. Hold down ALT and press a NON-NUMPAD right arrow, then release + ALT key. If any symbol is typed the test failed. + 2. Hold down ALT and press one after another the following + NUMPAD keys: 0, 1, 2, 8. Release ALT key. If the Euro symbol + is not typed the test failed + 3. Hold down ALT and press one after another the following + NUMPAD keys: 0, 2, 2, 7. Release ALT key. If nothing or + the blank symbol is typed the test failed + If all the steps are done successfully the test PASSed, + else test FAILS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(initialize()) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame f = new Frame("key combination test"); + f.setLayout(new FlowLayout()); + TextField tf = new TextField("TextField"); + f.add(tf); + TextArea ta = new TextArea("TextArea"); + f.add(ta); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java b/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java new file mode 100644 index 00000000000..9d3e6d85637 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5100806 + * @summary TextArea.select(0,0) does not de-select the selected text properly + * @key headful + * @run main CorrectTextComponentSelectionTest + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; +import java.lang.reflect.InvocationTargetException; + +public class CorrectTextComponentSelectionTest { + static TextField tf = new TextField("TextField"); + static TextArea ta = new TextArea("TextArea"); + static Robot r; + static Frame frame; + static volatile Color color_center; + static volatile Point loc; + + public static void main(String[] args) throws Exception { + try { + r = new Robot(); + EventQueue.invokeAndWait(() -> { + initialize(); + }); + r.waitForIdle(); + r.delay(1000); + + test(tf); + test(ta); + System.out.println("Test Passed!"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void initialize() { + frame = new Frame("TextComponent Selection Test"); + frame.setLayout(new BorderLayout()); + + // We should place to the text components the long strings in order to + // cover the components by the selection completely + String sf = ""; + for (int i = 0; i < 50; i++) { + sf = sf + " "; + } + tf.setText(sf); + // We check the color of the text component in order to find out the + // bug reproducible situation + tf.setForeground(Color.WHITE); + tf.setBackground(Color.WHITE); + + String sa = ""; + for (int i = 0; i < 50; i++) { + for (int j = 0; j < 50; j++) { + sa = sa + " "; + } + sa = sa + "\n"; + } + ta.setText(sa); + ta.setForeground(Color.WHITE); + ta.setBackground(Color.WHITE); + + frame.add(tf, "North"); + frame.add(ta, "South"); + frame.setSize(200, 200); + frame.setVisible(true); + } + + private static void test(TextComponent tc) throws Exception { + if (tc instanceof TextField) { + System.out.println("TextField testing ..."); + } else if (tc instanceof TextArea) { + System.out.println("TextArea testing ..."); + } + + r.waitForIdle(); + r.delay(100); + EventQueue.invokeAndWait(() -> { + tc.requestFocus(); + tc.selectAll(); + tc.select(0, 0); + }); + + r.waitForIdle(); + r.delay(100); + EventQueue.invokeAndWait(() -> { + loc = tc.getLocationOnScreen(); + }); + r.waitForIdle(); + r.delay(100); + + EventQueue.invokeAndWait(() -> { + color_center = r.getPixelColor(loc.x + tc.getWidth() / 2, loc.y + tc.getHeight() / 2); + }); + + System.out.println("Color of the text component (CENTER) =" + color_center); + System.out.println("White color=" + Color.WHITE); + + if (color_center.getRGB() != Color.WHITE.getRGB()) { + throw new RuntimeException("Test Failed"); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/SelectionAndCaretColor.java b/test/jdk/java/awt/TextComponent/SelectionAndCaretColor.java new file mode 100644 index 00000000000..60b932e4be8 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/SelectionAndCaretColor.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6287895 + * @requires (os.family == "linux") + * @summary Test cursor and selected text incorrectly colored in TextField + * @key headful + * @run main SelectionAndCaretColor + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; +import java.awt.image.BufferedImage; + +public class SelectionAndCaretColor { + static TextField tf = new TextField(20); + static TextArea ta = new TextArea("", 1, 20, TextArea.SCROLLBARS_NONE); + static Robot r; + static Frame frame; + static volatile int flips; + + public static void main(String[] args) throws Exception { + try { + frame = new Frame("Selection and Caret color test"); + r = new Robot(); + + EventQueue.invokeAndWait(() -> { + frame.setLayout(new BorderLayout()); + tf.setFont(new Font("Monospaced", Font.PLAIN, 15)); + ta.setFont(new Font("Monospaced", Font.PLAIN, 15)); + + frame.add(tf, BorderLayout.NORTH); + frame.add(ta, BorderLayout.SOUTH); + frame.setSize(200, 200); + frame.setVisible(true); + }); + r.waitForIdle(); + r.delay(1000); + test(tf); + test(ta); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static int countFlips(TextComponent tc) { + int y = tc.getLocationOnScreen().y + tc.getHeight() / 2; + int x1 = tc.getLocationOnScreen().x + 5; + int x2 = tc.getLocationOnScreen().x + tc.getWidth() - 5; + + int[] fb = {tc.getBackground().getRGB(), tc.getForeground().getRGB()}; + int i = 0; + int flips = 0; + + BufferedImage img = r.createScreenCapture(new Rectangle(x1, y, x2 - x1, 1)); + for (int x = 0; x < x2 - x1; x++) { + int c = img.getRGB(x, 0); + if (c == fb[i]) { + ; + } else if (c == fb[1 - i]) { + flips++; + i = 1 - i; + } else { + throw new RuntimeException("Invalid color detected: " + + Integer.toString(c, 16) + " instead of " + + Integer.toString(fb[i], 16)); + } + } + return flips; + } + + private static void test(TextComponent tc) throws Exception { + if (tc instanceof TextField) { + System.out.println("TextField testing ..."); + } else if (tc instanceof TextArea) { + System.out.println("TextArea testing ..."); + } + + // now passing along the component's vertical center, + // skipping 5px from both sides, + // we should see bg - textcolor - bg - selcolor - + // seltextcolor - selcolor - bg + // that is bg-fg-bg-fg-bg-fg-bg, 6 flips + + EventQueue.invokeAndWait(() -> { + tc.setForeground(Color.green); + tc.setBackground(Color.magenta); + + tc.setText(" I I "); + tc.select(5, 10); + tc.requestFocus(); + }); + r.waitForIdle(); + r.delay(200); + EventQueue.invokeAndWait(() -> { + flips = countFlips(tc); + }); + if (flips != 6) { + throw new RuntimeException("Invalid number of flips: " + + flips + " instead of 6"); + } + EventQueue.invokeAndWait(() -> { + // same for caret: spaces in the tc, caret in the middle + // bg-fg-bg - 2 flips + + tc.select(0, 0); + tc.setText(" "); + tc.setCaretPosition(5); + }); + r.waitForIdle(); + r.delay(200); + + for (int i = 0; i < 10; i++) { + EventQueue.invokeAndWait(() -> { + flips = countFlips(tc); + }); + + if (flips == 2) { + break; + } + if (flips == 0) { + continue; + } + throw new RuntimeException("Invalid number of flips: " + + flips + " instead of 2"); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/SelectionTest.java b/test/jdk/java/awt/TextComponent/SelectionTest.java new file mode 100644 index 00000000000..d29818d7621 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/SelectionTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4056231 + * @summary Checks that TextComponents don't grab the global CDE selection + * upon construction if their own selection is null. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SelectionTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class SelectionTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. "Select some text in another window, then click the button.", + 2. "If the text in the other window is de-selected, the test FAILS.", + "If the text remains selected, the test PASSES." + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(initialize()) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Selection Test"); + frame.setLayout(new BorderLayout()); + Button b = new Button("Select some text in another window, then" + + " click me"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frame.add(new TextField("text field test")); + frame.add(new TextArea("text area test")); + } + }); + frame.add(b); + frame.setSize(400, 400); + return frame; + } +} From e00355a036936c5290cf8d85fd3c4f743b0ad23a Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Thu, 17 Apr 2025 06:40:54 +0000 Subject: [PATCH 222/843] 8353958: Open source several AWT ScrollPane tests - Batch 2 Reviewed-by: prr, psadhukhan --- test/jdk/ProblemList.txt | 1 + .../ScrollPane/ScrollPaneAsNeededTest.java | 67 ++++++++ .../ScrollPane/ScrollPaneComponentTest.java | 125 +++++++++++++++ .../awt/ScrollPane/ScrollPaneEventType.java | 81 ++++++++++ .../java/awt/ScrollPane/ScrollPaneSize.java | 97 ++++++++++++ .../ScrollPanechildViewportTest.java | 146 ++++++++++++++++++ 6 files changed, 517 insertions(+) create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPaneAsNeededTest.java create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPaneComponentTest.java create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPaneEventType.java create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPaneSize.java create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPanechildViewportTest.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index a0d9f6586ba..ac4828eadca 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -441,6 +441,7 @@ java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java 8203004 linux-all +java/awt/ScrollPane/ScrollPaneScrollType/ScrollPaneEventType.java 8296516 macosx-all java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147 linux-all,windows-all,macosx-all diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneAsNeededTest.java b/test/jdk/java/awt/ScrollPane/ScrollPaneAsNeededTest.java new file mode 100644 index 00000000000..e4be90fae31 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneAsNeededTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4152524 + * @summary ScrollPane AS_NEEDED always places scrollbars first time component + * is laid out + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneAsNeededTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.awt.ScrollPane; + +public class ScrollPaneAsNeededTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. You will see a frame titled 'ScrollPane as needed' + of minimum possible size in the middle of the screen. + 2. If for the first resize of frame(using mouse) to + a very big size(may be, to half the area of the screen) + the scrollbars(any - horizontal, vertical or both) + appear, click FAIL else, click PASS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneAsNeededTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame f = new Frame("ScrollPane as needed"); + f.setLayout(new BorderLayout()); + ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + sp.add(new Button("TEST")); + f.add("Center", sp); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneComponentTest.java b/test/jdk/java/awt/ScrollPane/ScrollPaneComponentTest.java new file mode 100644 index 00000000000..b2fc4c77b63 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneComponentTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4100671 + * @summary removing and adding back ScrollPane component does not work + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneComponentTest + */ + +import java.awt.Adjustable; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class ScrollPaneComponentTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Notice the scrollbars (horizontal and vertical) + in the Frame titled 'ScrollPane Component Test' + 2. Click the button labeled 'Remove and add back + ScrollPane Contents' + 3. If the Scrollbars (horizontal or vertical or both) + disappears in the Frame, then press FAIL, else press PASS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneComponentTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame fr = new Frame("ScrollPane Component Test"); + fr.setLayout(new BorderLayout()); + ScrollTester test = new ScrollTester(); + + fr.add(test); + fr.pack(); + fr.setSize(200, 200); + + Adjustable vadj = test.pane.getVAdjustable(); + Adjustable hadj = test.pane.getHAdjustable(); + vadj.setUnitIncrement(5); + hadj.setUnitIncrement(5); + return fr; + } +} + +class Box extends Component { + public Dimension getPreferredSize() { + System.out.println("asked for size"); + return new Dimension(300, 300); + } + + public void paint(Graphics gr) { + super.paint(gr); + gr.setColor(Color.red); + gr.drawLine(5, 5, 295, 5); + gr.drawLine(295, 5, 295, 295); + gr.drawLine(295, 295, 5, 295); + gr.drawLine(5, 295, 5, 5); + System.out.println("Painted!!"); + } +} + +class ScrollTester extends Panel { + public ScrollPane pane; + private final Box child; + + class Handler implements ActionListener { + public void actionPerformed(ActionEvent e) { + System.out.println("Removing scrollable component"); + pane.remove(child); + System.out.println("Adding back scrollable component"); + pane.add(child); + System.out.println("Done Adding back scrollable component"); + } + } + + public ScrollTester() { + pane = new ScrollPane(); + pane.setSize(200, 200); + child = new Box(); + pane.add(child); + setLayout(new BorderLayout()); + Button changeScrollContents = new Button("Remove and add back ScrollPane Contents"); + changeScrollContents.setBackground(Color.red); + changeScrollContents.addActionListener(new Handler()); + add("North", changeScrollContents); + add("Center", pane); + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneEventType.java b/test/jdk/java/awt/ScrollPane/ScrollPaneEventType.java new file mode 100644 index 00000000000..47b4ae416c1 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneEventType.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4075484 + * @summary Tests that events of different types are generated for the + * corresponding scroll actions. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneEventType + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.ScrollPane; +import java.awt.event.AdjustmentListener; + +public class ScrollPaneEventType { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. This test verifies that when user performs some scrolling operation on + ScrollPane the correct AdjustmentEvent is being generated. + 2. To test this, press on: + - scrollbar's arrows and verify that UNIT event is generated, + - scrollbar's grey area(non-thumb) and verify that BLOCK event is + generated, + - drag scrollbar's thumb and verify that TRACK event is generated + If you see correct events for both scroll bars then test is PASSED. + Otherwise it is FAILED. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneEventType::initialize) + .logArea() + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame frame = new Frame("ScrollPane event type test"); + frame.setLayout(new BorderLayout()); + ScrollPane pane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + pane.add(new Button("press") { + public Dimension getPreferredSize() { + return new Dimension(1000, 1000); + } + }); + + AdjustmentListener listener = e -> PassFailJFrame.log(e.toString()); + pane.getHAdjustable().addAdjustmentListener(listener); + pane.getVAdjustable().addAdjustmentListener(listener); + frame.add(pane); + frame.setSize(200, 200); + return frame; + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneSize.java b/test/jdk/java/awt/ScrollPane/ScrollPaneSize.java new file mode 100644 index 00000000000..3130563d4a9 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneSize.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4117404 + * @summary Tests that child component is always at least large as scrollpane + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneSize + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.util.List; + +public class ScrollPaneSize { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Three frames representing the three different ScrollPane scrollbar + policies will appear. + 2. Verify that when you resize the windows, the child component in the + scrollpane always expands to fill the scrollpane. The scrollpane + background is colored red to show any improper bleed through. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(ScrollPaneSize::initialize) + .positionTestUIRightColumn() + .build() + .awaitAndCheck(); + } + + static List initialize() { + return List.of(new ScrollFrame("SCROLLBARS_AS_NEEDED", ScrollPane.SCROLLBARS_AS_NEEDED), + new ScrollFrame("SCROLLBARS_ALWAYS", ScrollPane.SCROLLBARS_ALWAYS), + new ScrollFrame("SCROLLBARS_NEVER", ScrollPane.SCROLLBARS_NEVER)); + } +} + +class ScrollFrame extends Frame { + ScrollFrame(String title, int policy) { + super(title); + setLayout(new GridLayout(1, 1)); + ScrollPane c = new ScrollPane(policy); + c.setBackground(Color.red); + Panel panel = new TestPanel(); + c.add(panel); + add(c); + pack(); + Dimension size = panel.getPreferredSize(); + Insets insets = getInsets(); + setSize(size.width + 45 + insets.right + insets.left, + size.height + 20 + insets.top + insets.bottom); + } +} + +class TestPanel extends Panel { + TestPanel() { + setLayout(new FlowLayout()); + setBackground(Color.white); + + Button b1, b2, b3; + add(b1 = new Button("Button1")); + add(b2 = new Button("Button2")); + add(b3 = new Button("Button3")); + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPanechildViewportTest.java b/test/jdk/java/awt/ScrollPane/ScrollPanechildViewportTest.java new file mode 100644 index 00000000000..0dc0772aeba --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPanechildViewportTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4094581 + * @summary ScrollPane does not refresh properly when child is just smaller than viewport + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPanechildViewportTest + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class ScrollPanechildViewportTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Click "Slightly Large" and ensure scrollbars are VISIBLE + 2. Click "Slightly Small" and ensure there are NO scrollbars + 3. Click "Smaller" and ensure there are NO scrollbars + 4. If everything is ok, click PASS, else click FAIL. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPanechildViewportTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + return new Test(); + } +} + +class Test extends Frame implements ActionListener { + Button b1, b2, b3; + MyPanel p; + int state; // 0 = slightly large, 1 = slightly smaller, 2 = smaller + + public Test() { + ScrollPane sp = new ScrollPane(); + p = new MyPanel(); + p.setBackground(Color.yellow); + state = 1; + sp.add(p); + add(sp, "Center"); + + Panel p1 = new Panel(); + b1 = new Button("Slightly Large"); + b1.addActionListener(this); + p1.add(b1); + b2 = new Button("Slightly Small"); + b2.addActionListener(this); + p1.add(b2); + b3 = new Button("Smaller"); + b3.addActionListener(this); + p1.add(b3); + + add(p1, "South"); + + setSize(400, 200); + //added to test to move test frame away from instructions + setLocation(0, 350); + } + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + + // set size to small and re-validate the panel to get correct size of + // scrollpane viewport without scrollbars + + state = 2; + p.invalidate(); + validate(); + + Dimension pd = ((ScrollPane) p.getParent()).getViewportSize(); + + if (source.equals(b1)) { + p.setBackground(Color.green); + state = 0; + } else if (source.equals(b2)) { + p.setBackground(Color.yellow); + state = 1; + } else if (source.equals(b3)) { + p.setBackground(Color.red); + state = 2; + } + + p.invalidate(); + validate(); + System.out.println("Panel Size = " + p.getSize()); + System.out.println("ScrollPane Viewport Size = " + pd); + System.out.println(" "); + } + + class MyPanel extends Panel { + public Dimension getPreferredSize() { + Dimension d = null; + Dimension pd = ((ScrollPane) getParent()).getViewportSize(); + switch (state) { + case 0 -> { + d = new Dimension(pd.width + 2, pd.height + 2); + System.out.println("Preferred size: " + d); + } + case 1 -> { + d = new Dimension(pd.width - 2, pd.height - 2); + System.out.println("Preferred size: " + d); + } + case 2 -> { + d = new Dimension(50, 50); + System.out.println("Preferred size: " + d); + } + } + return d; + } + } +} From a4e9da3747fe0a3c27e414787eaa97f80b24f5de Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Thu, 17 Apr 2025 06:59:01 +0000 Subject: [PATCH 223/843] 8354191: GTK LaF should use pre-multiplied alpha same as cairo Reviewed-by: avu, prr --- .../sun/java/swing/plaf/gtk/GTKEngine.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index f9f63076781..2540f6e7880 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -532,14 +532,7 @@ class GTKEngine { native_paint_background(widget, state, x - x0, y - y0, w, h); } - private static final ColorModel[] COLOR_MODELS = { - // Transparency.OPAQUE - new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000), - // Transparency.BITMASK - new DirectColorModel(25, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x01000000), - // Transparency.TRANSLUCENT - ColorModel.getRGBdefault(), - }; + private static final ColorModel[] COLOR_MODELS = new ColorModel[3]; private static final int[][] BAND_OFFSETS = { { 0x00ff0000, 0x0000ff00, 0x000000ff }, // OPAQUE @@ -609,8 +602,8 @@ class GTKEngine { WritableRaster raster = Raster.createPackedRaster( dataBuffer, w0, h0, w0, bands, null); - ColorModel cm = COLOR_MODELS[transparency - 1]; - BufferedImage img = new BufferedImage(cm, raster, false, null); + ColorModel cm = colorModelFor(transparency); + BufferedImage img = new BufferedImage(cm, raster, true, null); if (useCache) { cache.setImage(getClass(), null, w0, h0, cacheArgs, img); } @@ -618,6 +611,18 @@ class GTKEngine { return img; } + private ColorModel colorModelFor(int transparency) { + synchronized (COLOR_MODELS) { + int index = transparency - 1; + if (COLOR_MODELS[index] == null) { + COLOR_MODELS[index] = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration() + .getColorModel(transparency); + } + return COLOR_MODELS[index]; + } + } + /** * Notify native layer of theme change, and flush cache */ From fabf67c376708a3be80d2a4e67d30d226d6e6af8 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Thu, 17 Apr 2025 07:21:34 +0000 Subject: [PATCH 224/843] 8354625: Compile::igv_print_graph_to_network doesn't use its second parameter Reviewed-by: rcastanedalo, thartmann --- src/hotspot/share/opto/compile.cpp | 4 ++-- src/hotspot/share/opto/compile.hpp | 2 +- src/hotspot/share/opto/node.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 9e29ecb7616..e4e82cbddab 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -5265,10 +5265,10 @@ void Compile::igv_print_method_to_file(const char* phase_name, bool append) { void Compile::igv_print_method_to_network(const char* phase_name) { ResourceMark rm; GrowableArray empty_list; - igv_print_graph_to_network(phase_name, (Node*) C->root(), empty_list); + igv_print_graph_to_network(phase_name, empty_list); } -void Compile::igv_print_graph_to_network(const char* name, Node* node, GrowableArray& visible_nodes) { +void Compile::igv_print_graph_to_network(const char* name, GrowableArray& visible_nodes) { if (_debug_network_printer == nullptr) { _debug_network_printer = new IdealGraphPrinter(C); } else { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 271013f29c5..6f505e502b5 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -680,7 +680,7 @@ public: void igv_print_method_to_file(const char* phase_name = "Debug", bool append = false); void igv_print_method_to_network(const char* phase_name = "Debug"); - void igv_print_graph_to_network(const char* name, Node* node, GrowableArray& visible_nodes); + void igv_print_graph_to_network(const char* name, GrowableArray& visible_nodes); static IdealGraphPrinter* debug_file_printer() { return _debug_file_printer; } static IdealGraphPrinter* debug_network_printer() { return _debug_network_printer; } #endif diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index d00bd3d3943..76e19360910 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -2057,7 +2057,7 @@ void PrintBFS::print() { if (_print_igv) { Compile* C = Compile::current(); C->init_igv(); - C->igv_print_graph_to_network("PrintBFS", (Node*) C->root(), _print_list); + C->igv_print_graph_to_network("PrintBFS", _print_list); } } else { _output->print_cr("No nodes to print."); From 1138a186eb670e2c0662bda69c35680b41f4d66c Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Thu, 17 Apr 2025 07:24:14 +0000 Subject: [PATCH 225/843] 8344251: C2: remove blackholes with dead control input Reviewed-by: shade, thartmann, kvn --- src/hotspot/share/opto/cfgnode.cpp | 4 ++ src/hotspot/share/opto/cfgnode.hpp | 1 + .../compiler/blackhole/DeadBhElimination.java | 70 +++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 12 ++++ 4 files changed, 87 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 5bf0d6facc1..4885d44a13d 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -3109,6 +3109,10 @@ void NeverBranchNode::format( PhaseRegAlloc *ra_, outputStream *st) const { } #endif +Node* BlackholeNode::Ideal(PhaseGVN* phase, bool can_reshape) { + return remove_dead_region(phase, can_reshape) ? this : nullptr; +} + #ifndef PRODUCT void BlackholeNode::format(PhaseRegAlloc* ra, outputStream* st) const { st->print("blackhole "); diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 6786089a203..a0e780c0e57 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -735,6 +735,7 @@ public: virtual int Opcode() const; virtual uint ideal_reg() const { return 0; } // not matched in the AD file virtual const Type* bottom_type() const { return TypeTuple::MEMBAR; } + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); const RegMask &in_RegMask(uint idx) const { // Fake the incoming arguments mask for blackholes: accept all registers diff --git a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java new file mode 100644 index 00000000000..0fb503d2c44 --- /dev/null +++ b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Red Hat and/or its affiliates. All rights reserved. + * 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 8344251 + * @summary Test that blackhole without control input are removed + * @library /test/lib / + * @run driver compiler.blackhole.DeadBhElimination + */ + +package compiler.blackhole; + +import compiler.lib.ir_framework.*; + +public class DeadBhElimination { + public static void main(String[] args) { + TestFramework.runWithFlags( + "-XX:-TieredCompilation", + "-XX:+UnlockExperimentalVMOptions", + // Prevent the dead branches to be compiled into an uncommon trap + // instead of generating a BlackholeNode. + "-XX:PerMethodTrapLimit=0", + "-XX:PerMethodSpecTrapLimit=0", + "-XX:CompileCommand=blackhole,compiler.blackhole.DeadBhElimination::iAmABlackhole" + ); + } + + static public void iAmABlackhole(int x) {} + + @Test + @IR(counts = {IRNode.BLACKHOLE, "1"}, phase = CompilePhase.AFTER_PARSING) + @IR(failOn = {IRNode.BLACKHOLE}, phase = CompilePhase.FINAL_CODE) + static void removalAfterLoopOpt() { + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + // b == 77, known after first loop opts round + // loop is detected as empty loop + + if (b == 78) { // dead + iAmABlackhole(a); + } + } + + +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 6d58b35f53c..e7340dd0d8f 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -2717,6 +2717,11 @@ public class IRNode { macroNodes(MOD_D, regex); } + public static final String BLACKHOLE = PREFIX + "BLACKHOLE" + POSTFIX; + static { + fromBeforeRemoveUselessToFinalCode(BLACKHOLE, "Blackhole"); + } + /* * Utility methods to set up IR_NODE_MAPPINGS. */ @@ -2843,6 +2848,13 @@ public class IRNode { beforeMatching(irNodePlaceholder, regex); } + private static void fromBeforeRemoveUselessToFinalCode(String irNodePlaceholder, String irNodeRegex) { + String regex = START + irNodeRegex + MID + END; + IR_NODE_MAPPINGS.put(irNodePlaceholder, new SinglePhaseRangeEntry(CompilePhase.PRINT_IDEAL, regex, + CompilePhase.BEFORE_REMOVEUSELESS, + CompilePhase.FINAL_CODE)); + } + /** * Apply {@code regex} on all ideal graph phases starting from {@link CompilePhase#PHASEIDEALLOOP1} which is the * first phase that could contain vector nodes from super word. From 5125ceb922540ef695d2fa4b3c7880e00dd078c3 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 17 Apr 2025 11:47:21 +0000 Subject: [PATCH 226/843] 8349405: Redundant and confusing null checks on data from CP::resolved_klasses Reviewed-by: dholmes, iklam --- src/hotspot/share/oops/constantPool.cpp | 26 +++++++++---------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index f6a94a984ce..0d3b44351f8 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -589,8 +589,9 @@ void ConstantPool::remove_resolved_klass_if_non_deterministic(int cp_index) { if (!can_archive) { int resolved_klass_index = klass_slot_at(cp_index).resolved_klass_index(); - resolved_klasses()->at_put(resolved_klass_index, nullptr); + // This might be at a safepoint but do this in the right order. tag_at_put(cp_index, JVM_CONSTANT_UnresolvedClass); + resolved_klasses()->at_put(resolved_klass_index, nullptr); } LogStreamHandle(Trace, cds, resolve) log; @@ -669,9 +670,8 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int cp_ind // the unresolved_klasses() array. if (this_cp->tag_at(cp_index).is_klass()) { Klass* klass = this_cp->resolved_klasses()->at(resolved_klass_index); - if (klass != nullptr) { - return klass; - } + assert(klass != nullptr, "must be resolved"); + return klass; } // This tag doesn't change back to unresolved class unless at a safepoint. @@ -724,12 +724,12 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int cp_ind trace_class_resolution(this_cp, k); } - Klass** adr = this_cp->resolved_klasses()->adr_at(resolved_klass_index); - Atomic::release_store(adr, k); // The interpreter assumes when the tag is stored, the klass is resolved // and the Klass* stored in _resolved_klasses is non-null, so we need // hardware store ordering here. // We also need to CAS to not overwrite an error from a racing thread. + Klass** adr = this_cp->resolved_klasses()->adr_at(resolved_klass_index); + Atomic::release_store(adr, k); jbyte old_tag = Atomic::cmpxchg((jbyte*)this_cp->tag_addr_at(cp_index), (jbyte)JVM_CONSTANT_UnresolvedClass, @@ -738,7 +738,7 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int cp_ind // We need to recheck exceptions from racing thread and return the same. if (old_tag == JVM_CONSTANT_UnresolvedClassInError) { // Remove klass. - this_cp->resolved_klasses()->at_put(resolved_klass_index, nullptr); + Atomic::store(adr, (Klass*)nullptr); throw_resolution_error(this_cp, cp_index, CHECK_NULL); } @@ -758,7 +758,7 @@ Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int w if (this_cp->tag_at(which).is_klass()) { Klass* k = this_cp->resolved_klasses()->at(resolved_klass_index); - assert(k != nullptr, "should be resolved"); + assert(k != nullptr, "must be resolved"); return k; } else if (this_cp->tag_at(which).is_unresolved_klass_in_error()) { return nullptr; @@ -1147,16 +1147,8 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, // don't trigger resolution if the constant might need it switch (tag.value()) { case JVM_CONSTANT_Class: - { - CPKlassSlot kslot = this_cp->klass_slot_at(cp_index); - int resolved_klass_index = kslot.resolved_klass_index(); - if (this_cp->resolved_klasses()->at(resolved_klass_index) == nullptr) { - (*status_return) = false; - return nullptr; - } - // the klass is waiting in the CP; go get it + assert(this_cp->resolved_klass_at(cp_index) != nullptr, "must be resolved"); break; - } case JVM_CONSTANT_String: case JVM_CONSTANT_Integer: case JVM_CONSTANT_Float: From 9502ab0bf5ce8623776d295ff5260d717dfb9467 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Thu, 17 Apr 2025 12:26:15 +0000 Subject: [PATCH 227/843] 8354766: Test TestUnexported.java javac build fails Reviewed-by: nbenalla, jpai --- .../jdk/javadoc/doclet/testUnexported/TestUnexported.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/langtools/jdk/javadoc/doclet/testUnexported/TestUnexported.java b/test/langtools/jdk/javadoc/doclet/testUnexported/TestUnexported.java index aae257a0b55..798a034ae13 100644 --- a/test/langtools/jdk/javadoc/doclet/testUnexported/TestUnexported.java +++ b/test/langtools/jdk/javadoc/doclet/testUnexported/TestUnexported.java @@ -27,6 +27,8 @@ * @summary Hide superclasses from conditionally exported packages * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main * @build javadoc.tester.* toolbox.ToolBox * @run main TestUnexported */ From e9c8986a65df534ee2a396cb3b49fe3dbcaf6a44 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 17 Apr 2025 12:31:30 +0000 Subject: [PATCH 228/843] 8354493: Opensource Several MultiScreen and Insets related tests Reviewed-by: psadhukhan, tr --- test/jdk/java/awt/Multiscreen/DialogTest.java | 236 ++++++++++++++++++ .../java/awt/Multiscreen/FillThisScreen.java | 140 +++++++++++ .../Multiscreen/IMCandidateWindowTest.java | 104 ++++++++ 3 files changed, 480 insertions(+) create mode 100644 test/jdk/java/awt/Multiscreen/DialogTest.java create mode 100644 test/jdk/java/awt/Multiscreen/FillThisScreen.java create mode 100644 test/jdk/java/awt/Multiscreen/IMCandidateWindowTest.java diff --git a/test/jdk/java/awt/Multiscreen/DialogTest.java b/test/jdk/java/awt/Multiscreen/DialogTest.java new file mode 100644 index 00000000000..fbd72bfd6f0 --- /dev/null +++ b/test/jdk/java/awt/Multiscreen/DialogTest.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Button; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.ScrollPane; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.WindowConstants; + +import jtreg.SkippedException; + +/* + * @test + * @bug 4368500 + * @key multimon + * @summary Dialog needs a constructor with GraphicsConfiguration + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual DialogTest + */ + +public class DialogTest { + static GraphicsDevice[] gds; + + private static Frame f; + private static Frame dummyFrame = new Frame(); + private static Dialog dummyDialog = new Dialog(dummyFrame); + + public static void main(String[] args) throws Exception { + gds = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + if (gds.length < 2) { + throw new SkippedException("You have only one monitor in your system" + + " - test skipped"); + } + + String INSTRUCTIONS = """ + This test tests the multiscreen functionality of Dialogs and JDialogs. + You should see the message "X screens detected", where X + is the number of screens on your system. If X is incorrect, press Fail. + + In the test window, there are a list of buttons representing each + type of dialog for each screen. + If there aren't buttons for every screen in your system, press Fail. + + Press each button, and the indicated type of dialog should appear + on the indicated screen. + Modal dialogs should not allow to click on the Instructions or + DialogTest windows. + + The buttons turn yellow once they have been pressed, to keep track + of test progress. + + If all Dialogs appear correctly, press Pass. + If Dialogs appear on the wrong screen or don't behave in + proper modality, press Fail."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .logArea(5) + .testUI(DialogTest::init) + .build() + .awaitAndCheck(); + } + + public static Frame init() { + PassFailJFrame.log(gds.length + " screens detected."); + f = new Frame("DialogTest UI"); + f.setSize(400, 400); + MyScrollPane sp = new MyScrollPane(); + + Panel p = new Panel(); + p.setLayout(new GridLayout(0, 1)); + + for (int i = 0; i < gds.length; i++) { + Button btn; + + //screen # , modal, frame-owned, swing + btn = new MyButton(new DialogInfo(i, false, false, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, false, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, false, true, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, true, false)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, false, false, true)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, false, true)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, false, true, true)); + p.add(btn); + + btn = new MyButton(new DialogInfo(i, true, true, true)); + p.add(btn); + + } + sp.add(p); + f.add(sp); + return f; + } + + static class MyScrollPane extends ScrollPane { + @Override + public Dimension getPreferredSize() { + return f.getSize(); + } + } + + static class MyButton extends Button { + public MyButton(DialogInfo info) { + setLabel(info.toString()); + addActionListener(new PutupDialog(info)); + } + } + + static class PutupDialog implements ActionListener { + DialogInfo info; + + public PutupDialog(DialogInfo info) { + this.info = info; + } + + @Override + public void actionPerformed(ActionEvent e) { + ((Button) (e.getSource())).setBackground(Color.yellow); + Dialog d = info.createDialog(); + d.show(); + } + } + + static class DialogInfo { + int num; + boolean modal; + boolean frameOwned; + boolean swing; + + public DialogInfo(int num, boolean modal, boolean frameOwned, boolean swing) { + this.num = num; + this.modal = modal; + this.frameOwned = frameOwned; + this.swing = swing; + } + + public Dialog createDialog() { + GraphicsConfiguration gc = gds[num].getDefaultConfiguration(); + + Dialog d; + + if (swing) { + if (frameOwned) { + d = new JDialog(dummyFrame, toString(), modal, gc); + } else { + d = new JDialog(dummyDialog, toString(), modal, gc); + } + + ((JDialog) d).setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); + if (modal) { + ((JDialog) d).getContentPane().add(new JLabel("Check that I am modal!")); + } + } else { + if (frameOwned) { + d = new Dialog(dummyFrame, toString(), modal, gc); + } else { + d = new Dialog(dummyDialog, toString(), modal, gc); + } + + d.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + e.getComponent().hide(); + } + }); + if (modal) { + d.add(new Label("Check that I am modal!")); + } + } + + d.setLocation(new Point((int) (gc.getBounds().getX() + 20) + , (int) (gc.getBounds().getY() + 20))); + d.setSize(300, 100); + + return d; + } + + public String toString() { + return "Screen " + num + (frameOwned ? " Frame-owned" : " Dialog-owned") + + (modal ? " modal " : " non-modal ") + + (swing ? "JDialog" : "Dialog"); + } + } +} + + diff --git a/test/jdk/java/awt/Multiscreen/FillThisScreen.java b/test/jdk/java/awt/Multiscreen/FillThisScreen.java new file mode 100644 index 00000000000..542127827ec --- /dev/null +++ b/test/jdk/java/awt/Multiscreen/FillThisScreen.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Button; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.GridLayout; +import java.awt.Rectangle; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import jtreg.SkippedException; + +/* + * @test + * @bug 4356756 + * @key multimon + * @summary Return all screen devices for physical and virtual display devices + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual FillThisScreen + */ + +public class FillThisScreen { + private static Frame f; + private static Button b; + private static Rectangle oldSize; + private static boolean fillmode = true; + static GraphicsDevice[] gs; + + public static void main(String[] args) throws Exception { + gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + if (gs.length < 2) { + throw new SkippedException("You have only one monitor in your system" + + " - test skipped"); + } + + String INSTRUCTIONS = """ + This test is for testing the bounds of a multimonitor system. + You will see a Frame with several buttons: one marked 'Fill + This Screen' and an additional button for each display on your system. + + First, drag the Frame onto each display and click the + 'Fill This Screen' button. + + The Frame should resize to take up the entire display area + of the screen it is on, and the button text changes to say, + 'Get Smaller'. + + Click the button again to restore the Frame. + + Next, use the 'Move to screen' buttons to move the Frame to + each display and again click the 'Fill This Screen' button. + + If the number of 'Move to Screen' buttons is not equals to + the number of screens on your system, the test fails. + + If the Frame always correctly resizes to take up ONLY the + entire screen it is on (and not a different screen, or all + screens), the test passes else it fails."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(FillThisScreen::init) + .build() + .awaitAndCheck(); + } + + public static Frame init() { + Button tempBtn; + + f = new Frame("Drag Me Around"); + f.setLayout(new GridLayout(0, 1)); + + b = new Button("Fill This Screen"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (fillmode) { + oldSize = f.getBounds(); + Rectangle r = f.getGraphicsConfiguration().getBounds(); + f.setBounds(r); + b.setLabel("Get Smaller"); + } else { + f.setBounds(oldSize); + b.setLabel("Fill This Screen"); + } + fillmode = !fillmode; + } + }); + f.add(b); + + for (int i = 0; i < gs.length; i++) { + tempBtn = new Button("Move to screen:" + i); + tempBtn.addActionListener(new WinMover(i)); + f.add(tempBtn); + } + f.setSize(300, 100); + return f; + } + + private static class WinMover implements ActionListener { + int scrNum; + + public WinMover(int scrNum) { + this.scrNum = scrNum; + } + + public void actionPerformed(ActionEvent e) { + Rectangle newBounds = gs[scrNum].getDefaultConfiguration().getBounds(); + f.setLocation(newBounds.x + newBounds.width / 2, + newBounds.y + newBounds.height / 2); + } + + } +} diff --git a/test/jdk/java/awt/Multiscreen/IMCandidateWindowTest.java b/test/jdk/java/awt/Multiscreen/IMCandidateWindowTest.java new file mode 100644 index 00000000000..6af3188156d --- /dev/null +++ b/test/jdk/java/awt/Multiscreen/IMCandidateWindowTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.FlowLayout; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; + +import javax.swing.JFrame; +import javax.swing.JTextField; + +import jtreg.SkippedException; + +/* + * @test + * @bug 4805862 + * @key multimon + * @requires (os.family == "windows") + * @summary Tests IM candidate window is positioned correctly for the + * text components inside a window in multiscreen configurations, if + * this window has negative coordinates + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual IMCandidateWindowTest + */ + +public class IMCandidateWindowTest { + static GraphicsConfiguration gc; + + public static void main(String[] args) throws Exception { + GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getScreenDevices(); + if (gds.length < 2) { + throw new SkippedException("You have only one monitor in your system" + + " - test skipped"); + } + + GraphicsDevice gd = null; + + for (int i = 0; i < gds.length; i++) { + gc = gds[i].getDefaultConfiguration(); + if ((gc.getBounds().x < 0) || (gc.getBounds().y < 0)) { + gd = gds[i]; + break; + } + } + + if (gd == null) { + // no screens with negative coords + throw new SkippedException("No screens with negative coords - test skipped"); + } + + String INSTRUCTIONS = """ + This test is for windows + Test requirements: installed support for asian languages + Chinese (PRC) w/ Chinese QuanPing input method. + Multiscreen environment where one of the monitors has negative coords + Go to the text field in the opened Frame. Switch to Chinese language and + start typing "ka". + Note, that IM helper window is appeared. + If this window is appeared near the text field, press PASS button. + If this window is appeared at the edge of the screen or on another + screen, press FAIL button"""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(IMCandidateWindowTest::createUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createUI() { + Rectangle b = gc.getBounds(); + + JFrame f = new JFrame("Frame", gc); + f.setBounds(b.x + b.width / 2 - 150, b.y + b.height / 2 - 100, 300, 200); + f.getContentPane().setLayout(new FlowLayout()); + JTextField tf = new JTextField(10); + f.getContentPane().add(tf); + return f; + } +} From 4c99489420bd73159eca6bae22442f7b29156c1d Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Thu, 17 Apr 2025 13:07:19 +0000 Subject: [PATCH 229/843] 8354285: Open source Swing tests Batch 3 Reviewed-by: abhiscxk --- .../MotifLAFMenuAcceleratorDelimiter.java | 95 +++++++++++++++++++ .../motif/SplitPane/4141400/bug4141400.java | 71 ++++++++++++++ .../windows/MenuItem/4685843/bug4685843.java | 87 +++++++++++++++++ 3 files changed, 253 insertions(+) create mode 100644 test/jdk/com/sun/java/swing/plaf/motif/MenuItem/AcceleratorDelimiter/MotifLAFMenuAcceleratorDelimiter.java create mode 100644 test/jdk/com/sun/java/swing/plaf/motif/SplitPane/4141400/bug4141400.java create mode 100644 test/jdk/com/sun/java/swing/plaf/windows/MenuItem/4685843/bug4685843.java diff --git a/test/jdk/com/sun/java/swing/plaf/motif/MenuItem/AcceleratorDelimiter/MotifLAFMenuAcceleratorDelimiter.java b/test/jdk/com/sun/java/swing/plaf/motif/MenuItem/AcceleratorDelimiter/MotifLAFMenuAcceleratorDelimiter.java new file mode 100644 index 00000000000..3d1d9cadd8a --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/motif/MenuItem/AcceleratorDelimiter/MotifLAFMenuAcceleratorDelimiter.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4210461 + * @summary Tests that Motif Look & Feel's MenuItem Accelerator Delimiter is + * shown properly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MotifLAFMenuAcceleratorDelimiter + */ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +public class MotifLAFMenuAcceleratorDelimiter { + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("The Motif LAF failed to instantiate"); + } + + String INSTRUCTIONS = """ + The visual design specification for the Motif LAF asks for + a "+" to delimit the other two entities in a menu item's + accelerator. + + As a point of reference, the visual design specifications for the + L&Fs are as follows: JLF/Metal = "-", Mac = "-", Motif = "+", + Windows = "+". + + Click on "Menu" of "MotifLAFMenuAcceleratorDelimiter" window, + make sure it shows MenuItem with label "Hi There! ^+H" or + "Hi There! Ctrl+H". + + If it shows same label test passed otherwise failed. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(MotifLAFMenuAcceleratorDelimiter::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JFrame fr = new JFrame("MotifLAFMenuAcceleratorDelimiter"); + JPanel menuPanel = new JPanel(); + JMenuBar menuBar = new JMenuBar(); + menuBar.setOpaque(true); + JMenu exampleMenu = new JMenu("Menu"); + JMenuItem hiMenuItem = new JMenuItem("Hi There!"); + hiMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, + ActionEvent.CTRL_MASK)); + exampleMenu.add(hiMenuItem); + menuBar.add(exampleMenu); + menuPanel.add(menuBar); + + fr.setLayout(new BorderLayout()); + fr.add(menuPanel, BorderLayout.CENTER); + fr.setSize(250,100); + return fr; + } +} diff --git a/test/jdk/com/sun/java/swing/plaf/motif/SplitPane/4141400/bug4141400.java b/test/jdk/com/sun/java/swing/plaf/motif/SplitPane/4141400/bug4141400.java new file mode 100644 index 00000000000..2202c7726a3 --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/motif/SplitPane/4141400/bug4141400.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4141400 + * @summary Tests that the divider of JSplitPane can be moved only by + * dragging its thumb under Motif LAF + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4141400 + */ + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JSplitPane; +import javax.swing.UIManager; + +public class bug4141400 { + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("Failed to set Motif LAF"); + } + + String INSTRUCTIONS = """ + Place mouse cursor somewhere on the split pane divider, but outside + its thumb. Then try to move the divider. It should not move. If it + does not move, the test passes, otherwise it fails. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(70) + .testUI(bug4141400::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JFrame fr = new JFrame("bug4141400"); + JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, + true, + new JButton("Button 1"), + new JButton("Button 2")); + fr.add(pane); + fr.setSize(250, 300); + return fr; + } +} diff --git a/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/4685843/bug4685843.java b/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/4685843/bug4685843.java new file mode 100644 index 00000000000..dbab77aca3f --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/4685843/bug4685843.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4685843 + * @requires (os.family == "windows") + * @summary Tests that disabled JCheckBoxMenuItem's are drawn properly in + * Windows LAF + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4685843 + */ + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.UIManager; + +public class bug4685843 { + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel ( + "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("Failed to set Windows LAF"); + } + + String INSTRUCTIONS = """ + In the window named "bug4685843" open File menu. + If all three disabled items are drawn properly press "Pass". + Otherwise press "Fail". + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(bug4685843::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JMenuBar jMenuBar = new JMenuBar(); + JMenu jMenu = new JMenu("File"); + JMenuItem jMenuItem = new JMenuItem("JMenuItem"); + JCheckBoxMenuItem jCheckBoxMenuItem = + new JCheckBoxMenuItem("JCheckBoxMenuItem"); + JRadioButtonMenuItem jRadioButtonMenuItem = + new JRadioButtonMenuItem("JRadioButtonMenuItem"); + + jMenuItem.setEnabled(false); + jMenu.add(jMenuItem); + jCheckBoxMenuItem.setEnabled(false); + jMenu.add(jCheckBoxMenuItem); + jRadioButtonMenuItem.setEnabled(false); + jMenu.add(jRadioButtonMenuItem); + jMenuBar.add(jMenu); + + JFrame mainFrame = new JFrame("bug4685843"); + mainFrame.setJMenuBar(jMenuBar); + mainFrame.setSize(200, 200); + return mainFrame; + } +} From e21387e0454e821e5720e781138dcc4c24a14ec7 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 17 Apr 2025 13:08:49 +0000 Subject: [PATCH 230/843] 8354365: Opensource few Modal and Full Screen related tests Reviewed-by: jdv, tr --- test/jdk/ProblemList.txt | 1 + .../NonfocusableFrameFullScreenTest.java | 139 ++++++++++++++++++ .../awt/Modal/AddRemoveTransientForsTest.java | 123 ++++++++++++++++ .../java/awt/Modal/DialogLosesFocusTest.java | 107 ++++++++++++++ .../Modal/NativeDialogToFrontBackTest.java | 118 +++++++++++++++ 5 files changed, 488 insertions(+) create mode 100644 test/jdk/java/awt/FullScreen/NonfocusableFrameFullScreenTest.java create mode 100644 test/jdk/java/awt/Modal/AddRemoveTransientForsTest.java create mode 100644 test/jdk/java/awt/Modal/DialogLosesFocusTest.java create mode 100644 test/jdk/java/awt/Modal/NativeDialogToFrontBackTest.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index ac4828eadca..4a00130d3aa 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -391,6 +391,7 @@ java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665 macosx-all +java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326 macosx-all java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021 macosx-all java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all diff --git a/test/jdk/java/awt/FullScreen/NonfocusableFrameFullScreenTest.java b/test/jdk/java/awt/FullScreen/NonfocusableFrameFullScreenTest.java new file mode 100644 index 00000000000..a273adff6cc --- /dev/null +++ b/test/jdk/java/awt/FullScreen/NonfocusableFrameFullScreenTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GraphicsEnvironment; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JPanel; + +/* + * @test + * @bug 6225472 6682536 + * @requires (os.family != "linux") + * @summary Tests that non-focusable Frame in full-screen mode overlaps the task bar. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NonfocusableFrameFullScreenTest + */ + +public class NonfocusableFrameFullScreenTest extends JPanel { + boolean fullscreen = false; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + 1. Press "Show Frame" button to show a Frame with two buttons. + + 2. Press the button "To Full Screen" to bring the frame to + full-screen mode: + + The frame should overlap the taskbar + + 3. Press "To Windowed" button: + The frame should return to its original size. + The frame shouldn't be alwaysOnTop. + + 4. Press "Set Always On Top" button and make sure the frame + is alwaysOnTop, then press "To Full Screen" button + and then "To Windowed" button: + + The frame should return to its original size keeping alwaysOnTop + state on. + + Press Pass if everything is as expected."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(NonfocusableFrameFullScreenTest::new) + .build() + .awaitAndCheck(); + } + + private NonfocusableFrameFullScreenTest() { + Button b = new Button("Show Frame"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showFrame(); + } + }); + setLayout(new BorderLayout()); + add(b, BorderLayout.CENTER); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 100); + } + + public void showFrame() { + Frame frame = new Frame("Test Frame"); + + Button button = new Button("To Full Screen"); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (fullscreen) { + GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(). + setFullScreenWindow(null); + button.setLabel("To Full Screen"); + fullscreen = false; + } else { + GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(). + setFullScreenWindow(frame); + button.setLabel("To Windowed"); + fullscreen = true; + } + frame.validate(); + } + }); + + Button button2 = new Button("Set Always On Top"); + button2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (frame.isAlwaysOnTop()) { + button2.setLabel("Set Always On Top"); + frame.setAlwaysOnTop(false); + } else { + button2.setLabel("Set Not Always On Top"); + frame.setAlwaysOnTop(true); + } + frame.validate(); + } + }); + + frame.setLayout(new BorderLayout()); + frame.add(button, BorderLayout.WEST); + frame.add(button2, BorderLayout.EAST); + frame.setBounds(400, 200, 350, 100); + frame.setFocusableWindowState(false); + frame.setVisible(true); + } +} diff --git a/test/jdk/java/awt/Modal/AddRemoveTransientForsTest.java b/test/jdk/java/awt/Modal/AddRemoveTransientForsTest.java new file mode 100644 index 00000000000..65b66e8ce8d --- /dev/null +++ b/test/jdk/java/awt/Modal/AddRemoveTransientForsTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Frame; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/* + * @test + * @bug 6271779 + * @summary This test shows and hides a modal dialog several times without destroying its + * peer. Without the fix this may lead to application (or even WM) hang. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddRemoveTransientForsTest + */ + +public class AddRemoveTransientForsTest { + + private static Dialog d1; + private static Dialog d2; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + When the test starts, a frame is shown with a button 'Show Dialog D1'. + + 1. Press the button 'Show Dialog D1' to show a modal dialog D1 with a button + 'Show dialog D2'. + + 2. Press the button 'Show dialog D2' to show another modal dialog D2 with a button + 'Close'. + + 3. Press the button 'Close' to close dialog D2. + + 4. Repeat steps 2 and 3 several times (at least 3-4 times). + + If the application is not hung, press Pass. + + NOTE: all the modal dialogs must be closed before pressing Pass button."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(AddRemoveTransientForsTest::init) + .build() + .awaitAndCheck(); + } + + public static Frame init() { + Frame f = new Frame("AddRemoveTransientForsTest Frame"); + Button b = new Button("Show dialog D1"); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + d1.setVisible(true); + } + }); + f.add(b); + f.setSize(200, 100); + + WindowListener wl = new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) + { + e.getWindow().dispose(); + } + }; + + d1 = new Dialog(f, "D1", true); + d1.setBounds(200, 200, 200, 100); + d1.addWindowListener(wl); + Button b1 = new Button("Show dialog D2"); + b1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + d2.setVisible(true); + } + }); + d1.add(b1); + + d2 = new Dialog(d1, "D2", true); + d2.setBounds(300, 300, 200, 100); + Button b2 = new Button("Close"); + b2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + d2.setVisible(false); + } + }); + d2.add(b2); + + return f; + } +} diff --git a/test/jdk/java/awt/Modal/DialogLosesFocusTest.java b/test/jdk/java/awt/Modal/DialogLosesFocusTest.java new file mode 100644 index 00000000000..738c2c29ee2 --- /dev/null +++ b/test/jdk/java/awt/Modal/DialogLosesFocusTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/* + * @test + * @bug 6278150 + * @key headful + * @summary Initially modal blocked window causes modal dialog to lose focus + * @run main DialogLosesFocusTest + */ + +public class DialogLosesFocusTest { + private static Frame parent; + private static Dialog dialog; + private static Frame blocked; + private static volatile boolean failed; + + public static void main(String[] args) throws Exception { + try { + createAndShowUI(); + + sleepForMsecs(10000); + + if (failed) { + throw new RuntimeException("Test Failed"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (parent != null) { + parent.dispose(); + } + if (dialog != null) { + dialog.dispose(); + } + if (blocked != null) { + blocked.dispose(); + } + }); + } + } + + public static void createAndShowUI() throws Exception { + EventQueue.invokeAndWait(() -> { + parent = new Frame("Parent frame"); + parent.setBounds(0, 0, 300, 100); + parent.setVisible(true); + }); + + sleepForMsecs(1000); + + EventQueue.invokeLater(() -> { + dialog = new Dialog(parent, "Modal dialog", Dialog.ModalityType.APPLICATION_MODAL); + dialog.setBounds(100, 120, 300, 100); + dialog.setVisible(true); + }); + + sleepForMsecs(1000); + + EventQueue.invokeAndWait(() -> { + blocked = new Frame("Blocked frame"); + blocked.setBounds(200, 240, 300, 100); + blocked.addWindowListener(new WindowAdapter() { + @Override + public void windowActivated(WindowEvent we) { + if (dialog.isVisible()) { + failed = true; + } + } + }); + blocked.setVisible(true); + }); + } + + private static void sleepForMsecs(int t) { + try { + Thread.sleep(t); + } catch (Exception z) {} + } +} diff --git a/test/jdk/java/awt/Modal/NativeDialogToFrontBackTest.java b/test/jdk/java/awt/Modal/NativeDialogToFrontBackTest.java new file mode 100644 index 00000000000..6c41ef73b1e --- /dev/null +++ b/test/jdk/java/awt/Modal/NativeDialogToFrontBackTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Dialog; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.util.List; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.print.PageFormat; +import java.awt.print.PrinterJob; + +/* + * @test + * @bug 6393608 + * @summary Tests that toBack/toFront methods works correctly for native dialogs + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NativeDialogToFrontBackTest + */ + +public class NativeDialogToFrontBackTest { + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + When the test starts two frames appear: 'Control' and 'Blocked' + 1. Click on the 'Show file dialog' button + 2. Drag the file dialog so it partially overlaps the 'Blocked' frame + 3. 'Blocked' frame must be below the file dialog, if not - press Fail + 3. Click on the 'Blocked to front' button + 4. 'Blocked' frame must still be below the file dialog, if not - press Fail + 5. Close the file dialog + 6. Repeat steps 2 to 4 with print and page dialogs using the corresponding button + 7. If 'Blocked' frame is always below File/Print/Page dialog, press Pass"""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(NativeDialogToFrontBackTest::init) + .positionTestUI(WindowLayouts::rightOneColumn) + .build() + .awaitAndCheck(); + } + + public static List init() { + Frame blocked = new Frame("Blocked"); + blocked.setSize(200, 200); + + Frame control = new Frame("Control"); + control.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + control.setLayout(new FlowLayout()); + + Button showFileDialog = new Button("Show file dialog"); + showFileDialog.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + new FileDialog(control, "File dialog").setVisible(true); + } + }); + control.add(showFileDialog); + + Button showPrintDialog = new Button("Show print dialog"); + showPrintDialog.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + PrinterJob.getPrinterJob().printDialog(); + } + }); + control.add(showPrintDialog); + + Button showPageDialog = new Button("Show page dialog"); + showPageDialog.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + PrinterJob.getPrinterJob().pageDialog(new PageFormat()); + } + }); + control.add(showPageDialog); + + Button blockedToFront = new Button("Blocked to front"); + blockedToFront.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) + { + blocked.toFront(); + } + }); + control.add(blockedToFront); + + control.setSize(200, 200); + return List.of(control, blocked); + } +} From dda4b5a4ade2e5d7225117e58fce4038bb0e0f1b Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Thu, 17 Apr 2025 13:36:05 +0000 Subject: [PATCH 231/843] 8354418: Open source Swing tests Batch 4 Reviewed-by: abhiscxk --- .../WindowsLAFMenuAcceleratorDelimiter.java | 95 ++++++++++++++++++ .../4227768/bug4227768.java | 99 +++++++++++++++++++ .../4305725/bug4305725.java | 97 ++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 test/jdk/com/sun/java/swing/plaf/windows/MenuItem/AcceleratorDelimiter/WindowsLAFMenuAcceleratorDelimiter.java create mode 100644 test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4227768/bug4227768.java create mode 100644 test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4305725/bug4305725.java diff --git a/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/AcceleratorDelimiter/WindowsLAFMenuAcceleratorDelimiter.java b/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/AcceleratorDelimiter/WindowsLAFMenuAcceleratorDelimiter.java new file mode 100644 index 00000000000..adb1d93c9fe --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/AcceleratorDelimiter/WindowsLAFMenuAcceleratorDelimiter.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4210461 + * @requires (os.family == "windows") + * @summary Tests that Windows Look & Feel's MenuItem Accelerator Delimiter is + * shown properly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual WindowsLAFMenuAcceleratorDelimiter + */ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +public class WindowsLAFMenuAcceleratorDelimiter { + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel( + "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("The Windows LAF failed to instantiate"); + } + + String INSTRUCTIONS = """ + The visual design specification for the Windows LAF asks for + a "+" to delimit the other two entities in a menuitem's + accelerator. + + As a point of reference, the visual design specifications for the + L&Fs are as follows: JLF/Metal = "-", Mac = "-", Motif = "+", + Windows = "+". + + Click on "Menu" of "WindowsLAFMenuAcceleratorDelimiter" window, + make sure it shows MenuItem with label "Hi There! Ctrl+H". + + If it shows same label test passed otherwise failed. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(WindowsLAFMenuAcceleratorDelimiter::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JFrame fr = new JFrame("WindowsLAFMenuAcceleratorDelimiter"); + JPanel menuPanel = new JPanel(); + JMenuBar menuBar = new JMenuBar(); + menuBar.setOpaque(true); + JMenu exampleMenu = new JMenu("Menu"); + JMenuItem hiMenuItem = new JMenuItem("Hi There!"); + hiMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, + ActionEvent.CTRL_MASK)); + exampleMenu.add(hiMenuItem); + menuBar.add(exampleMenu); + menuPanel.add(menuBar); + + fr.setLayout(new BorderLayout()); + fr.add(menuPanel, BorderLayout.CENTER); + fr.setSize(250, 100); + return fr; + } +} diff --git a/test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4227768/bug4227768.java b/test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4227768/bug4227768.java new file mode 100644 index 00000000000..ef9cc90bea0 --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4227768/bug4227768.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4227768 + * @requires (os.family == "windows") + * @summary Tests Z-ordering of Windows Look-and-Feel JInternalFrames + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4227768 + */ + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.beans.PropertyVetoException; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.UIManager; + +public class bug4227768 { + private static JDesktopPane desktop ; + private static JFrame frame; + private static int openFrameCount = 0; + private static final int xOffset = 30; + private static final int yOffset = 30; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel + ("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("Failed to set Windows LAF"); + } + + String INSTRUCTIONS = """ + Close the internal frame titled "Document #4". The internal frame + titled "Document #3" should get active. Now close the internal + frame titled "Document #2". The internal frame titled "Document #3" + should remain active. If something is not like this, then test + failed. Otherwise test succeeded. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4227768::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + frame = new JFrame("bug4227768"); + frame.setSize(screenSize.width / 3, screenSize.height / 3); + frame.add(desktop = new JDesktopPane()); + createFrame(); + createFrame(); + createFrame(); + createFrame(); + desktop.putClientProperty("JDesktopPane.dragMode", "outline"); + return frame; + } + + protected static void createFrame() { + JInternalFrame internalFrame = new JInternalFrame + ("Document #" + (++openFrameCount), true, true, true, true); + internalFrame.setSize(frame.getWidth() / 2, frame.getHeight() / 2); + internalFrame.setLocation(xOffset * openFrameCount, + yOffset * openFrameCount); + desktop.add(internalFrame); + internalFrame.setVisible(true); + try { + internalFrame.setSelected(true); + } catch (PropertyVetoException e) { + throw new RuntimeException(e); + } + } +} diff --git a/test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4305725/bug4305725.java b/test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4305725/bug4305725.java new file mode 100644 index 00000000000..4b9a462c472 --- /dev/null +++ b/test/jdk/com/sun/java/swing/plaf/windows/WindowsDesktopManager/4305725/bug4305725.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4305725 + * @requires (os.family == "windows") + * @summary Tests if in Win LAF the JOptionPane.showInternalMessageDialog() is + * not maximized to match background maximized internal frame. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4305725 + */ + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.UIManager; + +public class bug4305725 implements ActionListener { + private static JDesktopPane desktop ; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel + ("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException("Failed to set Windows LAF"); + } + + String INSTRUCTIONS = """ + Maximize the internal frame, then call Exit from File menu. + You will see a message box. If message box is also the size of + internal frame, then test failed. If it is of usual size, + then test is passed. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4305725::initialize) + .build() + .awaitAndCheck(); + } + + private static JFrame initialize() { + JFrame frame = new JFrame("bug4305725"); + frame.add(desktop = new JDesktopPane()); + JMenuBar mb = new JMenuBar() ; + JMenu menu = new JMenu("File"); + mb.add(menu) ; + JMenuItem menuItem = menu.add(new JMenuItem("Exit")); + menuItem.addActionListener(new bug4305725()) ; + frame.setJMenuBar(mb) ; + Dimension sDim = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setSize(sDim.width / 2, sDim.height / 2) ; + JInternalFrame internalFrame = new JInternalFrame + ("Internal", true, true, true, true); + internalFrame.setSize(frame.getWidth(), frame.getHeight() / 2); + internalFrame.setVisible(true); + desktop.add(internalFrame, JLayeredPane.FRAME_CONTENT_LAYER); + return frame; + } + + @Override + public void actionPerformed(ActionEvent aEvent) { + JOptionPane.showInternalMessageDialog(desktop, "Exiting test app"); + } +} From abb23828f9dc5f4cdb75d5b924dd6f45925102cd Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Thu, 17 Apr 2025 13:45:47 +0000 Subject: [PATCH 232/843] 8350807: Certificates using MD5 algorithm that are disabled by default are incorrectly allowed in TLSv1.3 when re-enabled Reviewed-by: mullan --- .../security/ssl/CertSignAlgsExtension.java | 19 +- .../sun/security/ssl/CertificateMessage.java | 118 ++++----- .../sun/security/ssl/CertificateRequest.java | 18 +- .../classes/sun/security/ssl/ClientHello.java | 6 +- .../security/ssl/PreSharedKeyExtension.java | 9 +- .../classes/sun/security/ssl/ServerHello.java | 43 +--- .../security/ssl/SessionTicketExtension.java | 9 +- .../ssl/SignatureAlgorithmsExtension.java | 22 +- .../sun/security/ssl/SignatureScheme.java | 33 ++- .../CriticalSubjectAltName.java | 3 +- .../net/ssl/templates/SSLSocketTemplate.java | 6 +- .../HttpsURLConnection/DNSIdentities.java | 4 +- .../IPAddressIPIdentities.java | 4 +- .../HttpsURLConnection/IPIdentities.java | 4 +- .../https/HttpsURLConnection/Identities.java | 4 +- ...NotAllowedInTLS13CertificateSignature.java | 231 ++++++++++++++++++ 16 files changed, 351 insertions(+), 182 deletions(-) create mode 100644 test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java diff --git a/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java b/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java index 2772ecff337..b975290d09d 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/CertSignAlgsExtension.java @@ -99,13 +99,7 @@ final class CertSignAlgsExtension { } // Produce the extension. - if (chc.localSupportedCertSignAlgs == null) { - chc.localSupportedCertSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols, - CERTIFICATE_SCOPE); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); int vectorLen = SignatureScheme.sizeInRecord() * chc.localSupportedCertSignAlgs.size(); @@ -245,15 +239,8 @@ final class CertSignAlgsExtension { } // Produce the extension. - if (shc.localSupportedCertSignAlgs == null) { - shc.localSupportedCertSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, - List.of(shc.negotiatedProtocol), - CERTIFICATE_SCOPE); - } - + // localSupportedCertSignAlgs has been already updated when we set + // the negotiated protocol. int vectorLen = SignatureScheme.sizeInRecord() * shc.localSupportedCertSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java index cdb65bd329a..c055673b45b 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -697,46 +697,6 @@ final class CertificateMessage { } } - /** - * When a failure happens during certificate checking from an - * {@link X509TrustManager}, determine what TLS alert description - * to use. - * - * @param cexc The exception thrown by the {@link X509TrustManager} - * - * @return A byte value corresponding to a TLS alert description number. - */ - private static Alert getCertificateAlert( - ClientHandshakeContext chc, CertificateException cexc) { - // The specific reason for the failure will determine how to - // set the alert description value - Alert alert = Alert.CERTIFICATE_UNKNOWN; - - Throwable baseCause = cexc.getCause(); - if (baseCause instanceof CertPathValidatorException cpve) { - Reason reason = cpve.getReason(); - if (reason == BasicReason.REVOKED) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_REVOKED; - } else if ( - reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_UNKNOWN; - } else if (reason == BasicReason.ALGORITHM_CONSTRAINED) { - alert = Alert.UNSUPPORTED_CERTIFICATE; - } else if (reason == BasicReason.EXPIRED) { - alert = Alert.CERTIFICATE_EXPIRED; - } else if (reason == BasicReason.INVALID_SIGNATURE || - reason == BasicReason.NOT_YET_VALID) { - alert = Alert.BAD_CERTIFICATE; - } - } - - return alert; - } - } /** @@ -1329,37 +1289,57 @@ final class CertificateMessage { return certs; } - /** - * When a failure happens during certificate checking from an - * {@link X509TrustManager}, determine what TLS alert description - * to use. - * - * @param cexc The exception thrown by the {@link X509TrustManager} - * - * @return A byte value corresponding to a TLS alert description number. - */ - private static Alert getCertificateAlert( - ClientHandshakeContext chc, CertificateException cexc) { - // The specific reason for the failure will determine how to - // set the alert description value - Alert alert = Alert.CERTIFICATE_UNKNOWN; + } - Throwable baseCause = cexc.getCause(); - if (baseCause instanceof CertPathValidatorException cpve) { - Reason reason = cpve.getReason(); - if (reason == BasicReason.REVOKED) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_REVOKED; - } else if ( - reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { - alert = chc.staplingActive ? - Alert.BAD_CERT_STATUS_RESPONSE : - Alert.CERTIFICATE_UNKNOWN; + /** + * When a failure happens during certificate checking from an + * {@link X509TrustManager}, determine what TLS alert description + * to use. + * + * @param cexc The exception thrown by the {@link X509TrustManager} + * @return A byte value corresponding to a TLS alert description number. + */ + private static Alert getCertificateAlert( + ClientHandshakeContext chc, CertificateException cexc) { + // The specific reason for the failure will determine how to + // set the alert description value + Alert alert = Alert.CERTIFICATE_UNKNOWN; + + Throwable baseCause = cexc.getCause(); + if (baseCause instanceof CertPathValidatorException cpve) { + Reason reason = cpve.getReason(); + if (reason == BasicReason.REVOKED) { + alert = chc.staplingActive ? + Alert.BAD_CERT_STATUS_RESPONSE : + Alert.CERTIFICATE_REVOKED; + } else if (reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { + alert = chc.staplingActive ? + Alert.BAD_CERT_STATUS_RESPONSE : + Alert.CERTIFICATE_UNKNOWN; + } else if (reason == BasicReason.EXPIRED) { + alert = Alert.CERTIFICATE_EXPIRED; + } else if (reason == BasicReason.INVALID_SIGNATURE + || reason == BasicReason.NOT_YET_VALID) { + alert = Alert.BAD_CERTIFICATE; + } else if (reason == BasicReason.ALGORITHM_CONSTRAINED) { + alert = Alert.UNSUPPORTED_CERTIFICATE; + + // Per TLSv1.3 RFC we MUST abort the handshake with a + // "bad_certificate" alert if we reject certificate + // because of the signature using MD5 or SHA1 algorithm. + if (chc.negotiatedProtocol != null + && chc.negotiatedProtocol.useTLS13PlusSpec()) { + final String exMsg = cexc.getMessage().toUpperCase(); + + if (exMsg.contains("MD5WITH") + || exMsg.contains("SHA1WITH")) { + alert = Alert.BAD_CERTIFICATE; + } } } - - return alert; } + + return alert; } + } diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java index 062d4d77a58..66b8c048703 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java @@ -636,25 +636,11 @@ final class CertificateRequest { // The producing happens in server side only. ServerHandshakeContext shc = (ServerHandshakeContext) context; - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols, - HANDSHAKE_SCOPE); - } - - if (shc.localSupportedCertSignAlgs == null) { - shc.localSupportedCertSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols, - CERTIFICATE_SCOPE); - } - // According to TLSv1.2 RFC, CertificateRequest message must // contain signature schemes supported for both: // handshake signatures and certificate signatures. + // localSupportedSignAlgs and localSupportedCertSignAlgs have been + // already updated when we set the negotiated protocol. List certReqSignAlgs = new ArrayList<>(shc.localSupportedSignAlgs); certReqSignAlgs.retainAll(shc.localSupportedCertSignAlgs); diff --git a/src/java.base/share/classes/sun/security/ssl/ClientHello.java b/src/java.base/share/classes/sun/security/ssl/ClientHello.java index e75076b11d6..3e43921520d 100644 --- a/src/java.base/share/classes/sun/security/ssl/ClientHello.java +++ b/src/java.base/share/classes/sun/security/ssl/ClientHello.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -825,6 +825,10 @@ final class ClientHello { "Negotiated protocol version: " + negotiatedProtocol.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(context); + // Consume the handshake message for the specific protocol version. if (negotiatedProtocol.isDTLS) { if (negotiatedProtocol.useTLS13PlusSpec()) { diff --git a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java index 9e843a0e4a5..4751708e5dc 100644 --- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java @@ -42,7 +42,6 @@ import sun.security.ssl.SessionTicketExtension.SessionTicketSpec; import sun.security.util.HexDumpEncoder; import static sun.security.ssl.SSLExtension.*; -import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; /** * Pack of the "pre_shared_key" extension. @@ -445,13 +444,7 @@ final class PreSharedKeyExtension { // localSupportedCertSignAlgs field is populated. This is particularly // important when client authentication was used in an initial session, // and it is now being resumed. - if (shc.localSupportedCertSignAlgs == null) { - shc.localSupportedCertSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols, - CERTIFICATE_SCOPE); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(shc); // Validate the required client authentication. if (result && diff --git a/src/java.base/share/classes/sun/security/ssl/ServerHello.java b/src/java.base/share/classes/sun/security/ssl/ServerHello.java index f19964dd5c7..303095a0722 100644 --- a/src/java.base/share/classes/sun/security/ssl/ServerHello.java +++ b/src/java.base/share/classes/sun/security/ssl/ServerHello.java @@ -25,9 +25,6 @@ package sun.security.ssl; -import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; -import static sun.security.ssl.SignatureScheme.HANDSHAKE_SCOPE; - import java.io.IOException; import java.nio.ByteBuffer; import java.security.AlgorithmConstraints; @@ -272,22 +269,6 @@ final class ServerHello { "Not resumption, and no new session is allowed"); } - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols, - HANDSHAKE_SCOPE); - } - - if (shc.localSupportedCertSignAlgs == null) { - shc.localSupportedCertSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols, - CERTIFICATE_SCOPE); - } - SSLSessionImpl session = new SSLSessionImpl(shc, CipherSuite.C_NULL); session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize); @@ -522,22 +503,6 @@ final class ServerHello { "Not resumption, and no new session is allowed"); } - if (shc.localSupportedSignAlgs == null) { - shc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols, - HANDSHAKE_SCOPE); - } - - if (shc.localSupportedCertSignAlgs == null) { - shc.localSupportedCertSignAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, shc.activeProtocols, - CERTIFICATE_SCOPE); - } - SSLSessionImpl session = new SSLSessionImpl(shc, CipherSuite.C_NULL); session.setMaximumPacketSize(shc.sslConfig.maximumPacketSize); @@ -959,6 +924,10 @@ final class ServerHello { "Negotiated protocol version: " + serverVersion.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); + // TLS 1.3 key share extension may have produced client // possessions for TLS 1.3 key exchanges. // @@ -1010,6 +979,10 @@ final class ServerHello { "Negotiated protocol version: " + serverVersion.name); } + // Protocol version is negotiated, update locally supported + // signature schemes according to the protocol being used. + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); + if (serverHello.serverRandom.isVersionDowngrade(chc)) { throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER, "A potential protocol version downgrade attack"); diff --git a/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java b/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java index 60f630ccbd2..6cf930619f7 100644 --- a/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/SessionTicketExtension.java @@ -40,7 +40,6 @@ import javax.net.ssl.SSLSessionContext; import static sun.security.ssl.SSLExtension.CH_SESSION_TICKET; import static sun.security.ssl.SSLExtension.SH_SESSION_TICKET; -import static sun.security.ssl.SignatureScheme.CERTIFICATE_SCOPE; import sun.security.ssl.SSLExtension.ExtensionConsumer; import sun.security.ssl.SSLExtension.SSLExtensionSpec; @@ -353,13 +352,7 @@ final class SessionTicketExtension { return new byte[0]; } - if (chc.localSupportedCertSignAlgs == null) { - chc.localSupportedCertSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols, - CERTIFICATE_SCOPE); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); return chc.resumingSession.getPskIdentity(); } diff --git a/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java b/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java index 2b36d35e78d..80029e73afb 100644 --- a/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/SignatureAlgorithmsExtension.java @@ -187,13 +187,7 @@ final class SignatureAlgorithmsExtension { } // Produce the extension. - if (chc.localSupportedSignAlgs == null) { - chc.localSupportedSignAlgs = - SignatureScheme.getSupportedAlgorithms( - chc.sslConfig, - chc.algorithmConstraints, chc.activeProtocols, - HANDSHAKE_SCOPE); - } + SignatureScheme.updateHandshakeLocalSupportedAlgs(chc); int vectorLen = SignatureScheme.sizeInRecord() * chc.localSupportedSignAlgs.size(); @@ -417,18 +411,14 @@ final class SignatureAlgorithmsExtension { } // Produce the extension. - List sigAlgs = - SignatureScheme.getSupportedAlgorithms( - shc.sslConfig, - shc.algorithmConstraints, - List.of(shc.negotiatedProtocol), - HANDSHAKE_SCOPE); - - int vectorLen = SignatureScheme.sizeInRecord() * sigAlgs.size(); + // localSupportedSignAlgs has been already updated when we + // set the negotiated protocol. + int vectorLen = SignatureScheme.sizeInRecord() + * shc.localSupportedSignAlgs.size(); byte[] extData = new byte[vectorLen + 2]; ByteBuffer m = ByteBuffer.wrap(extData); Record.putInt16(m, vectorLen); - for (SignatureScheme ss : sigAlgs) { + for (SignatureScheme ss : shc.localSupportedSignAlgs) { Record.putInt16(m, ss.id); } diff --git a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java index b817cc3fb9d..b3ed5810c56 100644 --- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java +++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java @@ -374,9 +374,40 @@ enum SignatureScheme { && (namedGroup == null || namedGroup.isPermitted(constraints)); } + // Helper method to update all locally supported signature schemes for + // a given HandshakeContext. + static void updateHandshakeLocalSupportedAlgs(HandshakeContext hc) { + // To improve performance we only update when necessary. + // No need to do anything if we already computed the local supported + // algorithms and either there is no negotiated protocol yet or the + // only active protocol ends up to be the negotiated protocol. + if (hc.localSupportedSignAlgs != null + && hc.localSupportedCertSignAlgs != null + && (hc.negotiatedProtocol == null + || hc.activeProtocols.size() == 1)) { + return; + } + + List protocols = hc.negotiatedProtocol != null ? + List.of(hc.negotiatedProtocol) : + hc.activeProtocols; + + hc.localSupportedSignAlgs = getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + protocols, + HANDSHAKE_SCOPE); + + hc.localSupportedCertSignAlgs = getSupportedAlgorithms( + hc.sslConfig, + hc.algorithmConstraints, + protocols, + CERTIFICATE_SCOPE); + } + // Get local supported algorithm collection complying to algorithm // constraints and SSL scopes. - static List getSupportedAlgorithms( + private static List getSupportedAlgorithms( SSLConfiguration config, SSLAlgorithmConstraints constraints, List activeProtocols, diff --git a/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java b/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java index d4eca8b5776..cb11b17ebb5 100644 --- a/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java +++ b/test/jdk/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,6 +105,7 @@ public class CriticalSubjectAltName implements HostnameVerifier { (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket sslServerSocket = (SSLServerSocket) sslssf.createServerSocket(serverPort); + sslServerSocket.setEnabledProtocols(new String[]{"TLSv1.2"}); serverPort = sslServerSocket.getLocalPort(); /* diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java index b67f8978304..ce1a99a7f1e 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, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,7 +245,7 @@ public class SSLSocketTemplate extends SSLContextTemplate { // // The server side takes care of the issue if the server cannot // get started in 90 seconds. The client side would just ignore - // the test case if the serer is not ready. + // the test case if the server is not ready. boolean serverIsReady = serverCondition.await(90L, TimeUnit.SECONDS); if (!serverIsReady) { @@ -378,7 +378,7 @@ public class SSLSocketTemplate extends SSLContextTemplate { * Check various exception conditions. */ if ((local != null) && (remote != null)) { - // If both failed, return the curthread's exception. + // If both failed, return the current thread's exception. local.addSuppressed(remote); exception = local; } else if (local != null) { diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java index 0d479d60fd2..4b2dece0c75 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -893,7 +893,7 @@ public class DNSIdentities { TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java index bd6c62c603c..a15093c821e 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -901,7 +901,7 @@ public class IPAddressIPIdentities { TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java index 91f0020f7d1..6ea62526566 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -900,7 +900,7 @@ public class IPIdentities { TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff --git a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java index 3764b3de688..53960c05895 100644 --- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java +++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/Identities.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -893,7 +893,7 @@ public class Identities { TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); - SSLContext ctx = SSLContext.getInstance("TLS"); + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); if (keyCertStr != null) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); diff --git a/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java b/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java new file mode 100644 index 00000000000..ed61aace3f4 --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/MD5NotAllowedInTLS13CertificateSignature.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8350807 + * @summary Certificates using MD5 algorithm that are disabled by default are + * incorrectly allowed in TLSv1.3 when re-enabled. + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /javax/net/ssl/templates + * /test/lib + * @run main/othervm MD5NotAllowedInTLS13CertificateSignature + */ + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertTrue; +import static jdk.test.lib.Utils.runAndCheckException; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.List; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import jdk.test.lib.security.CertificateBuilder; +import jdk.test.lib.security.SecurityUtils; +import sun.security.x509.AuthorityKeyIdentifierExtension; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNames; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.SerialNumber; +import sun.security.x509.X500Name; + +public class MD5NotAllowedInTLS13CertificateSignature extends + SSLSocketTemplate { + + private final String protocol; + private X509Certificate trustedCert; + private X509Certificate serverCert; + private X509Certificate clientCert; + private KeyPair serverKeys; + private KeyPair clientKeys; + + protected MD5NotAllowedInTLS13CertificateSignature(String protocol) + throws Exception { + super(); + this.protocol = protocol; + setupCertificates(); + } + + public static void main(String[] args) throws Exception { + // MD5 is disabled by default in java.security config file, + // re-enable it for our test. + SecurityUtils.removeFromDisabledAlgs( + "jdk.certpath.disabledAlgorithms", List.of("MD5")); + SecurityUtils.removeFromDisabledAlgs( + "jdk.tls.disabledAlgorithms", List.of("MD5withRSA")); + + // Should fail on TLSv1.3 and up. + runAndCheckException( + // The conditions to reproduce the bug being fixed only met when + // 'TLS' is specified, i.e. when older versions of protocol are + // supported besides TLSv1.3. + () -> new MD5NotAllowedInTLS13CertificateSignature("TLS").run(), + serverEx -> { + Throwable clientEx = serverEx.getSuppressed()[0]; + assertTrue(clientEx instanceof SSLHandshakeException); + assertEquals(clientEx.getMessage(), "(bad_certificate) " + + "PKIX path validation failed: " + + "java.security.cert.CertPathValidatorException: " + + "Algorithm constraints check failed on signature" + + " algorithm: MD5withRSA"); + }); + + // Should run fine on TLSv1.2. + new MD5NotAllowedInTLS13CertificateSignature("TLSv1.2").run(); + } + + @Override + public SSLContext createServerSSLContext() throws Exception { + return getSSLContext( + trustedCert, serverCert, serverKeys.getPrivate(), protocol); + } + + @Override + public SSLContext createClientSSLContext() throws Exception { + return getSSLContext( + trustedCert, clientCert, clientKeys.getPrivate(), protocol); + } + + private static SSLContext getSSLContext( + X509Certificate trustedCertificate, X509Certificate keyCertificate, + PrivateKey privateKey, String protocol) + throws Exception { + + // create a key store + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(null, null); + + // import the trusted cert + ks.setCertificateEntry("TLS Signer", trustedCertificate); + + // generate certificate chain + Certificate[] chain = new Certificate[2]; + chain[0] = keyCertificate; + chain[1] = trustedCertificate; + + // import the key entry. + final char[] passphrase = "passphrase".toCharArray(); + ks.setKeyEntry("Whatever", privateKey, passphrase, chain); + + // Using PKIX TrustManager - this is where MD5 signature check is done. + TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(ks); + + // create SSL context + SSLContext ctx = SSLContext.getInstance(protocol); + + // Using "SunX509" which doesn't check peer supported signature + // algorithms, so we check against local supported signature + // algorithms which constitutes the fix being tested. + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + return ctx; + } + + // Certificate-building helper methods. + // Certificates are signed with signature using MD5WithRSA algorithm. + + private void setupCertificates() throws Exception { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(1024); + KeyPair caKeys = kpg.generateKeyPair(); + this.serverKeys = kpg.generateKeyPair(); + this.clientKeys = kpg.generateKeyPair(); + + this.trustedCert = createTrustedCert(caKeys); + + this.serverCert = customCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + serverKeys.getPublic(), caKeys.getPublic()) + .addBasicConstraintsExt(false, false, -1) + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + + this.clientCert = customCertificateBuilder( + "CN=localhost, OU=SSL-Client, O=Some-Org, L=Some-City, ST=Some-State, C=US", + clientKeys.getPublic(), caKeys.getPublic()) + .addBasicConstraintsExt(false, false, -1) + .build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); + } + + private static X509Certificate createTrustedCert(KeyPair caKeys) + throws Exception { + SecureRandom random = new SecureRandom(); + + KeyIdentifier kid = new KeyIdentifier(caKeys.getPublic()); + GeneralNames gns = new GeneralNames(); + GeneralName name = new GeneralName(new X500Name( + "O=Some-Org, L=Some-City, ST=Some-State, C=US")); + gns.add(name); + BigInteger serialNumber = BigInteger.valueOf( + random.nextLong(1000000) + 1); + return customCertificateBuilder( + "O=Some-Org, L=Some-City, ST=Some-State, C=US", + caKeys.getPublic(), caKeys.getPublic()) + .setSerialNumber(serialNumber) + .addExtension(new AuthorityKeyIdentifierExtension(kid, gns, + new SerialNumber(serialNumber))) + .addBasicConstraintsExt(true, true, -1) + .build(null, caKeys.getPrivate(), "MD5WithRSA"); + } + + private static CertificateBuilder customCertificateBuilder( + String subjectName, PublicKey publicKey, PublicKey caKey) + throws CertificateException, IOException { + SecureRandom random = new SecureRandom(); + + CertificateBuilder builder = new CertificateBuilder() + .setSubjectName(subjectName) + .setPublicKey(publicKey) + .setNotAfter( + Date.from(Instant.now().minus(1, ChronoUnit.HOURS))) + .setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS))) + .setSerialNumber( + BigInteger.valueOf(random.nextLong(1000000) + 1)) + .addSubjectKeyIdExt(publicKey) + .addAuthorityKeyIdExt(caKey); + builder.addKeyUsageExt( + new boolean[]{true, true, true, true, true, true}); + + return builder; + } + +} From 86f3eafade20bd901b0657ab9ad1bdf12d1143c2 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Thu, 17 Apr 2025 13:59:44 +0000 Subject: [PATCH 233/843] 8353009: Improve documentation for Windows AArch64 builds Reviewed-by: erikj, ihse --- doc/building.html | 14 ++++++++++++++ doc/building.md | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/doc/building.html b/doc/building.html index 95cda58e828..1e6f99e97c9 100644 --- a/doc/building.html +++ b/doc/building.html @@ -1722,6 +1722,20 @@ packages in the sysroot, configure the build with --with-devkit=$DEVKIT \ --with-sysroot=$SYSROOT

and run make normally.

+

Building for Windows AArch64

+

The Visual Studio Build Tools can be used for building the JDK +without a full Visual Studio installation. To set up the Visual Studio +2022 Build Tools on a Windows AArch64 machine for a native build, launch +the installer as follows in a Windows command prompt:

+
vs_buildtools.exe --quiet --wait --norestart --nocache ^
+--installPath "%ProgramFiles(x86)%\Microsoft Visual Studio\2022\BuildTools" ^
+--add Microsoft.VisualStudio.Component.VC.CoreBuildTools ^
+--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ^
+--add Microsoft.VisualStudio.Component.Windows11SDK.22621
+

To generate Windows AArch64 builds using Cygwin on a Windows x64 +machine, you must set the proper target platform by adding +--openjdk-target=aarch64-unknown-cygwin to your configure +command line.

Build Performance

Building the JDK requires a lot of horsepower. Some of the build tools can be adjusted to utilize more or less of resources such as diff --git a/doc/building.md b/doc/building.md index 914473916b4..18e030baa9e 100644 --- a/doc/building.md +++ b/doc/building.md @@ -1457,6 +1457,24 @@ sh ./configure --with-jvm-variants=server \ and run `make` normally. +#### Building for Windows AArch64 +The Visual Studio Build Tools can be used for building the JDK without a full +Visual Studio installation. To set up the Visual Studio 2022 Build Tools on a +Windows AArch64 machine for a native build, launch the installer as follows +in a Windows command prompt: + +``` +vs_buildtools.exe --quiet --wait --norestart --nocache ^ +--installPath "%ProgramFiles(x86)%\Microsoft Visual Studio\2022\BuildTools" ^ +--add Microsoft.VisualStudio.Component.VC.CoreBuildTools ^ +--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ^ +--add Microsoft.VisualStudio.Component.Windows11SDK.22621 +``` + +To generate Windows AArch64 builds using Cygwin on a Windows x64 machine, +you must set the proper target platform by adding +`--openjdk-target=aarch64-unknown-cygwin` to your configure command line. + ## Build Performance Building the JDK requires a lot of horsepower. Some of the build tools can be From cd8adf13ed6579fad9e777aa291146fa653288b0 Mon Sep 17 00:00:00 2001 From: Ferenc Rakoczi Date: Thu, 17 Apr 2025 14:01:46 +0000 Subject: [PATCH 234/843] 8354926: Remove remnants of debugging in the fix for JDK-8348561 and JDK-8349721 Reviewed-by: adinn --- src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp | 2 +- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp index 1107ec0a8f8..c8b215b6eb4 100644 --- a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp @@ -44,7 +44,7 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(compiler, 75000 ZGC_ONLY(+5000)) \ + do_arch_blob(compiler, 65000 ZGC_ONLY(+5000)) \ do_stub(compiler, vector_iota_indices) \ do_arch_entry(aarch64, compiler, vector_iota_indices, \ vector_iota_indices, vector_iota_indices) \ diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 6bf300ced42..c555e393ca5 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -714,7 +714,6 @@ void VM_Version::initialize_cpu_information(void) { get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len); desc_len = (int)strlen(_cpu_desc); snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _features_string); - fprintf(stderr, "_features_string = \"%s\"", _features_string); _initialized = true; } From d1d81dd01ca6f3fc1e4710e6055c5a3185f43d9a Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Thu, 17 Apr 2025 15:37:05 +0000 Subject: [PATCH 235/843] 8353953: con/sun/jdi tests should be fixed to not always require includevirtualthreads=y Reviewed-by: sspitsyn, amenkov --- test/jdk/com/sun/jdi/EventQueueDisconnectTest.java | 4 ++-- .../jdi/RedefineNestmateAttr/TestNestmateAttr.java | 3 ++- test/jdk/com/sun/jdi/TestScaffold.java | 12 ++++++++++-- test/jdk/com/sun/jdi/VMConnection.java | 6 +++--- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/test/jdk/com/sun/jdi/EventQueueDisconnectTest.java b/test/jdk/com/sun/jdi/EventQueueDisconnectTest.java index c050cb792eb..848046186ef 100644 --- a/test/jdk/com/sun/jdi/EventQueueDisconnectTest.java +++ b/test/jdk/com/sun/jdi/EventQueueDisconnectTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ public class EventQueueDisconnectTest { public static void main(String args[]) throws Exception { VMConnection connection = new VMConnection( "com.sun.jdi.CommandLineLaunch:", - VirtualMachine.TRACE_NONE); + VirtualMachine.TRACE_NONE, false); connection.setConnectorArg("main", "EventQueueDisconnectTarg"); String debuggeeVMOptions = VMConnection.getDebuggeeVMOptions(); if (!debuggeeVMOptions.equals("")) { diff --git a/test/jdk/com/sun/jdi/RedefineNestmateAttr/TestNestmateAttr.java b/test/jdk/com/sun/jdi/RedefineNestmateAttr/TestNestmateAttr.java index 76bd3bf5dc1..21ea9f38921 100644 --- a/test/jdk/com/sun/jdi/RedefineNestmateAttr/TestNestmateAttr.java +++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/TestNestmateAttr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,6 +213,7 @@ public class TestNestmateAttr extends TestScaffold { TestNestmateAttr (String[] args) { super(args); + enableIncludeVirtualthreads(); // need to run debug agent with includevirtualthreads=y } public static void main(String[] args) throws Throwable { diff --git a/test/jdk/com/sun/jdi/TestScaffold.java b/test/jdk/com/sun/jdi/TestScaffold.java index e410ae2c76d..92779738998 100644 --- a/test/jdk/com/sun/jdi/TestScaffold.java +++ b/test/jdk/com/sun/jdi/TestScaffold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,9 @@ abstract public class TestScaffold extends TargetAdapter { private boolean redefineAsynchronously = false; private ReferenceType mainStartClass = null; + // Set true by tests that need the debug agent to be run with includevirtualthreads=y. + private boolean includeVThreads = false; + ThreadReference mainThread; /** * We create a VMDeathRequest, SUSPEND_ALL, to sync the BE and FE. @@ -84,6 +87,10 @@ abstract public class TestScaffold extends TargetAdapter { } } + void enableIncludeVirtualthreads() { + includeVThreads = true; + } + boolean getExceptionCaught() { return exceptionCaught; } @@ -588,7 +595,8 @@ abstract public class TestScaffold extends TargetAdapter { argInfo.targetVMArgs = VMConnection.getDebuggeeVMOptions() + " " + argInfo.targetVMArgs; connection = new VMConnection(argInfo.connectorSpec, - argInfo.traceFlags); + argInfo.traceFlags, + includeVThreads); addListener(new TargetAdapter() { public void eventSetComplete(EventSet set) { diff --git a/test/jdk/com/sun/jdi/VMConnection.java b/test/jdk/com/sun/jdi/VMConnection.java index 1444393e46b..64eef3c38f7 100644 --- a/test/jdk/com/sun/jdi/VMConnection.java +++ b/test/jdk/com/sun/jdi/VMConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,9 +123,9 @@ class VMConnection { return arguments; } - VMConnection(String connectSpec, int traceFlags) { + VMConnection(String connectSpec, int traceFlags, boolean includeVThreads) { String nameString; - String argString = "includevirtualthreads=y"; + String argString = "includevirtualthreads=" + (includeVThreads ? 'y' : 'n'); int index = connectSpec.indexOf(':'); if (index == -1) { nameString = connectSpec; From e639cd6a775fabb057b684c70f85b94f84fa5d04 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Thu, 17 Apr 2025 16:18:56 +0000 Subject: [PATCH 236/843] 8353213: Open source several swing tests batch3 Reviewed-by: prr --- .../bug4331515.java | 68 +++++++++++++++ .../AddMouseListenerTest.java | 68 +++++++++++++++ .../plaf/basic/BasicToolBarUI/bug4305622.java | 87 +++++++++++++++++++ .../plaf/basic/BasicToolBarUI/bug4331392.java | 73 ++++++++++++++++ 4 files changed, 296 insertions(+) create mode 100644 test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java create mode 100644 test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java create mode 100644 test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java create mode 100644 test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java diff --git a/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java b/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java new file mode 100644 index 00000000000..3129148b362 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicInternalFrameTitlePane/bug4331515.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4331515 + * @requires (os.family == "windows") + * @summary System menu of an internal frame shouldn't have duplicated items in Win L&F + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4331515 + */ + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.UIManager; + +public class bug4331515 { + static final String INSTRUCTIONS = """ + Open the system menu of internal frame "JIF" placed in the frame "Test". + If this menu contains duplicates of some items then test FAILS, else + test PASSES. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + PassFailJFrame.builder() + .title("bug4331515 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4331515::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame fr = new JFrame("System Menu in JIF Test"); + JDesktopPane dp = new JDesktopPane(); + fr.setContentPane(dp); + JInternalFrame jif = new JInternalFrame("JIF", true, true, true, true); + dp.add(jif); + jif.setBounds(20, 20, 120, 100); + jif.setVisible(true); + fr.setSize(200, 200); + return fr; + } +} diff --git a/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java b/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java new file mode 100644 index 00000000000..79ae9bd5ec8 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicSplitPaneDivider/AddMouseListenerTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4165874 + * @summary Adds a MouseListener to the splitpane divider. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddMouseListenerTest + */ + +import java.awt.Component; +import java.awt.event.MouseAdapter; + +import javax.swing.JFrame; +import javax.swing.JSplitPane; + +public class AddMouseListenerTest { + static final String INSTRUCTIONS = """ + Try dragging the split pane divider, if you can, click PASS, + else click FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("AddMouseListenerTest Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(AddMouseListenerTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JSplitPane With ActionListener Test"); + JSplitPane sp = new JSplitPane(); + + sp.setContinuousLayout(true); + Component[] children = sp.getComponents(); + for (int counter = children.length - 1; counter >= 0; counter--) { + children[counter].addMouseListener(new MouseAdapter() {}); + } + f.getContentPane().add(sp); + f.setSize(400, 400); + return f; + } +} diff --git a/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java b/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java new file mode 100644 index 00000000000..5fdae14e747 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4305622.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4305622 + * @summary MetalToolBarUI.installUI invokeLater causes flickering + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4305622 + */ + +import java.awt.BorderLayout; +import java.awt.Color; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; +import javax.swing.UIManager; +import javax.swing.border.LineBorder; + + +public class bug4305622 { + private static JFrame fr; + static final String INSTRUCTIONS = """ + Press button "Create ToolBar" at frame "Create ToolBar Test". + If you see any flickering during creating of toolbar + then the test FAILS, otherwise the test PASSES. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4305622 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4305622::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + fr = new JFrame("Create ToolBar Test"); + JButton button = new JButton("Create ToolBar"); + button.addActionListener(ae -> addToolBar()); + fr.add(button, BorderLayout.SOUTH); + fr.setSize(400, 400); + return fr; + } + + static void addToolBar() { + fr.repaint(); + fr.revalidate(); + JToolBar toolbar = new JToolBar(); + + JButton btn = new JButton("Button 1"); + btn.setBorder(new LineBorder(Color.red, 30)); + toolbar.add(btn); + + btn = new JButton("Button 2"); + btn.setBorder(new LineBorder(Color.red, 30)); + toolbar.add(btn); + + toolbar.updateUI(); + fr.add(toolbar, BorderLayout.NORTH); + } +} diff --git a/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java b/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java new file mode 100644 index 00000000000..eaca65bfa6d --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicToolBarUI/bug4331392.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4331392 + * @summary Tests if BasicToolBarUI has bogus logic that prevents vertical + * toolbars from docking + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4331392 + */ + +import java.awt.BorderLayout; +import java.awt.Container; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; + +public class bug4331392 { + static final String INSTRUCTIONS = """ + Try to dock the toolbar across all the edges of frame. If you succeed, + then the test PASSES. Otherwise, it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4331392 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4331392::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("JToolBar Docking Test"); + Container c = frame.getContentPane(); + + JToolBar tbar = new JToolBar(JToolBar.VERTICAL); + + tbar.add(new JButton("A")); + tbar.add(new JButton("B")); + tbar.add(new JButton("C")); + + JButton b = new JButton("Hello"); + c.add(b, BorderLayout.CENTER); + c.add(tbar, BorderLayout.EAST); + frame.setSize(300, 300); + return frame; + } +} From 566092256861d6c7142fe22cc709ecb70f9db937 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Thu, 17 Apr 2025 16:20:35 +0000 Subject: [PATCH 237/843] 8353070: Clean up and open source couple AWT Graphics related tests (Part 1) Reviewed-by: serb --- .../java/awt/Graphics/LineLocationTest.java | 106 ++++++++++++++ .../java/awt/Graphics/NativeWin32Clear.java | 136 ++++++++++++++++++ .../java/awt/Graphics/PolygonFillTest.java | 96 +++++++++++++ test/jdk/java/awt/Graphics/TallText.java | 69 +++++++++ 4 files changed, 407 insertions(+) create mode 100644 test/jdk/java/awt/Graphics/LineLocationTest.java create mode 100644 test/jdk/java/awt/Graphics/NativeWin32Clear.java create mode 100644 test/jdk/java/awt/Graphics/PolygonFillTest.java create mode 100644 test/jdk/java/awt/Graphics/TallText.java diff --git a/test/jdk/java/awt/Graphics/LineLocationTest.java b/test/jdk/java/awt/Graphics/LineLocationTest.java new file mode 100644 index 00000000000..5c382ceac95 --- /dev/null +++ b/test/jdk/java/awt/Graphics/LineLocationTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4094059 + * @summary drawing to a subclass of canvas didn't draw to the correct location. + * @key headful + * @run main LineLocationTest + */ + +import java.awt.AWTException; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +public class LineLocationTest extends Frame { + private DrawScreen screen; + + public void initialize() { + setSize(400, 400); + setLocationRelativeTo(null); + setTitle("Line Location Test"); + Panel p = new Panel(); + screen = new DrawScreen(); + p.add(screen); + p.setLocation(50, 50); + p.setSize(300, 300); + add(p); + setBackground(Color.white); + setForeground(Color.blue); + setVisible(true); + } + + public void requestCoordinates(Rectangle r) { + Point location = screen.getLocationOnScreen(); + Dimension size = screen.getSize(); + r.setBounds(location.x, location.y, size.width, size.height); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + LineLocationTest me = new LineLocationTest(); + EventQueue.invokeAndWait(me::initialize); + try { + Robot robot = new Robot(); + robot.delay(1000); + Rectangle coords = new Rectangle(); + EventQueue.invokeAndWait(() -> { + me.requestCoordinates(coords); + }); + BufferedImage capture = robot.createScreenCapture(coords); + robot.delay(2000); + for (int y = 0; y < capture.getHeight(); y++) { + for (int x = 0; x < capture.getWidth(); x++) { + int blue = Color.blue.getRGB(); + if (capture.getRGB(x, y) == blue) { + throw new RuntimeException("Blue detected at " + x + ", " + y); + } + } + } + } finally { + EventQueue.invokeAndWait(me::dispose); + } + } +} + +class DrawScreen extends Canvas { + public Dimension getPreferredSize() { + return new Dimension(300, 300); + } + + public void paint(Graphics g) { + g.setColor(Color.blue); + g.drawLine(5, -3145583, 50, -3145583); + } +} diff --git a/test/jdk/java/awt/Graphics/NativeWin32Clear.java b/test/jdk/java/awt/Graphics/NativeWin32Clear.java new file mode 100644 index 00000000000..6cef4fa810a --- /dev/null +++ b/test/jdk/java/awt/Graphics/NativeWin32Clear.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4216180 + * @summary This test verifies that Graphics2D.setBackground and clearRect + * performs correctly regardless of antialiasing hint. + * @key headful + * @run main NativeWin32Clear + */ + +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +public class NativeWin32Clear extends Frame { + + public void initialize() { + setLocationRelativeTo(null); + setSize(300, 200); + setBackground(Color.red); + setVisible(true); + } + + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + Dimension d = getSize(); + g2.setBackground(Color.green); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2.clearRect(0, 0, d.width / 2, d.height); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + g2.clearRect(d.width / 2, 0, d.width / 2, d.height); + g2.setColor(Color.black); + } + + public void cleanup() { + setVisible(false); + dispose(); + } + + public void requestCoordinates(Rectangle r) { + Insets insets = getInsets(); + Point location = getLocationOnScreen(); + Dimension size = getSize(); + r.x = location.x + insets.left + 5; + r.y = location.y + insets.top + 5; + r.width = size.width - (insets.left + insets.right + 10); + r.height = size.height - (insets.top + insets.bottom + 10); + } + + /* + * Check color match within allowed deviation. + * Prints first non-matching pixel coordinates and actual and expected values. + * Returns true if image is filled with the provided color, false otherwise. + */ + private boolean checkColor(BufferedImage img, Color c, int delta) { + int cRed = c.getRed(); + int cGreen = c.getGreen(); + int cBlue = c.getBlue(); + for (int y = 0; y < img.getHeight(); y++) { + for (int x = 0; x < img.getWidth(); x++) { + int rgb = img.getRGB(x, y); + int red = (rgb & 0x00ff0000) >> 16; + int green = (rgb & 0x0000ff00) >> 8; + int blue = rgb & 0x000000ff; + if (cRed > (red + delta) || cRed < (red - delta) + || cGreen > (green + delta) || cGreen < (green - delta) + || cBlue > (blue + delta) || cBlue < (blue - delta)) { + System.err.println("Color at coordinates (" + x + ", " + y + ") does not match"); + System.err.println("Expected color: " + c.getRGB()); + System.err.println("Actual color: " + rgb); + System.err.println("Allowed deviation: " + delta); + return false; + } + } + } + return true; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + NativeWin32Clear test = new NativeWin32Clear(); + try { + EventQueue.invokeAndWait(test::initialize); + Robot robot = new Robot(); + Rectangle coords = new Rectangle(); + EventQueue.invokeAndWait(() -> { + test.requestCoordinates(coords); + }); + robot.delay(2000); + robot.mouseMove(coords.x - 50, coords.y - 50); + robot.waitForIdle(); + BufferedImage capture = robot.createScreenCapture(coords); + robot.delay(2000); + if (!test.checkColor(capture, Color.green, 5)) { + throw new RuntimeException("Incorrect color encountered, check error log for details"); + } + } finally { + EventQueue.invokeAndWait(test::cleanup); + } + } +} diff --git a/test/jdk/java/awt/Graphics/PolygonFillTest.java b/test/jdk/java/awt/Graphics/PolygonFillTest.java new file mode 100644 index 00000000000..72c216f9e4b --- /dev/null +++ b/test/jdk/java/awt/Graphics/PolygonFillTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4465509 4453725 4489667 + * @summary verify that fillPolygon completely fills area defined by drawPolygon + * @key headful + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PolygonFillTest +*/ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Polygon; +import java.lang.reflect.InvocationTargetException; + +public class PolygonFillTest extends Frame { + Polygon poly; + static String INSTRUCTIONS = """ + There should be two hourglass shapes drawn inside the window + called "Polygon Fill Test". The outline should be blue + and the interior should be green and there should be no gaps + between the filled interior and the outline nor should the green + filler spill outside the blue outline. You may need + to use a screen magnifier to inspect the smaller shape + on the left to verify that there are no gaps. + + If both polygons painted correctly press "Pass" otherwise press "Fail". + """; + + public PolygonFillTest() { + poly = new Polygon(); + poly.addPoint(0, 0); + poly.addPoint(10, 10); + poly.addPoint(0, 10); + poly.addPoint(10, 0); + setSize(300, 300); + setTitle("Polygon Fill Test"); + } + + public void paint(Graphics g) { + int w = getWidth(); + int h = getHeight(); + Image img = createImage(20, 20); + Graphics g2 = img.getGraphics(); + drawPolys(g2, 20, 20, 5, 5); + g2.dispose(); + drawPolys(g, w, h, (w / 4) - 5, (h / 2) - 5); + g.drawImage(img, (3 * w / 4) - 40, (h / 2) - 40, 80, 80, null); + } + + public void drawPolys(Graphics g, int w, int h, int x, int y) { + g.setColor(Color.white); + g.fillRect(0, 0, w, h); + g.translate(x, y); + g.setColor(Color.green); + g.fillPolygon(poly); + g.setColor(Color.blue); + g.drawPolygon(poly); + g.translate(-x, -y); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Polygon Fill Instructions") + .instructions(INSTRUCTIONS) + .testUI(PolygonFillTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/Graphics/TallText.java b/test/jdk/java/awt/Graphics/TallText.java new file mode 100644 index 00000000000..b21b8a985d0 --- /dev/null +++ b/test/jdk/java/awt/Graphics/TallText.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4844952 + * @summary test large text draws properly to the screen + * @key headful + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TallText + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.lang.reflect.InvocationTargetException; + +public class TallText extends Frame { + static String INSTRUCTIONS = """ + There should be a window called "Tall Text Test" that contains text "ABCDEFGHIJ". + Test should be properly displayed: no missing letters + and all letters fit within the frame without overlapping. + If all letters are properly displayed press "Pass", otherwise press "Fail". + """; + + public TallText() { + setSize(800, 200); + setTitle("Tall Text Test"); + } + + public void paint(Graphics g) { + Font font = new Font("dialog", Font.PLAIN, 99); + g.setFont(font); + g.setColor(Color.black); + g.drawString("ABCDEFGHIJ", 10, 150); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Tall Text Instructions") + .instructions(INSTRUCTIONS) + .testUI(TallText::new) + .build() + .awaitAndCheck(); + } +} From 04c32fc08a67eaf6d3f47a0f9ea3d620b7ec6a07 Mon Sep 17 00:00:00 2001 From: Johannes Graham Date: Thu, 17 Apr 2025 16:22:00 +0000 Subject: [PATCH 238/843] 8354522: Clones of DecimalFormat cause interferences when used concurrently Reviewed-by: jlu, naoto --- .../share/classes/java/text/DigitList.java | 8 +- .../text/Format/DecimalFormat/CloneTest.java | 167 ++++++++++++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 test/jdk/java/text/Format/DecimalFormat/CloneTest.java diff --git a/src/java.base/share/classes/java/text/DigitList.java b/src/java.base/share/classes/java/text/DigitList.java index fde0e93214a..f269698d6da 100644 --- a/src/java.base/share/classes/java/text/DigitList.java +++ b/src/java.base/share/classes/java/text/DigitList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -725,7 +725,13 @@ final class DigitList implements Cloneable { char[] newDigits = new char[digits.length]; System.arraycopy(digits, 0, newDigits, 0, digits.length); other.digits = newDigits; + + // data and tempBuilder do not need to be copied because they do + // not carry significant information. They will be recreated on demand. + // Setting them to null is needed to avoid sharing across clones. + other.data = null; other.tempBuilder = null; + return other; } catch (CloneNotSupportedException e) { throw new InternalError(e); diff --git a/test/jdk/java/text/Format/DecimalFormat/CloneTest.java b/test/jdk/java/text/Format/DecimalFormat/CloneTest.java new file mode 100644 index 00000000000..fa46b09d6ac --- /dev/null +++ b/test/jdk/java/text/Format/DecimalFormat/CloneTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8354522 + * @summary Check for cloning interference + * @library /test/lib + * @run junit/othervm --add-opens=java.base/java.text=ALL-UNNAMED CloneTest + */ + +import jtreg.SkippedException; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.*; + +public class CloneTest { + + // Note: this is a white-box test that may fail if the implementation is changed + @Test + public void testClone() { + DecimalFormat df = new DecimalFormat("#"); + new CloneTester(df).testClone(); + } + + // Note: this is a white-box test that may fail if the implementation is changed + @Test + public void testCloneAfterInit() { + DecimalFormat df = new DecimalFormat("#"); + + // This initial use of the formatter initialises its internal state, which could + // subsequently be shared across clones. This is key to reproducing this specific + // issue. + String _ = df.format(Math.PI); + new CloneTester(df).testClone(); + } + + private static class CloneTester { + private final Field digitListField; + private final Class digitListClass; + private final DecimalFormat original; + + public CloneTester(DecimalFormat original) { + this.original = original; + try { + digitListField = DecimalFormat.class.getDeclaredField("digitList"); + digitListField.setAccessible(true); + + DecimalFormat df = new DecimalFormat(); + Object digitList = digitListField.get(df); + + digitListClass = digitList.getClass(); + } catch (ReflectiveOperationException e) { + throw new SkippedException("reflective access in white-box test failed", e); + } + } + + public void testClone() { + try { + DecimalFormat dfClone = (DecimalFormat) original.clone(); + + Object digits = valFromDigitList(original, "digits"); + assertNotSame(digits, valFromDigitList(dfClone, "digits")); + + + Object data = valFromDigitList(original, "data"); + if (data != null) { + assertNotSame(data, valFromDigitList(dfClone, "data")); + } + + Object tempBuilder = valFromDigitList(original, "tempBuilder"); + if (tempBuilder != null) { + assertNotSame(data, valFromDigitList(dfClone, "data")); + } + + assertEquals(digitListField.get(original), digitListField.get(dfClone)); + } catch (ReflectiveOperationException e) { + throw new SkippedException("reflective access in white-box test failed", e); + } + } + + private Object valFromDigitList(DecimalFormat df, String fieldName) throws ReflectiveOperationException { + Object digitList = digitListField.get(df); + Field field = digitListClass.getDeclaredField(fieldName); + field.setAccessible(true); + + return field.get(digitList); + } + } + + // Tests that when DecimalFormat is cloned after use with + // a long double/BigDecimal, clones will be independent. This is not an + // exhaustive test. This tests for the issue of the same DigitList.data + // array being reused across clones of DecimalFormat. + + @Test + public void testCloneIndependence() { + AtomicInteger mismatchCount = new AtomicInteger(0); + DecimalFormat df = new DecimalFormat("#"); + CountDownLatch startSignal = new CountDownLatch(1); + + // This initial use of the formatter initialises its internal state, which could + // subsequently be shared across clones. This is key to reproducing this specific + // issue. + String _ = df.format(Math.PI); + + try (var ex = Executors.newThreadPerTaskExecutor(Thread.ofPlatform().factory())) { + for (int i = 0; i < 5; i++) { + final int finalI = i; + // Each thread gets its own clone of df + DecimalFormat threadDf = (DecimalFormat) df.clone(); + Runnable task = () -> { + try { + startSignal.await(); + for (int j = 0; j < 1_000; j++) { + if (mismatchCount.get() > 0) { + // Exit early if mismatch has already occurred + break; + } + + int value = finalI * j; + String dfString = threadDf.format(BigDecimal.valueOf(value)); + String str = String.valueOf(value); + if (!str.equals(dfString)) { + mismatchCount.getAndIncrement(); + System.err.println("mismatch: str = " + str + " dfString = " + dfString); + break; + } + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }; + ex.execute(task); + } + startSignal.countDown(); // let all tasks start working at the same time + } + assertEquals(0, mismatchCount.get()); + } +} From e163a76f2bacf06980026feb7e645e616ffe2ad4 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Thu, 17 Apr 2025 16:26:36 +0000 Subject: [PATCH 239/843] 8354106: Clean up and open source KeyEvent related tests (Part 2) Reviewed-by: abhiscxk, prr --- .../event/KeyEvent/KeyPressedModifiers.java | 108 ++++++++++++++++++ test/jdk/java/awt/event/KeyEvent/KeyTest.java | 104 +++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 test/jdk/java/awt/event/KeyEvent/KeyPressedModifiers.java create mode 100644 test/jdk/java/awt/event/KeyEvent/KeyTest.java diff --git a/test/jdk/java/awt/event/KeyEvent/KeyPressedModifiers.java b/test/jdk/java/awt/event/KeyEvent/KeyPressedModifiers.java new file mode 100644 index 00000000000..08958bdbac2 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyPressedModifiers.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4174399 + * @summary Check that modifier values are set on a KeyPressed event + * when a modifier key is pressed. + * @key headful + * @run main KeyPressedModifiers + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class KeyPressedModifiers extends Frame implements KeyListener { + static AtomicBoolean shiftDown = new AtomicBoolean(false); + static AtomicBoolean controlDown = new AtomicBoolean(false); + static AtomicBoolean altDown = new AtomicBoolean(false); + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + KeyPressedModifiers test = new KeyPressedModifiers(); + try { + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.delay(500); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_ALT); + robot.delay(500); + robot.waitForIdle(); + if (!shiftDown.get() || !controlDown.get() || !altDown.get()) { + String error = "Following key modifiers were not registered:" + + (shiftDown.get() ? "" : " SHIFT") + + (controlDown.get() ? "" : " CONTROL") + + (altDown.get() ? "" : " ALT"); + throw new RuntimeException(error); + } + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } + + public void initUI() { + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + setSize(350, 100); + setVisible(true); + tf.requestFocus(); + } + + public void keyTyped(KeyEvent ignore) { + } + + public void keyReleased(KeyEvent ignore) { + } + + public void keyPressed(KeyEvent e) { + System.out.println(e); + switch (e.getKeyCode()) { + case KeyEvent.VK_SHIFT: + shiftDown.set(e.isShiftDown()); + break; + case KeyEvent.VK_CONTROL: + controlDown.set(e.isControlDown()); + break; + case KeyEvent.VK_ALT: + altDown.set(e.isAltDown()); + break; + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyTest.java b/test/jdk/java/awt/event/KeyEvent/KeyTest.java new file mode 100644 index 00000000000..d11798b4473 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4151419 4090870 4169733 + * @summary Ensures that KeyEvent has right results for the following + * keys -=\[];,./ + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual KeyTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class KeyTest extends Frame implements KeyListener { + + static String INSTRUCTIONS = """ + Click on the text field in window named "Check KeyChar values" + Type the following keys/characters in the TextField: + - = \\ [ ] ; , . / + Verify that the keyChar and keyCode is correct for each key pressed. + Remember that the keyCode for the KEY_TYPED event should be zero. + Also verify that the character you typed appears in the TextField. + + Key Name keyChar Keycode + ------------------------------------- + - Minus - 45 45 + = Equals = 61 61 + \\ Slash \\ 92 92 + [ Left Brace [ 91 91 + ] Right Brace ] 93 93 + ; Semicolon ; 59 59 + , Comma , 44 44 + . Period . 46 46 + / Front Slash / 47 47 + """; + public KeyTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + + } + + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent evt) { + printKey(evt); + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + if (evt.isActionKey()) { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar() + " Action Key"); + } else { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar()); + } + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + PassFailJFrame.builder() + .title("KeyTest Instructions") + .instructions(INSTRUCTIONS) + .logArea(20) + .testUI(KeyTest::new) + .build() + .awaitAndCheck(); + } +} From 3e3dff6767f467b53c739c34b4350dd6840534a3 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 17 Apr 2025 16:31:24 +0000 Subject: [PATCH 240/843] 8354451: Open source some more Swing popup menu tests Reviewed-by: jdv, kizune --- .../javax/swing/JPopupMenu/bug4188832.java | 82 ++++++ .../javax/swing/JPopupMenu/bug4212464.java | 142 ++++++++++ .../javax/swing/JPopupMenu/bug4234793.java | 242 ++++++++++++++++++ 3 files changed, 466 insertions(+) create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4188832.java create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4212464.java create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4234793.java diff --git a/test/jdk/javax/swing/JPopupMenu/bug4188832.java b/test/jdk/javax/swing/JPopupMenu/bug4188832.java new file mode 100644 index 00000000000..9c958ebc1ef --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4188832.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary Test that medium weight submenus are not hidden by a heavyweight canvas. + * @bug 4188832 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4188832 + */ + +import java.awt.Color; +import java.awt.Panel; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +public class bug4188832 { + + static final String INSTRUCTIONS = """ + Select the File menu, then select the "Save As..." submenu. + If you can see the submenu items displayed, press PASS, else press FAIL + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4188832::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + // for Medium Weight menus + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + JFrame frame = new JFrame("bug4188832"); + + // Create the menus + JMenuBar menuBar = new JMenuBar(); + JMenu fileMenu = new JMenu("File"); + menuBar.add(fileMenu); + fileMenu.add(new JMenuItem("New")); + fileMenu.add(new JMenuItem("Open")); + fileMenu.add(new JMenuItem("Save")); + JMenu sm = new JMenu("Save As..."); + // these guys don't show up + sm.add(new JMenuItem("This")); + sm.add(new JMenuItem("That")); + fileMenu.add(sm); + fileMenu.add(new JMenuItem("Exit")); + frame.setJMenuBar(menuBar); + + Panel field = new Panel(); // a heavyweight container + field.setBackground(Color.blue); + frame.add(field); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4212464.java b/test/jdk/javax/swing/JPopupMenu/bug4212464.java new file mode 100644 index 00000000000..c1c434f6b16 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4212464.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4212464 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Verify popup menu borders are drawn correctly when switching L&Fs + * @run main/manual bug4212464 + */ + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4212464 extends JFrame implements ActionListener { + + static String strMotif = "Motif"; + static String motifClassName = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + + static String strMetal = "Metal"; + static String metalClassName = "javax.swing.plaf.metal.MetalLookAndFeel"; + + static bug4212464 frame; + static JPopupMenu popup; + + static final String INSTRUCTIONS = """ + This test is to see whether popup menu borders behave properly when switching + back and forth between Motif and Metal L&F. The initial L&F is Metal. + + Pressing the mouse button on the label in the center of the test window brings + up a popup menu. + + In order to test, use the labeled buttons to switch the look and feel. + Clicking a button will cause the menu to be hidden. This is OK. Just click the label again. + Switch back and forth and verify that the popup menu border changes consistently + and there is a title for the menu when using Motif L&F (Metal won't have a title). + + Make sure you switch back and forth several times. + If the change is consistent, press PASS otherwise press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4212464::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + UIManager.setLookAndFeel(metalClassName); // initialize to Metal. + } catch (Exception e) { + throw new RuntimeException(e); + } + frame = new bug4212464("bug4212464"); + popup = new JPopupMenu("Test"); + popup.add("Item 1"); + popup.add("Item 2"); + popup.add("Item 3"); + popup.add("Item 4"); + + JPanel p = new JPanel(); + p.setLayout(new FlowLayout()); + JButton motif = (JButton)p.add(new JButton(strMotif)); + JButton metal = (JButton)p.add(new JButton(strMetal)); + motif.setActionCommand(motifClassName); + metal.setActionCommand(metalClassName); + motif.addActionListener(frame); + metal.addActionListener(frame); + frame.add(BorderLayout.NORTH, p); + + JLabel l = new JLabel("Click any mouse button on this big label"); + l.setFont(new Font(Font.DIALOG, Font.PLAIN, 20)); + l.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + popup.show(e.getComponent(), e.getX(), e.getY()); + } + }); + frame.add(BorderLayout.CENTER, l); + frame.setSize(500, 400); + return frame; + } + + public bug4212464(String title) { + super(title); + } + + public void actionPerformed(ActionEvent e) { + String str = e.getActionCommand(); + if (str.equals(metalClassName) || str.equals(motifClassName)) { + changeLNF(str); + } else { + System.out.println("ActionEvent: " + str); + } + } + + public void changeLNF(String str) { + System.out.println("Changing LNF to " + str); + try { + UIManager.setLookAndFeel(str); + SwingUtilities.updateComponentTreeUI(frame); + SwingUtilities.updateComponentTreeUI(popup); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4234793.java b/test/jdk/javax/swing/JPopupMenu/bug4234793.java new file mode 100644 index 00000000000..9ad91e5165f --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4234793.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4234793 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary PopupMenuListener popupMenuCanceled is never called + * @run main/manual bug4234793 + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.KeyStroke; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +/** + * For all 3 components (JPopupMenu, JComboBox, JPopup) when the popup is visible, + * the popupMenuCanceled should be invoked in these two circumstances: + * + * 1. The ESCAPE key is pressed while the popup is open. + * + * 2. The mouse is clicked on another component. + * + */ + +public class bug4234793 extends JFrame implements PopupMenuListener { + + static final String INSTRUCTIONS = """ + The test window will contain several kinds of menus. + + * A menu bar with two menus labeled "1 - First Menu" and "2 - Second Menu" + * A drop down combo box - ie a button which pops up a menu when clicked + * Clicking any where on the background of the window will display a popup menu + + That is 4 menus in total. + + For each case, verify that the menu can be cancelled (hidden) in two ways + 1) Click to display the menu, then to hide it, press the ESCAPE key. + 2) Click to display the menu, then to hide it, LEFT click on the window background. + Note : the popup menu must be displayed using RIGHT click, the others use LEFT click. + + Notice each time you perform a hide/cancel action an appropriate message should + appear in the log area + If this is true for all 8 combinations of menus + hide actions the test PASSES + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4234793::createUI) + .logArea() + .build() + .awaitAndCheck(); + } + + private static String[] numData = { + "One", "Two", "Three", "Four", "Five", "Six", "Seven" + }; + + private static String[] dayData = { + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + + private static char[] mnDayData = { + 'M', 'T', 'W', 'R', 'F', 'S', 'U' + }; + + bug4234793(String title) { + super(title); + } + + static volatile JPopupMenu popupMenu; + static volatile bug4234793 frame; + + static JFrame createUI() { + frame = new bug4234793("bug4234793"); + frame.setJMenuBar(createMenuBar()); + JPanel panel = createContentPane(); + frame.add(panel); + + // CTRL-down will show the popup. + panel.getInputMap().put(KeyStroke.getKeyStroke( + KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP"); + panel.getActionMap().put("OPEN_POPUP", new PopupHandler()); + panel.addMouseListener(new PopupListener(popupMenu)); + panel.setPreferredSize(new Dimension(400, 300)); + frame.setSize(400, 300); + return frame; + } + + static class PopupListener extends MouseAdapter { + private JPopupMenu popup; + + public PopupListener(JPopupMenu popup) { + this.popup = popup; + } + + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + + public void mouseClicked(MouseEvent ex) { + } + + private void maybeShowPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(e.getComponent(), e.getX(), e.getY()); + } + } + } + + static class PopupHandler extends AbstractAction { + public void actionPerformed(ActionEvent e) { + if (!popupMenu.isVisible()) + popupMenu.show((Component)e.getSource(), 40, 40); + } + } + + static JPanel createContentPane() { + popupMenu = new JPopupMenu(); + JMenuItem item; + for (int i = 0; i < dayData.length; i++) { + item = popupMenu.add(new JMenuItem(dayData[i], mnDayData[i])); + } + popupMenu.addPopupMenuListener(frame); + + JComboBox combo = new JComboBox(numData); + combo.addPopupMenuListener(frame); + JPanel comboPanel = new JPanel(); + comboPanel.add(combo); + + JPanel panel = new JPanel(new BorderLayout()); + + panel.add(new JLabel("Right click on the panel to show the PopupMenu"), BorderLayout.NORTH); + panel.add(comboPanel, BorderLayout.CENTER); + + return panel; + } + + static JMenuBar createMenuBar() { + JMenuBar menubar = new JMenuBar(); + JMenuItem menuitem; + + JMenu menu = new JMenu("1 - First Menu"); + menu.setMnemonic('1'); + menu.getPopupMenu().addPopupMenuListener(frame); + + menubar.add(menu); + for (int i = 0; i < 10; i ++) { + menuitem = new JMenuItem("1 JMenuItem" + i); + menuitem.setMnemonic('0' + i); + menu.add(menuitem); + } + + // second menu + menu = new JMenu("2 - Second Menu"); + menu.getPopupMenu().addPopupMenuListener(frame); + menu.setMnemonic('2'); + + menubar.add(menu); + for (int i = 0; i < 5; i++) { + menuitem = new JMenuItem("2 JMenuItem" + i); + menuitem.setMnemonic('0' + i); + menu.add(menuitem); + } + + JMenu submenu = new JMenu("Sub Menu"); + submenu.setMnemonic('S'); + submenu.getPopupMenu().addPopupMenuListener(frame); + for (int i = 0; i < 5; i++) { + menuitem = new JMenuItem("S JMenuItem" + i); + menuitem.setMnemonic('0' + i); + submenu.add(menuitem); + } + menu.add(new JSeparator()); + menu.add(submenu); + + return menubar; + } + + // PopupMenuListener methods. + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("popupmenu visible: " + source.getClass().getName()); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("popupMenuWillBecomeInvisible: " + source.getClass().getName()); + } + + public void popupMenuCanceled(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("POPUPMENU CANCELED: " + source.getClass().getName()); + } +} From 31e293b0821b754f0fd0dd3a9d9143a0fd43a256 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 17 Apr 2025 16:32:46 +0000 Subject: [PATCH 241/843] 8354552: Open source a few Swing tests Reviewed-by: dnguyen, psadhukhan --- .../ScrollToReferenceTest.java | 91 ++++++++++++++++++ .../ScrollToReferenceTest/test.html | 93 +++++++++++++++++++ test/jdk/javax/swing/JLabel/bug4106007.java | 66 +++++++++++++ test/jdk/javax/swing/JLabel/bug4945795.java | 73 +++++++++++++++ 4 files changed, 323 insertions(+) create mode 100644 test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/ScrollToReferenceTest.java create mode 100644 test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/test.html create mode 100644 test/jdk/javax/swing/JLabel/bug4106007.java create mode 100644 test/jdk/javax/swing/JLabel/bug4945795.java diff --git a/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/ScrollToReferenceTest.java b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/ScrollToReferenceTest.java new file mode 100644 index 00000000000..5d96dd70dd1 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/ScrollToReferenceTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4194428 + * @summary Checks that scrolling an href to visible scrolls it to the top of the page. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollToReferenceTest + */ + +import java.awt.Container; +import java.awt.Dimension; +import java.io.IOException; +import java.net.URL; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; + +public class ScrollToReferenceTest { + + static final String INSTRUCTIONS = """ + Wait for the html document to finish loading, click on the anchor + with text 'CLICK ME'. If 'should be at top of editor pane' is + scrolled to the top of the visible region of the text, click PASS, + otherwise click FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(ScrollToReferenceTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("ScrollToReferenceTest"); + JEditorPane pane = new JEditorPane(); + + try { + pane.setPage(ScrollToReferenceTest.class.getResource("test.html")); + } catch (IOException ioe) { + PassFailJFrame.forceFail("Couldn't find html file"); + } + + + pane.addHyperlinkListener(new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED && + e.getURL() != null) { + try { + pane.setPage(e.getURL()); + } catch (IOException ioe) { + pane.setText("error finding url, click fail!"); + } + } + } + }); + pane.setEditable(false); + JScrollPane sp = new JScrollPane(pane); + sp.setPreferredSize(new Dimension(400, 400)); + frame.add(sp); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/test.html b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/test.html new file mode 100644 index 00000000000..d7e82e516db --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/ScrollToReferenceTest/test.html @@ -0,0 +1,93 @@ + + +

Click ME! +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

should be at top of editor pane +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

a +

TEST! +

a + + diff --git a/test/jdk/javax/swing/JLabel/bug4106007.java b/test/jdk/javax/swing/JLabel/bug4106007.java new file mode 100644 index 00000000000..b78813809c1 --- /dev/null +++ b/test/jdk/javax/swing/JLabel/bug4106007.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4106007 + * @summary Multi-line JLabel is now supported for HTML labels. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4106007 + * */ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; + +public class bug4106007 { + + static final String INSTRUCTIONS = """ + The test window should have a label spanning multiple lines. + If it is press PASS, else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4106007::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Bug4106007"); + frame.setLayout(new BorderLayout()); + String str = ""; + String longLine = + "I hope multi-line JLabel is now supported and you can see several lines instead of one long line. "; + str += longLine; + str += longLine; + str += ""; + JLabel lab = new JLabel(str); + frame.add(lab, BorderLayout.NORTH); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JLabel/bug4945795.java b/test/jdk/javax/swing/JLabel/bug4945795.java new file mode 100644 index 00000000000..56f6e0eb60f --- /dev/null +++ b/test/jdk/javax/swing/JLabel/bug4945795.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4945795 + * @summary With mnemonic hiding turned on, Java does not display all mnemonics with ALT key + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4945795 + * */ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.UIManager; + +public class bug4945795 { + + static final String INSTRUCTIONS = """ + This test is for the Swing Windows Look And Feel. + A test window will be displayed with the label 'Mnemonic Test' + Click the mouse in the test window to make sure it has keyboard focus. + Now press and hold the 'Alt' key. + An underline should be displayed below the initial 'M' character. + If it is press PASS, else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4945795::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame mainFrame = new JFrame("Bug4945795"); + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ex) { + throw new RuntimeException("Can not set system look and feel"); + } + mainFrame.setLayout(new BorderLayout()); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JLabel label = new JLabel("Mnemonic test"); + label.setDisplayedMnemonic('M'); + mainFrame.add(label, BorderLayout.NORTH); + mainFrame.setSize(400, 300); + return mainFrame; + } +} From 4eae9b5ba61bfe262b43346a7499c98c1a54d2fe Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Thu, 17 Apr 2025 17:40:38 +0000 Subject: [PATCH 242/843] 8354541: Remove Shenandoah post barrier expand loop opts Reviewed-by: shade --- .../shenandoah/c2/shenandoahBarrierSetC2.cpp | 5 - .../shenandoah/c2/shenandoahBarrierSetC2.hpp | 4 +- .../gc/shenandoah/c2/shenandoahSupport.cpp | 236 ------------------ .../gc/shenandoah/c2/shenandoahSupport.hpp | 6 - src/hotspot/share/opto/compile.hpp | 1 - .../TestShenandoahBarrierExpansion.java | 2 +- 6 files changed, 3 insertions(+), 251 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index a7e854aaf83..8df4413cc2f 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -826,11 +826,6 @@ bool ShenandoahBarrierSetC2::optimize_loops(PhaseIdealLoop* phase, LoopOptsMode assert(UseShenandoahGC, "only for shenandoah"); ShenandoahBarrierC2Support::pin_and_expand(phase); return true; - } else if (mode == LoopOptsShenandoahPostExpand) { - assert(UseShenandoahGC, "only for shenandoah"); - visited.clear(); - ShenandoahBarrierC2Support::optimize_after_expansion(visited, nstack, worklist, phase); - return true; } return false; } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp index 61f8bfb1140..5bf549203ea 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp @@ -120,8 +120,8 @@ public: virtual Node* step_over_gc_barrier(Node* c) const; virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const; virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const; - virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return mode == LoopOptsShenandoahExpand || mode == LoopOptsShenandoahPostExpand; } - virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return mode == LoopOptsShenandoahExpand || mode == LoopOptsShenandoahPostExpand; } + virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return mode == LoopOptsShenandoahExpand; } + virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return mode == LoopOptsShenandoahExpand; } // Support for macro expanded GC barriers virtual void register_potential_barrier_node(Node* node) const; diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 860bcb38038..4652dbce0e3 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -51,12 +51,6 @@ bool ShenandoahBarrierC2Support::expand(Compile* C, PhaseIterGVN& igvn) { C->clear_major_progress(); PhaseIdealLoop::optimize(igvn, LoopOptsShenandoahExpand); if (C->failing()) return false; - - C->set_major_progress(); - if (!C->optimize_loops(igvn, LoopOptsShenandoahPostExpand)) { - return false; - } - C->clear_major_progress(); C->process_for_post_loop_opts_igvn(igvn); if (C->failing()) return false; @@ -1504,236 +1498,6 @@ Node* ShenandoahBarrierC2Support::get_load_addr(PhaseIdealLoop* phase, VectorSet } -void ShenandoahBarrierC2Support::move_gc_state_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase) { - IdealLoopTree *loop = phase->get_loop(iff); - Node* loop_head = loop->_head; - Node* entry_c = loop_head->in(LoopNode::EntryControl); - - Node* bol = iff->in(1); - Node* cmp = bol->in(1); - Node* andi = cmp->in(1); - Node* load = andi->in(1); - - assert(is_gc_state_load(load), "broken"); - if (!phase->is_dominator(load->in(0), entry_c)) { - Node* mem_ctrl = nullptr; - Node* mem = dom_mem(load->in(MemNode::Memory), loop_head, Compile::AliasIdxRaw, mem_ctrl, phase); - load = load->clone(); - load->set_req(MemNode::Memory, mem); - load->set_req(0, entry_c); - phase->register_new_node(load, entry_c); - andi = andi->clone(); - andi->set_req(1, load); - phase->register_new_node(andi, entry_c); - cmp = cmp->clone(); - cmp->set_req(1, andi); - phase->register_new_node(cmp, entry_c); - bol = bol->clone(); - bol->set_req(1, cmp); - phase->register_new_node(bol, entry_c); - - phase->igvn().replace_input_of(iff, 1, bol); - } -} - -bool ShenandoahBarrierC2Support::identical_backtoback_ifs(Node* n, PhaseIdealLoop* phase) { - if (!n->is_If() || n->is_CountedLoopEnd()) { - return false; - } - Node* region = n->in(0); - - if (!region->is_Region()) { - return false; - } - Node* dom = phase->idom(region); - if (!dom->is_If()) { - return false; - } - - if (!is_heap_stable_test(n) || !is_heap_stable_test(dom)) { - return false; - } - - IfNode* dom_if = dom->as_If(); - Node* proj_true = dom_if->proj_out(1); - Node* proj_false = dom_if->proj_out(0); - - for (uint i = 1; i < region->req(); i++) { - if (phase->is_dominator(proj_true, region->in(i))) { - continue; - } - if (phase->is_dominator(proj_false, region->in(i))) { - continue; - } - return false; - } - - return true; -} - -bool ShenandoahBarrierC2Support::merge_point_safe(Node* region) { - for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { - Node* n = region->fast_out(i); - if (n->is_LoadStore()) { - // Splitting a LoadStore node through phi, causes it to lose its SCMemProj: the split if code doesn't have support - // for a LoadStore at the region the if is split through because that's not expected to happen (LoadStore nodes - // should be between barrier nodes). It does however happen with Shenandoah though because barriers can get - // expanded around a LoadStore node. - return false; - } - } - return true; -} - - -void ShenandoahBarrierC2Support::merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase) { - assert(is_heap_stable_test(n), "no other tests"); - if (identical_backtoback_ifs(n, phase)) { - Node* n_ctrl = n->in(0); - if (phase->can_split_if(n_ctrl) && merge_point_safe(n_ctrl)) { - IfNode* dom_if = phase->idom(n_ctrl)->as_If(); - if (is_heap_stable_test(n)) { - Node* gc_state_load = n->in(1)->in(1)->in(1)->in(1); - assert(is_gc_state_load(gc_state_load), "broken"); - Node* dom_gc_state_load = dom_if->in(1)->in(1)->in(1)->in(1); - assert(is_gc_state_load(dom_gc_state_load), "broken"); - if (gc_state_load != dom_gc_state_load) { - phase->igvn().replace_node(gc_state_load, dom_gc_state_load); - } - } - PhiNode* bolphi = PhiNode::make_blank(n_ctrl, n->in(1)); - Node* proj_true = dom_if->proj_out(1); - Node* proj_false = dom_if->proj_out(0); - Node* con_true = phase->igvn().makecon(TypeInt::ONE); - Node* con_false = phase->igvn().makecon(TypeInt::ZERO); - - for (uint i = 1; i < n_ctrl->req(); i++) { - if (phase->is_dominator(proj_true, n_ctrl->in(i))) { - bolphi->init_req(i, con_true); - } else { - assert(phase->is_dominator(proj_false, n_ctrl->in(i)), "bad if"); - bolphi->init_req(i, con_false); - } - } - phase->register_new_node(bolphi, n_ctrl); - phase->igvn().replace_input_of(n, 1, bolphi); - phase->do_split_if(n); - } - } -} - -IfNode* ShenandoahBarrierC2Support::find_unswitching_candidate(const IdealLoopTree* loop, PhaseIdealLoop* phase) { - // Find first invariant test that doesn't exit the loop - LoopNode *head = loop->_head->as_Loop(); - IfNode* unswitch_iff = nullptr; - Node* n = head->in(LoopNode::LoopBackControl); - int loop_has_sfpts = -1; - while (n != head) { - Node* n_dom = phase->idom(n); - if (n->is_Region()) { - if (n_dom->is_If()) { - IfNode* iff = n_dom->as_If(); - if (iff->in(1)->is_Bool()) { - BoolNode* bol = iff->in(1)->as_Bool(); - if (bol->in(1)->is_Cmp()) { - // If condition is invariant and not a loop exit, - // then found reason to unswitch. - if (is_heap_stable_test(iff) && - (loop_has_sfpts == -1 || loop_has_sfpts == 0)) { - assert(!loop->is_loop_exit(iff), "both branches should be in the loop"); - if (loop_has_sfpts == -1) { - for(uint i = 0; i < loop->_body.size(); i++) { - Node *m = loop->_body[i]; - if (m->is_SafePoint() && !m->is_CallLeaf()) { - loop_has_sfpts = 1; - break; - } - } - if (loop_has_sfpts == -1) { - loop_has_sfpts = 0; - } - } - if (!loop_has_sfpts) { - unswitch_iff = iff; - } - } - } - } - } - } - n = n_dom; - } - return unswitch_iff; -} - - -void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, Node_Stack &stack, Node_List &old_new, PhaseIdealLoop* phase) { - Node_List heap_stable_tests; - stack.push(phase->C->start(), 0); - do { - Node* n = stack.node(); - uint i = stack.index(); - - if (i < n->outcnt()) { - Node* u = n->raw_out(i); - stack.set_index(i+1); - if (!visited.test_set(u->_idx)) { - stack.push(u, 0); - } - } else { - stack.pop(); - if (n->is_If() && is_heap_stable_test(n)) { - heap_stable_tests.push(n); - } - } - } while (stack.size() > 0); - - for (uint i = 0; i < heap_stable_tests.size(); i++) { - Node* n = heap_stable_tests.at(i); - assert(is_heap_stable_test(n), "only evacuation test"); - merge_back_to_back_tests(n, phase); - } - - if (!phase->C->major_progress()) { - VectorSet seen; - for (uint i = 0; i < heap_stable_tests.size(); i++) { - Node* n = heap_stable_tests.at(i); - IdealLoopTree* loop = phase->get_loop(n); - if (loop != phase->ltree_root() && - loop->_child == nullptr && - !loop->_irreducible) { - Node* head = loop->_head; - if (head->is_Loop() && - (!head->is_CountedLoop() || head->as_CountedLoop()->is_main_loop() || head->as_CountedLoop()->is_normal_loop()) && - !seen.test_set(head->_idx)) { - IfNode* iff = find_unswitching_candidate(loop, phase); - if (iff != nullptr) { - Node* bol = iff->in(1); - if (head->as_Loop()->is_strip_mined()) { - head->as_Loop()->verify_strip_mined(0); - } - move_gc_state_test_out_of_loop(iff, phase); - - AutoNodeBudget node_budget(phase); - - if (loop->policy_unswitching(phase)) { - if (head->as_Loop()->is_strip_mined()) { - OuterStripMinedLoopNode* outer = head->as_CountedLoop()->outer_loop(); - hide_strip_mined_loop(outer, head->as_CountedLoop(), phase); - } - phase->do_unswitching(loop, old_new); - } else { - // Not proceeding with unswitching. Move load back in - // the loop. - phase->igvn().replace_input_of(iff, 1, bol); - } - } - } - } - } - } -} - #ifdef ASSERT static bool has_never_branch(Node* root) { for (uint i = 1; i < root->req(); i++) { diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp index 164502e6358..93572cddc5b 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp @@ -63,12 +63,7 @@ private: static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, DecoratorSet decorators, PhaseIdealLoop* phase); static void test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase); - static void move_gc_state_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase); - static void merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase); - static bool merge_point_safe(Node* region); - static bool identical_backtoback_ifs(Node *n, PhaseIdealLoop* phase); static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase); - static IfNode* find_unswitching_candidate(const IdealLoopTree *loop, PhaseIdealLoop* phase); static Node* get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* lrb); public: @@ -80,7 +75,6 @@ public: static bool expand(Compile* C, PhaseIterGVN& igvn); static void pin_and_expand(PhaseIdealLoop* phase); - static void optimize_after_expansion(VectorSet& visited, Node_Stack& nstack, Node_List& old_new, PhaseIdealLoop* phase); #ifdef ASSERT static void verify(RootNode* root); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 6f505e502b5..33b9187e262 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -106,7 +106,6 @@ enum LoopOptsMode { LoopOptsNone, LoopOptsMaxUnroll, LoopOptsShenandoahExpand, - LoopOptsShenandoahPostExpand, LoopOptsSkipSplitIf, LoopOptsVerify }; diff --git a/test/hotspot/jtreg/compiler/gcbarriers/TestShenandoahBarrierExpansion.java b/test/hotspot/jtreg/compiler/gcbarriers/TestShenandoahBarrierExpansion.java index 84a34695092..6a1431c43df 100644 --- a/test/hotspot/jtreg/compiler/gcbarriers/TestShenandoahBarrierExpansion.java +++ b/test/hotspot/jtreg/compiler/gcbarriers/TestShenandoahBarrierExpansion.java @@ -71,7 +71,7 @@ public class TestShenandoahBarrierExpansion { @Test @IR(failOn = IRNode.IF, phase = CompilePhase.AFTER_PARSING) - @IR(counts = { IRNode.IF, "3" }, phase = CompilePhase.BARRIER_EXPANSION) + @IR(counts = { IRNode.IF, "4" }, phase = CompilePhase.BARRIER_EXPANSION) private static void testLoadTwoFieldObjectAndEscape() { final A field2 = staticField2; final A field3 = staticField3; From 7b0618859a7764b0d4c8b893a19dfb64f4351c07 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Thu, 17 Apr 2025 18:31:10 +0000 Subject: [PATCH 243/843] 8354464: Additional cleanup setting up native.encoding Reviewed-by: naoto, alanb --- src/java.base/share/native/libjava/System.c | 11 ++----- .../unix/native/libjava/java_props_md.c | 4 --- .../windows/native/libjava/java_props_md.c | 33 +++++-------------- 3 files changed, 12 insertions(+), 36 deletions(-) diff --git a/src/java.base/share/native/libjava/System.c b/src/java.base/share/native/libjava/System.c index 530828b1742..b1feaf3dff7 100644 --- a/src/java.base/share/native/libjava/System.c +++ b/src/java.base/share/native/libjava/System.c @@ -23,6 +23,7 @@ * questions. */ +#include #include #include "jni.h" @@ -147,15 +148,9 @@ Java_jdk_internal_util_SystemProps_00024Raw_platformProperties(JNIEnv *env, jcla PUTPROP(propArray, _line_separator_NDX, sprops->line_separator); /* basic encoding properties, always non-NULL */ -#ifdef MACOSX - /* - * Since sun_jnu_encoding is now hard-coded to UTF-8 on Mac, we don't - * want to use it to overwrite native.encoding - */ + assert(sprops->encoding != NULL); + assert(sprops->sun_jnu_encoding != NULL); PUTPROP(propArray, _native_encoding_NDX, sprops->encoding); -#else - PUTPROP(propArray, _native_encoding_NDX, sprops->sun_jnu_encoding); -#endif PUTPROP(propArray, _sun_jnu_encoding_NDX, sprops->sun_jnu_encoding); /* encodings for standard streams, may be NULL */ diff --git a/src/java.base/unix/native/libjava/java_props_md.c b/src/java.base/unix/native/libjava/java_props_md.c index 5adfeb0f894..6db307088b0 100644 --- a/src/java.base/unix/native/libjava/java_props_md.c +++ b/src/java.base/unix/native/libjava/java_props_md.c @@ -27,7 +27,6 @@ #include #include #endif -#include #include #include #ifndef ARCHPROPNAME @@ -465,9 +464,6 @@ GetJavaProperties(JNIEnv *env) sprops.sun_jnu_encoding = sprops.encoding; #endif - assert(sprops.encoding != NULL); - assert(sprops.sun_jnu_encoding != NULL); - if (isatty(STDOUT_FILENO) == 1) { sprops.stdout_encoding = sprops.encoding; } diff --git a/src/java.base/windows/native/libjava/java_props_md.c b/src/java.base/windows/native/libjava/java_props_md.c index 8fb1ee83841..275dd3795c5 100644 --- a/src/java.base/windows/native/libjava/java_props_md.c +++ b/src/java.base/windows/native/libjava/java_props_md.c @@ -26,7 +26,6 @@ #include "jni.h" #include "jni_util.h" -#include #include #include #include @@ -47,7 +46,7 @@ typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); static BOOL SetupI18nProps(LCID lcid, char** language, char** script, char** country, - char** variant, char** encoding); + char** variant); #define PROPSIZE 9 // eight-letter + null terminator #define SNAMESIZE 86 // max number of chars for LOCALE_SNAME is 85 @@ -167,7 +166,7 @@ getEncodingFromLangID(LANGID langID) DllExport const char * getJavaIDFromLangID(LANGID langID) { - char * elems[5]; // lang, script, ctry, variant, encoding + char * elems[4]; // lang, script, ctry, variant char * ret; int index; @@ -176,12 +175,12 @@ getJavaIDFromLangID(LANGID langID) return NULL; } - for (index = 0; index < 5; index++) { + for (index = 0; index < 4; index++) { elems[index] = NULL; } if (SetupI18nProps(MAKELCID(langID, SORT_DEFAULT), - &(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4]))) { + &(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]))) { // there always is the "language" tag strcpy(ret, elems[0]); @@ -198,7 +197,7 @@ getJavaIDFromLangID(LANGID langID) ret = NULL; } - for (index = 0; index < 5; index++) { + for (index = 0; index < 4; index++) { if (elems[index] != NULL) { free(elems[index]); } @@ -263,7 +262,7 @@ cpu_isalist(void) static BOOL SetupI18nProps(LCID lcid, char** language, char** script, char** country, - char** variant, char** encoding) { + char** variant) { /* script */ char tmp[SNAMESIZE]; *script = malloc(PROPSIZE); @@ -320,11 +319,6 @@ SetupI18nProps(LCID lcid, char** language, char** script, char** country, strcpy(*variant, "NY"); } - /* encoding */ - *encoding = getEncodingInternal(lcid); - if (*encoding == NULL) { - return FALSE; - } return TRUE; } @@ -640,7 +634,6 @@ GetJavaProperties(JNIEnv* env) LCID userDefaultUILCID = MAKELCID(userDefaultUILang, SORTIDFROMLCID(userDefaultLCID)); { - char * display_encoding; HANDLE hStdOutErr; // Windows UI Language selection list only cares "language" @@ -659,23 +652,18 @@ GetJavaProperties(JNIEnv* env) &sprops.format_language, &sprops.format_script, &sprops.format_country, - &sprops.format_variant, - &sprops.encoding); + &sprops.format_variant); SetupI18nProps(userDefaultUILCID, &sprops.display_language, &sprops.display_script, &sprops.display_country, - &sprops.display_variant, - &display_encoding); - - if (sprops.encoding == NULL) { - sprops.encoding = "UTF-8"; - } + &sprops.display_variant); sprops.sun_jnu_encoding = getEncodingInternal(0); if (sprops.sun_jnu_encoding == NULL) { sprops.sun_jnu_encoding = "UTF-8"; } + sprops.encoding = sprops.sun_jnu_encoding; if (LANGIDFROMLCID(userDefaultLCID) == 0x0c04 && majorVersion == 6) { // MS claims "Vista has built-in support for HKSCS-2004. @@ -689,9 +677,6 @@ GetJavaProperties(JNIEnv* env) sprops.sun_jnu_encoding = "MS950_HKSCS"; } - assert(sprops.encoding != NULL); - assert(sprops.sun_jnu_encoding != NULL); - hStdOutErr = GetStdHandle(STD_OUTPUT_HANDLE); if (hStdOutErr != INVALID_HANDLE_VALUE && GetFileType(hStdOutErr) == FILE_TYPE_CHAR) { From 1b4b317aacbdfc499c28b00aeaf7120790a6c11a Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Thu, 17 Apr 2025 19:19:26 +0000 Subject: [PATCH 244/843] 8354789: Unnecessary null check in sun.awt.windows.WToolkit.getFontPeer Reviewed-by: aivanov, tr --- .../classes/sun/awt/windows/WToolkit.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java index 120f67dad19..e151a69a0f1 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -593,22 +593,20 @@ public final class WToolkit extends SunToolkit implements Runnable { @Override public FontPeer getFontPeer(String name, int style) { - FontPeer retval = null; String lcName = name.toLowerCase(); if (null != cacheFontPeer) { - retval = cacheFontPeer.get(lcName + style); - if (null != retval) { - return retval; + FontPeer cachedVal = cacheFontPeer.get(lcName + style); + if (null != cachedVal) { + return cachedVal; } } - retval = new WFontPeer(name, style); - if (retval != null) { - if (null == cacheFontPeer) { - cacheFontPeer = new Hashtable<>(5, 0.9f); - } - if (null != cacheFontPeer) { - cacheFontPeer.put(lcName + style, retval); - } + + FontPeer retval = new WFontPeer(name, style); + if (null == cacheFontPeer) { + cacheFontPeer = new Hashtable<>(5, 0.9f); + } + if (null != cacheFontPeer) { + cacheFontPeer.put(lcName + style, retval); } return retval; } From ad7c475fb1e23f583a33d58f0bd73ea0fb56740c Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Thu, 17 Apr 2025 19:53:45 +0000 Subject: [PATCH 245/843] 8353655: Clean up and open source KeyEvent related tests (Part 1) Reviewed-by: abhiscxk --- .../awt/event/KeyEvent/FrenchKeyboard.java | 71 ++++++++++ .../awt/event/KeyEvent/HomeEndKeyTest.java | 126 ++++++++++++++++++ .../java/awt/event/KeyEvent/NumpadTest.java | 119 +++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java create mode 100644 test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java create mode 100644 test/jdk/java/awt/event/KeyEvent/NumpadTest.java diff --git a/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java b/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java new file mode 100644 index 00000000000..c4765c9e17e --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/FrenchKeyboard.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4308606 + * @summary Tests whether the keys on the numeric keyboard work + * correctly under French input locale. + * @key i18n + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual FrenchKeyboard + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.lang.reflect.InvocationTargetException; + +public class FrenchKeyboard extends Frame { + static String INSTRUCTIONS = """ + This test is intended for computers with French input method. If French + input method can not be enabled or your keyboard does not have a numeric + keypad press "Pass" to skip the test. + Make sure that French input method is active and the NumLock is on. + Click on the text field in the window called "Check your keys" + and type once of each of the following keys on the numeric keypad: + /*-+1234567890 + If all the expected characters are displayed exactly once press "Pass". + If any characters do not display or display multiple times press "Fail". + """; + + public FrenchKeyboard() { + super("Check your keys"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + add(tf, BorderLayout.CENTER); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("FrenchKeyboard Instructions") + .instructions(INSTRUCTIONS) + .testUI(FrenchKeyboard::new) + .build() + .awaitAndCheck(); + } +} + diff --git a/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java b/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java new file mode 100644 index 00000000000..2c0155a0b60 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/HomeEndKeyTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4268912 4115514 + * summary Ensures that KeyEvent has right results for the following + * non-numpad keys: Home/Eng/PageUp/PageDn + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HomeEndKeyTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + + +public class HomeEndKeyTest extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + Before starting this test make sure that system shortcuts and + keybindings for the keys in the list below are disabled. + For example pressing "Print Screen" key should not launch + screen capturing software. + Click on the text field in the window named "Check keyCode values" + and one by one start typing the keys in the list below. + (If you do not have some of the keys on your keyboard skip it + and move to the next line). + After clicking each key look at the log area - the printed name + and key code should correspond to the ones for the key you typed. + Note that on some systems the graphical symbol for the key + can be printed instead of the symbolic name. + If you do not encounter unexpected key codes for the keys you typed, + press "Pass". Otherwise press "Fail". + + Key Keycode + ------------------------- + PrintScreen 154 + ScrollLock 145 + Pause 19 + + Insert 155 + Del 127 + Home 36 + End 35 + PageUp 33 + PageDown 34 + + Left Arrow 37 + Up Arrow 38 + Right Arrow 39 + Down Arrow 40 + """; + + public HomeEndKeyTest() { + super("Check KeyCode values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent ignore) { + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + String str; + switch (evt.getID()) { + case KeyEvent.KEY_PRESSED: + str = "KEY_PRESSED"; + break; + case KeyEvent.KEY_RELEASED: + str = "KEY_RELEASED"; + break; + default: + str = "unknown type"; + } + + str = str + ":name=" + KeyEvent.getKeyText(evt.getKeyCode()) + + " keyCode=" + evt.getKeyCode(); + PassFailJFrame.log(str); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("HomeEndKeyTest Instructions") + .instructions(INSTRUCTIONS) + .logArea(20) + .testUI(HomeEndKeyTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/NumpadTest.java b/test/jdk/java/awt/event/KeyEvent/NumpadTest.java new file mode 100644 index 00000000000..00c98ad4150 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/NumpadTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4083691 + * @summary Ensures that KeyEvent has right results for the following + * keys \*-+ + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NumpadTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + + +public class NumpadTest extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + This test requires a keyboard with a numeric keypad (numpad). + If your keyboard does not have a numpad press "Pass" to skip testing. + Make sure NumLock is on. + Click on the text field in the window named "Check KeyChar values". + Then, type the following keys/characters in the TextField. + using the numpad keys: + /*-+ + + Verify that the keyChar and keyCode is correct for each key pressed. + Remember that the keyCode for the KEY_TYPED event should be zero. + Also verify that the character you typed appears in the TextField. + + Key Name keyChar Keycode + ------------------------------------- + / Divide / 47 111 + * Multiply * 42 106 + - Subtract - 45 109 + + Add + 43 107 + + Now repeat with the NumLock off. + + If all keycodes are valid and expected characters appear + in the text field press "Pass". Otherwise press "Fail". + """; + + public NumpadTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent evt) { + printKey(evt); + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + switch (evt.getID()) { + case KeyEvent.KEY_TYPED: + break; + case KeyEvent.KEY_PRESSED: + break; + case KeyEvent.KEY_RELEASED: + break; + default: + return; + } + + if (evt.isActionKey()) { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar() + " Action Key"); + } else { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar()); + } + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + PassFailJFrame.builder() + .title("NumpadTest Instructions") + .instructions(INSTRUCTIONS) + .logArea(20) + .testUI(NumpadTest::new) + .build() + .awaitAndCheck(); + } +} From 38f138bc22ae705e8e09f75fe6bac4bb470dc29b Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 17 Apr 2025 23:37:45 +0000 Subject: [PATCH 246/843] 8354985: Add unit tests for Executor class from jpackage test lib Reviewed-by: almatvee --- .../jdk/jpackage/test/ExecutorTest.java | 370 ++++++++++++++++++ .../helpers/jdk/jpackage/test/Executor.java | 30 +- 2 files changed, 387 insertions(+), 13 deletions(-) create mode 100644 test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java new file mode 100644 index 00000000000..8175f49a2b2 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toSet; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.UncheckedIOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.function.Consumer; +import java.util.spi.ToolProvider; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class ExecutorTest extends JUnitAdapter { + + private record Command(List stdout, List stderr) { + Command { + stdout.forEach(Objects::requireNonNull); + stderr.forEach(Objects::requireNonNull); + } + + List asExecutable() { + final List commandline = new ArrayList<>(); + if (TKit.isWindows()) { + commandline.addAll(List.of("cmd", "/C")); + } else { + commandline.addAll(List.of("sh", "-c")); + } + commandline.add(Stream.concat(createEchoCommands(stdout), + createEchoCommands(stderr).map(v -> v + ">&2")).collect(joining(" && "))); + return commandline; + } + + private static Stream createEchoCommands(List lines) { + return lines.stream().map(line -> { + if (TKit.isWindows()) { + return "(echo " + line + ")"; + } else { + return "echo " + line; + } + }); + } + + ToolProvider asToolProvider() { + return new ToolProvider() { + + @Override + public int run(PrintWriter out, PrintWriter err, String... args) { + stdout.forEach(out::println); + stderr.forEach(err::println); + return 0; + } + + @Override + public String name() { + return "test"; + } + }; + } + } + + private enum OutputData { + EMPTY(List.of()), + ONE_LINE(List.of("Jupiter")), + MANY(List.of("Uranus", "Saturn", "Earth")); + + OutputData(List data) { + data.forEach(Objects::requireNonNull); + this.data = data; + } + + final List data; + } + + private record CommandSpec(OutputData stdout, OutputData stderr) { + CommandSpec { + Objects.requireNonNull(stdout); + Objects.requireNonNull(stderr); + } + + Command command() { + return new Command(stdout.data.stream().map(line -> { + return "stdout." + line; + }).toList(), stderr.data.stream().map(line -> { + return "stderr." + line; + }).toList()); + } + } + + public enum OutputControl { + DUMP(Executor::dumpOutput), + SAVE_ALL(Executor::saveOutput), + SAVE_FIRST_LINE(Executor::saveFirstLineOfOutput), + DISCARD_STDOUT(NOP), + DISCARD_STDERR(NOP), + ; + + OutputControl(Consumer configureExector) { + this.configureExector = Objects.requireNonNull(configureExector); + } + + Executor applyTo(Executor exec) { + configureExector.accept(exec); + return exec; + } + + static List> variants() { + final List> variants = new ArrayList<>(); + for (final var withDump : BOOLEAN_VALUES) { + variants.addAll(Stream.of( + Set.of(), + Set.of(SAVE_ALL), + Set.of(SAVE_FIRST_LINE), + Set.of(DISCARD_STDOUT), + Set.of(DISCARD_STDERR), + Set.of(SAVE_ALL, DISCARD_STDOUT), + Set.of(SAVE_FIRST_LINE, DISCARD_STDOUT), + Set.of(SAVE_ALL, DISCARD_STDERR), + Set.of(SAVE_FIRST_LINE, DISCARD_STDERR), + Set.of(SAVE_ALL, DISCARD_STDOUT, DISCARD_STDERR), + Set.of(SAVE_FIRST_LINE, DISCARD_STDOUT, DISCARD_STDERR) + ).map(v -> { + if (withDump) { + return Stream.concat(Stream.of(DUMP), v.stream()).collect(toSet()); + } else { + return v; + } + }).toList()); + } + return variants.stream().map(options -> { + return options.stream().filter(o -> { + return o.configureExector != NOP; + }).collect(toSet()); + }).distinct().toList(); + } + + private final Consumer configureExector; + + static final Set SAVE = Set.of(SAVE_ALL, SAVE_FIRST_LINE); + } + + public record OutputTestSpec(boolean toolProvider, Set outputControl, CommandSpec commandSpec) { + public OutputTestSpec { + outputControl.forEach(Objects::requireNonNull); + if (outputControl.containsAll(OutputControl.SAVE)) { + throw new IllegalArgumentException(); + } + Objects.requireNonNull(commandSpec); + } + + @Override + public String toString() { + final List tokens = new ArrayList<>(); + + if (toolProvider) { + tokens.add("tool-provider"); + } + + tokens.add("output=" + format(outputControl)); + tokens.add("command=" + commandSpec); + + return String.join(",", tokens.toArray(String[]::new)); + } + + void test() { + final var command = commandSpec.command(); + final var commandWithDiscardedStreams = discardStreams(command); + + final Executor.Result[] result = new Executor.Result[1]; + final var outputCapture = OutputCapture.captureOutput(() -> { + result[0] = createExecutor(command).executeWithoutExitCodeCheck(); + }); + + assertEquals(0, result[0].getExitCode()); + + assertEquals(expectedCapturedSystemOut(commandWithDiscardedStreams), outputCapture.outLines()); + assertEquals(expectedCapturedSystemErr(commandWithDiscardedStreams), outputCapture.errLines()); + + if (!saveOutput()) { + assertNull(result[0].getOutput()); + } else { + assertNotNull(result[0].getOutput()); + final var allExpectedOutput = expectedCommandOutput(command); + assertEquals(allExpectedOutput.isEmpty(), result[0].getOutput().isEmpty()); + if (!allExpectedOutput.isEmpty()) { + if (outputControl.contains(OutputControl.SAVE_ALL)) { + assertEquals(allExpectedOutput, result[0].getOutput()); + } else if (outputControl.contains(OutputControl.SAVE_FIRST_LINE)) { + assertEquals(1, result[0].getOutput().size()); + assertEquals(allExpectedOutput.getFirst(), result[0].getFirstLineOfOutput()); + } else { + throw new UnsupportedOperationException(); + } + } + } + } + + private boolean dumpOutput() { + return outputControl.contains(OutputControl.DUMP); + } + + private boolean saveOutput() { + return !Collections.disjoint(outputControl, OutputControl.SAVE); + } + + private boolean discardStdout() { + return outputControl.contains(OutputControl.DISCARD_STDOUT); + } + + private boolean discardStderr() { + return outputControl.contains(OutputControl.DISCARD_STDERR); + } + + private static String format(Set outputControl) { + return outputControl.stream().map(OutputControl::name).sorted().collect(joining("+")); + } + + private List expectedCapturedSystemOut(Command command) { + if (!dumpOutput() || (!toolProvider && !saveOutput())) { + return List.of(); + } else if(saveOutput()) { + return Stream.concat(command.stdout().stream(), command.stderr().stream()).toList(); + } else { + return command.stdout(); + } + } + + private List expectedCapturedSystemErr(Command command) { + if (!dumpOutput() || (!toolProvider && !saveOutput())) { + return List.of(); + } else if(saveOutput()) { + return List.of(); + } else { + return command.stderr(); + } + } + + private Command discardStreams(Command command) { + return new Command(discardStdout() ? List.of() : command.stdout(), discardStderr() ? List.of() : command.stderr()); + } + + private record OutputCapture(byte[] out, byte[] err, Charset outCharset, Charset errCharset) { + OutputCapture { + Objects.requireNonNull(out); + Objects.requireNonNull(err); + Objects.requireNonNull(outCharset); + Objects.requireNonNull(errCharset); + } + + List outLines() { + return toLines(out, outCharset); + } + + List errLines() { + return toLines(err, errCharset); + } + + private static List toLines(byte[] buf, Charset charset) { + try (var reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf), charset))) { + return reader.lines().filter(line -> { + return !line.contains("TRACE"); + }).toList(); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + static OutputCapture captureOutput(Runnable runnable) { + final var captureOut = new ByteArrayOutputStream(); + final var captureErr = new ByteArrayOutputStream(); + + final var out = System.out; + final var err = System.err; + try { + final var outCharset = System.out.charset(); + final var errCharset = System.err.charset(); + System.setOut(new PrintStream(captureOut, true, outCharset)); + System.setErr(new PrintStream(captureErr, true, errCharset)); + runnable.run(); + return new OutputCapture(captureOut.toByteArray(), captureErr.toByteArray(), outCharset, errCharset); + } finally { + try { + System.setOut(out); + } finally { + System.setErr(err); + } + } + } + } + + private List expectedCommandOutput(Command command) { + command = discardStreams(command); + return Stream.of(command.stdout(), command.stderr()).flatMap(List::stream).toList(); + } + + private Executor createExecutor(Command command) { + final Executor exec; + if (toolProvider) { + exec = Executor.of(command.asToolProvider()); + } else { + exec = Executor.of(command.asExecutable()); + } + + outputControl.forEach(control -> control.applyTo(exec)); + + return exec; + } + } + + @ParameterizedTest + @MethodSource + public void testSavedOutput(OutputTestSpec spec) { + spec.test(); + } + + public static List testSavedOutput() { + List testCases = new ArrayList<>(); + for (final var toolProvider : BOOLEAN_VALUES) { + for (final var outputControl : OutputControl.variants()) { + for (final var stdoutContent : List.of(OutputData.values())) { + for (final var stderrContent : List.of(OutputData.values())) { + final var commandSpec = new CommandSpec(stdoutContent, stderrContent); + testCases.add(new OutputTestSpec(toolProvider, outputControl, commandSpec)); + } + } + } + } + return testCases; + } + + private static final List BOOLEAN_VALUES = List.of(Boolean.TRUE, Boolean.FALSE); + private static final Consumer NOP = exec -> {}; +} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index 66cd422203b..053674960c4 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -29,9 +29,9 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.io.StringReader; +import java.io.Writer; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -50,8 +50,16 @@ import jdk.jpackage.internal.util.function.ThrowingSupplier; public final class Executor extends CommandArguments { public static Executor of(String... cmdline) { - return new Executor().setExecutable(cmdline[0]).addArguments( - Arrays.copyOfRange(cmdline, 1, cmdline.length)); + return of(List.of(cmdline)); + } + + public static Executor of(List cmdline) { + cmdline.forEach(Objects::requireNonNull); + return new Executor().setExecutable(cmdline.getFirst()).addArguments(cmdline.subList(1, cmdline.size())); + } + + public static Executor of(ToolProvider toolProvider, String... args) { + return new Executor().setToolProvider(toolProvider).addArguments(List.of(args)); } public Executor() { @@ -414,8 +422,8 @@ public final class Executor extends CommandArguments { || saveOutputType.contains(SaveOutputType.FULL)) { outputLines = outReader.lines().collect(Collectors.toList()); } else { - outputLines = Arrays.asList( - outReader.lines().findFirst().orElse(null)); + outputLines = Optional.ofNullable(outReader.readLine()).map(List::of).orElseGet(List::of); + outReader.transferTo(Writer.nullWriter()); } } finally { if (saveOutputType.contains(SaveOutputType.DUMP) && outputLines != null) { @@ -475,15 +483,11 @@ public final class Executor extends CommandArguments { final var exitCode = runToolProvider(ps, ps); ps.flush(); final List output; + final var bufAsString = buf.toString(); try (BufferedReader bufReader = new BufferedReader(new StringReader( - buf.toString()))) { + bufAsString))) { if (saveOutputType.contains(SaveOutputType.FIRST_LINE)) { - String firstLine = bufReader.lines().findFirst().orElse(null); - if (firstLine != null) { - output = List.of(firstLine); - } else { - output = null; - } + output = bufReader.lines().findFirst().map(List::of).orElseGet(List::of); } else if (saveOutputType.contains(SaveOutputType.FULL)) { output = bufReader.lines().collect(Collectors.toUnmodifiableList()); } else { @@ -495,7 +499,7 @@ public final class Executor extends CommandArguments { if (saveOutputType.contains(SaveOutputType.FULL)) { lines = output.stream(); } else { - lines = bufReader.lines(); + lines = new BufferedReader(new StringReader(bufAsString)).lines(); } lines.forEach(System.out::println); } From 0995b9409d910d816276673b5c06fdf7826bfac7 Mon Sep 17 00:00:00 2001 From: Anjian-Wen Date: Fri, 18 Apr 2025 02:20:39 +0000 Subject: [PATCH 247/843] 8354815: RISC-V: Change type of bitwise rotation shift to iRegIorL2I Reviewed-by: fyang, fjiang --- src/hotspot/cpu/riscv/riscv.ad | 14 ++++++-------- src/hotspot/cpu/riscv/riscv_b.ad | 20 +++++++++++++++----- src/hotspot/cpu/riscv/riscv_v.ad | 4 ++++ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index aca2f4dd488..1eb1464e7d9 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -6445,7 +6445,6 @@ instruct addI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immIAdd src2) %{ format %{ "addiw $dst, $src1, $src2\t#@addI_reg_imm" %} ins_encode %{ - int32_t con = (int32_t)$src2$$constant; __ addiw(as_Register($dst$$reg), as_Register($src1$$reg), $src2$$constant); @@ -6507,7 +6506,6 @@ instruct addP_reg_imm(iRegPNoSp dst, iRegP src1, immLAdd src2) %{ format %{ "addi $dst, $src1, $src2\t# ptr, #@addP_reg_imm" %} ins_encode %{ - // src2 is imm, so actually call the addi __ addi(as_Register($dst$$reg), as_Register($src1$$reg), $src2$$constant); @@ -6829,7 +6827,7 @@ instruct UmodL(iRegLNoSp dst, iRegL src1, iRegL src2) %{ // Integer Shifts // Shift Left Register -// In RV64I, only the low 5 bits of src2 are considered for the shift amount +// Only the low 5 bits of src2 are considered for the shift amount, all other bits are ignored. instruct lShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ match(Set dst (LShiftI src1 src2)); ins_cost(ALU_COST); @@ -6862,7 +6860,7 @@ instruct lShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{ %} // Shift Right Logical Register -// In RV64I, only the low 5 bits of src2 are considered for the shift amount +// Only the low 5 bits of src2 are considered for the shift amount, all other bits are ignored. instruct urShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ match(Set dst (URShiftI src1 src2)); ins_cost(ALU_COST); @@ -6895,7 +6893,7 @@ instruct urShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{ %} // Shift Right Arithmetic Register -// In RV64I, only the low 5 bits of src2 are considered for the shift amount +// Only the low 5 bits of src2 are considered for the shift amount, all other bits are ignored. instruct rShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{ match(Set dst (RShiftI src1 src2)); ins_cost(ALU_COST); @@ -6930,7 +6928,7 @@ instruct rShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{ // Long Shifts // Shift Left Register -// In RV64I, only the low 6 bits of src2 are considered for the shift amount +// Only the low 6 bits of src2 are considered for the shift amount, all other bits are ignored. instruct lShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{ match(Set dst (LShiftL src1 src2)); @@ -6965,7 +6963,7 @@ instruct lShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{ %} // Shift Right Logical Register -// In RV64I, only the low 6 bits of src2 are considered for the shift amount +// Only the low 6 bits of src2 are considered for the shift amount, all other bits are ignored. instruct urShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{ match(Set dst (URShiftL src1 src2)); @@ -7018,7 +7016,7 @@ instruct urShiftP_reg_imm(iRegLNoSp dst, iRegP src1, immI src2) %{ %} // Shift Right Arithmetic Register -// In RV64I, only the low 6 bits of src2 are considered for the shift amount +// Only the low 6 bits of src2 are considered for the shift amount, all other bits are ignored. instruct rShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{ match(Set dst (RShiftL src1 src2)); diff --git a/src/hotspot/cpu/riscv/riscv_b.ad b/src/hotspot/cpu/riscv/riscv_b.ad index ed9fca13a1b..beac10ec03d 100644 --- a/src/hotspot/cpu/riscv/riscv_b.ad +++ b/src/hotspot/cpu/riscv/riscv_b.ad @@ -25,7 +25,8 @@ // RISCV Bit-Manipulation Extension Architecture Description File -instruct rorI_imm_b(iRegINoSp dst, iRegI src, immI shift) %{ +// Rotate Right Word Immediate +instruct rorI_imm_b(iRegINoSp dst, iRegIorL2I src, immI shift) %{ predicate(UseZbb); match(Set dst (RotateRight src shift)); @@ -39,6 +40,7 @@ instruct rorI_imm_b(iRegINoSp dst, iRegI src, immI shift) %{ ins_pipe(ialu_reg_shift); %} +// Rotate Right Immediate instruct rorL_imm_b(iRegLNoSp dst, iRegL src, immI shift) %{ predicate(UseZbb); match(Set dst (RotateRight src shift)); @@ -53,7 +55,9 @@ instruct rorL_imm_b(iRegLNoSp dst, iRegL src, immI shift) %{ ins_pipe(ialu_reg_shift); %} -instruct rorI_reg_b(iRegINoSp dst, iRegI src, iRegI shift) %{ +// Rotate Right Word Register +// Only the low 5 bits of shift value are used, all other bits are ignored. +instruct rorI_reg_b(iRegINoSp dst, iRegIorL2I src, iRegIorL2I shift) %{ predicate(UseZbb); match(Set dst (RotateRight src shift)); @@ -65,7 +69,9 @@ instruct rorI_reg_b(iRegINoSp dst, iRegI src, iRegI shift) %{ ins_pipe(ialu_reg_reg); %} -instruct rorL_reg_b(iRegLNoSp dst, iRegL src, iRegI shift) %{ +// Rotate Right Register +// Only the low 6 bits of shift value are used, all other bits are ignored. +instruct rorL_reg_b(iRegLNoSp dst, iRegL src, iRegIorL2I shift) %{ predicate(UseZbb); match(Set dst (RotateRight src shift)); @@ -77,7 +83,9 @@ instruct rorL_reg_b(iRegLNoSp dst, iRegL src, iRegI shift) %{ ins_pipe(ialu_reg_reg); %} -instruct rolI_reg_b(iRegINoSp dst, iRegI src, iRegI shift) %{ +// Rotate Left Word Register +// Only the low 5 bits of shift value are used, all other bits are ignored. +instruct rolI_reg_b(iRegINoSp dst, iRegIorL2I src, iRegIorL2I shift) %{ predicate(UseZbb); match(Set dst (RotateLeft src shift)); @@ -89,7 +97,9 @@ instruct rolI_reg_b(iRegINoSp dst, iRegI src, iRegI shift) %{ ins_pipe(ialu_reg_reg); %} -instruct rolL_reg_b(iRegLNoSp dst, iRegL src, iRegI shift) %{ +// Rotate Left Register +// Only the low 6 bits of shift value are used, all other bits are ignored. +instruct rolL_reg_b(iRegLNoSp dst, iRegL src, iRegIorL2I shift) %{ predicate(UseZbb); match(Set dst (RotateLeft src shift)); diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 9b135215b3d..7c1ca4f8960 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -3499,6 +3499,7 @@ instruct vrotate_right(vReg dst, vReg src, vReg shift) %{ ins_pipe(pipe_slow); %} +// Only the low log2(SEW) bits of shift value are used, all other bits are ignored. instruct vrotate_right_reg(vReg dst, vReg src, iRegIorL2I shift) %{ match(Set dst (RotateRightV src (Replicate shift))); format %{ "vrotate_right_reg $dst, $src, $shift\t" %} @@ -3541,6 +3542,7 @@ instruct vrotate_right_masked(vReg dst_src, vReg shift, vRegMask_V0 v0) %{ ins_pipe(pipe_slow); %} +// Only the low log2(SEW) bits of shift value are used, all other bits are ignored. instruct vrotate_right_reg_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0) %{ match(Set dst_src (RotateRightV (Binary dst_src (Replicate shift)) v0)); format %{ "vrotate_right_reg_masked $dst_src, $dst_src, $shift, v0.t\t" %} @@ -3584,6 +3586,7 @@ instruct vrotate_left(vReg dst, vReg src, vReg shift) %{ ins_pipe(pipe_slow); %} +// Only the low log2(SEW) bits of shift value are used, all other bits are ignored. instruct vrotate_left_reg(vReg dst, vReg src, iRegIorL2I shift) %{ match(Set dst (RotateLeftV src (Replicate shift))); format %{ "vrotate_left_reg $dst, $src, $shift\t" %} @@ -3627,6 +3630,7 @@ instruct vrotate_left_masked(vReg dst_src, vReg shift, vRegMask_V0 v0) %{ ins_pipe(pipe_slow); %} +// Only the low log2(SEW) bits of shift value are used, all other bits are ignored. instruct vrotate_left_reg_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0) %{ match(Set dst_src (RotateLeftV (Binary dst_src (Replicate shift)) v0)); format %{ "vrotate_left_reg_masked $dst_src, $dst_src, $shift, v0.t\t" %} From 0feecb7c6a982e5c65df0242711ecdb0691cef87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C5=A0ipka?= Date: Fri, 18 Apr 2025 10:44:29 +0000 Subject: [PATCH 248/843] 8351851: Update PmemTest to run on AMD64 Reviewed-by: adinn --- test/jdk/java/nio/MappedByteBuffer/PmemTest.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/jdk/java/nio/MappedByteBuffer/PmemTest.java b/test/jdk/java/nio/MappedByteBuffer/PmemTest.java index 2771295c8a0..0c931b3606f 100644 --- a/test/jdk/java/nio/MappedByteBuffer/PmemTest.java +++ b/test/jdk/java/nio/MappedByteBuffer/PmemTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,25 +77,24 @@ * make test TEST=jdk/java/nio/MappedByteBuffer/PmemTest.java */ -/* @test +/* @test id=default_architecture_test_case * @summary Testing NVRAM mapped byte buffer support * @run main/manual PmemTest * @requires (os.family == "linux") - * @requires (os.arch == "x86_64") + * @requires ((os.arch == "x86_64")|(os.arch == "amd64")) */ -/* @test +/* @test id=other_architectures_test_case * @summary Testing NVRAM mapped byte buffer support * @run main/manual PmemTest * @requires (os.family == "linux") - * @requires ((os.arch == "amd64")|(os.arch == "aarch64")|(os.arch == "ppc64le")) + * @requires ((os.arch == "aarch64")|(os.arch == "ppc64le")) * @ignore The test described here is currently disabled on systems that are not * x64-based and lack an external NVRAM memory device. In order to re-enable the * test, you will need to mount the NVRAM device, which will typically appear as * /dev/pmem0, to the directory /mnt/pmem. Once that is done, you can follow the * instructions above to create a test directory and remove the ignore tag. */ - import java.io.File; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; @@ -173,4 +172,4 @@ public class PmemTest { "\n}"); } } -} +} \ No newline at end of file From eda7394551b470e9dc547be93711bcceac45f303 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Fri, 18 Apr 2025 12:05:01 +0000 Subject: [PATCH 249/843] 8354900: javax/swing/AbstractButton/bug4133768.java failing on macosx-aarch64 Reviewed-by: abhiscxk --- .../swing/AbstractButton/bug4133768.java | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/test/jdk/javax/swing/AbstractButton/bug4133768.java b/test/jdk/javax/swing/AbstractButton/bug4133768.java index ad5f56c0149..4ccec98c6ec 100644 --- a/test/jdk/javax/swing/AbstractButton/bug4133768.java +++ b/test/jdk/javax/swing/AbstractButton/bug4133768.java @@ -34,8 +34,11 @@ import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Point; import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.awt.image.BufferedImage; -import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import javax.swing.AbstractButton; import javax.swing.Icon; import javax.swing.ImageIcon; @@ -47,20 +50,28 @@ import javax.swing.JToggleButton; import javax.swing.SwingUtilities; public class bug4133768 { - private static Icon RED, GREEN; + private static Icon RED; + private static Icon GREEN; private static JFrame f; private static AbstractButton[] buttons; private static volatile Point buttonLocation; private static volatile int buttonWidth; private static volatile int buttonHeight; private static Robot robot; + private static int ROLLOVER_Y_OFFSET = 4; + private static CountDownLatch frameGainedFocusLatch = + new CountDownLatch(1); public static void main(String[] args) throws Exception { try { createTestImages(); createUI(); + f.requestFocus(); + if (!frameGainedFocusLatch.await(5, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't gain" + + " focus for frame"); + } robot = new Robot(); - robot.delay(1000); for (AbstractButton b : buttons) { testEnabledButton(b); } @@ -78,9 +89,9 @@ public class bug4133768 { } } - private static void createTestImages() throws IOException { - int imageWidth = 32; - int imageHeight = 32; + private static void createTestImages() { + int imageWidth = 100; + int imageHeight = 100; BufferedImage redImg = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g = redImg.createGraphics(); @@ -114,6 +125,12 @@ public class bug4133768 { b.setRolloverSelectedIcon(GREEN); buttonPanel.add(b); } + f.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + frameGainedFocusLatch.countDown(); + } + }); f.setLayout(new GridLayout(2, 1)); f.add(buttonPanel); f.pack(); @@ -123,7 +140,8 @@ public class bug4133768 { }); } - private static void testEnabledButton(AbstractButton button) throws Exception { + private static void testEnabledButton(AbstractButton button) + throws Exception { robot.waitForIdle(); SwingUtilities.invokeAndWait(() -> { buttonLocation = button.getLocationOnScreen(); @@ -131,7 +149,7 @@ public class bug4133768 { buttonHeight = button.getHeight(); }); robot.mouseMove(buttonLocation.x + buttonWidth / 2, - buttonLocation.y + buttonHeight / 2 ); + buttonLocation.y + ROLLOVER_Y_OFFSET); robot.delay(1000); Color buttonColor = robot.getPixelColor(buttonLocation.x + buttonWidth / 2, buttonLocation.y + buttonHeight / 2); @@ -141,16 +159,15 @@ public class bug4133768 { } } - private static void testDisabledButton(AbstractButton button) throws Exception { + private static void testDisabledButton(AbstractButton button) + throws Exception { robot.waitForIdle(); SwingUtilities.invokeAndWait(() -> { buttonLocation = button.getLocationOnScreen(); buttonWidth = button.getWidth(); buttonHeight = button.getHeight(); }); - robot.mouseMove(buttonLocation.x + buttonWidth / 2, - buttonLocation.y + buttonHeight / 2 ); - robot.delay(1000); + robot.delay(200); Color buttonColor = robot.getPixelColor(buttonLocation.x + buttonWidth / 2, buttonLocation.y + buttonHeight / 2); if (buttonColor.equals(Color.GREEN) || From 22e8a97a1ce4e1c781fbc6f1e271c477fe95f069 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 18 Apr 2025 12:12:52 +0000 Subject: [PATCH 250/843] 8354988: Separate stderr and stdout in Executor class from jpackage test lib Reviewed-by: almatvee --- .../jdk/jpackage/test/ExecutorTest.java | 29 +- .../jdk/jpackage/test/PackageTestTest.java | 2 +- .../helpers/jdk/jpackage/test/Executor.java | 668 ++++++++++++++---- .../jdk/jpackage/test/JPackageCommand.java | 17 + .../jdk/jpackage/test/WindowsHelper.java | 13 +- test/jdk/tools/jpackage/share/BasicTest.java | 7 +- .../jpackage/windows/Win8301247Test.java | 36 +- 7 files changed, 601 insertions(+), 171 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java index 8175f49a2b2..c5d8aed845c 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java @@ -128,8 +128,8 @@ public class ExecutorTest extends JUnitAdapter { DUMP(Executor::dumpOutput), SAVE_ALL(Executor::saveOutput), SAVE_FIRST_LINE(Executor::saveFirstLineOfOutput), - DISCARD_STDOUT(NOP), - DISCARD_STDERR(NOP), + DISCARD_STDOUT(Executor::discardStdout), + DISCARD_STDERR(Executor::discardStderr), ; OutputControl(Consumer configureExector) { @@ -213,6 +213,9 @@ public class ExecutorTest extends JUnitAdapter { assertEquals(expectedCapturedSystemOut(commandWithDiscardedStreams), outputCapture.outLines()); assertEquals(expectedCapturedSystemErr(commandWithDiscardedStreams), outputCapture.errLines()); + assertEquals(expectedResultStdout(commandWithDiscardedStreams), result[0].stdout().getOutput()); + assertEquals(expectedResultStderr(commandWithDiscardedStreams), result[0].stderr().getOutput()); + if (!saveOutput()) { assertNull(result[0].getOutput()); } else { @@ -272,6 +275,28 @@ public class ExecutorTest extends JUnitAdapter { } } + private List expectedResultStdout(Command command) { + return expectedResultStream(command.stdout()); + } + + private List expectedResultStderr(Command command) { + if (outputControl.contains(OutputControl.SAVE_FIRST_LINE) && !command.stdout().isEmpty()) { + return List.of(); + } + return expectedResultStream(command.stderr()); + } + + private List expectedResultStream(List commandOutput) { + Objects.requireNonNull(commandOutput); + if (outputControl.contains(OutputControl.SAVE_ALL)) { + return commandOutput; + } else if (outputControl.contains(OutputControl.SAVE_FIRST_LINE)) { + return commandOutput.stream().findFirst().map(List::of).orElseGet(List::of); + } else { + return null; + } + } + private Command discardStreams(Command command) { return new Command(discardStdout() ? List.of() : command.stdout(), discardStderr() ? List.of() : command.stderr()); } diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java index 3e14022a70e..da94db30925 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java @@ -370,7 +370,7 @@ public class PackageTestTest extends JUnitAdapter { } catch (IOException ex) { throw new UncheckedIOException(ex); } - return new Executor.Result(actualJPackageExitCode, null, + return new Executor.Result(actualJPackageExitCode, this::getPrintableCommandLine).assertExitCodeIs(expectedExitCode); } }; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index 053674960c4..91625603a2b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -22,9 +22,12 @@ */ package jdk.jpackage.test; +import static java.util.stream.Collectors.joining; + import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; @@ -32,7 +35,6 @@ import java.io.StringReader; import java.io.Writer; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -63,7 +65,7 @@ public final class Executor extends CommandArguments { } public Executor() { - saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE)); + outputStreamsControl = new OutputStreamsControl(); winEnglishOutput = false; } @@ -131,54 +133,48 @@ public final class Executor extends CommandArguments { } /** - * Configures this instance to save full output that command will produce. - * This function is mutual exclusive with - * saveFirstLineOfOutput() function. + * Configures this instance to save all stdout and stderr streams from the to be + * executed command. + *

+ * This function is mutually exclusive with {@link #saveFirstLineOfOutput()}. * * @return this */ public Executor saveOutput() { - saveOutputType.remove(SaveOutputType.FIRST_LINE); - saveOutputType.add(SaveOutputType.FULL); - return this; + return saveOutput(true); } /** - * Configures how to save output that command will produce. If - * v is true, the function call is equivalent to - * saveOutput() call. If v is false, - * the function will result in not preserving command output. + * Configures if all stdout and stderr streams from the to be executed command + * should be saved. + *

+ * If v is true, the function call is equivalent to + * {@link #saveOutput()} call. If v is false, command + * output will not be saved. + * + * @parameter v if both stdout and stderr streams should be saved * * @return this */ public Executor saveOutput(boolean v) { - if (v) { - saveOutput(); - } else { - saveOutputType.remove(SaveOutputType.FIRST_LINE); - saveOutputType.remove(SaveOutputType.FULL); - } - return this; + return setOutputControl(v, OutputControlOption.SAVE_ALL); } /** - * Configures this instance to save only the first line out output that - * command will produce. This function is mutual exclusive with - * saveOutput() function. + * Configures this instance to save the first line of a stream merged from + * stdout and stderr streams from the to be executed command. + *

+ * This function is mutually exclusive with {@link #saveOutput()}. * * @return this */ public Executor saveFirstLineOfOutput() { - saveOutputType.add(SaveOutputType.FIRST_LINE); - saveOutputType.remove(SaveOutputType.FULL); - return this; + return setOutputControl(true, OutputControlOption.SAVE_FIRST_LINE); } /** - * Configures this instance to dump all output that command will produce to - * System.out and System.err. Can be used together with saveOutput() and - * saveFirstLineOfOutput() to save command output and also copy it in the - * default output streams. + * Configures this instance to dump both stdout and stderr streams from the to + * be executed command into {@link System.out}. * * @return this */ @@ -187,26 +183,60 @@ public final class Executor extends CommandArguments { } public Executor dumpOutput(boolean v) { - if (v) { - saveOutputType.add(SaveOutputType.DUMP); - } else { - saveOutputType.remove(SaveOutputType.DUMP); - } + return setOutputControl(v, OutputControlOption.DUMP); + } + + public Executor discardStdout(boolean v) { + outputStreamsControl.stdout().discard(v); return this; } - public record Result(int exitCode, List output, Supplier cmdline) { + public Executor discardStdout() { + return discardStdout(true); + } + public Executor discardStderr(boolean v) { + outputStreamsControl.stderr().discard(v); + return this; + } + + public Executor discardStderr() { + return discardStderr(true); + } + + public interface Output { + public List getOutput(); + + public default String getFirstLineOfOutput() { + return findFirstLineOfOutput().orElseThrow(); + } + + public default Optional findFirstLineOfOutput() { + return getOutput().stream().findFirst(); + } + } + + public record Result(int exitCode, CommandOutput output, Supplier cmdline) implements Output { public Result { + Objects.requireNonNull(output); Objects.requireNonNull(cmdline); } - public String getFirstLineOfOutput() { - return output.get(0); + public Result(int exitCode, Supplier cmdline) { + this(exitCode, CommandOutput.EMPTY, cmdline); } + @Override public List getOutput() { - return output; + return output.lines().orElse(null); + } + + public Output stdout() { + return createView(output.stdoutLines()); + } + + public Output stderr() { + return createView(output.stderrLines()); } public Result assertExitCodeIs(int expectedExitCode) { @@ -223,6 +253,15 @@ public final class Executor extends CommandArguments { public int getExitCode() { return exitCode; } + + private static Output createView(Optional> lines) { + return new Output() { + @Override + public List getOutput() { + return lines.orElse(null); + } + }; + } } public Result executeWithoutExitCodeCheck() { @@ -278,27 +317,42 @@ public final class Executor extends CommandArguments { private static final long serialVersionUID = 1L; } - /* - * Repeates command "max" times and waits for "wait" seconds between each - * execution until command returns expected error code. + /** + * Executes the configured command {@code max} at most times and waits for + * {@code wait} seconds between each execution until the command exits with + * {@code expectedCode} exit code. + * + * @param expectedExitCode the expected exit code of the command + * @param max the maximum times to execute the command + * @param wait number of seconds to wait between executions of the + * command */ - public Result executeAndRepeatUntilExitCode(int expectedCode, int max, int wait) { + public Result executeAndRepeatUntilExitCode(int expectedExitCode, int max, int wait) { try { return tryRunMultipleTimes(() -> { Result result = executeWithoutExitCodeCheck(); - if (result.getExitCode() != expectedCode) { + if (result.getExitCode() != expectedExitCode) { throw new BadResultException(result); } return result; - }, max, wait).assertExitCodeIs(expectedCode); + }, max, wait).assertExitCodeIs(expectedExitCode); } catch (BadResultException ex) { - return ex.getValue().assertExitCodeIs(expectedCode); + return ex.getValue().assertExitCodeIs(expectedExitCode); } } - /* - * Repeates a "task" "max" times and waits for "wait" seconds between each - * execution until the "task" returns without throwing an exception. + /** + * Calls {@code task.get()} at most {@code max} times and waits for {@code wait} + * seconds between each call until {@code task.get()} invocation returns without + * throwing {@link RuntimeException} exception. + *

+ * Returns the object returned by the first {@code task.get()} invocation that + * didn't throw an exception or rethrows the last exception if all of + * {@code max} attempts ended in exception being thrown. + * + * @param task the object of which to call {@link Supplier#get()} function + * @param max the maximum times to execute the command + * @param wait number of seconds to wait between executions of the */ public static T tryRunMultipleTimes(Supplier task, int max, int wait) { RuntimeException lastException = null; @@ -334,9 +388,10 @@ public final class Executor extends CommandArguments { return saveOutput().executeWithoutExitCodeCheck().getOutput(); } - private boolean withSavedOutput() { - return saveOutputType.contains(SaveOutputType.FULL) || saveOutputType.contains( - SaveOutputType.FIRST_LINE); + private Executor setOutputControl(boolean set, OutputControlOption v) { + outputStreamsControl.stdout().set(set, v); + outputStreamsControl.stderr().set(set, v); + return this; } private Path executablePath() { @@ -349,8 +404,8 @@ public final class Executor extends CommandArguments { // If relative path to executable is used it seems to be broken when // ProcessBuilder changes the directory. On Windows it changes the // directory first and on Linux it looks up for executable before - // changing the directory. So to stay of safe side, use absolute path - // to executable. + // changing the directory. Use absolute path to executable to play + // it safely on all platforms. return executable.toAbsolutePath(); } @@ -371,18 +426,14 @@ public final class Executor extends CommandArguments { if (winTmpDir != null) { builder.environment().put("TMP", winTmpDir); } + + outputStreamsControl.applyTo(builder); + StringBuilder sb = new StringBuilder(getPrintableCommandLine()); - if (withSavedOutput()) { - builder.redirectErrorStream(true); - sb.append("; save output"); - } else if (saveOutputType.contains(SaveOutputType.DUMP)) { - builder.inheritIO(); - sb.append("; inherit I/O"); - } else { - builder.redirectError(ProcessBuilder.Redirect.DISCARD); - builder.redirectOutput(ProcessBuilder.Redirect.DISCARD); - sb.append("; discard I/O"); - } + outputStreamsControl.describe().ifPresent(desc -> { + sb.append("; ").append(desc); + }); + if (directory != null) { builder.directory(directory.toFile()); sb.append(String.format("; in directory [%s]", directory)); @@ -414,98 +465,110 @@ public final class Executor extends CommandArguments { trace("Execute " + sb.toString() + "..."); Process process = builder.start(); - List outputLines = null; - if (withSavedOutput()) { - try (BufferedReader outReader = new BufferedReader( - new InputStreamReader(process.getInputStream()))) { - if (saveOutputType.contains(SaveOutputType.DUMP) - || saveOutputType.contains(SaveOutputType.FULL)) { - outputLines = outReader.lines().collect(Collectors.toList()); - } else { - outputLines = Optional.ofNullable(outReader.readLine()).map(List::of).orElseGet(List::of); - outReader.transferTo(Writer.nullWriter()); - } - } finally { - if (saveOutputType.contains(SaveOutputType.DUMP) && outputLines != null) { - outputLines.stream().forEach(System.out::println); - if (saveOutputType.contains(SaveOutputType.FIRST_LINE)) { - // Pick the first line of saved output if there is one - for (String line: outputLines) { - outputLines = List.of(line); - break; - } - } - } - } - } + final var output = combine( + processProcessStream(outputStreamsControl.stdout(), process.getInputStream()), + processProcessStream(outputStreamsControl.stderr(), process.getErrorStream())); final int exitCode = process.waitFor(); trace("Done. Exit code: " + exitCode); - final List output; - if (outputLines != null) { - output = Collections.unmodifiableList(outputLines); - } else { - output = null; - } return createResult(exitCode, output); } private int runToolProvider(PrintStream out, PrintStream err) { - trace("Execute " + getPrintableCommandLine() + "..."); + final var sb = new StringBuilder(getPrintableCommandLine()); + outputStreamsControl.describe().ifPresent(desc -> { + sb.append("; ").append(desc); + }); + trace("Execute " + sb + "..."); final int exitCode = toolProvider.run(out, err, args.toArray( String[]::new)); trace("Done. Exit code: " + exitCode); return exitCode; } - private Result createResult(int exitCode, List output) { - return new Result(exitCode, output, this::getPrintableCommandLine); + private Result runToolProvider() throws IOException { + final var toolProviderStreamConfig = ToolProviderStreamConfig.create(outputStreamsControl); + + final var exitCode = runToolProvider(toolProviderStreamConfig); + + final var output = combine( + read(outputStreamsControl.stdout(), toolProviderStreamConfig.out()), + read(outputStreamsControl.stderr(), toolProviderStreamConfig.err())); + return createResult(exitCode, output); } - private Result runToolProvider() throws IOException { - if (!withSavedOutput()) { - if (saveOutputType.contains(SaveOutputType.DUMP)) { - return createResult(runToolProvider(System.out, System.err), null); - } - - PrintStream nullPrintStream = new PrintStream(new OutputStream() { - @Override - public void write(int b) { - // Nop - } - }); - return createResult(runToolProvider(nullPrintStream, nullPrintStream), null); + private int runToolProvider(ToolProviderStreamConfig cfg) throws IOException { + try { + return runToolProvider(cfg.out().ps(), cfg.err().ps()); + } finally { + cfg.out().ps().flush(); + cfg.err().ps().flush(); } + } - try (ByteArrayOutputStream buf = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(buf)) { - final var exitCode = runToolProvider(ps, ps); - ps.flush(); - final List output; - final var bufAsString = buf.toString(); - try (BufferedReader bufReader = new BufferedReader(new StringReader( - bufAsString))) { - if (saveOutputType.contains(SaveOutputType.FIRST_LINE)) { - output = bufReader.lines().findFirst().map(List::of).orElseGet(List::of); - } else if (saveOutputType.contains(SaveOutputType.FULL)) { - output = bufReader.lines().collect(Collectors.toUnmodifiableList()); - } else { - output = null; - } - - if (saveOutputType.contains(SaveOutputType.DUMP)) { - Stream lines; - if (saveOutputType.contains(SaveOutputType.FULL)) { - lines = output.stream(); - } else { - lines = new BufferedReader(new StringReader(bufAsString)).lines(); - } - lines.forEach(System.out::println); + private static Optional> processProcessStream(OutputControl outputControl, InputStream in) throws IOException { + List outputLines = null; + try (final var bufReader = new BufferedReader(new InputStreamReader(in))) { + if (outputControl.dump() || outputControl.saveAll()) { + outputLines = bufReader.lines().toList(); + } else if (outputControl.saveFirstLine()) { + outputLines = Optional.ofNullable(bufReader.readLine()).map(List::of).orElseGet(List::of); + // Read all input, or the started process may exit with an error (cmd.exe does so). + bufReader.transferTo(Writer.nullWriter()); + } else { + // This should be empty input stream, fetch it anyway. + bufReader.transferTo(Writer.nullWriter()); + } + } finally { + if (outputControl.dump() && outputLines != null) { + outputLines.forEach(System.out::println); + if (outputControl.saveFirstLine()) { + outputLines = outputLines.stream().findFirst().map(List::of).orElseGet(List::of); } } - return createResult(exitCode, output); + if (!outputControl.save()) { + outputLines = null; + } } + return Optional.ofNullable(outputLines); + } + + private static Optional> read(OutputControl outputControl, CachingPrintStream cps) throws IOException { + final var bufferAsString = cps.bufferContents(); + try (final var bufReader = new BufferedReader(new StringReader(bufferAsString.orElse("")))) { + if (outputControl.saveFirstLine()) { + return Optional.of(bufReader.lines().findFirst().map(List::of).orElseGet(List::of)); + } else if (outputControl.saveAll()) { + return Optional.of(bufReader.lines().toList()); + } else if (bufferAsString.isPresent()) { + return Optional.of(List.of()); + } else { + return Optional.empty(); + } + } + } + + private CommandOutput combine(Optional> out, Optional> err) { + if (out.isEmpty() && err.isEmpty()) { + return new CommandOutput(); + } else if (out.isEmpty()) { + return new CommandOutput(err, -1); + } else if (err.isEmpty()) { + return new CommandOutput(out, Integer.MAX_VALUE); + } else { + final var combined = Stream.of(out, err).map(Optional::orElseThrow).flatMap(List::stream); + if (outputStreamsControl.stdout().saveFirstLine() && outputStreamsControl.stderr().saveFirstLine()) { + return new CommandOutput(Optional.of(combined.findFirst().map(List::of).orElseGet(List::of)), + Integer.min(1, out.orElseThrow().size())); + } else { + return new CommandOutput(Optional.of(combined.toList()), out.orElseThrow().size()); + } + } + } + + private Result createResult(int exitCode, CommandOutput output) { + return new Result(exitCode, output, this::getPrintableCommandLine); } public String getPrintableCommandLine() { @@ -539,16 +602,343 @@ public final class Executor extends CommandArguments { TKit.trace(String.format("exec: %s", msg)); } + private static PrintStream nullPrintStream() { + return new PrintStream(OutputStream.nullOutputStream()); + } + + private record OutputStreamsControl(OutputControl stdout, OutputControl stderr) { + OutputStreamsControl { + Objects.requireNonNull(stdout); + Objects.requireNonNull(stderr); + } + + OutputStreamsControl() { + this(new OutputControl(), new OutputControl()); + } + + void applyTo(ProcessBuilder pb) { + pb.redirectOutput(stdout.asProcessBuilderRedirect()); + pb.redirectError(stderr.asProcessBuilderRedirect()); + } + + Optional describe() { + final List tokens = new ArrayList<>(); + if (stdout.save() || stderr.save()) { + streamsLabel("save ", true).ifPresent(tokens::add); + } + if (stdout.dump() || stderr.dump()) { + streamsLabel("inherit ", true).ifPresent(tokens::add); + } + streamsLabel("discard ", false).ifPresent(tokens::add); + if (tokens.isEmpty()) { + return Optional.empty(); + } else { + return Optional.of(String.join("; ", tokens)); + } + } + + Optional streamsLabel(String prefix, boolean negate) { + Objects.requireNonNull(prefix); + final var str = Stream.of(stdoutLabel(negate), stderrLabel(negate)) + .filter(Optional::isPresent) + .map(Optional::orElseThrow) + .collect(joining("+")); + if (str.isEmpty()) { + return Optional.empty(); + } else { + return Optional.of(prefix + str); + } + } + + private Optional stdoutLabel(boolean negate) { + if ((stdout.discard() && !negate) || (!stdout.discard() && negate)) { + return Optional.of("out"); + } else { + return Optional.empty(); + } + } + + private Optional stderrLabel(boolean negate) { + if ((stderr.discard() && !negate) || (!stderr.discard() && negate)) { + return Optional.of("err"); + } else { + return Optional.empty(); + } + } + } + + private record CachingPrintStream(PrintStream ps, Optional buf) { + CachingPrintStream { + Objects.requireNonNull(ps); + Objects.requireNonNull(buf); + } + + Optional bufferContents() { + return buf.map(ByteArrayOutputStream::toString); + } + + static Builder build() { + return new Builder(); + } + + static final class Builder { + + Builder save(boolean v) { + save = v; + return this; + } + + Builder discard(boolean v) { + discard = v; + return this; + } + + Builder dumpStream(PrintStream v) { + dumpStream = v; + return this; + } + + CachingPrintStream create() { + final Optional buf; + if (save && !discard) { + buf = Optional.of(new ByteArrayOutputStream()); + } else { + buf = Optional.empty(); + } + + final PrintStream ps; + if (buf.isPresent() && dumpStream != null) { + ps = new PrintStream(new TeeOutputStream(List.of(buf.orElseThrow(), dumpStream)), true, dumpStream.charset()); + } else if (!discard) { + ps = buf.map(PrintStream::new).or(() -> Optional.ofNullable(dumpStream)).orElseGet(Executor::nullPrintStream); + } else { + ps = nullPrintStream(); + } + + return new CachingPrintStream(ps, buf); + } + + private boolean save; + private boolean discard; + private PrintStream dumpStream; + } + } + + private record ToolProviderStreamConfig(CachingPrintStream out, CachingPrintStream err) { + ToolProviderStreamConfig { + Objects.requireNonNull(out); + Objects.requireNonNull(err); + } + + static ToolProviderStreamConfig create(OutputStreamsControl cfg) { + final var errCfgBuilder = cfg.stderr().buildCachingPrintStream(System.err); + if (cfg.stderr().dump() && cfg.stderr().save()) { + errCfgBuilder.dumpStream(System.out); + } + return new ToolProviderStreamConfig( + cfg.stdout().buildCachingPrintStream(System.out).create(), errCfgBuilder.create()); + } + } + + private static final class OutputControl { + + boolean save() { + return save.isPresent(); + } + + boolean saveAll() { + return save.orElse(null) == OutputControlOption.SAVE_ALL; + } + + boolean saveFirstLine() { + return save.orElse(null) == OutputControlOption.SAVE_FIRST_LINE; + } + + boolean discard() { + return discard || (!dump && save.isEmpty()); + } + + boolean dump() { + return !discard && dump; + } + + OutputControl dump(boolean v) { + this.dump = v; + return this; + } + + OutputControl discard(boolean v) { + this.discard = v; + return this; + } + + OutputControl saveAll(boolean v) { + if (v) { + save = Optional.of(OutputControlOption.SAVE_ALL); + } else { + save = Optional.empty(); + } + return this; + } + + OutputControl saveFirstLine(boolean v) { + if (v) { + save = Optional.of(OutputControlOption.SAVE_FIRST_LINE); + } else { + save = Optional.empty(); + } + return this; + } + + OutputControl set(boolean set, OutputControlOption v) { + switch (v) { + case DUMP -> dump(set); + case SAVE_ALL -> saveAll(set); + case SAVE_FIRST_LINE -> saveFirstLine(set); + } + return this; + } + + ProcessBuilder.Redirect asProcessBuilderRedirect() { + if (discard()) { + return ProcessBuilder.Redirect.DISCARD; + } else if (dump && !save()) { + return ProcessBuilder.Redirect.INHERIT; + } else { + return ProcessBuilder.Redirect.PIPE; + } + } + + CachingPrintStream.Builder buildCachingPrintStream(PrintStream dumpStream) { + Objects.requireNonNull(dumpStream); + final var builder = CachingPrintStream.build().save(save()).discard(discard()); + if (dump()) { + builder.dumpStream(dumpStream); + } + return builder; + } + + private boolean dump; + private boolean discard; + private Optional save = Optional.empty(); + } + + private static final class TeeOutputStream extends OutputStream { + + public TeeOutputStream(Iterable streams) { + streams.forEach(Objects::requireNonNull); + this.streams = streams; + } + + @Override + public void write(int b) throws IOException { + for (final var out : streams) { + out.write(b); + } + } + + @Override + public void write(byte[] b) throws IOException { + for (final var out : streams) { + out.write(b); + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + for (final var out : streams) { + out.write(b, off, len); + } + } + + @Override + public void flush() throws IOException { + forEach(OutputStream::flush); + } + + @Override + public void close() throws IOException { + forEach(OutputStream::close); + } + + private void forEach(OutputStreamConsumer c) throws IOException { + IOException firstEx = null; + for (final var out : streams) { + try { + c.accept(out); + } catch (IOException e) { + if (firstEx == null) { + firstEx = e; + } + } + } + if (firstEx != null) { + throw firstEx; + } + } + + @FunctionalInterface + private static interface OutputStreamConsumer { + void accept(OutputStream out) throws IOException; + } + + private final Iterable streams; + } + + private static final class CommandOutput { + CommandOutput(Optional> lines, int stdoutLineCount) { + this.lines = Objects.requireNonNull(lines); + this.stdoutLineCount = stdoutLineCount; + } + + CommandOutput() { + this(Optional.empty(), 0); + } + + Optional> lines() { + return lines; + } + + Optional> stdoutLines() { + if (lines.isEmpty() || stdoutLineCount < 0) { + return Optional.empty(); + } + + final var theLines = lines.orElseThrow(); + if (stdoutLineCount == theLines.size()) { + return lines; + } else { + return Optional.of(theLines.subList(0, Integer.min(stdoutLineCount, theLines.size()))); + } + } + + Optional> stderrLines() { + if (lines.isEmpty() || stdoutLineCount > lines.orElseThrow().size()) { + return Optional.empty(); + } else if (stdoutLineCount == 0) { + return lines; + } else { + final var theLines = lines.orElseThrow(); + return Optional.of(theLines.subList(stdoutLineCount, theLines.size())); + } + } + + private final Optional> lines; + private final int stdoutLineCount; + + static final CommandOutput EMPTY = new CommandOutput(); + } + private ToolProvider toolProvider; private Path executable; - private Set saveOutputType; + private OutputStreamsControl outputStreamsControl; private Path directory; private Set removeEnvVars = new HashSet<>(); private Map setEnvVars = new HashMap<>(); private boolean winEnglishOutput; private String winTmpDir = null; - private static enum SaveOutputType { - NONE, FULL, FIRST_LINE, DUMP - }; + private static enum OutputControlOption { + SAVE_ALL, SAVE_FIRST_LINE, DUMP + } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index b4d2d1872eb..cb9e3a687c7 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -67,6 +67,8 @@ public class JPackageCommand extends CommandArguments { args.addAll(cmd.args); withToolProvider = cmd.withToolProvider; saveConsoleOutput = cmd.saveConsoleOutput; + discardStdout = cmd.discardStdout; + discardStderr = cmd.discardStderr; suppressOutput = cmd.suppressOutput; ignoreDefaultRuntime = cmd.ignoreDefaultRuntime; ignoreDefaultVerbose = cmd.ignoreDefaultVerbose; @@ -679,6 +681,18 @@ public class JPackageCommand extends CommandArguments { return this; } + public JPackageCommand discardStdout(boolean v) { + verifyMutable(); + discardStdout = v; + return this; + } + + public JPackageCommand discardStderr(boolean v) { + verifyMutable(); + discardStderr = v; + return this; + } + public JPackageCommand dumpOutput(boolean v) { verifyMutable(); suppressOutput = !v; @@ -770,6 +784,7 @@ public class JPackageCommand extends CommandArguments { private Executor createExecutor() { Executor exec = new Executor() .saveOutput(saveConsoleOutput).dumpOutput(!suppressOutput) + .discardStdout(discardStdout).discardStderr(discardStderr) .setDirectory(executeInDirectory) .addArguments(args); @@ -1272,6 +1287,8 @@ public class JPackageCommand extends CommandArguments { private Boolean withToolProvider; private boolean saveConsoleOutput; + private boolean discardStdout; + private boolean discardStderr; private boolean suppressOutput; private boolean ignoreDefaultRuntime; private boolean ignoreDefaultVerbose; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index bc67f6e417d..1c6ac9a7669 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -323,18 +323,19 @@ public class WindowsHelper { private static long[] findAppLauncherPIDs(JPackageCommand cmd, String launcherName) { // Get the list of PIDs and PPIDs of app launcher processes. Run setWinRunWithEnglishOutput(true) for JDK-8344275. // wmic process where (name = "foo.exe") get ProcessID,ParentProcessID - List output = Executor.of("wmic", "process", "where", "(name", + final var result = Executor.of("wmic", "process", "where", "(name", "=", "\"" + cmd.appLauncherPath(launcherName).getFileName().toString() + "\"", ")", "get", "ProcessID,ParentProcessID").dumpOutput(true).saveOutput(). - setWinRunWithEnglishOutput(true).executeAndGetOutput(); - if ("No Instance(s) Available.".equals(output.getFirst().trim())) { + setWinRunWithEnglishOutput(true).execute(); + if ("No Instance(s) Available.".equals(result.stderr().findFirstLineOfOutput().map(String::trim).orElse(""))) { return new long[0]; } - String[] headers = Stream.of(output.getFirst().split("\\s+", 2)).map( + final var stdout = result.stdout(); + String[] headers = Stream.of(stdout.getFirstLineOfOutput().split("\\s+", 2)).map( String::trim).map(String::toLowerCase).toArray(String[]::new); - Pattern pattern; + final Pattern pattern; if (headers[0].equals("parentprocessid") && headers[1].equals( "processid")) { pattern = Pattern.compile("^(?\\d+)\\s+(?\\d+)\\s+$"); @@ -346,7 +347,7 @@ public class WindowsHelper { "Unrecognizable output of \'wmic process\' command"); } - List processes = output.stream().skip(1).map(line -> { + List processes = stdout.getOutput().stream().skip(1).map(line -> { Matcher m = pattern.matcher(line); long[] pids = null; if (m.matches()) { diff --git a/test/jdk/tools/jpackage/share/BasicTest.java b/test/jdk/tools/jpackage/share/BasicTest.java index 68c1b2c76cb..bfcfe7587d4 100644 --- a/test/jdk/tools/jpackage/share/BasicTest.java +++ b/test/jdk/tools/jpackage/share/BasicTest.java @@ -237,20 +237,21 @@ public final class BasicTest { final var cmd = JPackageCommand.helloAppImage() .ignoreDefaultVerbose(true) .useToolProvider(false) + .discardStdout(true) .removeArgumentWithValue("--main-class"); if (verbose) { cmd.addArgument("--verbose"); } - final var textVerifier = Stream.of( + cmd.validateOutput(Stream.of( List.of("error.no-main-class-with-main-jar", "hello.jar"), List.of("error.no-main-class-with-main-jar.advice", "hello.jar") ).map(args -> { return JPackageStringBundle.MAIN.cannedFormattedString(args.getFirst(), args.subList(1, args.size()).toArray()); - }).map(CannedFormattedString::getValue).map(TKit::assertTextStream).reduce(TKit.TextStreamVerifier::andThen).orElseThrow(); + }).toArray(CannedFormattedString[]::new)); - textVerifier.apply(cmd.saveConsoleOutput(true).execute(1).getOutput().stream().filter(Predicate.not(JPackageCommand::withTimestamp))); + cmd.execute(1); } @Test diff --git a/test/jdk/tools/jpackage/windows/Win8301247Test.java b/test/jdk/tools/jpackage/windows/Win8301247Test.java index b0c11147a17..2f98141dcb4 100644 --- a/test/jdk/tools/jpackage/windows/Win8301247Test.java +++ b/test/jdk/tools/jpackage/windows/Win8301247Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,14 +21,12 @@ * questions. */ -import java.io.IOException; +import static jdk.jpackage.test.WindowsHelper.killAppLauncherProcess; + import java.time.Duration; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.HelloApp; -import static jdk.jpackage.test.WindowsHelper.killAppLauncherProcess; +import jdk.jpackage.test.JPackageCommand; /** * Test that terminating of the parent app launcher process automatically @@ -48,7 +46,7 @@ import static jdk.jpackage.test.WindowsHelper.killAppLauncherProcess; public class Win8301247Test { @Test - public void test() throws IOException, InterruptedException { + public void test() throws InterruptedException { var cmd = JPackageCommand.helloAppImage().ignoreFakeRuntime(); // Launch the app in a way it doesn't exit to let us trap app laucnher @@ -56,22 +54,20 @@ public class Win8301247Test { cmd.addArguments("--java-options", "-Djpackage.test.noexit=true"); cmd.executeAndAssertImageCreated(); - try ( // Launch the app in a separate thread - ExecutorService exec = Executors.newSingleThreadExecutor()) { - exec.execute(() -> { - HelloApp.executeLauncher(cmd); - }); + // Launch the app in a separate thread + new Thread(() -> { + HelloApp.executeLauncher(cmd); + }).start(); - // Wait a bit to let the app start - Thread.sleep(Duration.ofSeconds(10)); + // Wait a bit to let the app start + Thread.sleep(Duration.ofSeconds(10)); - // Find the main app launcher process and kill it - killAppLauncherProcess(cmd, null, 2); + // Find the main app launcher process and kill it + killAppLauncherProcess(cmd, null, 2); - // Wait a bit and check if child app launcher process is still running (it must NOT) - Thread.sleep(Duration.ofSeconds(5)); + // Wait a bit and check if child app launcher process is still running (it must NOT) + Thread.sleep(Duration.ofSeconds(5)); - killAppLauncherProcess(cmd, null, 0); - } + killAppLauncherProcess(cmd, null, 0); } } From bb08a70bd8deadc9c7522d1ce2ec779d5a6bd986 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 18 Apr 2025 17:01:42 +0000 Subject: [PATCH 251/843] 8355002: Clean up some mentions of "applet" in tests Reviewed-by: serb --- .../ChoiceLocationTest.java | 2 +- .../Dialog/CloseDialog/CloseDialogTest.java | 2 +- .../awt/Focus/ChoiceFocus/ChoiceFocus.java | 1 - .../FirstItemRemoveTest.java | 2 +- .../FocusEmptyListTest.java | 2 +- .../GetMousePositionWithOverlay.java | 2 +- .../GetMousePositionWithPopup.java | 4 +- .../PageSetupDlgBlockingTest.java | 1 - .../jdk/java/awt/TextArea/TextScrollTest.java | 2 +- .../DragUnicodeBetweenJVMTest.java | 1 - .../MissedHtmlAndRtfBug.java | 1 - .../DnDFileGroupDescriptor.java | 2 +- .../FileListBetweenJVMsTest.java | 1 - .../URIListBetweenJVMsTest.java | 1 - .../URIListToFileListBetweenJVMsTest.java | 1 - .../MenuDragMouseEventAbsoluteCoordsTest.java | 2 +- .../InfiniteRecursion_2.java | 12 +- .../InfiniteRecursion_3.java | 8 +- .../event/helpers/lwcomponents/LWButton.java | 12 +- .../EmbeddedFrameTest1.java | 4 +- test/jdk/java/awt/im/8041990/bug8041990.java | 2 +- .../java/awt/print/Dialog/DialogOrient.java | 3 - .../awt/print/PrinterJob/PrintDialog.java | 3 - .../print/PrinterJob/PrintDialogCancel.java | 3 - .../java/awt/print/PrinterJob/ThinLines.java | 3 - .../java/awt/regtesthelpers/AbstractTest.java | 2 - test/jdk/java/awt/regtesthelpers/Util.java | 2 - .../process/ProcessCommunicator.java | 2 +- .../sound/sampled/Clip/ClipFlushCrash.java | 2 +- .../sound/sampled/LinuxBlock/PlaySine.java | 2 +- .../javax/swing/JPopupMenu/bug4212464.java | 1 - .../swing/JTextArea/4697612/bug4697612.java | 2 +- .../swing/JTextArea/4697612/bug4697612.txt | 221 ------------------ .../parser/Parser/6990651/bug6990651.java | 2 +- .../SwingMark/src/AbstractSwingTest.java | 9 - .../client/SwingMark/src/JMTest_01.java | 8 - .../client/SwingMark/src/JMTest_02.java | 8 - .../client/SwingMark/src/JMTest_03.java | 8 - .../client/SwingMark/src/JMTest_04.java | 8 - .../client/SwingMark/src/JMTest_05.java | 8 - .../client/SwingMark/src/MenuTest.java | 8 - .../client/SwingMark/src/TypingTest.java | 4 - 42 files changed, 28 insertions(+), 346 deletions(-) delete mode 100644 test/jdk/javax/swing/JTextArea/4697612/bug4697612.txt diff --git a/test/jdk/java/awt/Choice/ChoiceLocationTest/ChoiceLocationTest.java b/test/jdk/java/awt/Choice/ChoiceLocationTest/ChoiceLocationTest.java index 78c83185cbe..5bff03d5b34 100644 --- a/test/jdk/java/awt/Choice/ChoiceLocationTest/ChoiceLocationTest.java +++ b/test/jdk/java/awt/Choice/ChoiceLocationTest/ChoiceLocationTest.java @@ -25,7 +25,7 @@ * @test * @key headful * @bug 7159566 - * @summary The choice positioned in the top of applet when clicking the choice. + * @summary The choice positioned in the top of window when clicking the choice. * @author Petr Pchelko * @library ../../regtesthelpers * @build Util diff --git a/test/jdk/java/awt/Dialog/CloseDialog/CloseDialogTest.java b/test/jdk/java/awt/Dialog/CloseDialog/CloseDialogTest.java index 4db2d52e4ea..93bf59d2757 100644 --- a/test/jdk/java/awt/Dialog/CloseDialog/CloseDialogTest.java +++ b/test/jdk/java/awt/Dialog/CloseDialog/CloseDialogTest.java @@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicReference; * @test * @key headful * @bug 8043705 - * @summary Can't exit color chooser dialog when running as an applet + * @summary Can't exit color chooser dialog when running in non-default AppContext * @modules java.desktop/sun.awt * @run main CloseDialogTest */ diff --git a/test/jdk/java/awt/Focus/ChoiceFocus/ChoiceFocus.java b/test/jdk/java/awt/Focus/ChoiceFocus/ChoiceFocus.java index 904992f96b2..2456379f0f9 100644 --- a/test/jdk/java/awt/Focus/ChoiceFocus/ChoiceFocus.java +++ b/test/jdk/java/awt/Focus/ChoiceFocus/ChoiceFocus.java @@ -32,7 +32,6 @@ @run main ChoiceFocus */ -import java.applet.*; import java.awt.*; import java.awt.event.*; import test.java.awt.regtesthelpers.Util; diff --git a/test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.java b/test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.java index 1efcee3e675..69bd1dd6c83 100644 --- a/test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.java +++ b/test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.java @@ -127,4 +127,4 @@ public class FirstItemRemoveTest extends Frame } -}// class AutomaticAppletTest +} diff --git a/test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java b/test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java index 67926b5fe19..1b1d4e4b5c4 100644 --- a/test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java +++ b/test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java @@ -99,4 +99,4 @@ public class FocusEmptyListTest extends Frame { }// start() -}// class AutomaticAppletTest +} diff --git a/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java b/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java index b380af149f6..fb3ea40a531 100644 --- a/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java +++ b/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java @@ -31,7 +31,7 @@ import javax.swing.SwingUtilities; * @test * @key headful * @bug 8012026 8196435 - * @summary Component.getMousePosition() does not work in an applet on MacOS + * @summary Component.getMousePosition() does not work in some cases on MacOS * @run main GetMousePositionWithOverlay */ diff --git a/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java b/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java index 5bfadc6fbe7..663942b7630 100644 --- a/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java +++ b/test/jdk/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java @@ -33,7 +33,7 @@ import javax.swing.SwingUtilities; * @test * @key headful * @bug 8012026 8027154 - * @summary Component.getMousePosition() does not work in an applet on MacOS + * @summary Component.getMousePosition() does not work in some cases on MacOS * * @requires (os.family == "windows") * @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1 GetMousePositionWithPopup @@ -48,7 +48,7 @@ import javax.swing.SwingUtilities; * @test * @key headful * @bug 8012026 8027154 - * @summary Component.getMousePosition() does not work in an applet on MacOS + * @summary Component.getMousePosition() does not work in some cases on MacOS * * @requires (os.family == "mac" | os.family == "linux") * @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1 GetMousePositionWithPopup diff --git a/test/jdk/java/awt/PrintJob/PageSetupDlgBlockingTest/PageSetupDlgBlockingTest.java b/test/jdk/java/awt/PrintJob/PageSetupDlgBlockingTest/PageSetupDlgBlockingTest.java index 9fbf48f3eb4..bc392ab9efe 100644 --- a/test/jdk/java/awt/PrintJob/PageSetupDlgBlockingTest/PageSetupDlgBlockingTest.java +++ b/test/jdk/java/awt/PrintJob/PageSetupDlgBlockingTest/PageSetupDlgBlockingTest.java @@ -34,7 +34,6 @@ import java.awt.*; import java.awt.print.*; import java.awt.event.*; import javax.swing.*; -import java.applet.*; public class PageSetupDlgBlockingTest extends Panel { public static Frame frame = new TestFrame("Test Frame"); diff --git a/test/jdk/java/awt/TextArea/TextScrollTest.java b/test/jdk/java/awt/TextArea/TextScrollTest.java index 4a92391e7af..fbd5c022580 100644 --- a/test/jdk/java/awt/TextArea/TextScrollTest.java +++ b/test/jdk/java/awt/TextArea/TextScrollTest.java @@ -38,7 +38,7 @@ import java.awt.TextArea; public class TextScrollTest extends Frame { private static final String INSTRUCTIONS = """ 1. A TextArea whose content starts with the text ", - 'Scroll till the' will appear on the applet ", + 'Scroll till the' will appear on the window ", 2. Use the Horizontal thumb button of the TextArea to view the entire", content of the TextArea", 3. While scrolling, if the text 'Scroll till the' appears repeatedly, Click Fail ", diff --git a/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java b/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java index 18159dce64f..aa785f54733 100644 --- a/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java +++ b/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java @@ -101,7 +101,6 @@ public class DragUnicodeBetweenJVMTest { processResults.printProcessStandartOutput(System.out); } - //We cannot make an instance of the applet without the default constructor public DragUnicodeBetweenJVMTest () { super(); } diff --git a/test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java b/test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java index 0254a3f0d41..3502cd4f9c5 100644 --- a/test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java +++ b/test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java @@ -123,7 +123,6 @@ public class MissedHtmlAndRtfBug { processResults.printProcessStandartOutput(System.out); } - //We cannot make an instance of the applet without the default constructor public MissedHtmlAndRtfBug() { super(); } diff --git a/test/jdk/java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.java b/test/jdk/java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.java index 51129f26408..b106deac73c 100644 --- a/test/jdk/java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.java +++ b/test/jdk/java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.java @@ -42,7 +42,7 @@ public class DnDFileGroupDescriptor { When the test starts, a RED panel appears. 1. Start MS Outlook program. Find and open the mail form with attachments. - 2. Select attachments from the mail and drag into a red field of applet. + 2. Select attachments from the mail and drag into a red field of the window. When the mouse enters the field during the process of drag, the application should change the cursor form to OLE-copy and field color to yellow. diff --git a/test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java b/test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java index 6fc7b9e049d..102ff501040 100644 --- a/test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java +++ b/test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java @@ -80,7 +80,6 @@ public class FileListBetweenJVMsTest { processResults.printProcessStandartOutput(System.out); } - //We cannot make an instance of the applet without the default constructor public FileListBetweenJVMsTest () { super(); } diff --git a/test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java b/test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java index e847752ee6a..6de649f846f 100644 --- a/test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java +++ b/test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java @@ -89,7 +89,6 @@ public class URIListBetweenJVMsTest { processResults.printProcessStandartOutput(System.out); } - //We cannot make an instance of the applet without the default constructor public URIListBetweenJVMsTest () { super(); } diff --git a/test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java b/test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java index f2e34493b8b..d9b6bd5e87c 100644 --- a/test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java +++ b/test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java @@ -77,7 +77,6 @@ public class URIListToFileListBetweenJVMsTest { processResults.printProcessStandartOutput(System.out); } - //We cannot make an instance of the applet without the default constructor public URIListToFileListBetweenJVMsTest() { super(); } diff --git a/test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.java b/test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.java index e0cfbaba1bb..41dc4709fc2 100644 --- a/test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.java +++ b/test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.java @@ -150,4 +150,4 @@ public class MenuDragMouseEventAbsoluteCoordsTest implements MouseListener } System.out.println(message); } -}// class AutomaticAppletTest +} diff --git a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.java b/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.java index 7db513eeac8..6022ed32094 100644 --- a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.java +++ b/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.java @@ -27,21 +27,17 @@ @bug 6480024 @library ../../../regtesthelpers @build Util Sysout AbstractTest - @summary stack overflow on mouse wheel rotation within JApplet + @summary stack overflow on mouse wheel rotation within a Window @run main InfiniteRecursion_2 */ /** * InfiniteRecursion_2.java * - * summary: put a JButton into JPanel and then put JPanel into Applet. - * Add MouseWheelListener to Applet. + * summary: put a JButton into JPanel and then put JPanel into the Window. + * Add MouseWheelListener to the Window * Add MouseListener to JPanel. * Rotating a wheel over the JButton would result in stack overflow. - - * summary: put a JButton into JApplet. - * Add MouseWheelListener to JApplet. - * Rotating a wheel over the JButton would result in stack overflow. */ import java.awt.*; @@ -79,7 +75,7 @@ public class InfiniteRecursion_2 extends Frame { this.addMouseWheelListener(new MouseWheelListener() { public void mouseWheelMoved(MouseWheelEvent e) { - System.out.println("Wheel moved on APPLET : "+e); + System.out.println("Wheel moved on Window : "+e); actualEvents++; } }); diff --git a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.java b/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.java index 911e7c10864..e1f2991a2fb 100644 --- a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.java +++ b/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.java @@ -27,15 +27,15 @@ @bug 6480024 @library ../../../regtesthelpers @build Util Sysout AbstractTest - @summary stack overflow on mouse wheel rotation within JApplet + @summary stack overflow on mouse wheel rotation within a Window @run main InfiniteRecursion_3 */ /** * InfiniteRecursion_3.java * - * summary: put a JButton into Applet. - * Add MouseWheelListener to Applet. + * summary: put a JButton into the Window. + * Add MouseWheelListener to the Window. * Rotating a wheel over the JButton would result in stack overflow. */ @@ -72,7 +72,7 @@ public class InfiniteRecursion_3 extends Frame { this.addMouseWheelListener(new MouseWheelListener() { public void mouseWheelMoved(MouseWheelEvent e) { - System.out.println("Wheel moved on APPLET : "+e); + System.out.println("Wheel moved on Window : "+e); actualEvents++; } }); diff --git a/test/jdk/java/awt/event/helpers/lwcomponents/LWButton.java b/test/jdk/java/awt/event/helpers/lwcomponents/LWButton.java index 866844e1ce7..e45d3d5f430 100644 --- a/test/jdk/java/awt/event/helpers/lwcomponents/LWButton.java +++ b/test/jdk/java/awt/event/helpers/lwcomponents/LWButton.java @@ -116,16 +116,8 @@ public class LWButton extends LWComponent { repaint(); } } - try { - unClicker uc = new unClicker(); - new Thread(uc).start(); - } catch (Exception e) { - // In case we're in an applet and the security has not been - // turned off (in which case we can't start a new thread) - // we can catch that and set the flag back to how it should be. - isInClick = false; - repaint(); - } + unClicker uc = new unClicker(); + new Thread(uc).start(); } /** diff --git a/test/jdk/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java b/test/jdk/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java index fd2acaad396..7942402af4f 100644 --- a/test/jdk/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java +++ b/test/jdk/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java @@ -25,7 +25,7 @@ @test @key headful @bug 6359129 - @summary REGRESSION: Popup menus dont respond to selections when extend outside Applet + @summary REGRESSION: Popup menus dont respond to selections when extend outside EmbeddedFrame @author oleg.sukhodolsky area=awt.grab @modules java.desktop/java.awt.peer java.desktop/sun.awt @@ -38,7 +38,7 @@ /** * EmbeddedFrameTest1.java * - * summary: REGRESSION: Popup menus dont respond to selections when extend outside Applet + * summary: REGRESSION: Popup menus dont respond to selections when extend outside EmbeddedFrame */ import java.awt.BorderLayout; diff --git a/test/jdk/java/awt/im/8041990/bug8041990.java b/test/jdk/java/awt/im/8041990/bug8041990.java index 303fde5a459..d4bf847592d 100644 --- a/test/jdk/java/awt/im/8041990/bug8041990.java +++ b/test/jdk/java/awt/im/8041990/bug8041990.java @@ -26,7 +26,7 @@ * @test * @key headful * @bug 8041990 - * @summary Language specific keys does not work in applets when opened outside the browser + * @summary Language specific keys does not work in non-default AppContexts of top-level windows * @author Petr Pchelko * @modules java.desktop/sun.awt */ diff --git a/test/jdk/java/awt/print/Dialog/DialogOrient.java b/test/jdk/java/awt/print/Dialog/DialogOrient.java index 6650ced64f4..b89f3950e99 100644 --- a/test/jdk/java/awt/print/Dialog/DialogOrient.java +++ b/test/jdk/java/awt/print/Dialog/DialogOrient.java @@ -34,9 +34,6 @@ import java.awt.event.*; import java.awt.geom.*; import java.awt.print.*; -// This test is a "main" test as applets would need Runtime permission -// "queuePrintJob". - public class DialogOrient implements Printable { private static void init() throws Exception { diff --git a/test/jdk/java/awt/print/PrinterJob/PrintDialog.java b/test/jdk/java/awt/print/PrinterJob/PrintDialog.java index fa9569e1aa7..395312aaa45 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintDialog.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintDialog.java @@ -42,9 +42,6 @@ import java.awt.*; import java.awt.event.*; import java.awt.print.*; -// This test is a "main" test as applets would need Runtime permission -// "queuePrintJob". - public class PrintDialog { diff --git a/test/jdk/java/awt/print/PrinterJob/PrintDialogCancel.java b/test/jdk/java/awt/print/PrinterJob/PrintDialogCancel.java index b2d3d3a2230..9a1884a5f54 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintDialogCancel.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintDialogCancel.java @@ -43,9 +43,6 @@ import java.awt.*; import java.awt.event.*; import java.awt.print.*; -// This test is a "main" test as applets would need Runtime permission -// "queuePrintJob". - public class PrintDialogCancel { diff --git a/test/jdk/java/awt/print/PrinterJob/ThinLines.java b/test/jdk/java/awt/print/PrinterJob/ThinLines.java index f8e4e60b319..95cbfed8796 100644 --- a/test/jdk/java/awt/print/PrinterJob/ThinLines.java +++ b/test/jdk/java/awt/print/PrinterJob/ThinLines.java @@ -42,9 +42,6 @@ import java.awt.*; import java.awt.event.*; import java.awt.print.*; -// This test is a "main" test as applets would need Runtime permission -// "queuePrintJob". - public class ThinLines implements Printable { private static final int INCH = 72; diff --git a/test/jdk/java/awt/regtesthelpers/AbstractTest.java b/test/jdk/java/awt/regtesthelpers/AbstractTest.java index f5c34cc6fbd..fbf66e45e3b 100644 --- a/test/jdk/java/awt/regtesthelpers/AbstractTest.java +++ b/test/jdk/java/awt/regtesthelpers/AbstractTest.java @@ -30,8 +30,6 @@ @build AbstractTest @run main YourTest - * Note that if you are about to create a test based on - * Applet-template, then put those lines into html-file, not in java-file. *

And put an * import test.java.awt.regtesthelpers.AbstractTest; * into the java source. diff --git a/test/jdk/java/awt/regtesthelpers/Util.java b/test/jdk/java/awt/regtesthelpers/Util.java index 6d570e903b6..45d9c89ee46 100644 --- a/test/jdk/java/awt/regtesthelpers/Util.java +++ b/test/jdk/java/awt/regtesthelpers/Util.java @@ -31,8 +31,6 @@ package test.java.awt.regtesthelpers; @build Util @run main YourTest - * Note that if you are about to create a test based on - * Applet-template, then put those lines into html-file, not in java-file. *

And put an * import test.java.awt.regtesthelpers.Util; * into the java source of test. diff --git a/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java b/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java index d6806947af2..3b173009d23 100644 --- a/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java +++ b/test/jdk/java/awt/regtesthelpers/process/ProcessCommunicator.java @@ -31,7 +31,7 @@ import java.io.*; * behavior such as DnD data transfer, Clipboard data transfer, focus * transfer etc., you could use the next scenario: * - * 1. Write an implementation for the parent JVM, using applet test. + * 1. Write an implementation for the parent JVM * 2. Write an implementation for the child JVM or native application, using * main() function. * 3. Execute child process using ProcessCommunicator.executeChildProcess() diff --git a/test/jdk/javax/sound/sampled/Clip/ClipFlushCrash.java b/test/jdk/javax/sound/sampled/Clip/ClipFlushCrash.java index a72509fdf53..2baeb499eac 100644 --- a/test/jdk/javax/sound/sampled/Clip/ClipFlushCrash.java +++ b/test/jdk/javax/sound/sampled/Clip/ClipFlushCrash.java @@ -35,7 +35,7 @@ import javax.sound.sampled.Mixer; * @test * @key sound * @bug 4946945 - * @summary Crash in javasound while running TicTacToe demo applet tiger b26 + * @summary Crash in javasound while running TicTacToe demo tiger b26 */ public class ClipFlushCrash { static int frameCount = 441000; // lets say 10 seconds diff --git a/test/jdk/javax/sound/sampled/LinuxBlock/PlaySine.java b/test/jdk/javax/sound/sampled/LinuxBlock/PlaySine.java index ab567dacb23..ceead0dae62 100644 --- a/test/jdk/javax/sound/sampled/LinuxBlock/PlaySine.java +++ b/test/jdk/javax/sound/sampled/LinuxBlock/PlaySine.java @@ -36,7 +36,7 @@ import javax.sound.sampled.SourceDataLine; * @test * @key sound * @bug 4834461 - * @summary Applet hang when you load it during sound card is in use + * @summary App hang when you load it during sound card is in use * @run main/manual PlaySine */ public class PlaySine { diff --git a/test/jdk/javax/swing/JPopupMenu/bug4212464.java b/test/jdk/javax/swing/JPopupMenu/bug4212464.java index c1c434f6b16..cbfecc989cc 100644 --- a/test/jdk/javax/swing/JPopupMenu/bug4212464.java +++ b/test/jdk/javax/swing/JPopupMenu/bug4212464.java @@ -36,7 +36,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; diff --git a/test/jdk/javax/swing/JTextArea/4697612/bug4697612.java b/test/jdk/javax/swing/JTextArea/4697612/bug4697612.java index ed7f3dba73f..ee01c38ed67 100644 --- a/test/jdk/javax/swing/JTextArea/4697612/bug4697612.java +++ b/test/jdk/javax/swing/JTextArea/4697612/bug4697612.java @@ -224,7 +224,7 @@ public class bug4697612 { text = new JTextArea(); try { InputStream is = - bug4697612.class.getResourceAsStream("bug4697612.txt"); + bug4697612.class.getResourceAsStream("bug4697612.java"); text.read(new InputStreamReader(is), null); } catch (IOException e) { throw new Error(e); diff --git a/test/jdk/javax/swing/JTextArea/4697612/bug4697612.txt b/test/jdk/javax/swing/JTextArea/4697612/bug4697612.txt deleted file mode 100644 index f7273541285..00000000000 --- a/test/jdk/javax/swing/JTextArea/4697612/bug4697612.txt +++ /dev/null @@ -1,221 +0,0 @@ - README - - Java(TM) 2 SDK, Standard Edition - Version 1.4.2 Beta - - For a more extensive HTML version of this file, see README.html. - -Contents - - * Introduction - * Release Notes - * Bug Reports and Feedback - * Java 2 SDK Documentation - * Redistribution - * Web Pages - - -Introduction - - Thank you for downloading this release of the Java(TM) 2 SDK, - Standard Edition. The Java 2 SDK is a development environment for - building applications, applets, and components that can be - deployed on the Java platform. - - The Java 2 SDK software includes tools useful for developing and - testing programs written in the Java programming language and - running on the Java platform. These tools are designed to be used - from the command line. Except for appletviewer, these tools do not - provide a graphical user interface. - - -Release Notes - - See the Release Notes on the Java Software web site for additional - information pertaining to this release. - - http://java.sun.com/j2se/1.4.2/relnotes.html - - The on-line release notes will be updated as needed, so you should - check it occasionally for the latest information. - - -Bug Reports and Feedback - - The Bug Parade Web Page on the Java Developer Connection(SM) web - site lets you search for and examine existing bug reports, submit - your own bug reports, and tell us which bug fixes matter most to you. - - http://java.sun.com/jdc/bugParade/ - - To directly submit a bug or request a feature, fill out this form: - - http://java.sun.com/cgi-bin/bugreport.cgi - - You can also send comments directly to Java Software engineering - team email addresses. - - http://java.sun.com/mail/ - - -Java 2 SDK Documentation - - The on-line Java 2 SDK Documentation contains API specifications, - feature descriptions, developer guides, tool reference pages, demos, - and links to related information. It is located at - - http://java.sun.com/j2se/1.4.2/docs/ - - The Java 2 SDK documentation is also available in a download bundle - which you can install locally on your machine. See the - Java 2 SDK download page: - - http://java.sun.com/j2se/1.4.2/download.html - - -Redistribution - - The term "vendors" used here refers to licensees, developers, - and independent software vendors (ISVs) who license and - distribute the Java 2 Runtime Environment with their programs. - Vendors must follow the terms of the Java 2 SDK, Standard - Edition, Binary Code License agreement. - Required vs. Optional Files - - The files that make up the Java 2 SDK, Standard Edition, are - divided into two categories: required and optional. Optional - files may be excluded from redistributions of the Java 2 SDK - at the vendor's discretion. The following section contains a - list of the files and directories that may optionally be - omitted from redistributions of the Java 2 SDK. All files not - in these lists of optional files must be included in - redistributions of the Java 2 SDK. - - Optional Files and Directories - - The following files may be optionally excluded from - redistributions: - - jre/lib/charsets.jar - Character conversion classes - jre/lib/ext/ - sunjce_provider.jar - the SunJCE provider for Java - Cryptography APIs - localedata.jar - contains many of the resources - needed for non US English locales - ldapsec.jar - contains security features supported - by the LDAP service provider - dnsns.jar - for the InetAddress wrapper of JNDI DNS - provider - bin/rmid and jre/bin/rmid - Java RMI Activation System Daemon - bin/rmiregistry and jre/bin/rmiregistry - Java Remote Object Registry - bin/tnameserv and jre/bin/tnameserv - Java IDL Name Server - bin/keytool and jre/bin/keytool - Key and Certificate Management Tool - bin/kinit and jre/bin/kinit - Used to obtain and cache Kerberos ticket-granting tickets - bin/klist and jre/bin/klist - Kerberos display entries in credentials cache and keytab - bin/ktab and jre/bin/ktab - Kerberos key table manager - bin/policytool and jre/bin/policytool - Policy File Creation and Management Tool - bin/orbd and jre/bin/orbd - Object Request Broker Daemon - bin/servertool and jre/bin/servertool - Java IDL Server Tool - src.zip - Archive of source files - - In addition, the Java Web Start product may be excluded from - redistributions. The Java Web Start product is contained in a - file named javaws-1_2-solaris-sparc-i.zip, - javaws-1_2-solaris-i586-i.zip, - javaws-1_2-linux-i586-i.zip, or - javaws-1_2-windows-i586-i.exe, depending on the platform. - - - Unlimited Strength Java Cryptography Extension - - Due to import control restrictions for some countries, the - Java Cryptography Extension (JCE) policy files shipped with - the Java 2 SDK, Standard Edition and the Java 2 Runtime - Environment allow strong but limited cryptography to be - used. These files are located at - - /lib/security/local_policy.jar - /lib/security/US_export_policy.jar - - where is the jre directory of the Java 2 - SDK or the top-level directory of the Java 2 Runtime - Environment. - - An unlimited strength version of these files indicating - no restrictions on cryptographic strengths is available - on the Java 2 SDK web site for those living in eligible - countries. Those living in eligible countries may download - the unlimited strength version and replace the strong - cryptography jar files with the unlimited strength files. - - - Endorsed Standards Override Mechanism - - An endorsed standard is a Java API defined through a standards - process other than the Java Community Process(SM) (JCP(SM)). - Because endorsed standards are defined outside the JCP, it is - anticipated that such standards will be revised between - releases of the Java 2 Platform. In order to take advantage of - new revisions to endorsed standards, developers and software - vendors may use the Endorsed Standards Override Mechanism to - provide newer versions of an endorsed standard than those - included in the Java 2 Platform as released by Sun Microsystems. - - For more information on the Endorsed Standards Override - Mechanism, including the list of platform packages that it may - be used to override, see - - http://java.sun.com/j2se/1.4.2/docs/guide/standards/ - - Classes in the packages listed on that web page may be replaced - only by classes implementing a more recent version of the API - as defined by the appropriate standards body. - - In addition to the packages listed in the document at the above - URL, which are part of the Java 2 Platform, Standard Edition - (J2SE(TM)) specification, redistributors of Sun's J2SE - Reference Implementation are allowed to override classes whose - sole purpose is to implement the functionality provided by - public APIs defined in these Endorsed Standards packages. - Redistributors may also override classes in the org.w3c.dom.* - packages, or other classes whose sole purpose is to implement - these APIs. - - -Sun Java Web Pages - - For additional information, refer to these Sun Microsystems pages - on the World Wide Web: - - http://java.sun.com/ - The Java Software web site, with the latest information on - Java technology, product information, news, and features. - http://java.sun.com/docs - Java Platform Documentation provides access to white papers, - the Java Tutorial and other documents. - http://java.sun.com/jdc - The Java Developer Connection(SM) web site. (Free registration - required.) Additional technical information, news, and - features; user forums; support information, and much more. - http://java.sun.com/products/ - Java Technology Products & API - - ------------------------------------------------------------------------- -The Java 2 SDK, Standard Edition, is a product of Sun Microsystems(TM), -Inc. This product includes code licensed from RSA Security. - -Copyright 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -California 95054, U.S.A. All rights reserved. diff --git a/test/jdk/javax/swing/text/html/parser/Parser/6990651/bug6990651.java b/test/jdk/javax/swing/text/html/parser/Parser/6990651/bug6990651.java index b939f3e148f..9dada22ba60 100644 --- a/test/jdk/javax/swing/text/html/parser/Parser/6990651/bug6990651.java +++ b/test/jdk/javax/swing/text/html/parser/Parser/6990651/bug6990651.java @@ -23,7 +23,7 @@ /* @test @bug 6990651 - @summary Regression: NPE when refreshing applet since 6u22-b01 + @summary Regression: NPE when refreshing embedded window since 6u22-b01 @author Pavel Porvatov @modules java.desktop/sun.awt */ diff --git a/test/jdk/performance/client/SwingMark/src/AbstractSwingTest.java b/test/jdk/performance/client/SwingMark/src/AbstractSwingTest.java index 52394054f29..8a62d196857 100644 --- a/test/jdk/performance/client/SwingMark/src/AbstractSwingTest.java +++ b/test/jdk/performance/client/SwingMark/src/AbstractSwingTest.java @@ -86,15 +86,6 @@ public abstract class AbstractSwingTest { */ public abstract void runTest(); - /** - * This method is used to determine if a test can be run from within - * an applet. If your test will cause security exceptions when run as - * an applet then you should return false from this method. - */ - public boolean canRunInApplet() { - return true; - } - public int getPaintCount() { return paintCount; } diff --git a/test/jdk/performance/client/SwingMark/src/JMTest_01.java b/test/jdk/performance/client/SwingMark/src/JMTest_01.java index 83127e3bc21..fcc5fe309ba 100644 --- a/test/jdk/performance/client/SwingMark/src/JMTest_01.java +++ b/test/jdk/performance/client/SwingMark/src/JMTest_01.java @@ -66,14 +66,6 @@ public class JMTest_01 extends AbstractSwingTest { int DOWN = 40; int UP = 38; - /** - * This test cannot run as an applet because it - * posts events to the event queue - */ - public boolean canRunInApplet() { - return false; - } - public JComponent getTestComponent() { JPanel panel = new JPanel(); diff --git a/test/jdk/performance/client/SwingMark/src/JMTest_02.java b/test/jdk/performance/client/SwingMark/src/JMTest_02.java index b77844162ab..680ada9f1df 100644 --- a/test/jdk/performance/client/SwingMark/src/JMTest_02.java +++ b/test/jdk/performance/client/SwingMark/src/JMTest_02.java @@ -67,14 +67,6 @@ public class JMTest_02 extends AbstractSwingTest { int repeat = 15; - /** - * This test cannot run as an applet because it - * posts events to the event queue - */ - public boolean canRunInApplet() { - return false; - } - public JComponent getTestComponent() { JPanel panel = new JPanel(); diff --git a/test/jdk/performance/client/SwingMark/src/JMTest_03.java b/test/jdk/performance/client/SwingMark/src/JMTest_03.java index eed96da1e93..38f5dff43bc 100644 --- a/test/jdk/performance/client/SwingMark/src/JMTest_03.java +++ b/test/jdk/performance/client/SwingMark/src/JMTest_03.java @@ -65,14 +65,6 @@ public class JMTest_03 extends AbstractSwingTest { int DOWN = 40; int UP = 38; - /** - * This test cannot run as an applet because it - * posts events to the event queue - */ - public boolean canRunInApplet() { - return false; - } - public JComponent getTestComponent() { JPanel panel = new JPanel(); diff --git a/test/jdk/performance/client/SwingMark/src/JMTest_04.java b/test/jdk/performance/client/SwingMark/src/JMTest_04.java index 4c4c7f65d32..cbb32e5b916 100644 --- a/test/jdk/performance/client/SwingMark/src/JMTest_04.java +++ b/test/jdk/performance/client/SwingMark/src/JMTest_04.java @@ -70,14 +70,6 @@ public class JMTest_04 extends AbstractSwingTest { String MENU_ITEM_STRING = "JMenuItem"; String SUB_MENU_STRING = "SubMenu"; - /** - * This test cannot run as an applet because it - * posts events to the event queue - */ - public boolean canRunInApplet() { - return false; - } - public JComponent getTestComponent() { loadBundle(); JPanel panel = new JPanel(); diff --git a/test/jdk/performance/client/SwingMark/src/JMTest_05.java b/test/jdk/performance/client/SwingMark/src/JMTest_05.java index bd4eea45f9b..dc2a0bd1489 100644 --- a/test/jdk/performance/client/SwingMark/src/JMTest_05.java +++ b/test/jdk/performance/client/SwingMark/src/JMTest_05.java @@ -65,14 +65,6 @@ public class JMTest_05 extends AbstractSwingTest { int DOWN = 40; int UP = 38; - /** - * This test cannot run as an applet because it - * posts events to the event queue - */ - public boolean canRunInApplet() { - return false; - } - public JComponent getTestComponent() { JPanel panel = new JPanel(); diff --git a/test/jdk/performance/client/SwingMark/src/MenuTest.java b/test/jdk/performance/client/SwingMark/src/MenuTest.java index 9d9d8751d3e..91ce63e7667 100644 --- a/test/jdk/performance/client/SwingMark/src/MenuTest.java +++ b/test/jdk/performance/client/SwingMark/src/MenuTest.java @@ -69,14 +69,6 @@ public class MenuTest extends AbstractSwingTest { int repeat = 50; - /** - * This test cannot run as an applet because it - * posts events to the event queue - */ - public boolean canRunInApplet() { - return false; - } - public JComponent getTestComponent() { listener = new MyListener(); diff --git a/test/jdk/performance/client/SwingMark/src/TypingTest.java b/test/jdk/performance/client/SwingMark/src/TypingTest.java index 0019f7bd2c4..440b8b09e87 100644 --- a/test/jdk/performance/client/SwingMark/src/TypingTest.java +++ b/test/jdk/performance/client/SwingMark/src/TypingTest.java @@ -52,10 +52,6 @@ public class TypingTest extends AbstractSwingTest { return panel; } - public boolean canRunInApplet() { - return false; - } - public String getTestName() { return "Typing"; } From a551cc929426590bfbbcaa4bd8bee5e4e8cfe16d Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Fri, 18 Apr 2025 17:07:16 +0000 Subject: [PATCH 252/843] 8353293: Open source several swing tests batch4 Reviewed-by: serb --- .../DrawEtchedRectTest.java | 77 ++++++++++++++++ .../basic/BasicHTML/4228104/bug4228104.java | 75 +++++++++++++++ .../plaf/basic/BasicHTML/4228104/duke.gif | Bin 0 -> 1929 bytes .../plaf/basic/BasicSliderUI/bug4220108.java | 75 +++++++++++++++ .../BasicSplitPaneUI/NegativeSizeTest.java | 87 ++++++++++++++++++ .../PreferredSizeLayoutTest.java | 71 ++++++++++++++ 6 files changed, 385 insertions(+) create mode 100644 test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java create mode 100644 test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java create mode 100644 test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/duke.gif create mode 100644 test/jdk/javax/swing/plaf/basic/BasicSliderUI/bug4220108.java create mode 100644 test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/NegativeSizeTest.java create mode 100644 test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java diff --git a/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java b/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java new file mode 100644 index 00000000000..0c5c501596c --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicGraphicsUtils/DrawEtchedRectTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4198822 + * @summary Tests that the bottom line drawn by + * BasicGraphicsUtils.drawEtchedRect extends to the end. + * @run main DrawEtchedRectTest + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; +import javax.swing.plaf.basic.BasicGraphicsUtils; + +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; + +public class DrawEtchedRectTest { + private static final int WIDTH = 200; + private static final int HEIGHT = 200; + private static final int RANGE = 10; + + public static void main(String[] args) throws Exception { + // Draw etched rectangle to a BufferedImage + BufferedImage image = new BufferedImage(WIDTH, HEIGHT, TYPE_INT_ARGB); + Graphics2D g2d = image.createGraphics(); + Component sq = new Component() { + public void paint(Graphics g) { + g.setColor(Color.WHITE); + g.fillRect(0, 0, WIDTH, HEIGHT); + BasicGraphicsUtils.drawEtchedRect(g, 0, 0, WIDTH, HEIGHT, + Color.black, Color.black, + Color.black, Color.black); + } + }; + sq.paint(g2d); + g2d.dispose(); + + // Check if connected at bottom-right corner + int c1; + int c2; + for (int i = 1; i < RANGE; i++) { + c1 = image.getRGB(WIDTH - i, HEIGHT - 1); + c2 = image.getRGB(WIDTH - 1, HEIGHT - i); + if (c1 == Color.WHITE.getRGB() || c2 == Color.WHITE.getRGB()) { + ImageIO.write(image, "png", new File("failImage.png")); + throw new RuntimeException("Bottom line is not connected!"); + } + } + } +} diff --git a/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java b/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java new file mode 100644 index 00000000000..451590c66ab --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/bug4228104.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4228104 + * @summary Tests work of BODY BACKGROUND tag in HTML renderer + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4228104 + */ + +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.JLabel; + +public class bug4228104 { + static final String INSTRUCTIONS = """ + There should be an image displaying dukes under the rows of digits. + If you can see it, the test PASSES. Otherwise, the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4228104 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4228104::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Background HTML Text Test"); + String dir = System.getProperty("test.src", + System.getProperty("user.dir")); + String htmlText1 = + "\n" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111" + + "
111111111111111111"; + JLabel button1 = new JLabel(htmlText1); + f.add(button1, BorderLayout.NORTH); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/duke.gif b/test/jdk/javax/swing/plaf/basic/BasicHTML/4228104/duke.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed32e0ff79b05c07b82863ce6fb07fa9898adaa2 GIT binary patch literal 1929 zcmWlYe^AtB8pi`HvM4_?{J2I$8$dLc1#@!R2zwgXMWdj^k;9xr+bDW&4{JlE8WpDj z7F-cwwK{H<)?L&#SJz$!;hJ{%BY2FYf)Wp^xl?aq!5Xcdi$c#hV~>m9_n-Hl=Xsy+ z=li^?*Q~;pZ+R1N1J40KRkeWM7ew3~jLM24A{CM-A}~TzqzYpq&od0GC=z71!w_=b z-==B0rt2t*nA}((5YSLs6a*Z@X__WqiSjTW6oLo{5km&|K1mGAimYjhs#wwZtvV8SV~7LCFpgub+-TTAk%UQb0dE_cj+pc?!+0o?qG$?% zVFD)%!w7Z;g)ndE8Uk6Aky=+kLaUQ{UW`XS?Nn*s@SQ{VmFgGdkV{&&98EcEQ5hjc@H$`e)fX zj@&GdchxpMUo|-A^M4iBP3(#Ib53Ap?5{nGT7SBA_V!o!TTzL5R~FUWe)4X?@iTd8 z1;TcF^rQLj?4p0uy?@ikb2eUSXdHVa_jIn=@W%a<6~57D>am6&Z!{lzc=@ZbuGB8` zpU38H8d~@82Da!+qdYG5ls&Cx?~|oPMnbqTHMw%I*KlV~?fc{rSwe29?Om}fsknG# z@n5IwY=4Mx>>0WJLG>=yJX^WbHA30iQ$H!X)3<4K zBe1|sf3NKKTS;)mg{$k(2eDJG^u5=&x{@M!V>EWgzRA((>}?o{WQBehp1mIHU!BGG zYz5_6B(+KIVdCVoum2ItM&gXZd+SB^vQTN=a zeYbbah=i-xCho2{4Pazv_i%2mH`EkM{r8XYDLbdY@(a7Ud}$%!$QrTN_DqwNXA9~g zTGKxKyfto7NDp;5A3O5zgb(hyxjN@OAG!(zy^*Ug4!yjF=Y*8aHA@ovB1({&a4;sR zTf1CVC{>Pgy`m$lG;P1$pC_6F7u%iP+qz0q4{lXT`i9g-ThiYgO^GXC`f?JNo*|@p zr{b%U-tSKw99q0|YJa9{Va?`H{IaNICo>p5lGEY*+IDR4bfIUwq~CTRuC_mGWA%~W zea{@eKJ(Iq^7MvdsPsR%&vt$@4i&s?bPptz#y#!FcRZEaMS0WFTyXMCUEfsNxnJ_9 zPwpt`Er4O>``2G{7=4r1GCSTO8#0xw+{<^L4X(K8y1wKj72KLrYD}Y7SJuY7y==wf z;UkI5?(v?h+4r;vR{P*U`ul~=D@U7K5$eV8c!%rX-38vE>azU80UrhFXCv#d`(ylZS4+i2a^vI91MTIxCx%9gd2&N&D9RC&xcpx8#f=GZv%9;F z#?CEVT%UV$nk;L%RJA+d=f8ZB@U*Xz-TZbG?HKKT(VJZMBH!)$#qRuwbFc%Aljqha zoNBs8od~V$_^vux0ZSk!iP!hI($t35SxY8`FV{pxCjpU}Ova2VIg1&>V)CvvMb_ cardLayout.show(mainPanel, "split")); + f.add(button, BorderLayout.SOUTH); + f.setSize(400, 300); + return f; + } +} diff --git a/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java b/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java new file mode 100644 index 00000000000..76d0e45b8eb --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicSplitPaneUI/PreferredSizeLayoutTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4208549 + * @summary Makes sure preferred size returned by layout managers used by + * JSplitPane is correct. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PreferredSizeLayoutTest + */ + +import java.awt.Container; +import java.awt.FlowLayout; + +import javax.swing.JFrame; +import javax.swing.JSplitPane; + +public class PreferredSizeLayoutTest { + static final String INSTRUCTIONS = """ + If the buttons in the JSplitpanes do not have '...' in them, + click PASS, otherwise click FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("PreferredSizeLayoutTest Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(PreferredSizeLayoutTest::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Preferred Size Layout Test"); + Container parent = f.getContentPane(); + JSplitPane sp = new JSplitPane(); + + parent.setLayout(new FlowLayout()); + + sp.setOrientation(JSplitPane.HORIZONTAL_SPLIT); + parent.add(sp); + sp = new JSplitPane(); + sp.setOrientation(JSplitPane.VERTICAL_SPLIT); + parent.add(sp); + f.setSize(400, 300); + return f; + } +} From 924638c471b0bf4a00a890ce6a3fd7e118cdd578 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Fri, 18 Apr 2025 17:08:46 +0000 Subject: [PATCH 253/843] 8353661: Open source several swing tests batch5 Reviewed-by: jdv --- test/jdk/javax/swing/JSlider/bug4186062.java | 99 +++++++++++++ test/jdk/javax/swing/JSlider/bug4275631.java | 132 ++++++++++++++++++ test/jdk/javax/swing/JSlider/bug4382876.java | 110 +++++++++++++++ .../javax/swing/plaf/windows/bug4991587.java | 95 +++++++++++++ 4 files changed, 436 insertions(+) create mode 100644 test/jdk/javax/swing/JSlider/bug4186062.java create mode 100644 test/jdk/javax/swing/JSlider/bug4275631.java create mode 100644 test/jdk/javax/swing/JSlider/bug4382876.java create mode 100644 test/jdk/javax/swing/plaf/windows/bug4991587.java diff --git a/test/jdk/javax/swing/JSlider/bug4186062.java b/test/jdk/javax/swing/JSlider/bug4186062.java new file mode 100644 index 00000000000..1db2f1bba6c --- /dev/null +++ b/test/jdk/javax/swing/JSlider/bug4186062.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4382876 + * @summary Tests if JSlider fires ChangeEvents when thumb is clicked and not moved + * @key headful + * @run main bug4186062 + */ + +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeListener; + +public class bug4186062 { + private static JFrame f; + private static JSlider slider; + private static volatile Point loc; + private static volatile int labelNum; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("JSlider Click Value Test"); + f.setSize(400, 200); + f.setLocationRelativeTo(null); + f.setVisible(true); + JPanel panel = new JPanel(); + slider = new JSlider(); + final JLabel label = new JLabel("0"); + labelNum = 0; + + ChangeListener listener = e -> { + labelNum++; + label.setText("" + labelNum); + }; + slider.addChangeListener(listener); + + panel.add(slider); + panel.add(label); + f.add(panel); + }); + + Robot r = new Robot(); + r.setAutoDelay(100); + r.waitForIdle(); + r.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + loc = slider.getLocationOnScreen(); + loc.setLocation(loc.x + (slider.getWidth() / 2), + loc.y + (slider.getHeight() / 2)); + }); + + r.mouseMove(loc.x, loc.y); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (labelNum > 0) { + throw new RuntimeException(labelNum + " ChangeEvents fired. " + + "Test failed"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JSlider/bug4275631.java b/test/jdk/javax/swing/JSlider/bug4275631.java new file mode 100644 index 00000000000..4d0aa555721 --- /dev/null +++ b/test/jdk/javax/swing/JSlider/bug4275631.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4275631 + * @summary Tests if vertical JSlider is properly aligned in large container + * @key headful + * @run main bug4275631 + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.Robot; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; + +public class bug4275631 { + private static final int OFFSET = 1; + private static JFrame f; + private static JSlider slider1; + private static JSlider slider2; + private static volatile Point loc1; + private static volatile Point loc2; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("JSlider Alignment Test"); + f.setSize(400, 200); + f.setLocationRelativeTo(null); + + // Create two sliders, verify the alignment on the slider to be + // used in the border layout + slider1 = new JSlider(JSlider.VERTICAL, 0, 99, 50); + slider1.setInverted(true); + slider1.setMajorTickSpacing(10); + slider1.setMinorTickSpacing(1); + slider1.setPaintTicks(true); + slider1.setPaintLabels(true); + slider2 = new JSlider(JSlider.VERTICAL, 0, 99, 50); + slider2.setInverted(true); + slider2.setMajorTickSpacing(10); + slider2.setMinorTickSpacing(1); + slider2.setPaintTicks(true); + slider2.setPaintLabels(true); + + // Try to center the natural way, using a border layout in the "Center" + JPanel borderPanel = new JPanel(); + borderPanel.setLayout(new BorderLayout()); + borderPanel.setBorder(BorderFactory.createTitledBorder("BorderLayout")); + borderPanel.add(slider1, BorderLayout.CENTER); + borderPanel.setPreferredSize(new Dimension(200, 200)); + + // Try to center using GridBagLayout, with glue on left + // and right to squeeze slider into place + JPanel gridBagPanel = new JPanel(new GridBagLayout()); + gridBagPanel.setBorder(BorderFactory.createTitledBorder("GridBagLayout")); + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 1; + c.fill = GridBagConstraints.VERTICAL; + c.weighty = 1.0; + gridBagPanel.add(slider2, c); + c.gridx = 0; + c.fill = GridBagConstraints.BOTH; + c.weighty = 0.0; + gridBagPanel.add(Box.createHorizontalGlue(), c); + c.gridx = 2; + c.fill = GridBagConstraints.BOTH; + gridBagPanel.add(Box.createHorizontalGlue(), c); + gridBagPanel.setPreferredSize(new Dimension(200, 200)); + + f.add(borderPanel, BorderLayout.WEST); + f.add(gridBagPanel, BorderLayout.EAST); + f.setVisible(true); + }); + + Robot r = new Robot(); + r.setAutoDelay(100); + r.waitForIdle(); + r.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + loc1 = slider1.getLocationOnScreen(); + loc1.setLocation(loc1.x + (slider1.getWidth() / 2), + loc1.y + (slider1.getHeight() / 2)); + + loc2 = slider2.getLocationOnScreen(); + loc2.setLocation(loc2.x + (slider2.getWidth() / 2), + loc2.y + (slider2.getHeight() / 2)); + }); + + if (loc1.y > loc2.y + OFFSET || loc1.y < loc2.y - OFFSET) { + throw new RuntimeException("JSlider position is not aligned!"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JSlider/bug4382876.java b/test/jdk/javax/swing/JSlider/bug4382876.java new file mode 100644 index 00000000000..b9ec64aab21 --- /dev/null +++ b/test/jdk/javax/swing/JSlider/bug4382876.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4382876 + * @summary Tests how PgUp and PgDn keys work with JSlider + * @key headful + * @run main bug4382876 + */ + +import java.awt.BorderLayout; +import java.awt.ComponentOrientation; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.JFrame; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; + +public class bug4382876 { + private static Robot r; + private static JFrame f; + private static JSlider slider; + private static boolean upFail; + private static boolean downFail; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("JSlider PageUp/Down Test"); + f.setSize(300, 200); + f.setLocationRelativeTo(null); + f.setVisible(true); + slider = new JSlider(-1000, -900, -1000); + slider.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + slider.putClientProperty("JSlider.isFilled", Boolean.TRUE); + f.add(slider, BorderLayout.CENTER); + }); + + r = new Robot(); + r.setAutoDelay(100); + r.waitForIdle(); + r.delay(1000); + + r.keyPress(KeyEvent.VK_PAGE_UP); + SwingUtilities.invokeAndWait(() -> { + if (slider.getValue() < -1000) { + System.out.println("PAGE_UP VAL: " + slider.getValue()); + upFail = true; + } + }); + if (upFail) { + writeFailImage(); + throw new RuntimeException("Slider value did NOT change with PAGE_UP"); + } + r.keyPress(KeyEvent.VK_PAGE_DOWN); + SwingUtilities.invokeAndWait(() -> { + if (slider.getValue() > -1000) { + System.out.println("PAGE_DOWN VAL: " + slider.getValue()); + downFail = true; + } + }); + if (downFail) { + writeFailImage(); + throw new RuntimeException("Slider value did NOT change with PAGE_DOWN"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void writeFailImage() throws IOException { + GraphicsConfiguration ge = GraphicsEnvironment + .getLocalGraphicsEnvironment().getDefaultScreenDevice() + .getDefaultConfiguration(); + BufferedImage failImage = r.createScreenCapture(ge.getBounds()); + ImageIO.write(failImage, "png", new File("failImage.png")); + } +} diff --git a/test/jdk/javax/swing/plaf/windows/bug4991587.java b/test/jdk/javax/swing/plaf/windows/bug4991587.java new file mode 100644 index 00000000000..e4e4fde2b86 --- /dev/null +++ b/test/jdk/javax/swing/plaf/windows/bug4991587.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4991587 + * @requires (os.family == "windows") + * @summary Tests that disabled JButton text is positioned properly in Windows L&F + * @modules java.desktop/com.sun.java.swing.plaf.windows + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4991587 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.AbstractButton; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.UIManager; + +import com.sun.java.swing.plaf.windows.WindowsButtonUI; + +public class bug4991587 { + static final String INSTRUCTIONS = """ + There are two buttons: enabled (left) and disabled (right). + Ensure that the disabled button text is painted entirely + inside the blue bounding rectangle, just like the enabled + button (use it as an example of how this should look like). + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + PassFailJFrame.builder() + .title("bug4991587 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4991587::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Disabled JButton Text Test"); + f.setLayout(new FlowLayout()); + f.setSize(400, 100); + + JButton button1 = new JButton("\u0114 Enabled JButton"); + button1.setUI(new MyButtonUI()); + f.add(button1); + + JButton button2 = new JButton("\u0114 Disabled JButton"); + button2.setEnabled(false); + button2.setUI(new MyButtonUI()); + f.add(button2); + + return f; + } + + static class MyButtonUI extends WindowsButtonUI { + protected void paintText(Graphics g, AbstractButton b, + Rectangle textRect, String text) { + g.setColor(Color.blue); + g.drawRect(textRect.x, + textRect.y, + textRect.width + 1, // add 1 for the shadow, otherwise it + // will be painted over the textRect + textRect.height); + super.paintText(g, b, textRect, text); + } + } +} From f8f1be3de56986c06f368334b7c64ef50f0117cf Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 18 Apr 2025 18:50:08 +0000 Subject: [PATCH 254/843] 8353552: Opensource Several Font related tests - Batch 3 8355048: ProblemList TestGlyphVectorLayout.java on all platforms Reviewed-by: serb, aivanov --- test/jdk/ProblemList.txt | 1 + .../jdk/java/awt/font/BoldItalicFontTest.java | 73 +++++++ .../GlyphVector/TestGlyphVectorLayout.java | 121 +++++++++++ .../GlyphVector/TestSetGlyphPositions.java | 96 +++++++++ .../jdk/java/awt/font/Rotate/RotateTest1.java | 97 +++++++++ .../java/awt/font/TestGraphicPlacement.java | 199 ++++++++++++++++++ 6 files changed, 587 insertions(+) create mode 100644 test/jdk/java/awt/font/BoldItalicFontTest.java create mode 100644 test/jdk/java/awt/font/GlyphVector/TestGlyphVectorLayout.java create mode 100644 test/jdk/java/awt/font/GlyphVector/TestSetGlyphPositions.java create mode 100644 test/jdk/java/awt/font/Rotate/RotateTest1.java create mode 100644 test/jdk/java/awt/font/TestGraphicPlacement.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 4a00130d3aa..b0a97929c6d 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -796,6 +796,7 @@ java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all java/awt/print/PrinterJob/PrintTextTest.java 8148334 macosx-all +java/awt/font/GlyphVector/TestGlyphVectorLayout.java 8354987 generic-all java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all diff --git a/test/jdk/java/awt/font/BoldItalicFontTest.java b/test/jdk/java/awt/font/BoldItalicFontTest.java new file mode 100644 index 00000000000..7fdefcfe2b5 --- /dev/null +++ b/test/jdk/java/awt/font/BoldItalicFontTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; + +/* + * @test + * @bug 4935871 + * @summary Check that correct type faces are used regardless of bold/italic styles + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual/othervm -Duser.language=ja -Duser.country=JP BoldItalicFontTest + */ + +public class BoldItalicFontTest { + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + This test is reproduced with a non-English user locale only. + All the letters "X" in the first line should be in serif font. + All the letters "X" in the second line should be in sans-serif font. + + If so, press Pass, else press Fail."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(BoldItalicFontTest::createUI) + .build() + .awaitAndCheck(); + } + + private static Frame createUI() { + String[] faces = { Font.SERIF, Font.SANS_SERIF }; + int[] styles = { 0, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC }; + + Frame f = new Frame("BoldItalicFontTest Test UI"); + f.setLayout(new GridLayout(faces.length, styles.length)); + for (int fn = 0; fn < faces.length; fn++) { + for (int sn = 0; sn < styles.length; sn++) { + Label l = new Label("X"); + Font f1 = new Font(faces[fn], styles[sn], 36); + l.setFont(f1); + f.add(l); + } + } + f.setSize(300, 300); + return f; + } +} diff --git a/test/jdk/java/awt/font/GlyphVector/TestGlyphVectorLayout.java b/test/jdk/java/awt/font/GlyphVector/TestGlyphVectorLayout.java new file mode 100644 index 00000000000..b183b652642 --- /dev/null +++ b/test/jdk/java/awt/font/GlyphVector/TestGlyphVectorLayout.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.font.GlyphVector; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4615017 + * @summary Display two GlyphVectors, and ensure they are of the same length. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestGlyphVectorLayout + */ + +public class TestGlyphVectorLayout extends JPanel { + private final Font font; + private final FontRenderContext frc; + private final String text; + + private GlyphVector aftergv; + private Rectangle pbounds; + private Rectangle2D vbounds; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + Two lines of text should appear, the top one with boxes + (red and blue) around it. + The two lines should be of the same length, and the boxes around the + top line should 'fit' the text with no empty space between the end + of the text and the box. + + Pass the test if this is true."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TestGlyphVectorLayout::new) + .build() + .awaitAndCheck(); + } + + private TestGlyphVectorLayout() { + setBackground(Color.WHITE); + font = new Font(Font.DIALOG, Font.PLAIN, 24); + frc = new FontRenderContext(null, false, false); + text = "this is a test of glyph vector"; + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(550, 150); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + + float x = 50; + float y = 50; + AffineTransform oldtx = g2d.getTransform(); + g2d.translate(x, y); + g2d.scale(1.5, 1.5); + + g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + + g2d.setColor(Color.BLACK); + + GlyphVector gv = font.createGlyphVector(frc, text); // new each time + g2d.drawGlyphVector(gv, 0, 0); + + if (vbounds == null) { + vbounds = gv.getVisualBounds(); + pbounds = gv.getPixelBounds(g2d.getFontRenderContext(), 0, 0); + aftergv = gv; + } + g2d.drawGlyphVector(aftergv, 0, 30); + + g2d.setColor(Color.BLUE); + g2d.draw(vbounds); + + g2d.setTransform(oldtx); + g2d.setColor(Color.RED); + g2d.draw(pbounds); + } +} diff --git a/test/jdk/java/awt/font/GlyphVector/TestSetGlyphPositions.java b/test/jdk/java/awt/font/GlyphVector/TestSetGlyphPositions.java new file mode 100644 index 00000000000..f56d8214395 --- /dev/null +++ b/test/jdk/java/awt/font/GlyphVector/TestSetGlyphPositions.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.font.GlyphVector; +import java.awt.font.FontRenderContext; +import java.awt.geom.Point2D; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4180379 + * @summary set the positions of glyphs in the GlyphVector to other than + * their default x, y positions, and verify that the rendered glyphs are + * in the new positions, not the default positions. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestSetGlyphPositions + */ + +public class TestSetGlyphPositions extends JPanel { + GlyphVector gv = null; + + public static void main(String[] args) throws Exception { + final String INSTRUCTIONS = """ + 'TopLeft text and >' should appear towards the top left of the frame, + and '< and BottomRight text' should appear towards the bottom right. + + There should be some space between the '>' and '<' symbols, both vertically + and horizontally. + + Pass the test if this is true."""; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(TestSetGlyphPositions::new) + .build() + .awaitAndCheck(); + } + + public TestSetGlyphPositions() { + setBackground(Color.WHITE); + setSize(550, 150); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(550, 150); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + + if (gv == null) { + Font font = new Font(Font.DIALOG, Font.PLAIN, 36); + FontRenderContext frc = g2d.getFontRenderContext(); + String str = "TopLeft> Date: Fri, 18 Apr 2025 19:38:09 +0000 Subject: [PATCH 255/843] 8355051: Problemlist java/awt/Graphics2D/CopyAreaOOB.java on macosx-aarch64 Reviewed-by: prr, aivanov --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index b0a97929c6d..075ce0e9c10 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -473,6 +473,7 @@ java/awt/MenuBar/TestNoScreenMenuBar.java 8265987 macosx-all java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8266283 generic-all java/awt/Graphics2D/DrawString/RotTransText.java 8316878 linux-all +java/awt/Graphics2D/CopyAreaOOB.java 8343106 macosx-aarch64 java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java 8257529 windows-x64 java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.java 8302787 windows-all java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.java 8302787 windows-all From bf63f9ffa5e107ecb01e67dbef785a7bf4c89f16 Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Fri, 18 Apr 2025 20:58:21 +0000 Subject: [PATCH 256/843] 8353319: Open source Swing tests - Set 3 Reviewed-by: abhiscxk, dnguyen --- test/jdk/javax/swing/JFrame/bug4419914.java | 130 +++++++++++++++--- .../jdk/javax/swing/JRootPane/bug4614623.java | 84 +++++++++++ .../javax/swing/JTabbedPane/bug4613811.java | 82 +++++++++++ test/jdk/javax/swing/JWindow/bug4251781.java | 76 ++++++++++ 4 files changed, 350 insertions(+), 22 deletions(-) create mode 100644 test/jdk/javax/swing/JRootPane/bug4614623.java create mode 100644 test/jdk/javax/swing/JTabbedPane/bug4613811.java create mode 100644 test/jdk/javax/swing/JWindow/bug4251781.java diff --git a/test/jdk/javax/swing/JFrame/bug4419914.java b/test/jdk/javax/swing/JFrame/bug4419914.java index 4574b1ac3d6..f87dcc8c468 100644 --- a/test/jdk/javax/swing/JFrame/bug4419914.java +++ b/test/jdk/javax/swing/JFrame/bug4419914.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,55 +28,141 @@ * @library /java/awt/regtesthelpers * @build PassFailJFrame * @run main/manual bug4419914 -*/ + */ import java.awt.BorderLayout; import java.awt.ComponentOrientation; -import javax.swing.JButton; -import javax.swing.JFrame; +import java.awt.Frame; +import java.awt.Window; +import java.util.List; import java.util.Locale; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JWindow; public class bug4419914 { + private static JFrame frame; private static final String INSTRUCTIONS = """ - 1. You will see a frame with five buttons. - 2. Confirm that each button is placed as follows: - NORTH - END CENTER START - SOUTH - 3. Press the "NORTH" button and confirm the button is focused. - 4. Press TAB repeatedly and confirm that the TAB focus moves from right to left. - (NORTH - START - CENTER - END - SOUTH - NORTH - START - CENTER - ...) + This test verifies tab movement on RTL component orientation + in JWindow, JFrame and JDialog. - If there's anything different from the above items, click Fail else click Pass."""; + When test starts 3 test windows are displayed - JFrame, JWindow and JDialog. + Follow the instructions below and if any condition does not hold + press FAIL. + + 1. Confirm that each button in the child window is placed as follows: + + For JFrame: + NORTH + END CENTER START + SOUTH + + For JWindow: + END CENTER START + QUIT + + For JDialog: + END CENTER START + + 3. Press on the "START" button in case of JWindow & JDialog and "NORTH" + in case of JFrame, confirm that the respective button is focused. + + 4. Press TAB repeatedly and confirm that the TAB focus moves + from right to left. + + For JFrame: + (NORTH - START - CENTER - END - SOUTH - NORTH - START - CENTER - ...) + + For JWindow: + (START - CENTER - END - QUIT - START - CENTER - END - QUIT - ...) + + For JDialog: + (START - CENTER - END - START - CENTER - END - ...) + + If all of the above conditions are true press PASS else FAIL. + """; public static void main(String[] args) throws Exception { PassFailJFrame.builder() - .title("Tab movement Instructions") .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) - .columns(48) - .testUI(bug4419914::createTestUI) + .columns(45) + .testTimeOut(10) + .testUI(bug4419914::createAndShowUI) + .positionTestUI(WindowLayouts::rightOneColumn) .build() .awaitAndCheck(); } - private static JFrame createTestUI() { - JFrame frame = new JFrame("bug4419914"); + private static List createAndShowUI() { + return List.of(createJFrame(), createJWindow(), createJDialog()); + } + + private static JFrame createJFrame() { + frame = new JFrame("bug4419914 JFrame"); frame.setFocusCycleRoot(true); + // Tab movement set to RTL frame.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); frame.setLocale(Locale.ENGLISH); frame.enableInputMethods(false); + // Component placement within content pane set to RTL frame.getContentPane().setComponentOrientation( - ComponentOrientation.RIGHT_TO_LEFT); + ComponentOrientation.RIGHT_TO_LEFT); frame.getContentPane().setLocale(Locale.ENGLISH); - frame.getContentPane().setLayout(new BorderLayout()); + frame.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); frame.add(new JButton("START"), BorderLayout.LINE_START); frame.add(new JButton("NORTH"), BorderLayout.NORTH); - frame.setSize(300, 150); + frame.setSize(300, 160); return frame; } + + private static JWindow createJWindow() { + JWindow window = new JWindow(frame); + window.setFocusableWindowState(true); + // Tab movement set to RTL + window.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + window.setLocale(new Locale("en")); + window.enableInputMethods(false); + + // Component placement within content pane set to RTL + window.getContentPane().setComponentOrientation( + ComponentOrientation.RIGHT_TO_LEFT); + window.getContentPane().setLocale(new Locale("en")); + window.setLayout(new BorderLayout()); + window.add(new JLabel("bug4419914 JWindow"), BorderLayout.NORTH); + window.add(new JButton("START"), BorderLayout.LINE_START); + window.add(new JButton("CENTER"), BorderLayout.CENTER); + window.add(new JButton("END"), BorderLayout.LINE_END); + + JButton quitButton = new JButton("QUIT"); + quitButton.addActionListener(e1 -> window.dispose()); + window.add(quitButton, BorderLayout.SOUTH); + window.setSize(300, 153); + window.requestFocus(); + return window; + } + + private static JDialog createJDialog() { + JDialog dialog = new JDialog((Frame) null, "bug4419914 JDialog"); + // Tab movement set to RTL + dialog.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + dialog.setLocale(new Locale("en")); + dialog.enableInputMethods(false); + + // Component placement within content pane set to RTL + dialog.getContentPane().setComponentOrientation( + ComponentOrientation.RIGHT_TO_LEFT); + dialog.getContentPane().setLocale(new Locale("en")); + dialog.setLayout(new BorderLayout()); + dialog.add(new JButton("CENTER"), BorderLayout.CENTER); + dialog.add(new JButton("END"), BorderLayout.LINE_END); + dialog.add(new JButton("START"), BorderLayout.LINE_START); + dialog.setSize(300, 160); + return dialog; + } } diff --git a/test/jdk/javax/swing/JRootPane/bug4614623.java b/test/jdk/javax/swing/JRootPane/bug4614623.java new file mode 100644 index 00000000000..9a714d3cdfd --- /dev/null +++ b/test/jdk/javax/swing/JRootPane/bug4614623.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4614623 + * @requires (os.family == "windows") + * @summary Tests that w2k mnemonic underlining works when there's no + focus owner + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4614623 + */ + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.UIManager; + +public class bug4614623 { + private static final String INSTRUCTIONS = """ + This test verifies if the short-cut character + (menu mnemonic) is underlined when the ALT key is held down. + + Check if the following is true. + 1) Press Alt key. The letter 'F' (menu mnemonic) of + the "File" menu should now be underlined. + 2) Release the Alt key, the selection background (light grey) + should appear around the "File" menu. Compare "About" menu + with "File" menu to see the light grey selection background. + + If the above is true, press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(62) + .rows(12) + .testUI(bug4614623::createAndShowUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4614623 - File menu test"); + JMenuBar menuBar = new JMenuBar(); + + JMenu fileMenu = new JMenu("File"); + fileMenu.setMnemonic('F'); + menuBar.add(fileMenu); + + JMenu about = new JMenu("About"); + menuBar.add(about); + menuBar.setSize(300, 100); + + frame.setJMenuBar(menuBar); + menuBar.requestFocus(); + frame.setSize(300, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/bug4613811.java b/test/jdk/javax/swing/JTabbedPane/bug4613811.java new file mode 100644 index 00000000000..ecad64e95f8 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4613811.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4613811 + * @summary Scrollable Buttons of JTabbedPane don't + * get enabled or disabled on selecting tab + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4613811 + */ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTabbedPane; + +public class bug4613811 { + private static final String INSTRUCTIONS = """ + Select different tabs and check that the scrollable + buttons are correctly enabled and disabled. + + When the very first tab (Tab 1) is fully visible + On macOS: + the left arrow button should NOT be visible. + + On other platforms: + the left arrow button should be disabled. + + If the last tab (Tab 5) is fully visible + On macOS: + the right arrow button should NOT be visible. + + On other platforms: + the right arrow button should be disabled. + + If the above is true press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(30) + .testUI(bug4613811::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4613811 - JTabbedPane Test"); + final JTabbedPane tabPane = new JTabbedPane(JTabbedPane.TOP, + JTabbedPane.SCROLL_TAB_LAYOUT); + for (int i = 1; i <= 5; i++) { + tabPane.addTab("TabbedPane: Tab " + i, null, new JLabel("Tab " + i)); + } + frame.add(tabPane, BorderLayout.CENTER); + frame.setResizable(false); + frame.setSize(400, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JWindow/bug4251781.java b/test/jdk/javax/swing/JWindow/bug4251781.java new file mode 100644 index 00000000000..0152db71f24 --- /dev/null +++ b/test/jdk/javax/swing/JWindow/bug4251781.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4251781 + * @summary Tests that JWindow repaint is optimized (background is not + cleared). + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4251781 + */ + +import java.awt.Color; +import java.awt.Container; +import javax.swing.JButton; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JWindow; + +public class bug4251781 { + private static final String INSTRUCTIONS = """ + Press the button at the bottom-right corner of the gray + window with the mouse. + If the window DOES NOT flicker when you press and/or release + the mouse button press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4251781::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JWindow createAndShowUI() { + JWindow w = new JWindow(); + final Container pane = w.getContentPane(); + pane.setLayout(null); + pane.setBackground(Color.GRAY.darker()); + + final JPopupMenu popup = new JPopupMenu(); + popup.add(new JMenuItem("item 1")); + popup.add(new JMenuItem("exit")); + + JButton b = new JButton("menu"); + b.setBounds(350, 250, 50, 50); + b.addActionListener(ev -> popup.show(pane, 0, 0)); + pane.add(b); + + w.setSize(400, 300); + return w; + } +} From 38f9b3a9738de7896d840fc114a76ced3b77c269 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Fri, 18 Apr 2025 21:11:41 +0000 Subject: [PATCH 257/843] 8353748: Open source several swing tests batch6 Reviewed-by: kizune --- .../javax/swing/JTree/NodeChangedTest.java | 72 +++++++++++ test/jdk/javax/swing/JTree/bug4118860.java | 97 ++++++++++++++ test/jdk/javax/swing/JTree/bug4169215.java | 65 ++++++++++ test/jdk/javax/swing/JTree/bug4196987.java | 70 ++++++++++ test/jdk/javax/swing/JTree/bug4270654.java | 76 +++++++++++ test/jdk/javax/swing/JTree/bug4618767.java | 121 ++++++++++++++++++ 6 files changed, 501 insertions(+) create mode 100644 test/jdk/javax/swing/JTree/NodeChangedTest.java create mode 100644 test/jdk/javax/swing/JTree/bug4118860.java create mode 100644 test/jdk/javax/swing/JTree/bug4169215.java create mode 100644 test/jdk/javax/swing/JTree/bug4196987.java create mode 100644 test/jdk/javax/swing/JTree/bug4270654.java create mode 100644 test/jdk/javax/swing/JTree/bug4618767.java diff --git a/test/jdk/javax/swing/JTree/NodeChangedTest.java b/test/jdk/javax/swing/JTree/NodeChangedTest.java new file mode 100644 index 00000000000..5461136c57b --- /dev/null +++ b/test/jdk/javax/swing/JTree/NodeChangedTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4199472 + * @summary Tests that node changed for the root of the tree update the + * structure. + * @run main NodeChangedTest + */ + +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; + +public class NodeChangedTest { + public static void main(String[] args) { + // Create 3 nodes + final DefaultMutableTreeNode root = new DefaultMutableTreeNode("root", + true); + final DefaultMutableTreeNode child = new DefaultMutableTreeNode("child", + true); + final DefaultMutableTreeNode leaf = new DefaultMutableTreeNode("leaf", + false); + root.add(child); + child.add(leaf); + + final JTree tree = new JTree(root); + + // Change the root node + root.setUserObject("New root"); + ((DefaultTreeModel) tree.getModel()).nodeChanged(root); + + // Check + if (!root.getUserObject().toString().equals("New root")) { + throw new RuntimeException("Failed changing root node for default model."); + } + + // Change to large model + tree.setLargeModel(true); + tree.setRowHeight(20); + root.setUserObject("root"); + tree.setModel(new DefaultTreeModel(root)); + root.setUserObject("New root"); + ((DefaultTreeModel) tree.getModel()).nodeChanged(root); + + // Check again + if (!root.getUserObject().toString().equals("New root")) { + throw new RuntimeException("Failed changing root node for large model."); + } + } +} diff --git a/test/jdk/javax/swing/JTree/bug4118860.java b/test/jdk/javax/swing/JTree/bug4118860.java new file mode 100644 index 00000000000..eb266eb9324 --- /dev/null +++ b/test/jdk/javax/swing/JTree/bug4118860.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4118860 + * @summary setToggleClickCount/getToggleClickCount have been added. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4118860 + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridLayout; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTree; + +public class bug4118860 { + static final String INSTRUCTIONS = """ + Push the "Single Click" button and try expanding/contracting + branch nodes of the tree with one left mouse button click + on the label part of the node (not the icon or handles). + + Then push the "Double Click" button and try doing the same using + left mouse button double click. Single click shouldn't cause + expanding/contracting. A double click should now be required + to expand/contract nodes. + + If it works then the test PASSES, else the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4118860 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4118860::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("ToggleClickCount Test"); + JTree tr = new JTree(); + JPanel p = new JPanel(); + p.setBackground(Color.red); + p.setLayout(new GridLayout(1, 1)); + tr.setOpaque(false); + p.add(tr); + f.add(p, BorderLayout.CENTER); + JPanel bp = new JPanel(); + JButton bt1 = new JButton("Single Click"); + bt1.addActionListener(e -> { + tr.setToggleClickCount(1); + if (tr.getToggleClickCount() != 1) { + throw new RuntimeException("ToggleClickCount doesn't set..."); + } + }); + JButton bt2 = new JButton("Double Click"); + bt2.addActionListener(e -> { + tr.setToggleClickCount(2); + if (tr.getToggleClickCount() != 2) { + throw new RuntimeException("ToggleClickCount doesn't set..."); + } + }); + bp.setLayout(new GridLayout(1, 2)); + bp.add(bt1); + bp.add(bt2); + f.add(bp, BorderLayout.SOUTH); + f.setSize(300, 200); + return f; + } +} diff --git a/test/jdk/javax/swing/JTree/bug4169215.java b/test/jdk/javax/swing/JTree/bug4169215.java new file mode 100644 index 00000000000..0b8780b3939 --- /dev/null +++ b/test/jdk/javax/swing/JTree/bug4169215.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4169215 + * @summary Accessibility hierarchy JTree node test. + * @run main bug4169215 + */ + +import javax.accessibility.AccessibleContext; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; + +public class bug4169215 { + public static void main(String[] args) { + // create the tree + DefaultMutableTreeNode root = new DefaultMutableTreeNode("top"); + DefaultMutableTreeNode nodeA = new DefaultMutableTreeNode("A"); + DefaultMutableTreeNode nodeB = new DefaultMutableTreeNode("B"); + root.add(nodeA); + root.add(nodeB); + JTree tree = new JTree(root); + + // find the AccessibleContext of the tree + AccessibleContext actree = tree.getAccessibleContext(); + + // find the AccessibleContext of top node of the tree + AccessibleContext act = actree.getAccessibleChild(0).getAccessibleContext(); + + // find the AccessibleContext of the first child of the table -> + // the AccessibleContext of nodeA + AccessibleContext accA = act.getAccessibleChild(0).getAccessibleContext(); + + // find the AccessibleContext of the next sibling of nodeA, by getting + // child+1 of the parent (the table) + AccessibleContext accB = act.getAccessibleChild( + accA.getAccessibleIndexInParent()+1).getAccessibleContext(); + + // look to see who the sibling is. + if (accB.getAccessibleName().compareTo("B") != 0) { + throw new RuntimeException("Parent node is a sibling instead!"); + } + } +} diff --git a/test/jdk/javax/swing/JTree/bug4196987.java b/test/jdk/javax/swing/JTree/bug4196987.java new file mode 100644 index 00000000000..1387b669b05 --- /dev/null +++ b/test/jdk/javax/swing/JTree/bug4196987.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4196987 + * @summary Test Metal L&F JTree expander icons transparency. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4196987 + */ + +import java.awt.Color; +import java.awt.GridLayout; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.UIManager; + +public class bug4196987 { + static final String INSTRUCTIONS = """ + If the background of tree icons are red, the test PASSES. + Otherwise the test FAILS. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4196987 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4196987::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JTree Icon Transparency Test"); + JPanel p = new JPanel(); + p.setBackground(Color.red); + p.setLayout(new GridLayout(1, 1)); + JTree t = new JTree(); + t.setOpaque(false); + p.add(t); + f.add(p); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/javax/swing/JTree/bug4270654.java b/test/jdk/javax/swing/JTree/bug4270654.java new file mode 100644 index 00000000000..413626d7881 --- /dev/null +++ b/test/jdk/javax/swing/JTree/bug4270654.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4270654 + * @summary Tests that selection change in JTree does not cause unnecessary + scrolling. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4270654 + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; + +public class bug4270654 { + static final String INSTRUCTIONS = """ + Select the "dan" node and scroll to the right a little using the + scrollbar. Then press down arrow key. If the tree unscrolls back + to the left, the test FAILS. Otherwise, the test PASSES. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4270654 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4270654::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JTree Scroll Back Test"); + DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); + String[] lev1 = {"foo", "bar", "dan"}; + String[][] lev2 = { + {}, + {"small", "a nice big node for testing"}, + {"xyz", "pqd", "a really really big node for testing"}}; + for (int i = 0; i < lev1.length; i++) { + DefaultMutableTreeNode child = new DefaultMutableTreeNode(lev1[i]); + root.add(child); + for (int j = 0; j < lev2[i].length; j++) + child.add(new DefaultMutableTreeNode(lev2[i][j])); + } + final JTree tree = new JTree(root); + tree.expandRow(3); + f.add(new JScrollPane(tree)); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/javax/swing/JTree/bug4618767.java b/test/jdk/javax/swing/JTree/bug4618767.java new file mode 100644 index 00000000000..d8aa52c3952 --- /dev/null +++ b/test/jdk/javax/swing/JTree/bug4618767.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4618767 + * @summary First letter navigation in JTree interferes with mnemonics + * @key headful + * @run main bug4618767 + */ + +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +public class bug4618767 { + private static JFrame f; + private static final JTree tree = new + JTree(new String[] {"one", "two", "three", "four"}); + private static boolean menuSelected; + private static CountDownLatch listGainedFocusLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4618767 Test"); + JMenu menu = new JMenu("File"); + menu.setMnemonic('F'); + JMenuItem menuItem = new JMenuItem("item"); + menu.add(menuItem); + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + f.setJMenuBar(menuBar); + + menu.addMenuListener(new MenuListener() { + public void menuCanceled(MenuEvent e) {} + public void menuDeselected(MenuEvent e) {} + public void menuSelected(MenuEvent e) { + menuSelected = true; + } + }); + + tree.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + listGainedFocusLatch.countDown(); + } + }); + f.add(tree); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + runTest(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } + + private static void runTest() throws Exception { + if (!listGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't gain" + + " focus for list"); + } + Robot robot = new Robot(); + robot.setAutoDelay(200); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_O); + robot.keyRelease(KeyEvent.VK_O); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_F); + robot.keyRelease(KeyEvent.VK_ALT); + + SwingUtilities.invokeAndWait(() -> { + if (menuSelected && !tree.getSelectionPath() + .getLastPathComponent().toString().equals("one")) { + throw new RuntimeException("Mnemonics interferes with JTree" + + " item selection using KeyEvent"); + } + }); + } +} From 76dec47f00230214e9ba58714be5a3ad26f8308d Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Fri, 18 Apr 2025 21:35:17 +0000 Subject: [PATCH 258/843] 8354340: Open source Swing Tests - Set 6 Reviewed-by: azvegint, achung --- .../JViewport/ScrollRectToVisibleTest3.java | 165 ++++++++++++++++++ .../javax/swing/JViewport/SetViewRepaint.java | 114 ++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 test/jdk/javax/swing/JViewport/ScrollRectToVisibleTest3.java create mode 100644 test/jdk/javax/swing/JViewport/SetViewRepaint.java diff --git a/test/jdk/javax/swing/JViewport/ScrollRectToVisibleTest3.java b/test/jdk/javax/swing/JViewport/ScrollRectToVisibleTest3.java new file mode 100644 index 00000000000..bf96ab2fc46 --- /dev/null +++ b/test/jdk/javax/swing/JViewport/ScrollRectToVisibleTest3.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 headful + * @bug 4217252 + * @summary Verify that scrolling beyond the visible region and scrolling + * a component smaller than the viewport is not allowed. + * @library /javax/swing/regtesthelpers + * @build Util + * @run main/othervm -Dsun.java2d.uiScale=1 ScrollRectToVisibleTest3 + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; + +public class ScrollRectToVisibleTest3 { + private static JFrame frame; + private static JTable table; + private static JButton scrollButton; + private static volatile int clickCount = 0; + private static final String[] EXPECTED_TEXT = {"99 x 0", "98 x 0", + "97 x 0", "96 x 0"}; + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + SwingUtilities.invokeAndWait(ScrollRectToVisibleTest3::createTestUI); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle frameBounds = Util.invokeOnEDT(() -> getComponentBounds(frame)); + robot.delay(100); + Point scrollBtnLoc = Util.getCenterPoint(scrollButton); + + robot.mouseMove(scrollBtnLoc.x, scrollBtnLoc.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(50); + + int rowHeight = Util.invokeOnEDT(() -> table.getRowHeight()); + for (int i = 1; i <= 4; i++) { + robot.mouseMove(frameBounds.x + 50, + frameBounds.y + frameBounds.height - (rowHeight * i + 2)); + robot.delay(300); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + // 500 ms delay added so that current mouseClicked event + // is processed successfully before proceeding to the next + robot.delay(500); + } + if (clickCount != 4) { + throw new RuntimeException("Test Failed! Expected 4 mouse clicks" + + " but got " + clickCount); + } + } + + private static void createTestUI() { + frame = new JFrame("ScrollRectToVisibleTest3"); + table = new JTable(new TestModel()); + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + JTable testTable = (JTable) e.getComponent(); + int row = testTable.getSelectedRow(); + int column = testTable.getSelectedColumn(); + String cellContent = testTable.getValueAt(row, column).toString(); + if (!EXPECTED_TEXT[clickCount].equals(cellContent)) { + throw new RuntimeException(("Test failed! Table Cell Content" + + " at (row %d , col %d)\n Expected: %s vs Actual: %s") + .formatted(row, column, + EXPECTED_TEXT[clickCount], cellContent)); + } + clickCount++; + } + }); + + scrollButton = new JButton("Scroll"); + scrollButton.addActionListener(ae -> { + Rectangle bounds = table.getBounds(); + bounds.y = bounds.height + table.getRowHeight(); + bounds.height = table.getRowHeight(); + System.out.println("scrolling: " + bounds); + table.scrollRectToVisible(bounds); + System.out.println("bounds: " + table.getVisibleRect()); + }); + + frame.add(scrollButton, BorderLayout.NORTH); + frame.add(new JScrollPane(table), BorderLayout.CENTER); + frame.setSize(400, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + + private static class TestModel extends AbstractTableModel { + @Override + public String getColumnName(int column) { + return Integer.toString(column); + } + + @Override + public int getRowCount() { + return 100; + } + + @Override + public int getColumnCount() { + return 5; + } + + @Override + public Object getValueAt(int row, int col) { + return row + " x " + col; + } + + @Override + public boolean isCellEditable(int row, int column) { return false; } + + @Override + public void setValueAt(Object value, int row, int col) { + } + } + + private static Rectangle getComponentBounds(Component c) { + Point locationOnScreen = c.getLocationOnScreen(); + Dimension size = c.getSize(); + return new Rectangle(locationOnScreen, size); + } +} diff --git a/test/jdk/javax/swing/JViewport/SetViewRepaint.java b/test/jdk/javax/swing/JViewport/SetViewRepaint.java new file mode 100644 index 00000000000..379a3e4e33b --- /dev/null +++ b/test/jdk/javax/swing/JViewport/SetViewRepaint.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4128110 + * @summary Verify that JViewport.setViewportView() and JScrollPane.setViewport() + * force a re-layout and a repaint. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SetViewRepaint + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.GridLayout; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JViewport; + +public class SetViewRepaint { + private static final String INSTRUCTIONS = """ + Verify the following two cases: + + 1) Press "JViewport.setViewportView()" button and verify that + the blue label is replaced by a scrolling list. + + 2) Press "JScrollPane.setViewport()" button and verify that + the red label is replaced by a scrolling list as well. + + In either case the display should update automatically after + pressing the button. + + If the above is true, press PASS else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(30) + .testUI(SetViewRepaint::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("SetViewRepaint"); + JPanel p1 = new JPanel(new BorderLayout()); + JPanel p2 = new JPanel(new BorderLayout()); + + JLabel label1 = new ColorLabel(Color.BLUE, "Blue Label"); + final JList list1 = new JList(new String[]{"one", "two", "three", "four"}); + final JScrollPane sp1 = new JScrollPane(label1); + ActionListener doSetViewportView = e -> sp1.setViewportView(list1); + JButton b1 = new JButton("JViewport.setViewportView()"); + b1.addActionListener(doSetViewportView); + p1.add(sp1, BorderLayout.CENTER); + p1.add(b1, BorderLayout.SOUTH); + + JLabel label2 = new ColorLabel(Color.RED, "Red Label"); + final JList list2 = new JList(new String[]{"five", "six", "seven", "eight"}); + final JScrollPane sp2 = new JScrollPane(label2); + ActionListener doSetViewport = e -> { + JViewport vp = new JViewport(); + vp.setView(list2); + sp2.setViewport(vp); + }; + JButton b2 = new JButton("JScrollPane.setViewport()"); + b2.addActionListener(doSetViewport); + p2.add(sp2, BorderLayout.CENTER); + p2.add(b2, BorderLayout.SOUTH); + frame.setLayout(new GridLayout(1, 2)); + frame.add(p1); + frame.add(p2); + frame.setResizable(false); + frame.setSize(500, 120); + return frame; + } + + private static class ColorLabel extends JLabel { + ColorLabel(Color color, String text) { + super(text); + setForeground(Color.WHITE); + setBackground(color); + setOpaque(true); + setHorizontalAlignment(CENTER); + } + } +} From bd73127d7495244f93f941530db32b4559d45689 Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Fri, 18 Apr 2025 23:29:53 +0000 Subject: [PATCH 259/843] 8354532: Open source JFileChooser Tests - Set 7 Reviewed-by: prr --- .../javax/swing/JFileChooser/bug4357012.java | 99 +++++++++++++++ .../javax/swing/JFileChooser/bug4926884.java | 114 ++++++++++++++++++ .../javax/swing/JFileChooser/bug5045464.java | 68 +++++++++++ .../javax/swing/JFileChooser/bug6515169.java | 106 ++++++++++++++++ 4 files changed, 387 insertions(+) create mode 100644 test/jdk/javax/swing/JFileChooser/bug4357012.java create mode 100644 test/jdk/javax/swing/JFileChooser/bug4926884.java create mode 100644 test/jdk/javax/swing/JFileChooser/bug5045464.java create mode 100644 test/jdk/javax/swing/JFileChooser/bug6515169.java diff --git a/test/jdk/javax/swing/JFileChooser/bug4357012.java b/test/jdk/javax/swing/JFileChooser/bug4357012.java new file mode 100644 index 00000000000..2dfdcd336d5 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4357012.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4357012 + * @requires (os.family == "windows") + * @summary JFileChooser.showSaveDialog inconsistent with Windows Save Dialog + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4357012 + */ + +import java.io.File; +import java.io.IOException; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4357012 { + private static File workDir = null; + private static File dir = null; + private static File file = null; + private static final String INSTRUCTIONS = """ + + Test is for Windows LAF only +

In JFileChooser's files list : +

    +
  1. Select directory. Verify that the directory name doesn't + appear in "file name" field.
  2. +
  3. Select file. Verify that the file name appears in + "file name" field.
  4. +
  5. Select directory again. Verify that the previous file name + remains in file name field.
  6. +
+

+ + """; + + public static void main(String[] argv) throws Exception { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + createTestDir(); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(10) + .columns(40) + .testUI(bug4357012::createTestUI) + .build() + .awaitAndCheck(); + } finally { + if (workDir != null) { + System.out.println("Deleting '" + file + "': " + file.delete()); + System.out.println("Deleting '" + dir + "': " + dir.delete()); + System.out.println("Deleting '" + workDir + "': " + workDir.delete()); + } + } + } + + private static void createTestDir() throws IOException { + String tempDir = "."; + String fs = System.getProperty("file.separator"); + + workDir = new File(tempDir + fs + "bug4357012"); + System.out.println("Creating '" + workDir + "': " + workDir.mkdir()); + + dir = new File(workDir + fs + "Directory"); + System.out.println("Creating '" + dir + "': " + dir.mkdir()); + + file = new File(workDir + fs + "File.txt"); + System.out.println("Creating '" + file + "': " + file.createNewFile()); + } + + private static JComponent createTestUI() { + JFileChooser fc = new JFileChooser(workDir); + fc.setDialogType(JFileChooser.SAVE_DIALOG); + return fc; + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4926884.java b/test/jdk/javax/swing/JFileChooser/bug4926884.java new file mode 100644 index 00000000000..29d6c4e9134 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4926884.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4926884 + * @requires (os.family == "windows") + * @summary Win L&F: JFileChooser problems with "My Documents" folder + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4926884 + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4926884 { + private static final String INSTRUCTIONS = """ + Validate next statements step by step: + + 1. In the file list there are several dirs and files (like "ski", + "Snowboard" etc.) + 2. Select "Details" view mode. + 3. Make file list in focus (e.g. by pressing mouse button) + 4. Press key "w" several times with delay LESS than 1 second. + Selection should be changed across files started with letter "w" + (without case sensitive). + 5. Press key "w" several times with delay MORE than 1 second. + Selection should be changed across files started with letter "w" + (without case sensitive). + 6. Type "winnt" (with delay less than 1 second between letters) - + directory "winnt" should be selected. + 7. Change conditions: + - Move column "Name" to the second position + - Change sort mode by clicking column "Size" + 8. Repeat items 4-6 + + If above is true press PASS else FAIL + """; + + private static final String[] DIRS = {"www", "winnt", "ski"}; + private static final String[] FILES = {"Window", "weel", "mice", + "Wall", "Snowboard", "wood"}; + private static final File testDir = new File("."); + + public static void main(String[] argv) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + try { + createTestDir(); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(() -> new JFileChooser(testDir)) + .build() + .awaitAndCheck(); + } finally { + deleteTempDir(); + } + } + + private static void createTestDir() throws IOException { + testDir.mkdir(); + + for (String dir : DIRS) { + new File(testDir, dir).mkdir(); + } + + for (int i = 0; i < FILES.length; i++) { + + try (OutputStream outputStream = new FileOutputStream( + new File(testDir, FILES[i]))) { + for (int j = 0; j < i * 1024; j++) { + outputStream.write('#'); + } + } + } + } + + private static void deleteTempDir() { + File[] files = testDir.listFiles(); + + for (File file : files) { + if (file != null) { + file.delete(); + } + } + + testDir.delete(); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug5045464.java b/test/jdk/javax/swing/JFileChooser/bug5045464.java new file mode 100644 index 00000000000..0fbeedcec6b --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug5045464.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5045464 + * @requires (os.family == "linux") + * @summary Regression: GTK L&F, JFileChooser shows "null/" in folder list + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug5045464 + */ + +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug5045464 { + private static final String INSTRUCTIONS = """ + When the filechooser appears check the directory list (the left list). + If it starts with two items: "./" (current directory) + and "../" (parent directory) press PASS. + If something else is here (e.g. "null/" instead of "./") + press FAIL. + """; + + public static void main(String[] argv) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug5045464::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JFileChooser fc = new JFileChooser(); + fc.setControlButtonsAreShown(false); + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch (Exception ex) { + throw new RuntimeException("Test Failed!", ex); + } + SwingUtilities.updateComponentTreeUI(fc); + return fc; + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug6515169.java b/test/jdk/javax/swing/JFileChooser/bug6515169.java new file mode 100644 index 00000000000..98cd813eefb --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug6515169.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 6515169 + * @requires (os.family == "windows") + * @summary wrong grid header in JFileChooser + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug6515169 + */ + +import javax.swing.ButtonGroup; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug6515169 { + private static JFrame frame; + private static final String INSTRUCTIONS = """ + This test is to verify JFileChooser on Windows and Metal LAF. + Use the "Change LaF" menu to switch between the 2 LaF + and verify the following. + + a. Change view mode to "Details" + b. Check that 4 columns appear: Name, Size, Type and Date Modified + c. Change current directory by pressing any available subdirectory + or by pressing button "Up One Level". + d. Check that still four columns exist. + + Change LaF and repeat the steps a-d. + If all conditions are true press PASS, else FAIL. + """; + + public static void main(String[] argv) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug6515169::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + frame = new JFrame("bug6515169"); + JMenuBar bar = new JMenuBar(); + JMenu lafMenu = new JMenu("Change LaF"); + ButtonGroup lafGroup = new ButtonGroup(); + JCheckBoxMenuItem lafItem1 = new JCheckBoxMenuItem("Window LaF"); + lafItem1.addActionListener(e -> + setLaF(UIManager.getSystemLookAndFeelClassName())); + lafGroup.add(lafItem1); + lafMenu.add(lafItem1); + + JCheckBoxMenuItem lafItem2 = new JCheckBoxMenuItem("Metal LaF"); + lafItem2.addActionListener(e -> + setLaF(UIManager.getCrossPlatformLookAndFeelClassName())); + lafGroup.add(lafItem2); + lafMenu.add(lafItem2); + + bar.add(lafMenu); + frame.setJMenuBar(bar); + + String dir = "."; + JFileChooser fc = new JFileChooser(dir); + fc.setControlButtonsAreShown(false); + frame.add(fc); + frame.pack(); + + return frame; + } + + private static void setLaF(String laf) { + try { + UIManager.setLookAndFeel(laf); + SwingUtilities.updateComponentTreeUI(frame); + } catch (Exception e) { + throw new RuntimeException("Test Failed!", e); + } + } +} From 4f58af0a8dd5eced77259bed180f6af36501f502 Mon Sep 17 00:00:00 2001 From: Alexey Bakhtin Date: Sat, 19 Apr 2025 00:30:37 +0000 Subject: [PATCH 260/843] 8259540: MissingResourceException for key cvc-complex-type.2.4.d.1 Reviewed-by: joehw --- .../apache/xerces/internal/impl/msg/XMLSchemaMessages.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties index f6402e8f65e..4f15b428c8b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties @@ -56,6 +56,7 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: The content of element ''{0}'' is not complete. One of ''{1}'' is expected. cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ''{0}''. cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Invalid content was found starting with element ''{0}''. No child element is expected at this point. + cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: Invalid content was found starting with element ''{0}''. No child element ''{1}'' is expected at this point. cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}'' can occur a maximum of ''{2}'' times in the current sequence. This limit was exceeded. At this point one of ''{1}'' is expected. cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}'' can occur a maximum of ''{1}'' times in the current sequence. This limit was exceeded. No child element is expected at this point. cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. One more instance is required to satisfy this constraint. From c7c77eb6aa25cbf84ba4b7519e16c092c222e504 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 19 Apr 2025 07:48:54 +0000 Subject: [PATCH 261/843] 8354077: Get rid of offscreenSharingEnabled windows flag Reviewed-by: prr --- .../sun/java2d/windows/WindowsFlags.java | 32 ++----------------- .../libawt/java2d/windows/WindowsFlags.cpp | 9 +----- .../libawt/java2d/windows/WindowsFlags.h | 4 +-- 3 files changed, 4 insertions(+), 41 deletions(-) diff --git a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java index 5bf2ba3227f..7333eeda3dd 100644 --- a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java +++ b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,16 +55,6 @@ public class WindowsFlags { * This flag can force us to use d3d * anyway in these situations. Or, this flag can force us to * not use d3d in a situation where we would use it otherwise. - * offscreenSharingEnabled: usage: "-Dsun.java2d.offscreenSharing=true" - * Turns on the ability to share a hardware-accelerated - * offscreen surface through the JAWT interface. See - * src/windows/native/sun/windows/awt_DrawingSurface.* for - * more information. This capability is disabled by default - * pending more testing and time to work out the right - * solution; we do not want to expose more public JAWT api - * without being very sure that we will be willing to support - * that API in the future regardless of other native - * rendering pipeline changes. * magPresent: usage: "-Djavax.accessibility.screen_magnifier_present" * This flag is set either on the command line or in the * properties file. It tells Swing whether the user is @@ -101,7 +91,6 @@ public class WindowsFlags { private static boolean d3dOnScreenEnabled; private static boolean oglEnabled; private static boolean oglVerbose; - private static boolean offscreenSharingEnabled; private static boolean magPresent; private static boolean setHighDPIAware; // TODO: other flags, including nopixfmt @@ -206,8 +195,6 @@ public class WindowsFlags { if (d3dSet) { d3dVerbose = isBooleanPropTrueVerbose("sun.java2d.d3d"); } - offscreenSharingEnabled = - getBooleanProp("sun.java2d.offscreenSharing", false); String dpiOverride = System.getProperty("sun.java2d.dpiaware"); if (dpiOverride != null) { setHighDPIAware = dpiOverride.equalsIgnoreCase("true"); @@ -217,16 +204,6 @@ public class WindowsFlags { setHighDPIAware = sunLauncherProperty.equalsIgnoreCase("SUN_STANDARD"); } - /* - // Output info based on some non-default flags: - if (offscreenSharingEnabled) { - System.out.println( - "Warning: offscreenSharing has been enabled. " + - "The use of this capability will change in future " + - "releases and applications that depend on it " + - "may not work correctly"); - } - */ /* System.out.println("WindowsFlags (Java):"); System.out.println(" ddEnabled: " + ddEnabled + "\n" + @@ -235,8 +212,7 @@ public class WindowsFlags { " d3dSet: " + d3dSet + "\n" + " oglEnabled: " + oglEnabled + "\n" + " oglVerbose: " + oglVerbose + "\n" + - " gdiBlitEnabled: " + gdiBlitEnabled + "\n" + - " offscreenSharingEnabled: " + offscreenSharingEnabled); + " gdiBlitEnabled: " + gdiBlitEnabled); */ } @@ -260,10 +236,6 @@ public class WindowsFlags { return gdiBlitEnabled; } - public static boolean isOffscreenSharingEnabled() { - return offscreenSharingEnabled; - } - public static boolean isMagPresent() { return magPresent; } diff --git a/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp b/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp index 528e95e326a..9ed0f38bd10 100644 --- a/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ BOOL useD3D = TRUE; // d3d enabled flag // initially is TRUE to allow D3D preloading BOOL forceD3DUsage; // force d3d on or off -jboolean g_offscreenSharing; // JAWT accelerated surface sharing BOOL setHighDPIAware; // Whether to set the high-DPI awareness flag extern WCHAR *j2dAccelKey; // Name of java2d root key @@ -89,10 +88,6 @@ void GetFlagValues(JNIEnv *env, jclass wFlagsClass) } useD3D = d3dEnabled; forceD3DUsage = d3dSet; - g_offscreenSharing = GetStaticBoolean(env, wFlagsClass, - "offscreenSharingEnabled"); - JNU_CHECK_EXCEPTION(env); - setHighDPIAware = (IS_WINVISTA && GetStaticBoolean(env, wFlagsClass, "setHighDPIAware")); JNU_CHECK_EXCEPTION(env); @@ -102,8 +97,6 @@ void GetFlagValues(JNIEnv *env, jclass wFlagsClass) (useD3D ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " d3dSet = %s", (forceD3DUsage ? "true" : "false")); - J2dTraceLn1(J2D_TRACE_INFO, " offscreenSharing = %s", - (g_offscreenSharing ? "true" : "false")); J2dTraceLn1(J2D_TRACE_INFO, " setHighDPIAware = %s", (setHighDPIAware ? "true" : "false")); } diff --git a/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.h b/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.h index 85ba1657000..d5e34fdaa69 100644 --- a/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.h +++ b/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.h @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +28,6 @@ extern BOOL useD3D; // d3d enabled flag extern BOOL forceD3DUsage; // force d3d on or off -extern jboolean g_offscreenSharing; // JAWT accelerated surface sharing extern BOOL setHighDPIAware; // whether to set High DPI Aware flag on Vista void SetD3DEnabledFlag(JNIEnv *env, BOOL d3dEnabled, BOOL d3dSet); From 128f2d1cadae3cf91e4c590e6dabe2086737b7dd Mon Sep 17 00:00:00 2001 From: Liming Liu Date: Sat, 19 Apr 2025 10:02:13 +0000 Subject: [PATCH 262/843] 8354572: Turn off AlwaysMergeDMB for Ampere CPU by default Reviewed-by: shade --- src/hotspot/cpu/aarch64/vm_version_aarch64.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index c555e393ca5..b2d34553487 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -161,6 +161,9 @@ void VM_Version::initialize() { (_model == CPU_MODEL_AMPERE_1A || _model == CPU_MODEL_AMPERE_1B)) { FLAG_SET_DEFAULT(CodeEntryAlignment, 32); } + if (FLAG_IS_DEFAULT(AlwaysMergeDMB)) { + FLAG_SET_DEFAULT(AlwaysMergeDMB, false); + } } // ThunderX From 4dd64b49716144cc697fb461ff88860e2cbcaaea Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Mon, 21 Apr 2025 11:41:45 +0000 Subject: [PATCH 263/843] 8354477: C2 SuperWord: make use of memory edges more explicit Reviewed-by: kvn, roland --- .../share/opto/superwordVTransformBuilder.cpp | 89 +++++++++---------- .../share/opto/superwordVTransformBuilder.hpp | 14 +-- src/hotspot/share/opto/vectorization.cpp | 4 + src/hotspot/share/opto/vectorization.hpp | 5 ++ src/hotspot/share/opto/vtransform.hpp | 5 +- 5 files changed, 62 insertions(+), 55 deletions(-) diff --git a/src/hotspot/share/opto/superwordVTransformBuilder.cpp b/src/hotspot/share/opto/superwordVTransformBuilder.cpp index d356fcd5109..83496f9d0be 100644 --- a/src/hotspot/share/opto/superwordVTransformBuilder.cpp +++ b/src/hotspot/share/opto/superwordVTransformBuilder.cpp @@ -34,9 +34,9 @@ void SuperWordVTransformBuilder::build() { // Connect all vtnodes with their inputs. Possibly create vtnodes for input // nodes that are outside the loop. - VectorSet vtn_dependencies; // Shared, but cleared for every vtnode. - build_inputs_for_vector_vtnodes(vtn_dependencies); - build_inputs_for_scalar_vtnodes(vtn_dependencies); + VectorSet vtn_memory_dependencies; // Shared, but cleared for every vtnode. + build_inputs_for_vector_vtnodes(vtn_memory_dependencies); + build_inputs_for_scalar_vtnodes(vtn_memory_dependencies); } void SuperWordVTransformBuilder::build_vector_vtnodes_for_packed_nodes() { @@ -58,75 +58,77 @@ void SuperWordVTransformBuilder::build_scalar_vtnodes_for_non_packed_nodes() { } } -void SuperWordVTransformBuilder::build_inputs_for_vector_vtnodes(VectorSet& vtn_dependencies) { +void SuperWordVTransformBuilder::build_inputs_for_vector_vtnodes(VectorSet& vtn_memory_dependencies) { for (int i = 0; i < _packset.length(); i++) { Node_List* pack = _packset.at(i); Node* p0 = pack->at(0); VTransformVectorNode* vtn = get_vtnode(p0)->isa_Vector(); assert(vtn != nullptr, "all packs must have vector vtnodes"); - vtn_dependencies.clear(); // Add every dependency only once per vtn. + vtn_memory_dependencies.clear(); // Add every memory dependency only once per vtn. if (p0->is_Load()) { - set_req_with_scalar(p0, vtn, vtn_dependencies, MemNode::Address); + set_req_with_scalar(p0, vtn, MemNode::Address); + for (uint k = 0; k < pack->size(); k++) { + add_memory_dependencies_of_node_to_vtnode(pack->at(k), vtn, vtn_memory_dependencies); + } } else if (p0->is_Store()) { - set_req_with_scalar(p0, vtn, vtn_dependencies, MemNode::Address); - set_req_with_vector(pack, vtn, vtn_dependencies, MemNode::ValueIn); + set_req_with_scalar(p0, vtn, MemNode::Address); + set_req_with_vector(pack, vtn, MemNode::ValueIn); + for (uint k = 0; k < pack->size(); k++) { + add_memory_dependencies_of_node_to_vtnode(pack->at(k), vtn, vtn_memory_dependencies); + } } else if (vtn->isa_ReductionVector() != nullptr) { - set_req_with_scalar(p0, vtn, vtn_dependencies, 1); // scalar init - set_req_with_vector(pack, vtn, vtn_dependencies, 2); // vector + set_req_with_scalar(p0, vtn, 1); // scalar init + set_req_with_vector(pack, vtn, 2); // vector } else { assert(vtn->isa_ElementWiseVector() != nullptr, "all other vtnodes are handled above"); if (VectorNode::is_scalar_rotate(p0) && p0->in(2)->is_Con() && Matcher::supports_vector_constant_rotates(p0->in(2)->get_int())) { - set_req_with_vector(pack, vtn, vtn_dependencies, 1); - set_req_with_scalar(p0, vtn, vtn_dependencies, 2); // constant rotation + set_req_with_vector(pack, vtn, 1); + set_req_with_scalar(p0, vtn, 2); // constant rotation } else if (VectorNode::is_roundopD(p0)) { - set_req_with_vector(pack, vtn, vtn_dependencies, 1); - set_req_with_scalar(p0, vtn, vtn_dependencies, 2); // constant rounding mode + set_req_with_vector(pack, vtn, 1); + set_req_with_scalar(p0, vtn, 2); // constant rounding mode } else if (p0->is_CMove()) { // Cmp + Bool + CMove -> VectorMaskCmp + VectorBlend. - set_all_req_with_vectors(pack, vtn, vtn_dependencies); + set_all_req_with_vectors(pack, vtn); VTransformBoolVectorNode* vtn_mask_cmp = vtn->in(1)->isa_BoolVector(); if (vtn_mask_cmp->test()._is_negated) { vtn->swap_req(2, 3); // swap if test was negated. } } else { - set_all_req_with_vectors(pack, vtn, vtn_dependencies); + set_all_req_with_vectors(pack, vtn); } } - - for (uint k = 0; k < pack->size(); k++) { - add_dependencies_of_node_to_vtnode(pack->at(k), vtn, vtn_dependencies); - } } } -void SuperWordVTransformBuilder::build_inputs_for_scalar_vtnodes(VectorSet& vtn_dependencies) { +void SuperWordVTransformBuilder::build_inputs_for_scalar_vtnodes(VectorSet& vtn_memory_dependencies) { for (int i = 0; i < _vloop_analyzer.body().body().length(); i++) { Node* n = _vloop_analyzer.body().body().at(i); VTransformScalarNode* vtn = get_vtnode(n)->isa_Scalar(); if (vtn == nullptr) { continue; } - vtn_dependencies.clear(); // Add every dependency only once per vtn. + vtn_memory_dependencies.clear(); // Add every dependency only once per vtn. if (n->is_Load()) { - set_req_with_scalar(n, vtn, vtn_dependencies, MemNode::Address); + set_req_with_scalar(n, vtn, MemNode::Address); + add_memory_dependencies_of_node_to_vtnode(n, vtn, vtn_memory_dependencies); } else if (n->is_Store()) { - set_req_with_scalar(n, vtn, vtn_dependencies, MemNode::Address); - set_req_with_scalar(n, vtn, vtn_dependencies, MemNode::ValueIn); + set_req_with_scalar(n, vtn, MemNode::Address); + set_req_with_scalar(n, vtn, MemNode::ValueIn); + add_memory_dependencies_of_node_to_vtnode(n, vtn, vtn_memory_dependencies); } else if (n->is_CountedLoop()) { continue; // Is "root", has no dependency. } else if (n->is_Phi()) { // CountedLoop Phi's: ignore backedge (and entry value). assert(n->in(0) == _vloop.cl(), "only Phi's from the CountedLoop allowed"); - set_req_with_scalar(n, vtn, vtn_dependencies, 0); + set_req_with_scalar(n, vtn, 0); continue; } else { - set_all_req_with_scalars(n, vtn, vtn_dependencies); + set_all_req_with_scalars(n, vtn); } - - add_dependencies_of_node_to_vtnode(n, vtn, vtn_dependencies); } } @@ -175,10 +177,9 @@ VTransformVectorNode* SuperWordVTransformBuilder::make_vector_vtnode_for_pack(co return vtn; } -void SuperWordVTransformBuilder::set_req_with_scalar(Node* n, VTransformNode* vtn, VectorSet& vtn_dependencies, const int index) { +void SuperWordVTransformBuilder::set_req_with_scalar(Node* n, VTransformNode* vtn, const int index) { VTransformNode* req = get_vtnode_or_wrap_as_input_scalar(n->in(index)); vtn->set_req(index, req); - vtn_dependencies.set(req->_idx); } // Either get the existing vtnode vector input (when input is a pack), or else make a @@ -273,46 +274,42 @@ VTransformNode* SuperWordVTransformBuilder::get_vtnode_or_wrap_as_input_scalar(N return vtn; } -void SuperWordVTransformBuilder::set_req_with_vector(const Node_List* pack, VTransformNode* vtn, VectorSet& vtn_dependencies, int j) { +void SuperWordVTransformBuilder::set_req_with_vector(const Node_List* pack, VTransformNode* vtn, int j) { VTransformNode* req = get_or_make_vtnode_vector_input_at_index(pack, j); vtn->set_req(j, req); - vtn_dependencies.set(req->_idx); } -void SuperWordVTransformBuilder::set_all_req_with_scalars(Node* n, VTransformNode* vtn, VectorSet& vtn_dependencies) { +void SuperWordVTransformBuilder::set_all_req_with_scalars(Node* n, VTransformNode* vtn) { assert(vtn->req() == n->req(), "scalars must have same number of reqs"); for (uint j = 0; j < n->req(); j++) { Node* def = n->in(j); if (def == nullptr) { continue; } - set_req_with_scalar(n, vtn, vtn_dependencies, j); + set_req_with_scalar(n, vtn, j); } } -void SuperWordVTransformBuilder::set_all_req_with_vectors(const Node_List* pack, VTransformNode* vtn, VectorSet& vtn_dependencies) { +void SuperWordVTransformBuilder::set_all_req_with_vectors(const Node_List* pack, VTransformNode* vtn) { Node* p0 = pack->at(0); assert(vtn->req() <= p0->req(), "must have at at most as many reqs"); // Vectors have no ctrl, so ignore it. for (uint j = 1; j < vtn->req(); j++) { Node* def = p0->in(j); if (def == nullptr) { continue; } - set_req_with_vector(pack, vtn, vtn_dependencies, j); + set_req_with_vector(pack, vtn, j); } } -void SuperWordVTransformBuilder::add_dependencies_of_node_to_vtnode(Node*n, VTransformNode* vtn, VectorSet& vtn_dependencies) { +void SuperWordVTransformBuilder::add_memory_dependencies_of_node_to_vtnode(Node*n, VTransformNode* vtn, VectorSet& vtn_memory_dependencies) { for (VLoopDependencyGraph::PredsIterator preds(_vloop_analyzer.dependency_graph(), n); !preds.done(); preds.next()) { Node* pred = preds.current(); if (!_vloop.in_bb(pred)) { continue; } + if (!preds.is_current_memory_edge()) { continue; } - // Only add memory dependencies to memory nodes. All others are taken care of with the req. - if (n->is_Mem() && !pred->is_Mem()) { continue; } - + // Only track every memory edge once. VTransformNode* dependency = get_vtnode(pred); + if (vtn_memory_dependencies.test_set(dependency->_idx)) { continue; } - // Reduction self-cycle? - if (vtn == dependency && _vloop_analyzer.reductions().is_marked_reduction(n)) { continue; } - - if (vtn_dependencies.test_set(dependency->_idx)) { continue; } - vtn->add_dependency(dependency); // Add every dependency only once per vtn. + assert(n->is_Mem() && pred->is_Mem(), "only memory edges"); + vtn->add_memory_dependency(dependency); // Add every dependency only once per vtn. } } diff --git a/src/hotspot/share/opto/superwordVTransformBuilder.hpp b/src/hotspot/share/opto/superwordVTransformBuilder.hpp index 847f870bef6..bff900377f6 100644 --- a/src/hotspot/share/opto/superwordVTransformBuilder.hpp +++ b/src/hotspot/share/opto/superwordVTransformBuilder.hpp @@ -54,8 +54,8 @@ private: void build(); void build_vector_vtnodes_for_packed_nodes(); void build_scalar_vtnodes_for_non_packed_nodes(); - void build_inputs_for_vector_vtnodes(VectorSet& vtn_dependencies); - void build_inputs_for_scalar_vtnodes(VectorSet& vtn_dependencies); + void build_inputs_for_vector_vtnodes(VectorSet& vtn_memory_dependencies); + void build_inputs_for_scalar_vtnodes(VectorSet& vtn_memory_dependencies); // Helper methods for building VTransform. VTransformNode* get_vtnode_or_null(Node* n) const { @@ -77,11 +77,11 @@ private: VTransformVectorNode* make_vector_vtnode_for_pack(const Node_List* pack) const; VTransformNode* get_or_make_vtnode_vector_input_at_index(const Node_List* pack, const int index); VTransformNode* get_vtnode_or_wrap_as_input_scalar(Node* n); - void set_req_with_scalar(Node* n, VTransformNode* vtn, VectorSet& vtn_dependencies, const int index); - void set_req_with_vector(const Node_List* pack, VTransformNode* vtn, VectorSet& vtn_dependencies, const int index); - void set_all_req_with_scalars(Node* n, VTransformNode* vtn, VectorSet& vtn_dependencies); - void set_all_req_with_vectors(const Node_List* pack, VTransformNode* vtn, VectorSet& vtn_dependencies); - void add_dependencies_of_node_to_vtnode(Node* n, VTransformNode* vtn, VectorSet& vtn_dependencies); + void set_req_with_scalar(Node* n, VTransformNode* vtn, const int index); + void set_req_with_vector(const Node_List* pack, VTransformNode* vtn, const int index); + void set_all_req_with_scalars(Node* n, VTransformNode* vtn); + void set_all_req_with_vectors(const Node_List* pack, VTransformNode* vtn); + void add_memory_dependencies_of_node_to_vtnode(Node* n, VTransformNode* vtn, VectorSet& vtn_memory_dependencies); }; #endif // SHARE_OPTO_SUPERWORD_VTRANSFORM_BUILDER_HPP diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp index e607a1065dd..d2cb62c92c9 100644 --- a/src/hotspot/share/opto/vectorization.cpp +++ b/src/hotspot/share/opto/vectorization.cpp @@ -399,6 +399,7 @@ VLoopDependencyGraph::PredsIterator::PredsIterator(const VLoopDependencyGraph& d _node(node), _dependency_node(dependency_graph.dependency_node(node)), _current(nullptr), + _is_current_memory_edge(false), _next_pred(0), _end_pred(node->req()), _next_memory_pred(0), @@ -418,11 +419,14 @@ VLoopDependencyGraph::PredsIterator::PredsIterator(const VLoopDependencyGraph& d void VLoopDependencyGraph::PredsIterator::next() { if (_next_pred < _end_pred) { _current = _node->in(_next_pred++); + _is_current_memory_edge = false; } else if (_next_memory_pred < _end_memory_pred) { int pred_bb_idx = _dependency_node->memory_pred_edge(_next_memory_pred++); _current = _dependency_graph._body.body().at(pred_bb_idx); + _is_current_memory_edge = true; } else { _current = nullptr; // done + _is_current_memory_edge = false; } } diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index d4b78515312..9d0887a993f 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -648,6 +648,7 @@ public: const DependencyNode* _dependency_node; Node* _current; + bool _is_current_memory_edge; // Iterate in node->in(i) int _next_pred; @@ -665,6 +666,10 @@ public: assert(!done(), "not done yet"); return _current; } + bool is_current_memory_edge() const { + assert(!done(), "not done yet"); + return _is_current_memory_edge; + } }; }; diff --git a/src/hotspot/share/opto/vtransform.hpp b/src/hotspot/share/opto/vtransform.hpp index 588da3cd56e..555f565360d 100644 --- a/src/hotspot/share/opto/vtransform.hpp +++ b/src/hotspot/share/opto/vtransform.hpp @@ -264,7 +264,8 @@ public: const VTransformNodeIDX _idx; private: - // _in is split into required inputs (_req), and additional dependencies. + // _in is split into required inputs (_req, i.e. all data dependencies), + // and memory dependencies. const uint _req; GrowableArray _in; GrowableArray _out; @@ -294,7 +295,7 @@ public: _in.at_put(j, tmp); } - void add_dependency(VTransformNode* n) { + void add_memory_dependency(VTransformNode* n) { assert(n != nullptr, "no need to add nullptr"); _in.push(n); n->add_out(this); From cd2d49f7119459f07844ce8201ca2320850cd51f Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Mon, 21 Apr 2025 17:37:58 +0000 Subject: [PATCH 264/843] 8354472: Clean up and open source KeyEvent related tests (Part 3) Reviewed-by: honkar --- .../awt/event/KeyEvent/CharUndefinedTest.java | 95 +++++++++++++ .../awt/event/KeyEvent/ExtendedKeysTest.java | 66 +++++++++ .../event/KeyEvent/KeyDownCaptureTest.java | 111 +++++++++++++++ .../event/KeyEvent/KeyEventToLightweight.java | 125 ++++++++++++++++ .../java/awt/event/KeyEvent/KeyModifiers.java | 134 ++++++++++++++++++ 5 files changed, 531 insertions(+) create mode 100644 test/jdk/java/awt/event/KeyEvent/CharUndefinedTest.java create mode 100644 test/jdk/java/awt/event/KeyEvent/ExtendedKeysTest.java create mode 100644 test/jdk/java/awt/event/KeyEvent/KeyDownCaptureTest.java create mode 100644 test/jdk/java/awt/event/KeyEvent/KeyEventToLightweight.java create mode 100644 test/jdk/java/awt/event/KeyEvent/KeyModifiers.java diff --git a/test/jdk/java/awt/event/KeyEvent/CharUndefinedTest.java b/test/jdk/java/awt/event/KeyEvent/CharUndefinedTest.java new file mode 100644 index 00000000000..bc58bdab14a --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/CharUndefinedTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4115484 4164672 4167893 + * @summary Ensures that KeyEvent has right keyChar for modifier and action keys. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CharUndefinedTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class CharUndefinedTest extends Frame implements KeyListener { + + static String INSTRUCTIONS = """ + Click on the text field inside the window named "Check KeyChar values". + Of any of the keys mentioned in this list that exist on your keyboard + press each of the listed keys once and also press them in two-key combinations such as + Control-Shift or Alt-Control. + The list of keys is: "Control, Shift, Meta, Alt, Command, Option". + After that press all function keys from F1 to F12 once, + Insert, Home, End, PageUp, PageDown and four arrow keys. + Check the log area below. If there are no messages starting with word "ERROR" + press "Pass" otherwise press "Fail". + """; + + public CharUndefinedTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + tf.requestFocus(); + } + + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { + PassFailJFrame.log("ERROR: KeyPressed: keyChar = " + e.getKeyChar() + + " keyCode = " + e.getKeyCode() + " " + e.getKeyText(e.getKeyCode())); + } + } + + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { + PassFailJFrame.log("ERROR: KeyTyped: keyChar = " + e.getKeyChar() + + " keyCode = " + e.getKeyCode() + " " + e.getKeyText(e.getKeyCode())); + } + } + + public void keyReleased(KeyEvent e) { + if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { + PassFailJFrame.log("ERROR: KeyReleased: keyChar = " + e.getKeyChar() + + " keyCode = " + e.getKeyCode() + " " + e.getKeyText(e.getKeyCode())); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .logArea(10) + .testUI(CharUndefinedTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/ExtendedKeysTest.java b/test/jdk/java/awt/event/KeyEvent/ExtendedKeysTest.java new file mode 100644 index 00000000000..1423b2a007e --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/ExtendedKeysTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4218892 4191924 4199284 + * @summary Unable to enter some chars via european keyboard layout(s) + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ExtendedKeysTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextArea; +import java.lang.reflect.InvocationTargetException; + +public class ExtendedKeysTest extends Frame { + static String INSTRUCTIONS = """ + This test requires Swiss German input. If the Swiss German input + can not be installed or configured press "Pass" to skip testing. + Click on the text area inside the window named "Check input". + Switch to Swiss German input and press key with "\\" on it + (usually this key is above or to the left of the main "Enter" key). + If you see a dollar sign press "Pass". + If you see any other character or question mark press "Fail". + """; + + public ExtendedKeysTest() { + super("Check input"); + setLayout(new BorderLayout()); + add(new TextArea(20, 20), "Center"); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(45) + .logArea(10) + .testUI(ExtendedKeysTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyDownCaptureTest.java b/test/jdk/java/awt/event/KeyEvent/KeyDownCaptureTest.java new file mode 100644 index 00000000000..bf2ab7ae958 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyDownCaptureTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4093998 + * @summary keyDown not called on subclasses of Component + * @key headful + * @run main KeyDownCaptureTest + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class KeyDownCaptureTest extends Frame implements KeyListener { + static AtomicBoolean passed = new AtomicBoolean(false); + + public KeyDownCaptureTest() { + super("Key Down Capture Test"); + } + + public void initUI() { + setLayout (new BorderLayout()); + setSize(200, 200); + setLocationRelativeTo(null); + Canvas canvas = new Canvas(); + canvas.setBackground(Color.RED); + canvas.addKeyListener(this); + add(canvas, BorderLayout.CENTER); + setVisible(true); + } + + public void middle(Point p) { + Point loc = getLocationOnScreen(); + Dimension size = getSize(); + p.setLocation(loc.x + (size.width / 2), loc.y + (size.height / 2)); + } + + @Override + public void keyTyped(KeyEvent ignore) {} + + @Override + public void keyPressed(KeyEvent e) { + passed.set(true); + } + + @Override + public void keyReleased(KeyEvent ignore) {} + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + KeyDownCaptureTest test = new KeyDownCaptureTest(); + try { + EventQueue.invokeAndWait((test::initUI)); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.delay(500); + robot.waitForIdle(); + Point target = new Point(); + EventQueue.invokeAndWait(() -> { + test.middle(target); + }); + robot.mouseMove(target.x, target.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SPACE); + robot.delay(100); + robot.waitForIdle(); + if (!passed.get()) { + throw new RuntimeException("KeyPressed has not arrived to canvas"); + } + } finally { + if (test != null) { + EventQueue.invokeAndWait(test::dispose); + } + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyEventToLightweight.java b/test/jdk/java/awt/event/KeyEvent/KeyEventToLightweight.java new file mode 100644 index 00000000000..de832bf2e6d --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyEventToLightweight.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4397557 + * @summary Check that focused lightweight component gets key events + * even if mouse is outside of it or on top of heavyweight component + * @key headful + * @run main KeyEventToLightweight + */ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.swing.JButton; + +public class KeyEventToLightweight extends Frame { + JButton lwbutton = new JButton("Select Me"); + Button hwbutton = new Button("Heavyweight"); + + AtomicBoolean aTyped = new AtomicBoolean(false); + AtomicBoolean bTyped = new AtomicBoolean(false); + AtomicBoolean cTyped = new AtomicBoolean(false); + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + KeyEventToLightweight test = new KeyEventToLightweight(); + try { + EventQueue.invokeAndWait(test::initUI); + test.performTest(); + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } + + public void initUI() { + this.setLayout(new FlowLayout()); + add(lwbutton); + add(hwbutton); + setSize(200, 200); + setLocationRelativeTo(null); + lwbutton.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_A) { + aTyped.set(true); + } else if (e.getKeyCode() == KeyEvent.VK_B) { + bTyped.set(true); + } else if (e.getKeyCode() == KeyEvent.VK_C) { + cTyped.set(true); + } + } + }); + setVisible(true); + } + + public void middleOf(Component c, Point p) { + Point loc = c.getLocationOnScreen(); + Dimension size = c.getSize(); + p.setLocation(loc.x + (size.width / 2), loc.y + (size.height / 2)); + } + + public void performTest() throws AWTException, InterruptedException, + InvocationTargetException { + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.delay(500); + robot.waitForIdle(); + Point target = new Point(); + EventQueue.invokeAndWait(() -> middleOf(lwbutton, target)); + robot.mouseMove(target.x, target.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(500); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); + robot.mouseMove(target.x - 200, target.y); + robot.keyPress(KeyEvent.VK_B); + robot.keyRelease(KeyEvent.VK_B); + robot.waitForIdle(); + robot.delay(500); + EventQueue.invokeAndWait(() -> middleOf(hwbutton, target)); + robot.mouseMove(target.x, target.y); + robot.keyPress(KeyEvent.VK_C); + robot.keyRelease(KeyEvent.VK_C); + if (!aTyped.get() || !bTyped.get() || !cTyped.get()) { + throw new RuntimeException("Key event was not delivered, case 1: " + + aTyped.get() + ", case 2: " + bTyped.get() + ", case 3: " + + cTyped.get()); + } + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/KeyModifiers.java b/test/jdk/java/awt/event/KeyEvent/KeyModifiers.java new file mode 100644 index 00000000000..13cc35581db --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/KeyModifiers.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4193779 4174399 + * @summary Ensures that KeyEvents have the right modifiers set + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jdk.test.lib.Platform + * @run main/manual KeyModifiers + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +import jdk.test.lib.Platform; + + +public class KeyModifiers extends Frame implements KeyListener { + public KeyModifiers() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + + String keys; + if (Platform.isWindows()) { + keys = "\"Shift-n\", \"Alt-n\"\n"; + } else if (Platform.isOSX()) { + keys = "\"Shift-n\", \"Alt-n\", \"Command-n\"\n"; + } else { + keys = "\"Shift-n\", \"Alt-n\", \"Meta-n\"\n"; + } + + String INSTRUCTIONS1 = """ + Click on the text field in the window named "Check KeyChar values" + and type the following key combinations: + """; + String INSTRUCTIONS2 = """ + After each combination check that the KeyPressed and KeyTyped modifiers + are correctly displayed. If modifiers are correct press "Pass", + otherwise press "Fail". + """; + PassFailJFrame.builder() + .title("KeyModifiers Test Instructions") + .instructions(INSTRUCTIONS1 + keys + INSTRUCTIONS2) + .columns(45) + .logArea(10) + .testUI(KeyModifiers::new) + .build() + .awaitAndCheck(); + } + + public void keyPressed(KeyEvent evt) { + int kc = evt.getKeyCode(); + + if (kc == KeyEvent.VK_CONTROL) { + return; + } + + if ((kc == KeyEvent.VK_SHIFT) || (kc == KeyEvent.VK_META) || + (kc == KeyEvent.VK_ALT) || (kc == KeyEvent.VK_ALT_GRAPH)) { + PassFailJFrame.log("Key pressed= " + KeyEvent.getKeyText(kc) + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } else { + PassFailJFrame.log("Key pressed = " + evt.getKeyChar() + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } + } + + public void keyTyped(KeyEvent evt) { + int kc = evt.getKeyCode(); + + if (kc == KeyEvent.VK_CONTROL) { + return; + } + + if ((kc == KeyEvent.VK_SHIFT) || (kc == KeyEvent.VK_META) || + (kc == KeyEvent.VK_ALT) || (kc == KeyEvent.VK_ALT_GRAPH)) { + PassFailJFrame.log("Key typed = " + KeyEvent.getKeyText(kc) + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } else { + PassFailJFrame.log("Key typed = " + evt.getKeyChar() + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } + } + + public void keyReleased(KeyEvent evt) { + int kc = evt.getKeyCode(); + + if (kc == KeyEvent.VK_CONTROL) + return; + + if ((kc == KeyEvent.VK_SHIFT) || (kc == KeyEvent.VK_META) || + (kc == KeyEvent.VK_ALT) || (kc == KeyEvent.VK_ALT_GRAPH)) { + PassFailJFrame.log("Key = released " + KeyEvent.getKeyText(kc) + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } else { + PassFailJFrame.log("Key released = " + evt.getKeyChar() + + " modifiers = " + InputEvent.getModifiersExText(evt.getModifiersEx())); + } + } +} From ecb54a05c6774e1a93d76b1181bda734129b6ace Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Mon, 21 Apr 2025 17:43:09 +0000 Subject: [PATCH 265/843] 8354523: runtime/Monitor/SyncOnValueBasedClassTest.java triggers SIGSEGV Co-authored-by: Martin Doerr Co-authored-by: Fei Yang Co-authored-by: Amit Kumar Reviewed-by: coleenp, aboldtch --- .../cpu/aarch64/c1_MacroAssembler_aarch64.cpp | 15 ++++++++------- .../cpu/aarch64/c2_MacroAssembler_aarch64.cpp | 2 +- .../cpu/aarch64/interp_masm_aarch64.cpp | 15 ++++++++------- .../cpu/aarch64/macroAssembler_aarch64.cpp | 9 ++++++++- src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp | 15 ++++++++------- src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp | 15 ++++++++------- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 18 +++++++++++++----- .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 15 ++++++++------- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 2 +- src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 15 ++++++++------- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 9 ++++++++- .../cpu/s390/c1_MacroAssembler_s390.cpp | 13 +++++++------ src/hotspot/cpu/s390/interp_masm_s390.cpp | 12 ++++++------ src/hotspot/cpu/s390/macroAssembler_s390.cpp | 10 ++++++++-- src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 13 +++++++------ src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 2 +- src/hotspot/cpu/x86/interp_masm_x86.cpp | 12 ++++++------ src/hotspot/cpu/x86/macroAssembler_x86.cpp | 8 +++++++- 18 files changed, 121 insertions(+), 79 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp index 6b1a5a7f1e0..afa2ddb47b4 100644 --- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp @@ -72,16 +72,17 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr null_check_offset = offset(); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(hdr, obj); - ldrb(hdr, Address(hdr, Klass::misc_flags_offset())); - tst(hdr, KlassFlags::_misc_is_value_based_class); - br(Assembler::NE, slow_case); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(disp_hdr, obj, hdr, temp, rscratch2, slow_case); } else if (LockingMode == LM_LEGACY) { + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(hdr, obj); + ldrb(hdr, Address(hdr, Klass::misc_flags_offset())); + tst(hdr, KlassFlags::_misc_is_value_based_class); + br(Assembler::NE, slow_case); + } + Label done; // Load object header ldr(hdr, Address(obj, hdr_offset)); diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index 605a05a44a7..56a91310dcd 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -360,7 +360,7 @@ void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Regist Label slow_path; if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. str(zr, Address(box, BasicLock::object_monitor_cache_offset_in_bytes())); } diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index d5ba85da989..dd1d7d1d2e1 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -693,17 +693,18 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) // Load object pointer into obj_reg %c_rarg3 ldr(obj_reg, Address(lock_reg, obj_offset)); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(tmp, obj_reg); - ldrb(tmp, Address(tmp, Klass::misc_flags_offset())); - tst(tmp, KlassFlags::_misc_is_value_based_class); - br(Assembler::NE, slow_case); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(lock_reg, obj_reg, tmp, tmp2, tmp3, slow_case); b(done); } else if (LockingMode == LM_LEGACY) { + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp, obj_reg); + ldrb(tmp, Address(tmp, Klass::misc_flags_offset())); + tst(tmp, KlassFlags::_misc_is_value_based_class); + br(Assembler::NE, slow_case); + } + // Load (object->mark() | 1) into swap_reg ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); orr(swap_reg, rscratch1, 1); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 1e226c70420..9a4b8e243a9 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -7034,10 +7034,17 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe ldr(mark, Address(obj, oopDesc::mark_offset_in_bytes())); if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. str(zr, Address(basic_lock, BasicObjectLock::lock_offset() + in_ByteSize((BasicLock::object_monitor_cache_offset_in_bytes())))); } + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(t1, obj); + ldrb(t1, Address(t1, Klass::misc_flags_offset())); + tst(t1, KlassFlags::_misc_is_value_based_class); + br(Assembler::NE, slow); + } + // Check if the lock-stack is full. ldrw(top, Address(rthread, JavaThread::lock_stack_top_offset())); cmpw(top, (unsigned)LockStack::end_offset()); diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index ac9c5984de0..77d3653aefd 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -83,16 +83,17 @@ void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox // Save object being locked into the BasicObjectLock... std(Roop, in_bytes(BasicObjectLock::obj_offset()), Rbox); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(Rscratch, Roop); - lbz(Rscratch, in_bytes(Klass::misc_flags_offset()), Rscratch); - testbitdi(CR0, R0, Rscratch, exact_log2(KlassFlags::_misc_is_value_based_class)); - bne(CR0, slow_int); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(Rbox, Roop, Rmark, Rscratch, slow_int); } else if (LockingMode == LM_LEGACY) { + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(Rscratch, Roop); + lbz(Rscratch, in_bytes(Klass::misc_flags_offset()), Rscratch); + testbitdi(CR0, R0, Rscratch, exact_log2(KlassFlags::_misc_is_value_based_class)); + bne(CR0, slow_int); + } + // ... and mark it unlocked. ori(Rmark, Rmark, markWord::unlocked_value); diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index 7a75dfd3de1..b51a0739d63 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -958,17 +958,18 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { // markWord displaced_header = obj->mark().set_unlocked(); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(tmp, object); - lbz(tmp, in_bytes(Klass::misc_flags_offset()), tmp); - testbitdi(CR0, R0, tmp, exact_log2(KlassFlags::_misc_is_value_based_class)); - bne(CR0, slow_case); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(monitor, object, header, tmp, slow_case); b(done); } else if (LockingMode == LM_LEGACY) { + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp, object); + lbz(tmp, in_bytes(Klass::misc_flags_offset()), tmp); + testbitdi(CR0, R0, tmp, exact_log2(KlassFlags::_misc_is_value_based_class)); + bne(CR0, slow_case); + } + // Load markWord from object into header. ld(header, oopDesc::mark_offset_in_bytes(), object); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index f82395b14fb..ca0a1344d14 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -3000,7 +3000,7 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister fla Label slow_path; if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. li(tmp1, 0); std(tmp1, in_bytes(BasicObjectLock::lock_offset()) + BasicLock::object_monitor_cache_offset_in_bytes(), box); } @@ -4999,19 +4999,27 @@ void MacroAssembler::atomically_flip_locked_state(bool is_unlock, Register obj, // - t1, t2: temporary register void MacroAssembler::lightweight_lock(Register box, Register obj, Register t1, Register t2, Label& slow) { assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking"); - assert_different_registers(box, obj, t1, t2); + assert_different_registers(box, obj, t1, t2, R0); Label push; - const Register top = t1; - const Register mark = t2; const Register t = R0; if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. li(t, 0); std(t, in_bytes(BasicObjectLock::lock_offset()) + BasicLock::object_monitor_cache_offset_in_bytes(), box); } + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(t1, obj); + lbz(t1, in_bytes(Klass::misc_flags_offset()), t1); + testbitdi(CR0, R0, t1, exact_log2(KlassFlags::_misc_is_value_based_class)); + bne(CR0, slow); + } + + const Register top = t1; + const Register mark = t2; + // Check if the lock-stack is full. lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread); cmplwi(CR0, top, LockStack::end_offset()); diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp index 76089e8dd45..29bf3e5f2ed 100644 --- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp @@ -61,16 +61,17 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr null_check_offset = offset(); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(hdr, obj); - lbu(hdr, Address(hdr, Klass::misc_flags_offset())); - test_bit(temp, hdr, exact_log2(KlassFlags::_misc_is_value_based_class)); - bnez(temp, slow_case, true /* is_far */); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(disp_hdr, obj, hdr, temp, t1, slow_case); } else if (LockingMode == LM_LEGACY) { + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(hdr, obj); + lbu(hdr, Address(hdr, Klass::misc_flags_offset())); + test_bit(temp, hdr, exact_log2(KlassFlags::_misc_is_value_based_class)); + bnez(temp, slow_case, /* is_far */ true); + } + Label done; // Load object header ld(hdr, Address(obj, hdr_offset)); diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index 99cbcedb8ff..39a49f8f1eb 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -289,7 +289,7 @@ void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Label slow_path; if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. sd(zr, Address(box, BasicLock::object_monitor_cache_offset_in_bytes())); } diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index f1f9414d98a..8be5408cb2b 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -736,17 +736,18 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) // Load object pointer into obj_reg c_rarg3 ld(obj_reg, Address(lock_reg, obj_offset)); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(tmp, obj_reg); - lbu(tmp, Address(tmp, Klass::misc_flags_offset())); - test_bit(tmp, tmp, exact_log2(KlassFlags::_misc_is_value_based_class)); - bnez(tmp, slow_case); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(lock_reg, obj_reg, tmp, tmp2, tmp3, slow_case); j(done); } else if (LockingMode == LM_LEGACY) { + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp, obj_reg); + lbu(tmp, Address(tmp, Klass::misc_flags_offset())); + test_bit(tmp, tmp, exact_log2(KlassFlags::_misc_is_value_based_class)); + bnez(tmp, slow_case); + } + // Load (object->mark() | 1) into swap_reg ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); ori(swap_reg, t0, 1); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index b5c311c341d..c6393be0714 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -6362,10 +6362,17 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe ld(mark, Address(obj, oopDesc::mark_offset_in_bytes())); if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. sd(zr, Address(basic_lock, BasicObjectLock::lock_offset() + in_ByteSize((BasicLock::object_monitor_cache_offset_in_bytes())))); } + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp1, obj); + lbu(tmp1, Address(tmp1, Klass::misc_flags_offset())); + test_bit(tmp1, tmp1, exact_log2(KlassFlags::_misc_is_value_based_class)); + bnez(tmp1, slow, /* is_far */ true); + } + // Check if the lock-stack is full. lwu(top, Address(xthread, JavaThread::lock_stack_top_offset())); mv(t, (unsigned)LockStack::end_offset()); diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp index 5691a2055b3..0e873250dca 100644 --- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp @@ -69,17 +69,18 @@ void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox // Save object being locked into the BasicObjectLock... z_stg(Roop, Address(Rbox, BasicObjectLock::obj_offset())); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(tmp, Roop); - z_tm(Address(tmp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); - branch_optimized(Assembler::bcondAllOne, slow_case); - } - assert(LockingMode != LM_MONITOR, "LM_MONITOR is already handled, by emit_lock()"); if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(Rbox, Roop, Rmark, tmp, slow_case); } else if (LockingMode == LM_LEGACY) { + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp, Roop); + z_tm(Address(tmp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); + branch_optimized(Assembler::bcondAllOne, slow_case); + } + NearLabel done; // Load object header. diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp index 48f4c7293a2..4ba99eb9e88 100644 --- a/src/hotspot/cpu/s390/interp_masm_s390.cpp +++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp @@ -1002,16 +1002,16 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { // markWord header = obj->mark().set_unlocked(); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(tmp, object); - z_tm(Address(tmp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); - z_btrue(slow_case); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(monitor, object, header, tmp, slow_case); } else if (LockingMode == LM_LEGACY) { + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp, object); + z_tm(Address(tmp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); + z_btrue(slow_case); + } + // Load markWord from object into header. z_lg(header, hdr_offset, object); diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 88aedd1b5c0..0129e604978 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -6363,11 +6363,17 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe z_lg(mark, Address(obj, mark_offset)); if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. const Address om_cache_addr = Address(basic_lock, BasicObjectLock::lock_offset() + in_ByteSize((BasicLock::object_monitor_cache_offset_in_bytes()))); z_mvghi(om_cache_addr, 0); } + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(temp1, obj); + z_tm(Address(temp1, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); + z_brne(slow); + } + // First we need to check if the lock-stack has room for pushing the object reference. z_lgf(top, Address(Z_thread, ls_top_offset)); @@ -6501,7 +6507,7 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(Register obj, Registe NearLabel slow_path; if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. z_mvghi(Address(box, BasicLock::object_monitor_cache_offset_in_bytes()), 0); } diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index b8873758b61..684347e35fa 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -55,16 +55,17 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr null_check_offset = offset(); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(hdr, obj, rscratch1); - testb(Address(hdr, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); - jcc(Assembler::notZero, slow_case); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(disp_hdr, obj, hdr, tmp, slow_case); } else if (LockingMode == LM_LEGACY) { Label done; + + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(hdr, obj, rscratch1); + testb(Address(hdr, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); + jcc(Assembler::notZero, slow_case); + } + // Load object header movptr(hdr, Address(obj, hdr_offset)); // and mark it as unlocked diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index a7967d83a4e..574bc081fce 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -476,7 +476,7 @@ void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Regist Label slow_path; if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. movptr(Address(box, BasicLock::object_monitor_cache_offset_in_bytes()), 0); } diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index bd029f2e4ac..d982495d883 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -1023,15 +1023,15 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) { // Load object pointer into obj_reg movptr(obj_reg, Address(lock_reg, obj_offset)); - if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(tmp_reg, obj_reg, rklass_decode_tmp); - testb(Address(tmp_reg, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); - jcc(Assembler::notZero, slow_case); - } - if (LockingMode == LM_LIGHTWEIGHT) { lightweight_lock(lock_reg, obj_reg, swap_reg, tmp_reg, slow_case); } else if (LockingMode == LM_LEGACY) { + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp_reg, obj_reg, rklass_decode_tmp); + testb(Address(tmp_reg, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); + jcc(Assembler::notZero, slow_case); + } + // Load immediate 1 into swap_reg %rax movl(swap_reg, 1); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 25de76a7e40..4d3bd12ed66 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -9584,10 +9584,16 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe movptr(reg_rax, Address(obj, oopDesc::mark_offset_in_bytes())); if (UseObjectMonitorTable) { - // Clear cache in case fast locking succeeds. + // Clear cache in case fast locking succeeds or we need to take the slow-path. movptr(Address(basic_lock, BasicObjectLock::lock_offset() + in_ByteSize((BasicLock::object_monitor_cache_offset_in_bytes()))), 0); } + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp, obj, rscratch1); + testb(Address(tmp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class); + jcc(Assembler::notZero, slow); + } + // Load top. movl(top, Address(thread, JavaThread::lock_stack_top_offset())); From 684d3b336e9cb31707d35e75f9b785e04e1fdbee Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Mon, 21 Apr 2025 18:25:59 +0000 Subject: [PATCH 266/843] 8354774: DocumentBuilderFactory getAttribute throws NPE Reviewed-by: naoto, lancea --- .../xsltc/trax/TransformerFactoryImpl.java | 15 +- .../xerces/internal/impl/PropertyManager.java | 34 +--- .../jaxp/DocumentBuilderFactoryImpl.java | 26 +-- .../internal/jaxp/DocumentBuilderImpl.java | 15 +- .../xerces/internal/jaxp/SAXParserImpl.java | 34 +--- .../jaxp/validation/XMLSchemaFactory.java | 22 +-- .../XMLSchemaValidatorComponentManager.java | 22 +-- .../classes/jdk/xml/internal/JdkXmlUtils.java | 43 ++++- .../jdk/xml/internal/XMLSecurityManager.java | 2 +- .../jaxp/libs/jaxp/library/JUnitTestUtil.java | 13 ++ .../jaxp/unittest/common/PropertiesTest.java | 162 ++++++++++++++++++ 11 files changed, 268 insertions(+), 120 deletions(-) create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/PropertiesTest.java diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java index 747ec8473fe..ee730d3900a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java @@ -371,17 +371,10 @@ public class TransformerFactoryImpl return _cdataChunkSize; } - /** Check to see if the property is managed by the security manager **/ - String propertyValue = (_xmlSecurityManager != null) ? - _xmlSecurityManager.getLimitAsString(name) : null; - if (propertyValue != null) { - return propertyValue; - } else { - propertyValue = (_xmlSecurityPropertyMgr != null) ? - _xmlSecurityPropertyMgr.getValue(name) : null; - if (propertyValue != null) { - return propertyValue; - } + //check if the property is managed by security manager + String value; + if ((value = JdkXmlUtils.getProperty(_xmlSecurityManager, _xmlSecurityPropertyMgr, name)) != null) { + return value; } // Throw an exception for all other attributes diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java index 2167c22e001..8d83f039617 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java @@ -27,13 +27,10 @@ package com.sun.org.apache.xerces.internal.impl; import com.sun.xml.internal.stream.StaxEntityResolverWrapper; import java.util.HashMap; import javax.xml.XMLConstants; -import javax.xml.catalog.CatalogFeatures; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLResolver; -import jdk.xml.internal.FeaturePropertyBase; import jdk.xml.internal.JdkConstants; -import jdk.xml.internal.JdkProperty; import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.XMLSecurityManager; import jdk.xml.internal.XMLSecurityPropertyManager; @@ -188,20 +185,13 @@ public class PropertyManager { if (XMLInputFactory.SUPPORT_DTD.equals(property)) { return fSecurityManager.is(XMLSecurityManager.Limit.STAX_SUPPORT_DTD); } - /** - * Check to see if the property is managed by the security manager * - */ - String propertyValue = (fSecurityManager != null) - ? fSecurityManager.getLimitAsString(property) : null; - /** - * Check to see if the property is managed by the security property - * manager - */ - if (propertyValue == null) { - propertyValue = (fSecurityPropertyMgr != null) - ? fSecurityPropertyMgr.getValue(property) : null; + + //check if the property is managed by security manager + String value; + if ((value = JdkXmlUtils.getProperty(fSecurityManager, fSecurityPropertyMgr, property)) != null) { + return value; } - return propertyValue != null ? propertyValue : supportedProps.get(property); + return supportedProps.get(property); } /** @@ -250,15 +240,9 @@ public class PropertyManager { return; } - //check if the property is managed by security manager - if (fSecurityManager == null - || !fSecurityManager.setLimit(property, JdkProperty.State.APIPROPERTY, value)) { - //check if the property is managed by security property manager - if (fSecurityPropertyMgr == null - || !fSecurityPropertyMgr.setValue(property, FeaturePropertyBase.State.APIPROPERTY, value)) { - //fall back to the existing property manager - supportedProps.put(property, value); - } + if (!JdkXmlUtils.setProperty(fSecurityManager, fSecurityPropertyMgr, property, value)) { + //fall back to the existing property manager + supportedProps.put(property, value); } if (equivalentProperty != null) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java index 6909f2b51ff..2939058e7d4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java @@ -29,7 +29,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.validation.Schema; -import jdk.xml.internal.JdkProperty; +import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.XMLSecurityManager; import jdk.xml.internal.XMLSecurityPropertyManager; import org.xml.sax.SAXException; @@ -114,20 +114,13 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { attributes = new HashMap<>(); } - //check if the property is managed by security manager - String pName; - if ((pName = fSecurityManager.find(name)) != null) { - // as the qName is deprecated, let the manager decide whether the - // value shall be changed - fSecurityManager.setLimit(name, JdkProperty.State.APIPROPERTY, value); - attributes.put(pName, fSecurityManager.getLimitAsString(pName)); + if (JdkXmlUtils.setProperty(fSecurityManager, fSecurityPropertyMgr, name, value)) { + // necessary as DocumentBuilder recreate property manager + // remove this line once that's changed + attributes.put(name, value); // no need to create a DocumentBuilderImpl return; - } else if ((pName = fSecurityPropertyMgr.find(name)) != null) { - attributes.put(pName, value); - return; } - attributes.put(name, value); // Test the attribute name by possibly throwing an exception @@ -146,13 +139,10 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { public Object getAttribute(String name) throws IllegalArgumentException { - //check if the property is managed by security manager - String pName; - if ((pName = fSecurityManager.find(name)) != null) { - return fSecurityManager.getLimitAsString(pName); - } else if ((pName = fSecurityPropertyMgr.find(name)) != null) { - return attributes.get(pName); + String value; + if ((value = JdkXmlUtils.getProperty(fSecurityManager, fSecurityPropertyMgr, name)) != null) { + return value; } // See if it's in the attributes Map diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java index a8af265c325..43b986b9939 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java @@ -43,7 +43,7 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; import jdk.xml.internal.FeaturePropertyBase.State; import jdk.xml.internal.JdkConstants; -import jdk.xml.internal.JdkProperty; +import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.XMLSecurityManager; import jdk.xml.internal.XMLSecurityPropertyManager; import jdk.xml.internal.XMLSecurityPropertyManager.Property; @@ -297,17 +297,10 @@ public class DocumentBuilderImpl extends DocumentBuilder } } } else { - //check if the property is managed by security manager - if (fSecurityManager == null || - !fSecurityManager.setLimit(name, JdkProperty.State.APIPROPERTY, val)) { - //check if the property is managed by security property manager - if (fSecurityPropertyMgr == null || - !fSecurityPropertyMgr.setValue(name, State.APIPROPERTY, val)) { - //fall back to the existing property manager - domParser.setProperty(name, val); - } + if (!JdkXmlUtils.setProperty(fSecurityManager, fSecurityPropertyMgr, name, val)) { + //fall back to the existing property manager + domParser.setProperty(name, val); } - } } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java index 053718c657d..fe435aabbcc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java @@ -43,7 +43,7 @@ import javax.xml.XMLConstants; import javax.xml.validation.Schema; import jdk.xml.internal.FeaturePropertyBase; import jdk.xml.internal.JdkConstants; -import jdk.xml.internal.JdkProperty; +import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.XMLSecurityManager; import jdk.xml.internal.XMLSecurityPropertyManager; import org.xml.sax.EntityResolver; @@ -569,20 +569,13 @@ public class SAXParserImpl extends javax.xml.parsers.SAXParser super.setProperty(name, value); } - //check if the property is managed by security manager - if (fSecurityManager == null || - !fSecurityManager.setLimit(name, JdkProperty.State.APIPROPERTY, value)) { - //check if the property is managed by security property manager - if (fSecurityPropertyMgr == null || - !fSecurityPropertyMgr.setValue(name, FeaturePropertyBase.State.APIPROPERTY, value)) { - //fall back to the existing property manager - if (!fInitProperties.containsKey(name)) { - fInitProperties.put(name, super.getProperty(name)); - } - super.setProperty(name, value); + if (!JdkXmlUtils.setProperty(fSecurityManager, fSecurityPropertyMgr, name, value)) { + //fall back to the existing property manager + if (!fInitProperties.containsKey(name)) { + fInitProperties.put(name, super.getProperty(name)); } + super.setProperty(name, value); } - } public synchronized Object getProperty(String name) @@ -596,19 +589,10 @@ public class SAXParserImpl extends javax.xml.parsers.SAXParser return fSAXParser.schemaLanguage; } - /** Check to see if the property is managed by the security manager **/ - String propertyValue = (fSecurityManager != null) ? - fSecurityManager.getLimitAsString(name) : null; - if (propertyValue != null) { - return propertyValue; - } else { - propertyValue = (fSecurityPropertyMgr != null) ? - fSecurityPropertyMgr.getValue(name) : null; - if (propertyValue != null) { - return propertyValue; - } + String value; + if ((value = JdkXmlUtils.getProperty(fSecurityManager, fSecurityPropertyMgr, name)) != null) { + return value; } - return super.getProperty(name); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java index 753fdea25cd..82960821f4d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java @@ -40,7 +40,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; import javax.xml.XMLConstants; -import javax.xml.catalog.CatalogFeatures.Feature; import javax.xml.stream.XMLEventReader; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; @@ -404,10 +403,11 @@ public final class XMLSchemaFactory extends SchemaFactory { } try { /** Check to see if the property is managed by the security manager **/ - String propertyValue = (fSecurityManager != null) ? - fSecurityManager.getLimitAsString(name) : null; - return propertyValue != null ? propertyValue : - fXMLSchemaLoader.getProperty(name); + String value; + if ((value = JdkXmlUtils.getProperty(fSecurityManager, fSecurityPropertyMgr, name)) != null) { + return value; + } + return fXMLSchemaLoader.getProperty(name); } catch (XMLConfigurationException e) { String identifier = e.getIdentifier(); @@ -513,15 +513,9 @@ public final class XMLSchemaFactory extends SchemaFactory { "property-not-supported", new Object [] {name})); } try { - //check if the property is managed by security manager - if (fSecurityManager == null || - !fSecurityManager.setLimit(name, JdkProperty.State.APIPROPERTY, object)) { - //check if the property is managed by security property manager - if (fSecurityPropertyMgr == null || - !fSecurityPropertyMgr.setValue(name, FeaturePropertyBase.State.APIPROPERTY, object)) { - //fall back to the existing property manager - fXMLSchemaLoader.setProperty(name, object); - } + if (!JdkXmlUtils.setProperty(fSecurityManager, fSecurityPropertyMgr, name, object)) { + //fall back to the existing property manager + fXMLSchemaLoader.setProperty(name, object); } } catch (XMLConfigurationException e) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java index bb4296349eb..419bfe4b250 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java @@ -48,7 +48,7 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import javax.xml.catalog.CatalogFeatures; import jdk.xml.internal.FeaturePropertyBase; import jdk.xml.internal.JdkConstants; -import jdk.xml.internal.JdkProperty; +import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.XMLSecurityManager; import jdk.xml.internal.XMLSecurityPropertyManager; import org.w3c.dom.ls.LSResourceResolver; @@ -353,7 +353,7 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin * Set the state of a feature. * * @param featureId The unique identifier (URI) of the feature. - * @param state The requested state of the feature (true or false). + * @param value The value of the feature (true or false). * * @exception XMLConfigurationException If the requested feature is not known. */ @@ -361,7 +361,7 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin if (PARSER_SETTINGS.equals(featureId)) { throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId); } - else if (value == false && (VALIDATION.equals(featureId) || SCHEMA_VALIDATION.equals(featureId))) { + else if (!value && (VALIDATION.equals(featureId) || SCHEMA_VALIDATION.equals(featureId))) { throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId); } else if (USE_GRAMMAR_POOL_ONLY.equals(featureId) && value != fUseGrammarPoolOnly) { @@ -452,18 +452,12 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin fComponents.put(propertyId, value); return; } - //check if the property is managed by security manager - if (fInitSecurityManager == null || - !fInitSecurityManager.setLimit(propertyId, JdkProperty.State.APIPROPERTY, value)) { - //check if the property is managed by security property manager - if (fSecurityPropertyMgr == null || - !fSecurityPropertyMgr.setValue(propertyId, FeaturePropertyBase.State.APIPROPERTY, value)) { - //fall back to the existing property manager - if (!fInitProperties.containsKey(propertyId)) { - fInitProperties.put(propertyId, super.getProperty(propertyId)); - } - super.setProperty(propertyId, value); + if (!JdkXmlUtils.setProperty(fInitSecurityManager, fSecurityPropertyMgr, propertyId, value)) { + //fall back to the existing property manager + if (!fInitProperties.containsKey(propertyId)) { + fInitProperties.put(propertyId, super.getProperty(propertyId)); } + super.setProperty(propertyId, value); } } diff --git a/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java b/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java index 1654c1b6cd5..93b63a746f1 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java +++ b/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,47 @@ public class JdkXmlUtils { private static final SAXParserFactory instance = getSAXFactory(false); } + /** + * Sets the property if it's managed by either XMLSecurityManager or XMLSecurityPropertyManager. + * @param xsm the XMLSecurityManager + * @param xspm the XMLSecurityPropertyManager + * @param property the property + * @param value the value + * @return true if the property is managed by either XMLSecurityManager or + * XMLSecurityPropertyManager, false otherwise + */ + public static boolean setProperty(XMLSecurityManager xsm, XMLSecurityPropertyManager xspm, + String property, Object value) { + if (xsm != null && xsm.find(property) != null) { + return xsm.setLimit(property, JdkProperty.State.APIPROPERTY, value); + + } else if (xspm != null && xspm.find(property) != null) { + return xspm.setValue(property, FeaturePropertyBase.State.APIPROPERTY, value); + } + return false; + } + + /** + * Returns the value of the property if it's managed by either XMLSecurityManager + * or XMLSecurityPropertyManager. + * @param xsm the XMLSecurityManager + * @param xspm the XMLSecurityPropertyManager + * @param property the property + * @return the value of the property if it's managed by either XMLSecurityManager + * or XMLSecurityPropertyManager, null otherwise + */ + public static String getProperty(XMLSecurityManager xsm, XMLSecurityPropertyManager xspm, + String property) { + String value = null; + if (xsm != null && (value = xsm.getLimitAsString(property)) != null) { + return value; + } + if (xspm != null) { + value = xspm.getValue(property); + } + return value; + } + /** * Returns the value. * diff --git a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java index 394bf28e02a..90c222de40e 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java +++ b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java @@ -361,7 +361,7 @@ public final class XMLSecurityManager { for (Limit limit : Limit.values()) { if (limit.is(propertyName)) { // current spec: new property name == systemProperty - return limit.systemProperty(); + return (limit.systemProperty != null) ? limit.systemProperty : limit.apiProperty; } } //ENTITYCOUNT's new name is qName diff --git a/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java b/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java index a31963f21de..f4eb3188242 100644 --- a/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java +++ b/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JUnitTestUtil.java @@ -32,6 +32,19 @@ public class JUnitTestUtil { public static final String CLS_DIR = System.getProperty("test.classes"); public static final String SRC_DIR = System.getProperty("test.src"); + // as in the Processors table in java.xml module summary + public enum Processor { + DOM, + SAX, + XMLREADER, + StAX, + VALIDATION, + TRANSFORM, + XSLTC, + DOMLS, + XPATH + }; + /** * Returns the System identifier (URI) of the source. * @param path the path to the source diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/PropertiesTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/PropertiesTest.java new file mode 100644 index 00000000000..1550c53794a --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/common/PropertiesTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package common; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLInputFactory; +import javax.xml.transform.TransformerFactory; +import javax.xml.validation.SchemaFactory; +import java.util.EnumSet; +import java.util.Set; +import java.util.stream.Stream; +import jaxp.library.JUnitTestUtil.Processor; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.xml.sax.XMLReader; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/* + * @test + * @bug 8354774 + * @summary Verifies JAXP API Properties as specified in the java.xml module. + * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest /test/lib + * @run junit/othervm common.PropertiesTest + */ +public class PropertiesTest { + private static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD; + private static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; + private static final String ACCESS_EXTERNAL_STYLESHEET = XMLConstants.ACCESS_EXTERNAL_STYLESHEET; + private static final String SP_ACCESS_EXTERNAL_DTD = "javax.xml.accessExternalDTD"; + private static final String SP_ACCESS_EXTERNAL_SCHEMA = "javax.xml.accessExternalSchema"; + private static final String SP_ACCESS_EXTERNAL_STYLESHEET = "javax.xml.accessExternalStylesheet"; + private static final String DEFAULT_VALUE = "all"; + /** + * Returns test data for testAccessExternalProperties + * @return test data for testAccessExternalProperties + */ + private static Stream testData() { + // Supported processors for Access External Properties + Set supportedProcessors1 = EnumSet.of(Processor.DOM, Processor.SAX, Processor.XMLREADER, + Processor.StAX, Processor.VALIDATION); + Set supportedProcessors2 = EnumSet.of(Processor.TRANSFORM); + + return Stream.of( + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_DTD, null, SP_ACCESS_EXTERNAL_DTD, null, DEFAULT_VALUE), + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_DTD, "http", SP_ACCESS_EXTERNAL_DTD, null, "http"), + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_DTD, null, SP_ACCESS_EXTERNAL_DTD, "https", "https"), + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_DTD, "http", SP_ACCESS_EXTERNAL_DTD, "https", "http"), + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_SCHEMA, null, SP_ACCESS_EXTERNAL_SCHEMA, null, DEFAULT_VALUE), + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_SCHEMA, "http", SP_ACCESS_EXTERNAL_SCHEMA, null, "http"), + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_SCHEMA, null, SP_ACCESS_EXTERNAL_SCHEMA, "https", "https"), + Arguments.of(supportedProcessors1, ACCESS_EXTERNAL_SCHEMA, "http", SP_ACCESS_EXTERNAL_SCHEMA, "https", "http"), + Arguments.of(supportedProcessors2, ACCESS_EXTERNAL_STYLESHEET, null, SP_ACCESS_EXTERNAL_STYLESHEET, null, DEFAULT_VALUE), + Arguments.of(supportedProcessors2, ACCESS_EXTERNAL_STYLESHEET, "http", SP_ACCESS_EXTERNAL_STYLESHEET, null, "http"), + Arguments.of(supportedProcessors2, ACCESS_EXTERNAL_STYLESHEET, null, SP_ACCESS_EXTERNAL_STYLESHEET, "https", "https"), + Arguments.of(supportedProcessors2, ACCESS_EXTERNAL_STYLESHEET, "http", SP_ACCESS_EXTERNAL_STYLESHEET, "https", "http") + ); + } + + /** + * Verifies that the Access External Properties are supported throughout the + * JAXP APIs. + * @param supportedProcessors the supported processors for the property + * @param apiProperty the API property + * @param apiValue the value of the API property + * @param sysProperty the System property corresponding to the API property + * @param sysValue the value of the System property + * @param expected the expected result + * @throws Exception if the test fails due to test configuration issues other + * than the expected result + */ + @ParameterizedTest + @MethodSource("testData") + public void testAccessExternalProperties(Set supportedProcessors, + String apiProperty, String apiValue, String sysProperty, String sysValue, + String expected) throws Exception { + for (Processor p : supportedProcessors) { + testProperties(p, apiProperty, apiValue, sysProperty, sysValue, + expected); + } + } + + /** + * Verifies that properties can be set via the JAXP APIs and their corresponding + * System Properties. + * @param processor the processor type + * @param apiProperty the API property + * @param apiValue the value to be set via the API property + * @param sysProperty the System Property + * @param sysValue the value to be set via the System property + * @param expected the expected result + * @throws Exception if the test fails, which can only happen if the property + * is set incorrectly. + */ + void testProperties(Processor processor, String apiProperty, String apiValue, + String sysProperty, String sysValue, String expected) + throws Exception { + Object ret1 = null; + if (sysValue != null) { + System.setProperty(sysProperty, sysValue); + } + switch (processor) { + case DOM: + DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); + if (apiValue != null) dbf.setAttribute(apiProperty, apiValue); + ret1 = dbf.getAttribute(apiProperty); + break; + case SAX: + SAXParser sp = SAXParserFactory.newDefaultInstance().newSAXParser(); + if (apiValue != null) sp.setProperty(apiProperty, apiValue); + ret1 = sp.getProperty(apiProperty); + break; + case XMLREADER: + XMLReader reader = SAXParserFactory.newDefaultInstance().newSAXParser().getXMLReader(); + if (apiValue != null) reader.setProperty(apiProperty, apiValue); + ret1 = reader.getProperty(apiProperty); + break; + case StAX: + XMLInputFactory xif = XMLInputFactory.newDefaultFactory(); + if (apiValue != null) xif.setProperty(apiProperty, apiValue); + ret1 = xif.getProperty(apiProperty); + break; + case VALIDATION: + SchemaFactory sf = SchemaFactory.newDefaultInstance(); + if (apiValue != null) sf.setProperty(apiProperty, apiValue); + ret1 = sf.getProperty(apiProperty); + break; + case TRANSFORM: + TransformerFactory tf = TransformerFactory.newDefaultInstance(); + if (apiValue != null) tf.setAttribute(apiProperty, apiValue); + ret1 = tf.getAttribute(apiProperty); + break; + } + + if (sysValue != null) System.clearProperty(sysProperty); + // property value is as expected + assertEquals(expected, ret1); + } +} From a7128d86eac2c40dbfa79811234ab6226fb4d080 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Mon, 21 Apr 2025 20:19:45 +0000 Subject: [PATCH 267/843] 8354653: Clean up and open source KeyEvent related tests (Part 4) Reviewed-by: serb --- .../java/awt/event/KeyEvent/AltGrTest.java | 90 +++++++++++++ test/jdk/java/awt/event/KeyEvent/CRTest.java | 124 ++++++++++++++++++ .../java/awt/event/KeyEvent/NumpadTest2.java | 108 +++++++++++++++ .../event/KeyEvent/TestDoubleKeyEvent.java | 87 ++++++++++++ 4 files changed, 409 insertions(+) create mode 100644 test/jdk/java/awt/event/KeyEvent/AltGrTest.java create mode 100644 test/jdk/java/awt/event/KeyEvent/CRTest.java create mode 100644 test/jdk/java/awt/event/KeyEvent/NumpadTest2.java create mode 100644 test/jdk/java/awt/event/KeyEvent/TestDoubleKeyEvent.java diff --git a/test/jdk/java/awt/event/KeyEvent/AltGrTest.java b/test/jdk/java/awt/event/KeyEvent/AltGrTest.java new file mode 100644 index 00000000000..9f771ea7e19 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/AltGrTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4122687 4209844 + * @summary Characters typed with AltGr have Alt bit set on + * KEY_TYPED events + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AltGrTest + */ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class AltGrTest extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + Switch to German (Germany) keyboard layout and type + few characters using key. + Note: on windows keyboards without an AltGr key, + you should use Ctrl-Alt to synthesize AltGr. + For example, on German keyboards, `@' is AltGr-Q + `{' is AltGr-7 and '[' is AltGr-8 + If you see the corresponding symbols appear in the text field + and there are no entries in log area starting with word "FAIL:" + press "Pass", otherwise press "Fail". + """; + + public AltGrTest() { + setLayout(new BorderLayout()); + TextField entry = new TextField(); + entry.addKeyListener(this); + add(entry, BorderLayout.CENTER); + pack(); + } + + public void keyTyped(KeyEvent e) { + PassFailJFrame.log("----"); + PassFailJFrame.log("Got " + e); + + if (e.isControlDown() || e.isAltDown()) { + PassFailJFrame.log("FAIL: character typed has following modifiers bits set:"); + PassFailJFrame.log((e.isControlDown() ? " Control" : "") + + (e.isAltDown() ? " Alt" : "")); + } + + if (!(e.isAltGraphDown())) { + PassFailJFrame.log("FAIL: AltGraph modifier is missing"); + } + } + + public void keyPressed(KeyEvent ignore) {} + public void keyReleased(KeyEvent ignore) {} + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(AltGrTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/CRTest.java b/test/jdk/java/awt/event/KeyEvent/CRTest.java new file mode 100644 index 00000000000..0cc17fd568e --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/CRTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4257434 + * @summary Ensures that the right results are produced by the + * carriage return keys. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CRTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicBoolean; + +public class CRTest extends Frame implements KeyListener, ActionListener { + StringBuilder error = new StringBuilder(); + AtomicBoolean actionCompleted = new AtomicBoolean(false); + static String INSTRUCTIONS = """ + This test requires keyboard with the numeric keypad (numpad). + If your keyboard does not have numpad press "Pass" to skip testing. + Click on the text field in window named "Check KeyChar values". + Press Enter on keypad. Then press Return key on a standard keyboard. + Then click on "Done" button. Test will pass or fail automatically. + """; + + public CRTest() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + + tf.addKeyListener(this); + tf.addActionListener(this); + + add(tf, BorderLayout.CENTER); + + Button done = new Button("Done"); + done.addActionListener((event) -> { + checkAndComplete(); + }); + add(done, BorderLayout.SOUTH); + pack(); + } + + public void checkAndComplete() { + if (!actionCompleted.get()) { + error.append("\nNo action received!"); + } + + if (!error.isEmpty()) { + PassFailJFrame.forceFail(error.toString()); + } else { + PassFailJFrame.forcePass(); + } + } + + public void keyPressed(KeyEvent evt) { + if ((evt.getKeyChar() != '\n') || (evt.getKeyCode() != KeyEvent.VK_ENTER)) { + error.append("\nKeyPressed: Unexpected code " + evt.getKeyCode()); + } else { + PassFailJFrame.log("KeyPressed Test PASSED"); + } + } + + public void keyTyped(KeyEvent evt) { + if ((evt.getKeyChar() != '\n') || (evt.getKeyCode() != KeyEvent.VK_UNDEFINED)) { + error.append("\nKeyTyped: Unexpected code " + evt.getKeyCode()); + } else { + PassFailJFrame.log("KeyTyped Test PASSED"); + } + } + + public void keyReleased(KeyEvent evt) { + if ((evt.getKeyChar() != '\n') || (evt.getKeyCode() != KeyEvent.VK_ENTER)) { + error.append("\nKeyReleased: Unexpected code " + evt.getKeyCode()); + } else { + PassFailJFrame.log("KeyReleased Test PASSED"); + } + } + + public void actionPerformed(ActionEvent evt) { + PassFailJFrame.log("ActionPerformed Test PASSED"); + actionCompleted.set(true); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(CRTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/NumpadTest2.java b/test/jdk/java/awt/event/KeyEvent/NumpadTest2.java new file mode 100644 index 00000000000..1ee47354318 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/NumpadTest2.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4279566 + * @summary Tests that numpad keys produce the correct key codes and + * key chars when both the NumLock and CapsLock are on. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual NumpadTest2 +*/ + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.lang.reflect.InvocationTargetException; + +public class NumpadTest2 extends Frame implements KeyListener { + static String INSTRUCTIONS = """ + Make sure that the NumLock and CapsLock are both ON. + Click on the text field inside the window named "Check KeyChar values" + Then, type the NumPad 7 key (not the regular 7 key). + Verify that the keyChar and keyCode is correct for each key pressed. + Remember that the keyCode for the KEY_TYPED event should be zero. + If 7 appears in the text field and the key code printed is correct + press "Pass", otherwise press "Fail". + + Key Name keyChar Keycode + ------------------------------------------------- + Numpad-7 Numpad-7 55 103 + """; + + public NumpadTest2() { + super("Check KeyChar values"); + setLayout(new BorderLayout()); + TextField tf = new TextField(30); + tf.addKeyListener(this); + add(tf, BorderLayout.CENTER); + pack(); + } + + public void keyPressed(KeyEvent evt) { + printKey(evt); + } + + public void keyTyped(KeyEvent evt) { + printKey(evt); + } + + public void keyReleased(KeyEvent evt) { + printKey(evt); + } + + protected void printKey(KeyEvent evt) { + switch (evt.getID()) { + case KeyEvent.KEY_TYPED: + break; + case KeyEvent.KEY_PRESSED: + break; + case KeyEvent.KEY_RELEASED: + break; + default: + System.out.println("Other Event "); + return; + } + + if (evt.isActionKey()) { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar() + " Action Key"); + } else { + PassFailJFrame.log("params= " + evt.paramString() + " KeyChar: " + + (int) evt.getKeyChar()); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(NumpadTest2::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/KeyEvent/TestDoubleKeyEvent.java b/test/jdk/java/awt/event/KeyEvent/TestDoubleKeyEvent.java new file mode 100644 index 00000000000..24e0bd553c8 --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/TestDoubleKeyEvent.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4495473 + * @summary Tests that when you press key on canvas-type heavyweight only one key event arrives + * @key headful + * @run main TestDoubleKeyEvent + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; +import javax.swing.JFrame; +import javax.swing.JWindow; +import javax.swing.JTextField; + +public class TestDoubleKeyEvent extends JFrame { + JWindow w; + JTextField tf; + + public void initUI() { + setLayout(new BorderLayout()); + setTitle("Double Key Event Test"); + setLocationRelativeTo(null); + setVisible(true); + w = new JWindow(this); + w.setLayout(new FlowLayout()); + tf = new JTextField(20); + w.add(tf); + w.pack(); + w.setLocationRelativeTo(null); + w.setVisible(true); + tf.requestFocus(); + } + + public void testAndClean() { + String str = tf.getText(); + w.dispose(); + dispose(); + if (str.length() != str.chars().distinct().count()) { + throw new RuntimeException("Duplicate characters found!"); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + TestDoubleKeyEvent test = new TestDoubleKeyEvent(); + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.waitForIdle(); + robot.delay(1000); + for (int i = 0; i < 15; i++) { + robot.keyPress(KeyEvent.VK_A + i); + robot.keyRelease(KeyEvent.VK_A + i); + robot.waitForIdle(); + } + robot.delay(1000); + EventQueue.invokeAndWait(test::testAndClean); + } +} From 8270cd0ad2e0df72f063f36853328a935595f71f Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Mon, 21 Apr 2025 20:23:15 +0000 Subject: [PATCH 268/843] 8353470: Clean up and open source couple AWT Graphics related tests (Part 2) Reviewed-by: serb --- test/jdk/ProblemList.txt | 1 + .../Graphics/GDIResourceExhaustionTest.java | 121 ++++++++++ .../awt/Graphics/RepeatedRepaintTest.java | 137 +++++++++++ .../java/awt/Graphics/SmallPrimitives.java | 224 ++++++++++++++++++ test/jdk/java/awt/Graphics/TextAfterXor.java | 123 ++++++++++ 5 files changed, 606 insertions(+) create mode 100644 test/jdk/java/awt/Graphics/GDIResourceExhaustionTest.java create mode 100644 test/jdk/java/awt/Graphics/RepeatedRepaintTest.java create mode 100644 test/jdk/java/awt/Graphics/SmallPrimitives.java create mode 100644 test/jdk/java/awt/Graphics/TextAfterXor.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 075ce0e9c10..e1e0a695ebc 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -143,6 +143,7 @@ java/awt/Focus/TestDisabledAutoTransfer.java 8159871 macosx-all,windows-all java/awt/Focus/TestDisabledAutoTransferSwing.java 6962362 windows-all java/awt/Focus/ActivateOnProperAppContextTest.java 8136516 macosx-all java/awt/Focus/FocusPolicyTest.java 7160904 linux-all +java/awt/Graphics/SmallPrimitives.java 8047070 macosx-all,linux-all java/awt/EventQueue/6980209/bug6980209.java 8198615 macosx-all java/awt/EventQueue/PushPopDeadlock/PushPopDeadlock.java 8024034 generic-all java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150 macosx-all diff --git a/test/jdk/java/awt/Graphics/GDIResourceExhaustionTest.java b/test/jdk/java/awt/Graphics/GDIResourceExhaustionTest.java new file mode 100644 index 00000000000..b8ba155da60 --- /dev/null +++ b/test/jdk/java/awt/Graphics/GDIResourceExhaustionTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 javax.imageio.ImageIO; +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4191297 + * @summary Tests that unreferenced GDI resources are correctly + * destroyed when no longer needed. + * @key headful + * @run main GDIResourceExhaustionTest + */ + +public class GDIResourceExhaustionTest extends Frame { + public void initUI() { + setSize(200, 200); + setUndecorated(true); + setLocationRelativeTo(null); + Panel labelPanel = new Panel(); + Label label = new Label("Red label"); + label.setBackground(Color.red); + labelPanel.add(label); + labelPanel.setLocation(20, 50); + add(labelPanel); + setVisible(true); + } + + public void paint(Graphics graphics) { + super.paint(graphics); + for (int rgb = 0; rgb <= 0xfff; rgb++) { + graphics.setColor(new Color(rgb)); + graphics.fillRect(0, 0, 5, 5); + } + } + + public void requestCoordinates(Rectangle r) { + Insets insets = getInsets(); + Point location = getLocationOnScreen(); + Dimension size = getSize(); + r.x = location.x + insets.left; + r.y = location.y + insets.top; + r.width = size.width - (insets.left + insets.right); + r.height = size.height - (insets.top + insets.bottom); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException, IOException { + GDIResourceExhaustionTest test = new GDIResourceExhaustionTest(); + try { + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.delay(2000); + Rectangle coords = new Rectangle(); + EventQueue.invokeAndWait(() -> { + test.requestCoordinates(coords); + }); + robot.mouseMove(coords.x - 50, coords.y - 50); + robot.waitForIdle(); + robot.delay(5000); + BufferedImage capture = robot.createScreenCapture(coords); + robot.delay(500); + boolean redFound = false; + int redRGB = Color.red.getRGB(); + for (int y = 0; y < capture.getHeight(); y++) { + for (int x = 0; x < capture.getWidth(); x++) { + if (capture.getRGB(x, y) == redRGB) { + redFound = true; + break; + } + if (redFound) { + break; + } + } + } + if (!redFound) { + File errorImage = new File("screenshot.png"); + ImageIO.write(capture, "png", errorImage); + throw new RuntimeException("Red label is not detected, possibly GDI resources exhausted"); + } + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } +} diff --git a/test/jdk/java/awt/Graphics/RepeatedRepaintTest.java b/test/jdk/java/awt/Graphics/RepeatedRepaintTest.java new file mode 100644 index 00000000000..140cb48630d --- /dev/null +++ b/test/jdk/java/awt/Graphics/RepeatedRepaintTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4081126 4129709 + * @summary Test for proper repainting on multiprocessor systems. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual RepeatedRepaintTest + */ +public class RepeatedRepaintTest extends Frame { + private Font font = null; + private Image background; + + static String INSTRUCTIONS = """ + The frame next to this window called "AWT Draw Test" has + some elements drawn on it. Move this window partially outside of the + screen bounds and then drag it back. Repeat it couple of times. + Drag the instructions window over the frame partially obscuring it. + If after number of attempts the frame content stops repainting + press "Fail", otherwise press "Pass". + """; + + public RepeatedRepaintTest() { + setTitle("AWT Draw Test"); + setSize(300, 300); + background = new BufferedImage(300, 300, BufferedImage.TYPE_INT_ARGB); + Graphics g = background.getGraphics(); + g.setColor(Color.black); + g.fillRect(0, 0, 300, 300); + g.dispose(); + } + + public void paint(Graphics g) { + Dimension dim = this.getSize(); + super.paint(g); + g.drawImage(background, 0, 0, dim.width, dim.height, null); + g.setColor(Color.white); + if (font == null) { + font = new Font("SansSerif", Font.PLAIN, 24); + } + g.setFont(font); + FontMetrics metrics = g.getFontMetrics(); + String message = "Draw Test"; + g.drawString(message, (dim.width / 2) - (metrics.stringWidth(message) / 2), + (dim.height / 2) + (metrics.getHeight() / 2)); + + int counter = 50; + for (int i = 0; i < 50; i++) { + counter += 4; + g.drawOval(counter, 50, i, i); + } + + counter = 20; + for (int i = 0; i < 100; i++) { + counter += 4; + g.drawOval(counter, 150, i, i); + } + g.setColor(Color.black); + g.drawLine(0, dim.height - 25, dim.width, dim.height - 25); + g.setColor(Color.gray); + g.drawLine(0, dim.height - 24, dim.width, dim.height - 24); + g.setColor(Color.lightGray); + g.drawLine(0, dim.height - 23, dim.width, dim.height - 23); + g.fillRect(0, dim.height - 22, dim.width, dim.height); + + + g.setXORMode(Color.blue); + g.fillRect(0, 0, 25, dim.height - 26); + g.setColor(Color.red); + g.fillRect(0, 0, 25, dim.height - 26); + g.setColor(Color.green); + g.fillRect(0, 0, 25, dim.height - 26); + g.setPaintMode(); + + Image img = createImage(50, 50); + Graphics imgGraphics = img.getGraphics(); + imgGraphics.setColor(Color.magenta); + imgGraphics.fillRect(0, 0, 50, 50); + imgGraphics.setColor(Color.yellow); + imgGraphics.drawString("offscreen", 0, 20); + imgGraphics.drawString("image", 0, 30); + + g.drawImage(img, dim.width - 100, dim.height - 100, Color.blue, null); + + g.setXORMode(Color.white); + drawAt(g, 100, 100, 50, 50); + drawAt(g, 105, 105, 50, 50); + drawAt(g, 110, 110, 50, 50); + } + + public void drawAt(Graphics g, int x, int y, int width, int height) { + g.setColor(Color.magenta); + g.fillRect(x, y, width, height); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Repeated Repaint Test Instructions") + .instructions(INSTRUCTIONS) + .testUI(RepeatedRepaintTest::new) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/Graphics/SmallPrimitives.java b/test/jdk/java/awt/Graphics/SmallPrimitives.java new file mode 100644 index 00000000000..7eb267cf0b9 --- /dev/null +++ b/test/jdk/java/awt/Graphics/SmallPrimitives.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Polygon; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4411814 4298688 4205762 4524760 4067534 + * @summary Check that Graphics rendering primitives function + * correctly when fed small and degenerate shapes + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SmallPrimitives + */ + + +public class SmallPrimitives extends Panel { + + static String INSTRUCTIONS = """ + In the borderless frame next to this window there should be a + set of tiny narrow blue polygons painted next to the green rectangles. + If rectangle is vertical the corresponding polygon is painted to the right of it, + if rectangle is horizontal the polygon is painted below it. + The length of the polygon should be roughly the same as the length of the + green rectangle next to it. If size is significantly different or any of the + polygons is not painted press "Fail" otherwise press "Pass". + Note: one may consider using screen magnifier to compare sizes. + """; + + public void paint(Graphics g) { + Dimension d = getSize(); + Polygon p; + GeneralPath gp; + + g.setColor(Color.white); + g.fillRect(0, 0, d.width, d.height); + + // Reposition for horizontal tests (below) + g.translate(0, 20); + + // Reference shapes + g.setColor(Color.green); + g.fillRect(10, 7, 11, 1); + g.fillRect(10, 17, 11, 2); + g.fillRect(10, 27, 11, 1); + g.fillRect(10, 37, 11, 1); + g.fillRect(10, 47, 11, 2); + g.fillRect(10, 57, 11, 2); + g.fillRect(10, 67, 11, 1); + g.fillRect(10, 77, 11, 2); + g.fillRect(10, 87, 11, 1); + g.fillRect(10, 97, 11, 1); + g.fillRect(10, 107, 11, 1); + g.fillRect(10, 117, 6, 1); g.fillRect(20, 117, 6, 1); + + // Potentially problematic test shapes + g.setColor(Color.blue); + g.drawRect(10, 10, 10, 0); + g.drawRect(10, 20, 10, 1); + g.drawRoundRect(10, 30, 10, 0, 0, 0); + g.drawRoundRect(10, 40, 10, 0, 4, 4); + g.drawRoundRect(10, 50, 10, 1, 0, 0); + g.drawRoundRect(10, 60, 10, 1, 4, 4); + g.drawOval(10, 70, 10, 0); + g.drawOval(10, 80, 10, 1); + p = new Polygon(); + p.addPoint(10, 90); + p.addPoint(20, 90); + g.drawPolyline(p.xpoints, p.ypoints, p.npoints); + p = new Polygon(); + p.addPoint(10, 100); + p.addPoint(20, 100); + g.drawPolygon(p.xpoints, p.ypoints, p.npoints); + ((Graphics2D) g).draw(new Line2D.Double(10, 110, 20, 110)); + gp = new GeneralPath(); + gp.moveTo(10, 120); + gp.lineTo(15, 120); + gp.moveTo(20, 120); + gp.lineTo(25, 120); + ((Graphics2D) g).draw(gp); + + // Polygon limit tests + p = new Polygon(); + trypoly(g, p); + p.addPoint(10, 120); + trypoly(g, p); + + // Reposition for vertical tests (below) + g.translate(20, -20); + + // Reference shapes + g.setColor(Color.green); + g.fillRect(7, 10, 1, 11); + g.fillRect(17, 10, 2, 11); + g.fillRect(27, 10, 1, 11); + g.fillRect(37, 10, 1, 11); + g.fillRect(47, 10, 2, 11); + g.fillRect(57, 10, 2, 11); + g.fillRect(67, 10, 1, 11); + g.fillRect(77, 10, 2, 11); + g.fillRect(87, 10, 1, 11); + g.fillRect(97, 10, 1, 11); + g.fillRect(107, 10, 1, 11); + g.fillRect(117, 10, 1, 6); g.fillRect(117, 20, 1, 6); + + // Potentially problematic test shapes + g.setColor(Color.blue); + g.drawRect(10, 10, 0, 10); + g.drawRect(20, 10, 1, 10); + g.drawRoundRect(30, 10, 0, 10, 0, 0); + g.drawRoundRect(40, 10, 0, 10, 4, 4); + g.drawRoundRect(50, 10, 1, 10, 0, 0); + g.drawRoundRect(60, 10, 1, 10, 4, 4); + g.drawOval(70, 10, 0, 10); + g.drawOval(80, 10, 1, 10); + p = new Polygon(); + p.addPoint(90, 10); + p.addPoint(90, 20); + g.drawPolyline(p.xpoints, p.ypoints, p.npoints); + p = new Polygon(); + p.addPoint(100, 10); + p.addPoint(100, 20); + g.drawPolygon(p.xpoints, p.ypoints, p.npoints); + ((Graphics2D) g).draw(new Line2D.Double(110, 10, 110, 20)); + gp = new GeneralPath(); + gp.moveTo(120, 10); + gp.lineTo(120, 15); + gp.moveTo(120, 20); + gp.lineTo(120, 25); + ((Graphics2D) g).draw(gp); + + // Polygon limit tests + p = new Polygon(); + trypoly(g, p); + p.addPoint(110, 10); + trypoly(g, p); + + // Reposition for oval tests + g.translate(0, 20); + + for (int i = 0, xy = 8; i < 11; i++) { + g.setColor(Color.green); + g.fillRect(xy, 5, i, 1); + g.fillRect(5, xy, 1, i); + g.setColor(Color.blue); + g.fillOval(xy, 8, i, 1); + g.fillOval(8, xy, 1, i); + xy += i + 2; + } + + g.translate(10, 10); + for (int i = 0, xy = 9; i < 6; i++) { + g.setColor(Color.green); + g.fillRect(xy, 5, i, 2); + g.fillRect(5, xy, 2, i); + g.setColor(Color.blue); + g.fillOval(xy, 8, i, 2); + g.fillOval(8, xy, 2, i); + xy += i + 2; + } + } + + public static void trypoly(Graphics g, Polygon p) { + g.drawPolygon(p); + g.drawPolygon(p.xpoints, p.ypoints, p.npoints); + g.drawPolyline(p.xpoints, p.ypoints, p.npoints); + g.fillPolygon(p); + g.fillPolygon(p.xpoints, p.ypoints, p.npoints); + } + + public Dimension getPreferredSize() { + return new Dimension(150, 150); + } + + public static Frame createFrame() { + Frame f = new Frame(); + SmallPrimitives sp = new SmallPrimitives(); + sp.setLocation(0, 0); + f.add(sp); + f.setUndecorated(true); + f.pack(); + return f; + } + + public static void main(String argv[]) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Small Primitives Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(SmallPrimitives::createFrame) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/Graphics/TextAfterXor.java b/test/jdk/java/awt/Graphics/TextAfterXor.java new file mode 100644 index 00000000000..c9dc56d8b80 --- /dev/null +++ b/test/jdk/java/awt/Graphics/TextAfterXor.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.RenderingHints; +import java.awt.image.VolatileImage; +import java.lang.reflect.InvocationTargetException; + +/* + * @test + * @bug 4505650 + * @summary Check that you can render solid text after doing XOR mode + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TextAfterXor + */ + +public class TextAfterXor extends Panel { + public static final int TESTW = 300; + public static final int TESTH = 100; + static String INSTRUCTIONS = """ + In the window called "Text After XOR Test" there should be two + composite components, at the bottom of each component the green text + "Test passes if this is green!" should be visible. + + On the top component this text should be green on all platforms. + On the bottom component it is possible that on non-Windows + platforms text can be of other color or not visible at all. + That does not constitute a problem. + + So if platform is Windows and green text appears twice or on any + other platform green text appears at least once press "Pass", + otherwise press "Fail". + """; + + VolatileImage vimg; + + public void paint(Graphics g) { + render(g); + g.drawString("(Drawing to screen)", 10, 60); + if (vimg == null) { + vimg = createVolatileImage(TESTW, TESTH); + } + do { + vimg.validate(null); + Graphics g2 = vimg.getGraphics(); + render(g2); + String not = vimg.getCapabilities().isAccelerated() ? "" : "not "; + g2.drawString("Image was " + not + "accelerated", 10, 55); + g2.drawString("(only matters on Windows)", 10, 65); + g2.dispose(); + g.drawImage(vimg, 0, TESTH, null); + } while (vimg.contentsLost()); + } + + public void render(Graphics g) { + g.setColor(Color.black); + g.fillRect(0, 0, TESTW, TESTH); + g.setColor(Color.white); + g.fillRect(5, 5, TESTW-10, TESTH-10); + + g.setColor(Color.black); + g.drawString("Test only passes if green string appears", 10, 20); + + g.setColor(Color.white); + g.setXORMode(Color.blue); + g.drawRect(30, 30, 10, 10); + g.setPaintMode(); + g.setColor(Color.green); + + ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.drawString("Test passes if this is green!", 10, 80); + + g.setColor(Color.black); + } + + public Dimension getPreferredSize() { + return new Dimension(TESTW, TESTH*2); + } + + public static Frame createFrame() { + Frame f = new Frame("Text After XOR Test"); + f.add(new TextAfterXor()); + f.pack(); + return f; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Text After XOR Instructions") + .instructions(INSTRUCTIONS) + .testUI(TextAfterXor::createFrame) + .build() + .awaitAndCheck(); + } +} From 1526dd81d9b5bf4abaac1546c370cf7a056d01dc Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Mon, 21 Apr 2025 20:24:20 +0000 Subject: [PATCH 269/843] 8354344: Test behavior after cut-over for future ISO 4217 currency Reviewed-by: naoto --- .../java/util/Currency/ValidateISO4217.java | 135 +++++++++++++++++- .../java/util/Currency/currency.properties | 2 + 2 files changed, 132 insertions(+), 5 deletions(-) diff --git a/test/jdk/java/util/Currency/ValidateISO4217.java b/test/jdk/java/util/Currency/ValidateISO4217.java index cd6e4f41a9f..607faefcfa4 100644 --- a/test/jdk/java/util/Currency/ValidateISO4217.java +++ b/test/jdk/java/util/Currency/ValidateISO4217.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,18 +26,44 @@ * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759 * 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269 * 8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653 + * 8354344 * @summary Validate ISO 4217 data for Currency class. * @modules java.base/java.util:open * jdk.localedata - * @run junit ValidateISO4217 + * @library /test/lib + * @run junit/othervm -DMOCKED.TIME=setup ValidateISO4217 + * @run main/othervm --patch-module java.base=${test.class.path} + * -DMOCKED.TIME=check -Djava.util.currency.data=${test.src}/currency.properties ValidateISO4217 + * @run junit/othervm --patch-module java.base=${test.class.path} + * -DMOCKED.TIME=true ValidateISO4217 + */ + +/* The run invocation order is important. The first invocation will generate + * class files for Currency that mock System.currentTimeMillis() as Long.MAX_VALUE, + * which is required by the subsequent invocations. The second invocation ensures that + * the module patch and mocked time are functioning correctly; it does not run any tests. + * The third invocation using the modded class files via a module patch allow us + * to test any cut-over dates after the transition. + * Valid MOCKED.TIME values are "setup", "check", and "true". */ import java.io.BufferedReader; import java.io.File; +import java.io.FileOutputStream; import java.io.FileReader; +import java.io.IOException; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.CodeTransform; +import java.lang.classfile.MethodTransform; +import java.lang.classfile.instruction.InvokeInstruction; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Paths; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Currency; import java.util.HashSet; import java.util.List; @@ -45,6 +71,7 @@ import java.util.Locale; import java.util.Set; import java.util.StringTokenizer; import java.util.TimeZone; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -113,10 +140,102 @@ public class ValidateISO4217 { {"XK", "EUR", "978", "2"}, // Kosovo }; private static SimpleDateFormat format = null; + private static final String MODULE_PATCH_LOCATION = + System.getProperty("test.classes") + "/java/util/"; + private static final String MOCKED_TIME = System.getProperty("MOCKED.TIME"); + + // Classes that should mock System.currentTimeMillis() + private static final String[] CLASSES = + Stream.concat( + Stream.of("Currency.class"), + Arrays.stream(Currency.class.getDeclaredClasses()) + .map(c -> "Currency$" + c.getSimpleName() + ".class") + ).toArray(String[]::new); + + // "check" invocation only runs the main method (and not any tests) to determine if the + // future time checking is correct + public static void main(String[] args) { + if (MOCKED_TIME.equals("check")) { + // Check that the module patch class files exist + checkModulePatchExists(); + // Check time is mocked + // Override for PK=PKR in test/currency.properties is PKZ - simple + // Override for PW=USD in test/currency.properties is MWP - special + assertEquals("PKZ", Currency.getInstance(Locale.of("", "PK")).getCurrencyCode(), + "Mocked time / module patch not working"); + assertEquals("MWP", Currency.getInstance(Locale.of("", "PW")).getCurrencyCode(), + "Mocked time / module patch not working"); + // Properly working. Do nothing and move to third invocation + } else { + throw new RuntimeException( + "Incorrect usage of ValidateISO4217. Main method invoked without proper system property value"); + } + } + + @BeforeAll + static void setUp() throws Exception { + checkUsage(); + setUpPatchedClasses(); + setUpTestingData(); + } + + // Enforce correct usage of ValidateISO4217 + static void checkUsage() { + if (MOCKED_TIME == null + || (!MOCKED_TIME.equals("setup") && !MOCKED_TIME.equals("true"))) { + throw new RuntimeException( + "Incorrect usage of ValidateISO4217. Missing \"MOCKED.TIME\" system property"); + } + if (MOCKED_TIME.equals("true")) { + checkModulePatchExists(); + } + } + + static void checkModulePatchExists() { + // Check that the module patch class files exist + for (String className : CLASSES) { + var file = new File(MODULE_PATCH_LOCATION + className); + assertTrue(file.isFile(), "Module patch class files missing"); + } + } + + // Patch the relevant classes required for module patch + static void setUpPatchedClasses() throws IOException { + if (MOCKED_TIME.equals("setup")) { + new File(MODULE_PATCH_LOCATION).mkdirs(); + for (String s : CLASSES) { + patchClass(s); + } + } + } + + // Mock calls of System.currentTimeMillis() within Currency to Long.MAX_VALUE. + // This effectively ensures that we are always past any cut-over dates. + private static void patchClass(String name) throws IOException { + CodeTransform codeTransform = (codeBuilder, e) -> { + switch (e) { + case InvokeInstruction i when + i.owner().asInternalName().equals("java/lang/System") + && i.name().equalsString("currentTimeMillis") -> + codeBuilder.loadConstant(Long.MAX_VALUE); // mock + default -> codeBuilder.accept(e); + } + }; + MethodTransform methodTransform = MethodTransform.transformingCode(codeTransform); + ClassTransform classTransform = ClassTransform.transformingMethods(methodTransform); + ClassFile cf = ClassFile.of(); + byte[] newBytes = cf.transformClass(cf.parse( + Files.readAllBytes(Paths.get(URI.create("jrt:/java.base/java/util/" + name)))), classTransform); + + String patchedClass = MODULE_PATCH_LOCATION + name; + var file = new File(patchedClass); + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(newBytes); + } + } // Sets up the following test data: // ISO4217Codes, additionalCodes, testCurrencies, codes - @BeforeAll static void setUpTestingData() throws Exception { // These functions laterally setup 'testCurrencies' and 'codes' // at the same time @@ -169,8 +288,8 @@ public class ValidateISO4217 { if (format == null) { createDateFormat(); } - // If the cut-over already passed, use the new curency for ISO4217Codes - if (format.parse(tokens.nextToken()).getTime() < System.currentTimeMillis()) { + // If the cut-over already passed, use the new currency for ISO4217Codes + if (format.parse(tokens.nextToken()).getTime() < currentTimeMillis()) { currency = tokens.nextToken(); numeric = tokens.nextToken(); minorUnit = tokens.nextToken(); @@ -320,4 +439,10 @@ public class ValidateISO4217 { bldr.append("\n"); return bldr.toString(); } + + // Either the current system time, or a mocked value equal to Long.MAX_VALUE + static long currentTimeMillis() { + var mocked = MOCKED_TIME.equals("true"); + return mocked ? Long.MAX_VALUE : System.currentTimeMillis(); + } } diff --git a/test/jdk/java/util/Currency/currency.properties b/test/jdk/java/util/Currency/currency.properties index ff5259e5933..0420d9cb501 100644 --- a/test/jdk/java/util/Currency/currency.properties +++ b/test/jdk/java/util/Currency/currency.properties @@ -13,6 +13,8 @@ MD=MDD,555,7 ME=MEE,555,8 MF=MFF,555,9 NO=EUR ,978 ,2, 2099-01-01T00:00:00 +PK=PKZ,999,0,3000-01-01T00:00:00 +PW=MWP,999,0,5000-01-01T00:00:00 SB=EUR,111,2, 2099-01-01T00:00:00 US=euR,978,2,2001-01-01T00:00:00 ZZ\t=\tZZZ\t,\t999\t,\t3 From f7155183d7f7c6fcea2090f906de69e02973a6d9 Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Mon, 21 Apr 2025 22:35:17 +0000 Subject: [PATCH 270/843] 8353011: Open source Swing JButton tests - Set 1 Reviewed-by: serb --- test/jdk/javax/swing/JButton/bug4151763.java | 94 +++++++++++++++ test/jdk/javax/swing/JButton/bug4415505.java | 77 +++++++++++++ test/jdk/javax/swing/JButton/bug4978274.java | 108 ++++++++++++++++++ .../javax/swing/JRadioButton/bug4673850.java | 104 +++++++++++++++++ test/jdk/javax/swing/JTable/bug4188504.java | 71 ++++++++++++ 5 files changed, 454 insertions(+) create mode 100644 test/jdk/javax/swing/JButton/bug4151763.java create mode 100644 test/jdk/javax/swing/JButton/bug4415505.java create mode 100644 test/jdk/javax/swing/JButton/bug4978274.java create mode 100644 test/jdk/javax/swing/JRadioButton/bug4673850.java create mode 100644 test/jdk/javax/swing/JTable/bug4188504.java diff --git a/test/jdk/javax/swing/JButton/bug4151763.java b/test/jdk/javax/swing/JButton/bug4151763.java new file mode 100644 index 00000000000..d04b623ec4e --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4151763.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4151763 + * @summary Tests that button icon is not drawn upon button border + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException + * @run main/manual bug4151763 + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; +import jtreg.SkippedException; + +public class bug4151763 { + private static final int IMAGE_SIZE = 150; + private static final String INSTRUCTIONS = """ + Verify that image icon is NOT painted outside + the black rectangle. + + If above is true press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4151763::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new SkippedException("Unsupported LaF", e); + } + + JFrame frame = new JFrame("bug4151763"); + final JButton b = new JButton(createImageIcon()); + b.setBorder(new CompoundBorder( + new EmptyBorder(20, 20, 20, 20), + new LineBorder(Color.BLACK))); + b.setPreferredSize(new Dimension(100, 100)); + + frame.setLayout(new FlowLayout()); + frame.add(b); + frame.setSize(400, 300); + return frame; + } + + private static ImageIcon createImageIcon() { + BufferedImage redImg = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, + BufferedImage.TYPE_INT_RGB); + Graphics2D g = redImg.createGraphics(); + g.setColor(Color.RED); + g.fillRect(0, 0, IMAGE_SIZE, IMAGE_SIZE); + g.dispose(); + return new ImageIcon(redImg); + } +} diff --git a/test/jdk/javax/swing/JButton/bug4415505.java b/test/jdk/javax/swing/JButton/bug4415505.java new file mode 100644 index 00000000000..58ba56e1b74 --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4415505.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4415505 + * @requires (os.family == "windows") + * @summary Tests JButton appearance under Windows LAF + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4415505 + */ + +import java.awt.FlowLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToggleButton; +import javax.swing.UIManager; + +public class bug4415505 { + private static final String INSTRUCTIONS = """ + +

This test is for Windows LaF. + Press the button named "Button" using mouse and check that it has + "pressed" look. It should look like the selected toggle button + near it.

+ +

If above is true press PASS else FAIL.

+ + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(5) + .columns(40) + .testUI(bug4415505::createAndShowUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JButton button = new JButton("Button"); + button.setFocusPainted(false); + JToggleButton tbutton = new JToggleButton("ToggleButton"); + tbutton.setSelected(true); + + JFrame jFrame = new JFrame("bug4415505"); + jFrame.setLayout(new FlowLayout(FlowLayout.CENTER)); + jFrame.add(button); + jFrame.add(tbutton); + jFrame.setSize(300, 100); + return jFrame; + } +} diff --git a/test/jdk/javax/swing/JButton/bug4978274.java b/test/jdk/javax/swing/JButton/bug4978274.java new file mode 100644 index 00000000000..6b152259caa --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4978274.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4978274 + * @summary Tests that JButton is painted with same visible height + * as toggle buttons + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4978274 + */ + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JToggleButton; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.OceanTheme; + +public class bug4978274 { + private static final String INSTRUCTIONS = """ + The toggle buttons must be painted to the same visible + height as button. In addition to that verify the following: + + a) All three buttons - "Button", "Toggle Btn" and + "Selected Toggle Btn" have the same border. + + b) Verify that when "Button" is pressed and moused over + it has the EXACT same border as "Toggle Btn" and + "Selected Toggle Btn" on press & mouse over. + + c) Click to the test window (panel) to disable/enable all + three buttons. In disabled state verify that all three + buttons have the exact same border. + + If all of the above conditions are true press PASS, else FAIL. + """; + + public static void main(String[] args) throws Exception { + MetalLookAndFeel.setCurrentTheme(new OceanTheme()); + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(createAndShowUI()) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4978274"); + frame.setLayout(new BorderLayout()); + + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + panel.setBorder(new EmptyBorder(12, 12, 12, 12)); + JButton jButton = new JButton("Button"); + JToggleButton jToggleButton = new JToggleButton("Selected Toggle Btn"); + jToggleButton.setSelected(true); + + panel.add(jButton); + panel.add(new JToggleButton("Toggle Btn")); + panel.add(jToggleButton); + + panel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent event) { + jButton.setEnabled(!jButton.isEnabled()); + jToggleButton.setEnabled(jButton.isEnabled()); + for(int i = 0; i < panel.getComponentCount(); i++) { + panel.getComponent(i).setEnabled(jButton.isEnabled()); + } + } + }); + + frame.add(panel); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JRadioButton/bug4673850.java b/test/jdk/javax/swing/JRadioButton/bug4673850.java new file mode 100644 index 00000000000..4f9058e978e --- /dev/null +++ b/test/jdk/javax/swing/JRadioButton/bug4673850.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4673850 + * @summary Tests that JRadioButton and JCheckBox checkmarks are painted entirely + * inside circular/rectangle checkboxes for Motif LaF. + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame jtreg.SkippedException + * @run main/manual bug4673850 + */ + +import java.awt.FlowLayout; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JRadioButton; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import jtreg.SkippedException; + +public class bug4673850 { + private static final String INSTRUCTIONS = """ + + + + + +

This test is for Motif LaF.

+ +

+ When the test starts, you'll see 2 radio buttons and 2 check boxes + with the checkmarks painted.

+ +

+ Ensure that all the button's checkmarks are painted entirely + within the circular/rectangle checkbox, NOT over them or outside them. +

+ + """; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + } catch (Exception e) { + throw new SkippedException("Unsupported LaF", e); + } + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(10) + .columns(45) + .testUI(createAndShowUI()) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4673850"); + frame.setLayout(new FlowLayout()); + + JRadioButton rb = new JRadioButton("RadioButt"); + rb.setSelected(true); + frame.add(rb); + JRadioButton rb2 = new JRadioButton("RadioButt"); + rb2.setHorizontalTextPosition(SwingConstants.LEFT); + rb2.setSelected(true); + frame.add(rb2); + + JCheckBox cb = new JCheckBox("CheckBox"); + cb.setSelected(true); + frame.add(cb); + JCheckBox cb2 = new JCheckBox("CheckBox"); + cb2.setHorizontalTextPosition(SwingConstants.LEFT); + cb2.setSelected(true); + frame.add(cb2); + frame.setSize(200, 150); + return frame; + } +} \ No newline at end of file diff --git a/test/jdk/javax/swing/JTable/bug4188504.java b/test/jdk/javax/swing/JTable/bug4188504.java new file mode 100644 index 00000000000..b58ee7def03 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4188504.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4188504 + * @summary setResizable for specified column. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4188504 + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +public class bug4188504 { + private static final String INSTRUCTIONS = """ + 1. A table is displayed with 3 columns - A, B, C. + + 2. Try to resize second column of table (Move mouse to the position + between "B" and "C" headers, press left mouse button and move to + right/left). + PLEASE NOTE: You may be able to swap the columns but make sure the + width of column B stays the same. + + 3. If the second column does not change its width then press PASS + otherwise press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(createAndShowUI()) + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame jFrame = new JFrame("bug4188504"); + JTable tableView = new JTable(4, 3); + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + tableView.getColumnModel().getColumn(1).setResizable(false); + + jFrame.add(new JScrollPane(tableView)); + jFrame.setSize(300, 150); + return jFrame; + } +} From 9a0cff692d6f96b8c89b1510cd2b4b1a8e318b6e Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Mon, 21 Apr 2025 23:11:03 +0000 Subject: [PATCH 271/843] 8353942: Open source Swing Tests - Set 5 Reviewed-by: serb, dnguyen --- .../DataTransfer/DragOverFeedbackTest.java | 117 +++++++++++++++++ .../ListDragOverFeedbackTest.java | 119 ++++++++++++++++++ .../javax/swing/DataTransfer/bug4655513.java | 106 ++++++++++++++++ .../swing/SwingUtilities/bug4369355.java | 87 +++++++++++++ .../swing/SwingUtilities/bug4967768.java | 66 ++++++++++ 5 files changed, 495 insertions(+) create mode 100644 test/jdk/javax/swing/DataTransfer/DragOverFeedbackTest.java create mode 100644 test/jdk/javax/swing/DataTransfer/ListDragOverFeedbackTest.java create mode 100644 test/jdk/javax/swing/DataTransfer/bug4655513.java create mode 100644 test/jdk/javax/swing/SwingUtilities/bug4369355.java create mode 100644 test/jdk/javax/swing/SwingUtilities/bug4967768.java diff --git a/test/jdk/javax/swing/DataTransfer/DragOverFeedbackTest.java b/test/jdk/javax/swing/DataTransfer/DragOverFeedbackTest.java new file mode 100644 index 00000000000..824f651a1a0 --- /dev/null +++ b/test/jdk/javax/swing/DataTransfer/DragOverFeedbackTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4514071 + * @summary Tests that JTable, JList and JTree provide drag-over feedback. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual DragOverFeedbackTest + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.datatransfer.DataFlavor; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.JTree; +import javax.swing.TransferHandler; + +public class DragOverFeedbackTest { + private static final String INSTRUCTIONS = """ + This test is designed to make sure that JTable, JTree, and JList + provide visual feedback when a DnD drag operation occurs over them. + + Click on the label where it says "DRAG FROM HERE" and begin dragging. + Drag over each of the three components (JTable, JTree, JList). + While you're dragging over them, they should visually indicate the + location where a drop would occur. This visual indication may use the + selection but could be some other visual. + + If above is true press PASS else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(DragOverFeedbackTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static final TransferHandler handler = new TransferHandler() { + public boolean canImport(JComponent comp, DataFlavor[] flavors) { + return true; + } + }; + + private static JFrame createTestUI() { + JFrame frame = new JFrame("DragOverFeedbackTest"); + final JLabel label = new JLabel("DRAG FROM HERE"); + label.setPreferredSize(new Dimension(400, 25)); + label.setTransferHandler(new TransferHandler("text")); + label.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent me) { + label.getTransferHandler().exportAsDrag(label, me, TransferHandler.COPY); + } + }); + JTable table = new JTable( + new String[][] {{"one"}, {"two"}, {"three"}, {"four"}}, + new String[] {"1"}); + table.setRowSelectionInterval(1, 1); + table.setTransferHandler(handler); + + JList list = new JList(new String[] {"one", "two", "three", "four"}); + list.setSelectedIndex(1); + list.setTransferHandler(handler); + + JTree tree = new JTree(); + tree.setSelectionRow(1); + tree.setTransferHandler(handler); + + frame.add(label, BorderLayout.NORTH); + + JPanel wrapper = new JPanel(); + wrapper.setLayout(new GridLayout(3, 1)); + table.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + wrapper.add(table); + list.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + wrapper.add(list); + tree.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + wrapper.add(tree); + frame.add(wrapper); + frame.setSize(500, 500); + return frame; + } +} diff --git a/test/jdk/javax/swing/DataTransfer/ListDragOverFeedbackTest.java b/test/jdk/javax/swing/DataTransfer/ListDragOverFeedbackTest.java new file mode 100644 index 00000000000..b41327a106e --- /dev/null +++ b/test/jdk/javax/swing/DataTransfer/ListDragOverFeedbackTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4546134 + * @summary Tests that JList shows the right drop location when it has multiple columns. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ListDragOverFeedbackTest + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.datatransfer.DataFlavor; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.TransferHandler; + +public class ListDragOverFeedbackTest { + private static final String INSTRUCTIONS = """ + JList should provide visual feedback when a DnD drag operation is + occurring over it. This test is to check that it provides the + feedback about the drop location correctly. + + Click on the label where it says "DRAG FROM HERE" and begin dragging. + Drag over each column in each of the three JLists and make sure that + the drop location indicated is appropriate for the mouse location. For + instance, if the mouse is in the first column, the drop location should + also be indicated in that first column. + + If above is true press PASS else press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(ListDragOverFeedbackTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static final TransferHandler handler = new TransferHandler() { + public boolean canImport(JComponent comp, DataFlavor[] flavors) { + return true; + } + }; + + private static JFrame createTestUI() { + String[] vals = new String[] { + "one", "two", "three", "four", "five", "six", "seven", "eight", + "nine", "ten", "eleven", "twelve", "thirteen", "fourteen"}; + + JFrame frame = new JFrame("ListDragOverFeedbackTest"); + final JLabel label = new JLabel("DRAG FROM HERE"); + label.setPreferredSize(new Dimension(400, 25)); + label.setTransferHandler(new TransferHandler("text")); + label.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent me) { + label.getTransferHandler().exportAsDrag(label, me, + TransferHandler.COPY); + } + }); + + JList list1 = new JList(vals); + list1.setTransferHandler(handler); + list1.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + + JList list2 = new JList(vals); + list2.setLayoutOrientation(JList.VERTICAL_WRAP); + list2.setTransferHandler(handler); + list2.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + + JList list3 = new JList(vals); + list3.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list3.setTransferHandler(handler); + list3.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + + JPanel wrapper = new JPanel(); + wrapper.setLayout(new GridLayout(3, 1)); + wrapper.add(list1); + wrapper.add(list2); + wrapper.add(list3); + + frame.add(label, BorderLayout.NORTH); + frame.add(wrapper); + frame.setSize(400, 500); + return frame; + } +} diff --git a/test/jdk/javax/swing/DataTransfer/bug4655513.java b/test/jdk/javax/swing/DataTransfer/bug4655513.java new file mode 100644 index 00000000000..c9f49f98939 --- /dev/null +++ b/test/jdk/javax/swing/DataTransfer/bug4655513.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 4655513 + * @summary TransferHandler doesn't recognize ACTION_LINK + as a valid drop action + * @library /javax/swing/regtesthelpers + * @build Util + * @run main bug4655513 + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + +public class bug4655513 { + private static final String LINK_URL = "http://www.example.com"; + private static volatile JEditorPane editor; + private static volatile JLabel dragSource; + private static JFrame frame; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(bug4655513::createAndShowGUI); + robot.waitForIdle(); + robot.delay(1000); + + Point dragStartLoc = Util.getCenterPoint(dragSource); + Point dragEndLoc = Util.getCenterPoint(editor); + robot.mouseMove(dragStartLoc.x, dragStartLoc.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + for (int y = dragStartLoc.y; y < dragEndLoc.y; y += 3) { + robot.mouseMove(dragStartLoc.x, y); + robot.delay(50); + } + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(500); + + SwingUtilities.invokeAndWait(() -> { + if (!editor.getText().contains(LINK_URL)) { + throw new RuntimeException("Test Failed! Drag & Drop did not work."); + } + }); + } finally { + SwingUtilities.invokeAndWait(frame::dispose); + } + } + + private static void createAndShowGUI() { + frame = new JFrame("Bug4655513 - Data Transfer"); + dragSource = new JLabel("To Test DnD, drag this label."); + dragSource.setForeground(Color.RED); + dragSource.setPreferredSize(new Dimension(250, 50)); + frame.add(dragSource, BorderLayout.NORTH); + + editor = new JEditorPane("text/plain", "Drop here."); + editor.setPreferredSize(new Dimension(250, 50)); + frame.add(new JScrollPane(editor), BorderLayout.CENTER); + + DragSource ds = new DragSource(); + DragGestureRecognizer rec = + ds.createDefaultDragGestureRecognizer(dragSource, + DnDConstants.ACTION_LINK, + dge -> dge.startDrag(null, new StringSelection(LINK_URL))); + frame.setSize(300, 150); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/SwingUtilities/bug4369355.java b/test/jdk/javax/swing/SwingUtilities/bug4369355.java new file mode 100644 index 00000000000..f55d888ef31 --- /dev/null +++ b/test/jdk/javax/swing/SwingUtilities/bug4369355.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 4369355 + * @summary To verify if SwingUtilities.convertPointToScreen() (for invisible frame) + * and SwingUtilities.convertPointFromScreen() return correct values + * @run main bug4369355 + */ + +import java.awt.Point; +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4369355 { + private static JFrame frame; + + private static volatile Point frameToScreenLoc; + private static volatile Point frameFromScreenLoc; + + private static final Point EXPECTED_FROM_SCREEN_LOC = new Point(0, 0); + private static final Point EXPECTED_TO_SCREEN_LOC = new Point(100, 100); + + public static void main (String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4369355"); + frame.setBounds(100, 100, 100, 100); + }); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + frameToScreenLoc = new Point(0, 0); + SwingUtilities.convertPointToScreen(frameToScreenLoc, frame); + }); + robot.delay(100); + + if (!frameToScreenLoc.equals(EXPECTED_TO_SCREEN_LOC)) { + throw new RuntimeException("SwingUtilities.convertPointToScreen()" + + " returns incorrect point " + frameToScreenLoc + "\n" + + "Should be " + EXPECTED_TO_SCREEN_LOC); + } + + SwingUtilities.invokeAndWait(() -> frame.setVisible(true)); + robot.delay(500); + + SwingUtilities.invokeAndWait(() -> { + frameFromScreenLoc = frame.getLocationOnScreen(); + SwingUtilities.convertPointFromScreen(frameFromScreenLoc, frame); + }); + robot.delay(100); + + if (!frameFromScreenLoc.equals(EXPECTED_FROM_SCREEN_LOC)) { + throw new RuntimeException("SwingUtilities.convertPointFromScreen()" + + " returns incorrect point " + frameFromScreenLoc + "\n" + + "Should be " + EXPECTED_FROM_SCREEN_LOC); + } + } finally { + SwingUtilities.invokeAndWait(frame::dispose); + } + } +} diff --git a/test/jdk/javax/swing/SwingUtilities/bug4967768.java b/test/jdk/javax/swing/SwingUtilities/bug4967768.java new file mode 100644 index 00000000000..43f9f7cabfb --- /dev/null +++ b/test/jdk/javax/swing/SwingUtilities/bug4967768.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4967768 + * @requires (os.family != "mac") + * @summary Tests that underline is painted correctly in mnemonics + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4967768 + */ + +import java.awt.Font; +import javax.swing.JButton; +import javax.swing.JPanel; + +public class bug4967768 { + private static final String INSTRUCTIONS = """ + When the test starts you'll see a button "Oops" + with the "p" letter underlined at the bottom + of the instruction frame. + + Ensure the underline cuts through the descender + of letter "p", i.e. the underline is painted + not below the letter but below the baseline. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .splitUIBottom(bug4967768::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JPanel createTestUI() { + JPanel panel = new JPanel(); + JButton but = new JButton("Oops"); + but.setFont(new Font("Dialog", Font.BOLD, 24)); + but.setMnemonic('p'); + panel.add(but); + return panel; + } +} From 47f78a7529a2b290a07394e053bcfaff4907b7e5 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 22 Apr 2025 00:27:25 +0000 Subject: [PATCH 272/843] 8354990: Improve negative tests coverage for jpackage signing 8354989: Bug in MacCertificate class Reviewed-by: almatvee --- .../jdk/jpackage/internal/MacAppBundler.java | 2 +- .../jdk/jpackage/internal/MacCertificate.java | 18 +- .../jdk/jpackage/internal/MacPkgBundler.java | 2 +- .../helpers/jdk/jpackage/test/MacSign.java | 375 +++++++++++++++--- .../jdk/jpackage/test/MacSignVerify.java | 226 +++++++++++ .../tools/jpackage/macosx/MacSignTest.java | 191 ++++++++- .../jpackage/macosx/base/SigningBase.java | 252 +++++------- 7 files changed, 824 insertions(+), 242 deletions(-) create mode 100644 test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java index 5da01aa293c..733321dec46 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java @@ -74,7 +74,7 @@ public class MacAppBundler extends AppImageBundler { } if (result != null) { - MacCertificate certificate = new MacCertificate(result); + MacCertificate certificate = new MacCertificate(result, keychain); if (!certificate.isValid()) { Log.error(MessageFormat.format(I18N.getString( diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java index 90f3a8c765b..c9dab481e0e 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,21 +39,25 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HexFormat; import java.util.List; import java.util.Locale; -import java.util.HexFormat; +import java.util.Objects; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class MacCertificate { private final String certificate; + private final Optional keychainName; - public MacCertificate(String certificate) { - this.certificate = certificate; + public MacCertificate(String certificate, String keychainName) { + this.certificate = Objects.requireNonNull(certificate); + this.keychainName = Optional.ofNullable(keychainName); } public boolean isValid() { - return verifyCertificate(this.certificate); + return verifyCertificate(); } public static String findCertificateKey(String keyPrefix, String teamName, @@ -295,7 +299,7 @@ public final class MacCertificate { return result; } - private boolean verifyCertificate(String certificate) { + private boolean verifyCertificate() { boolean result = false; try { @@ -303,7 +307,7 @@ public final class MacCertificate { Date certificateDate = null; try { - file = getFindCertificateOutputPEM(certificate, null); + file = getFindCertificateOutputPEM(certificate, keychainName.orElse(null)); if (file != null) { certificateDate = findCertificateDate( diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java index 2aca9bd0e1f..8328fa07851 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java @@ -130,7 +130,7 @@ public class MacPkgBundler extends MacBaseInstallerBundler { } if (result != null) { - MacCertificate certificate = new MacCertificate(result); + MacCertificate certificate = new MacCertificate(result, keychain); if (!certificate.isValid()) { Log.error(MessageFormat.format( diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java index 1d5dd16fe37..67ac921b919 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java @@ -29,9 +29,9 @@ import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; -import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UncheckedIOException; @@ -42,7 +42,9 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.security.MessageDigest; +import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; +import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Base64; @@ -63,6 +65,7 @@ import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import jdk.jpackage.internal.util.function.ExceptionBox; import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingSupplier; /** * Utilities to setup identities and keychains for sign testing. @@ -393,15 +396,52 @@ public final class MacSign { } List findCertificates() { - final var in = new ByteArrayInputStream( - security("find-certificate", "-ap", name).saveOutput().execute().getOutput().stream().collect(joining("\n")).getBytes(StandardCharsets.UTF_8)); - return toFunction(CERT_FACTORY::generateCertificates).apply(in).stream().map(X509Certificate.class::cast).toList(); + final List certs = new ArrayList<>(); + try (final var in = new BufferedInputStream(new ByteArrayInputStream( + security("find-certificate", "-ap", name).executeAndGetOutput().stream().collect(joining("\n")).getBytes(StandardCharsets.UTF_8)))) { + while (in.available() > 0) { + final X509Certificate cert; + try { + cert = (X509Certificate) CERT_FACTORY.generateCertificate(in); + } catch (Exception ex) { + TKit.trace("Failed to parse certificate data: " + ex); + continue; + } + certs.add(cert); + } + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + return certs; } public static void addToSearchList(Collection keychains) { security("list-keychains", "-d", "user", "-s", "login.keychain") - .addArguments(keychains.stream().map(Keychain::name).toList()) - .execute(); + .addArguments(keychains.stream().map(Keychain::name).toList()) + .execute(); + } + + public static void withAddedKeychains(Collection keychains, Runnable runnable) { + final var curKeychains = activeKeychainFiles(); + addToSearchList(keychains); + try { + runnable.run(); + } finally { + security("list-keychains", "-d", "user", "-s") + .addArguments(curKeychains.stream().map(Path::toString).toList()) + .execute(); + } + } + + private static List activeKeychainFiles() { + // $ security list-keychains + // "/Users/alexeysemenyuk/Library/Keychains/login.keychain-db" + // "/Library/Keychains/System.keychain" + return security("list-keychains", "-d", "user").executeAndGetOutput().stream().map(line -> { + return line.stripLeading(); + }).filter(line -> { + return line.charAt(0) == '"' && line.charAt(line.length() - 1) == '"'; + }).map(line -> line.substring(1, line.length() - 1)).map(Path::of).toList(); } private Executor createExecutor(String command) { @@ -409,40 +449,57 @@ public final class MacSign { } } - record ResolvedCertificateRequest(CertificateRequest request, X509Certificate cert, VerifyStatus verifyStatus) { + private enum VerifyStatus { + VERIFY_OK, + VERIFY_EXPIRED, + VERIFY_ERROR, + VERIFY_UNTRUSTED, + VERIFY_EXPIRED_UNTRUSTED, + UNVERIFIED + } + + private record ResolvedCertificateRequest(InstalledCertificate installed, X509Certificate cert, VerifyStatus verifyStatus) { ResolvedCertificateRequest { - Objects.requireNonNull(request); + Objects.requireNonNull(installed); Objects.requireNonNull(cert); Objects.requireNonNull(verifyStatus); } - enum VerifyStatus { - VERIFY_OK, - VERIFY_ERROR, - UNVERIFIED + CertificateRequest request() { + if (!verified()) { + throw new IllegalStateException(); + } + return new CertificateRequest(installed.name(), installed.type(), installed.days(), installed.expired(), + Set.of(VerifyStatus.VERIFY_OK, VerifyStatus.VERIFY_EXPIRED).contains(verifyStatus)); } ResolvedCertificateRequest(X509Certificate cert) { - this(new CertificateRequest(cert), cert, VerifyStatus.UNVERIFIED); + this(new InstalledCertificate(cert), cert, VerifyStatus.UNVERIFIED); } - ResolvedCertificateRequest copyVerified(boolean verifySuccess) { - return new ResolvedCertificateRequest(request, cert, - verifySuccess ? VerifyStatus.VERIFY_OK : VerifyStatus.VERIFY_ERROR); + ResolvedCertificateRequest copyVerified(VerifyStatus verifyStatus) { + if (verifyStatus == VerifyStatus.UNVERIFIED) { + throw new IllegalArgumentException(); + } + return new ResolvedCertificateRequest(installed, cert, verifyStatus); + } + + private boolean verified() { + return verifyStatus != VerifyStatus.UNVERIFIED; } } - record CertificateStats(List allResolvedCertificateRequests, - List allCertificates, List knownCertificateRequests, + private record CertificateStats(List allResolvedCertificateRequests, + List knownCertificateRequests, Map unmappedCertificates) { - private static CertificateStats get(KeychainWithCertsSpec spec) { + static CertificateStats get(KeychainWithCertsSpec spec) { return CACHE.computeIfAbsent(spec, CertificateStats::create); } Map> mapKnownCertificateRequests() { return knownCertificateRequests.stream().collect(groupingBy(x -> x, mapping(certificateRequest -> { - return allResolvedCertificateRequests.stream().filter(v -> { + return allVerifiedResolvedCertificateRequest().filter(v -> { return v.request().equals(certificateRequest); }).map(ResolvedCertificateRequest::cert); }, flatMapping(x -> x, toList())))); @@ -450,15 +507,19 @@ public final class MacSign { Set verifyFailedCertificateRequests() { return knownCertificateRequests.stream().filter(certificateRequest -> { - return allResolvedCertificateRequests.stream().anyMatch(v -> { - return v.request().equals(certificateRequest) && v.verifyStatus() == ResolvedCertificateRequest.VerifyStatus.VERIFY_ERROR; + return allVerifiedResolvedCertificateRequest().anyMatch(v -> { + return v.request().equals(certificateRequest) && v.verifyStatus() != certificateRequest.expectedVerifyStatus(); }); }).collect(toSet()); } Set unmappedCertificateRequests() { return Comm.compare(Set.copyOf(knownCertificateRequests), - allResolvedCertificateRequests.stream().map(ResolvedCertificateRequest::request).collect(toSet())).unique1(); + allVerifiedResolvedCertificateRequest().map(ResolvedCertificateRequest::request).collect(toSet())).unique1(); + } + + private Stream allVerifiedResolvedCertificateRequest() { + return allResolvedCertificateRequests.stream().filter(ResolvedCertificateRequest::verified); } private static CertificateStats create(KeychainWithCertsSpec spec) { @@ -482,24 +543,24 @@ public final class MacSign { continue; } - if (spec.certificateRequests().contains(resolvedCertificateRequest.request)) { + if (spec.certificateRequests().stream().anyMatch(resolvedCertificateRequest.installed()::match)) { final var certFile = workDir.resolve(CertificateHash.of(cert).toString() + ".pem"); - final var verifySuccess = verifyCertificate(resolvedCertificateRequest, spec.keychain(), certFile); - resolvedCertificateRequest = resolvedCertificateRequest.copyVerified(verifySuccess); + final var verifyStatus = verifyCertificate(resolvedCertificateRequest, spec.keychain(), certFile); + resolvedCertificateRequest = resolvedCertificateRequest.copyVerified(verifyStatus); } allResolvedCertificateRequests.add(resolvedCertificateRequest); } }); - return new CertificateStats(allResolvedCertificateRequests, List.copyOf(allCertificates), + return new CertificateStats(allResolvedCertificateRequests, List.copyOf(spec.certificateRequests()), unmappedCertificates); } private static final Map CACHE = new ConcurrentHashMap<>(); } - record PemData(String label, byte[] data) { + private record PemData(String label, byte[] data) { PemData { Objects.requireNonNull(label); Objects.requireNonNull(data); @@ -532,23 +593,41 @@ public final class MacSign { return String.format("-----%s-----\n", Objects.requireNonNull(str)); } - private final static Base64.Encoder ENCODER = Base64.getMimeEncoder(64, "\n".getBytes()); + private static final Base64.Encoder ENCODER = Base64.getMimeEncoder(64, "\n".getBytes()); } - public record CertificateHash(byte[] value) { + public enum DigestAlgorithm { + SHA1(20, () -> MessageDigest.getInstance("SHA-1")), + SHA256(32, () -> MessageDigest.getInstance("SHA-256")); + + DigestAlgorithm(int hashLength, ThrowingSupplier createDigest) { + this.hashLength = hashLength; + this.createDigest = createDigest; + } + + final int hashLength; + final ThrowingSupplier createDigest; + } + + public record CertificateHash(byte[] value, DigestAlgorithm alg) { public CertificateHash { Objects.requireNonNull(value); - if (value.length != 20) { - throw new IllegalArgumentException("Invalid SHA-1 hash"); + Objects.requireNonNull(alg); + if (value.length != alg.hashLength) { + throw new IllegalArgumentException(String.format("Invalid %s hash", alg)); } } public static CertificateHash of(X509Certificate cert) { + return of(cert, DigestAlgorithm.SHA1); + } + + public static CertificateHash of(X509Certificate cert, DigestAlgorithm alg) { return new CertificateHash(toSupplier(() -> { - final MessageDigest md = MessageDigest.getInstance("SHA-1"); + final MessageDigest md = alg.createDigest.get(); md.update(cert.getEncoded()); return md.digest(); - }).get()); + }).get(), alg); } @Override @@ -601,14 +680,61 @@ public final class MacSign { private final String verifyPolicy; } - public record CertificateRequest(String name, CertificateType type, int days) implements Comparable{ + public enum StandardCertificateNamePrefix { + CODE_SIGND("Developer ID Application: "), + INSTALLER("Developer ID Installer: "); + + StandardCertificateNamePrefix(String value) { + this.value = Objects.requireNonNull(value); + } + + public String value() { + return value; + } + + private final String value; + } + + public record NameWithPrefix(String prefix, String name) { + public NameWithPrefix { + Objects.requireNonNull(prefix); + Objects.requireNonNull(name); + } + } + + public record CertificateRequest(String name, CertificateType type, int days, boolean expired, boolean trusted) + implements Comparable { + public CertificateRequest { Objects.requireNonNull(name); Objects.requireNonNull(type); + if (days <= 0) { + throw new IllegalArgumentException(); + } } - CertificateRequest(X509Certificate cert) { - this(getSubjectCN(cert), getType(cert), getDurationInDays(cert)); + public String shortName() { + return nameWithPrefix().map(NameWithPrefix::name).orElseThrow(); + } + + public Optional nameWithPrefix() { + return Stream.of(StandardCertificateNamePrefix.values()).map(StandardCertificateNamePrefix::value).filter(prefix -> { + return name.startsWith(prefix); + }).map(prefix -> { + return new NameWithPrefix(prefix, name.substring(prefix.length())); + }).findAny(); + } + + VerifyStatus expectedVerifyStatus() { + if (expired && !trusted) { + return VerifyStatus.VERIFY_EXPIRED_UNTRUSTED; + } else if (!trusted) { + return VerifyStatus.VERIFY_UNTRUSTED; + } else if (expired) { + return VerifyStatus.VERIFY_EXPIRED; + } else { + return VerifyStatus.VERIFY_OK; + } } @Override @@ -623,8 +749,8 @@ public final class MacSign { return this; } - public Builder commonName(String v) { - commonName = v; + public Builder subjectCommonName(String v) { + subjectCommonName = v; return this; } @@ -638,8 +764,26 @@ public final class MacSign { return this; } + public Builder expired(boolean v) { + expired = v; + return this; + } + + public Builder expired() { + return expired(true); + } + + public Builder trusted(boolean v) { + trusted = v; + return this; + } + + public Builder untrusted() { + return trusted(false); + } + public CertificateRequest create() { - return new CertificateRequest(validatedCN(), type, days); + return new CertificateRequest(validatedCN(), type, days, expired, trusted); } private String validatedUserName() { @@ -647,13 +791,13 @@ public final class MacSign { } private String validatedCN() { - return Optional.ofNullable(commonName).orElseGet(() -> { + return Optional.ofNullable(subjectCommonName).orElseGet(() -> { switch (type) { case CODE_SIGN -> { - return "Developer ID Application: " + validatedUserName(); + return StandardCertificateNamePrefix.CODE_SIGND.value() + validatedUserName(); } case INSTALLER -> { - return "Developer ID Installer: " + validatedUserName(); + return StandardCertificateNamePrefix.INSTALLER.value() + validatedUserName(); } default -> { throw new UnsupportedOperationException(); @@ -663,9 +807,41 @@ public final class MacSign { } private String userName; - private String commonName; // CN + private String subjectCommonName; // CN private CertificateType type = CertificateType.CODE_SIGN; private int days = 365; + private boolean expired; + private boolean trusted = true; + } + + private static final Comparator COMPARATOR = + Comparator.comparing(CertificateRequest::name) + .thenComparing(Comparator.comparing(CertificateRequest::type)) + .thenComparing(Comparator.comparingInt(CertificateRequest::days)) + .thenComparing(Comparator.comparing(CertificateRequest::expired, Boolean::compare)) + .thenComparing(Comparator.comparing(CertificateRequest::trusted, Boolean::compare)); + } + + private record InstalledCertificate(String name, CertificateType type, int days, boolean expired) implements Comparable { + InstalledCertificate { + Objects.requireNonNull(name); + Objects.requireNonNull(type); + if (days <= 0) { + throw new IllegalArgumentException(); + } + } + + InstalledCertificate(X509Certificate cert) { + this(getSubjectCN(cert), getType(cert), getDurationInDays(cert), getExpired(cert)); + } + + boolean match(CertificateRequest request) { + return name.equals(request.name()) && type.equals(request.type()) && days == request.days() && expired == request.expired(); + } + + @Override + public int compareTo(InstalledCertificate o) { + return COMPARATOR.compare(this, o); } private static String getSubjectCN(X509Certificate cert) { @@ -697,13 +873,23 @@ public final class MacSign { private static int getDurationInDays(X509Certificate cert) { final var notBefore = cert.getNotBefore(); final var notAfter = cert.getNotAfter(); - return (int)TimeUnit.DAYS.convert(notAfter.getTime() - notBefore.getTime(), TimeUnit.MILLISECONDS); + return (int) TimeUnit.DAYS.convert(notAfter.getTime() - notBefore.getTime(), TimeUnit.MILLISECONDS); } - private static final Comparator COMPARATOR = - Comparator.comparing(CertificateRequest::name) - .thenComparing(Comparator.comparing(CertificateRequest::type)) - .thenComparing(Comparator.comparingInt(CertificateRequest::days)); + private static boolean getExpired(X509Certificate cert) { + try { + cert.checkValidity(); + return false; + } catch (CertificateExpiredException | CertificateNotYetValidException ex) { + return true; + } + } + + private static final Comparator COMPARATOR = + Comparator.comparing(InstalledCertificate::name) + .thenComparing(Comparator.comparing(InstalledCertificate::type)) + .thenComparing(Comparator.comparingInt(InstalledCertificate::days)) + .thenComparing(Comparator.comparing(InstalledCertificate::expired, Boolean::compare)); } /** @@ -715,8 +901,10 @@ public final class MacSign { * Created certificates will be imported into the keychains, and every * certificate will be marked as trusted. *

- * The user will be prompted to enter the user login password as - * many times as the number of unique certificates this function will create. + * The user will be prompted to enter the user login password as many times as + * the number of unique certificates this function will create. + *

+ * Created keychains will NOT be added to the keychain search list. * * @param specs the keychains and signing identities configuration */ @@ -767,14 +955,14 @@ public final class MacSign { "-A").execute(); }); - trustConfig.put(certPemFile.getValue(), keychains.getFirst()); + if (certPemFile.getKey().trusted()) { + trustConfig.put(certPemFile.getValue(), keychains.getFirst()); + } } // Trust certificates. trustCertificates(trustConfig); }); - - Keychain.addToSearchList(specs.stream().map(KeychainWithCertsSpec::keychain).toList()); } /** @@ -820,11 +1008,11 @@ public final class MacSign { TKit.trace(String.format("In [%s] keychain:", keychain.name())); final var certificateStat = certificateStats.get(keychain); final var resolvedCertificateRequests = certificateStat.allResolvedCertificateRequests().stream() - .sorted(Comparator.comparing(ResolvedCertificateRequest::request)).toList(); + .sorted(Comparator.comparing(ResolvedCertificateRequest::installed)).toList(); for (final var resolvedCertificateRequest : resolvedCertificateRequests) { TKit.trace(String.format(" Certificate with hash=%s: %s[%s]", CertificateHash.of(resolvedCertificateRequest.cert()), - resolvedCertificateRequest.request(), + resolvedCertificateRequest.installed(), resolvedCertificateRequest.verifyStatus())); } @@ -849,7 +1037,31 @@ public final class MacSign { return !missingKeychain && !missingCertificates && !invalidCertificates; } - public static Map mapCertificateRequests(KeychainWithCertsSpec spec) { + public final static class ResolvedKeychain { + public ResolvedKeychain(KeychainWithCertsSpec spec) { + this.spec = Objects.requireNonNull(spec); + } + + public KeychainWithCertsSpec spec() { + return spec; + } + + public Map mapCertificateRequests() { + if (certMap == null) { + synchronized (this) { + if (certMap == null) { + certMap = MacSign.mapCertificateRequests(spec); + } + } + } + return certMap; + } + + private final KeychainWithCertsSpec spec; + private volatile Map certMap; + } + + private static Map mapCertificateRequests(KeychainWithCertsSpec spec) { return CertificateStats.get(spec).mapKnownCertificateRequests().entrySet().stream().collect(toMap(Map.Entry::getKey, e -> { return e.getValue().stream().reduce((x, y) -> { throw new IllegalStateException(String.format( @@ -876,18 +1088,39 @@ public final class MacSign { }); } - private static boolean verifyCertificate(ResolvedCertificateRequest resolvedCertificateRequest, Keychain keychain, Path certFile) { + private static VerifyStatus verifyCertificate(ResolvedCertificateRequest resolvedCertificateRequest, Keychain keychain, Path certFile) { PemData.of(resolvedCertificateRequest.cert()).save(certFile, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); - for (final var mode : List.of("-q", "-v")) { - final var ok = security("verify-cert", "-L", "-n", mode, + Executor.Result result = null; + for (final var quite : List.of(true, false)) { + result = security("verify-cert", "-L", "-n", + quite ? "-q" : "-v", "-c", certFile.normalize().toString(), "-k", keychain.name(), - "-p", resolvedCertificateRequest.request().type().verifyPolicy()).executeWithoutExitCodeCheck().getExitCode() == 0; - if (ok) { - return true; + "-p", resolvedCertificateRequest.installed().type().verifyPolicy()).saveOutput(!quite).executeWithoutExitCodeCheck(); + if (result.exitCode() == 0) { + return VerifyStatus.VERIFY_OK; } } - return false; + + final var expired = result.getOutput().stream().anyMatch(line -> { + // Look up for "Certificate has expired, or is not yet valid (check date) [TemporalValidity]" string + return line.contains(" Certificate has expired, or is not yet valid (check date) [TemporalValidity]"); + }); + + final var untrusted = result.getOutput().stream().anyMatch(line -> { + // Look up for "The root of the certificate chain is not trusted [AnchorTrusted]" string + return line.contains(" The root of the certificate chain is not trusted [AnchorTrusted]"); + }); + + if (expired && untrusted) { + return VerifyStatus.VERIFY_EXPIRED_UNTRUSTED; + } else if (untrusted) { + return VerifyStatus.VERIFY_UNTRUSTED; + } else if (expired) { + return VerifyStatus.VERIFY_EXPIRED; + } else { + return VerifyStatus.VERIFY_ERROR; + } } private static void traceSigningEnvironment(Collection specs) { @@ -968,7 +1201,15 @@ public final class MacSign { "CN=" + certificateRequest.name() )); - final var openssl = Executor.of(OPENSSL.toString(), "req", + final Executor openssl; + if (certificateRequest.expired()) { + final var format = String.format("-%dd", certificateRequest.days + 1); + openssl = Executor.of(FAKETIME.toString(), "-f", format, OPENSSL.toString()); + } else { + openssl = Executor.of(OPENSSL.toString()); + } + + openssl.addArguments("req", "-x509", "-utf8", "-sha256", "-nodes", "-new", // Prevents LibreSSL variant of openssl command from hanging "-days", Integer.toString(certificateRequest.days()), @@ -1040,4 +1281,8 @@ public final class MacSign { // /usr/bin/openssl will preempt /usr/local/bin/openssl. // To workaround this jtreg behavior support specifying path to openssl command. private static final Path OPENSSL = Path.of(Optional.ofNullable(TKit.getConfigProperty("openssl")).orElse("openssl")); + + // faketime is not a standard macOS command. + // One way to get it is with Homebrew. + private static final Path FAKETIME = Path.of(Optional.ofNullable(TKit.getConfigProperty("faketime")).orElse("faketime")); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java new file mode 100644 index 00000000000..9fcd54d1566 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import static jdk.jpackage.test.MacSign.DigestAlgorithm.SHA256; + +import java.nio.file.Path; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HexFormat; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Pattern; +import jdk.jpackage.internal.util.PListReader; +import jdk.jpackage.test.MacSign.CertificateHash; +import jdk.jpackage.test.MacSign.CertificateRequest; + +/** + * Utilities to verify sign signatures. + */ +public final class MacSignVerify { + + public static void assertSigned(Path path, CertificateRequest certRequest) { + assertSigned(path); + TKit.assertEquals(certRequest.name(), findCodesignSignOrigin(path).orElse(null), + String.format("Check [%s] signed with certificate", path)); + } + + public static void assertAdhocSigned(Path path) { + assertSigned(path); + TKit.assertEquals(ADHOC_SIGN_ORIGIN, findCodesignSignOrigin(path).orElse(null), + String.format("Check [%s] signed with adhoc signature", path)); + } + + public static void assertUnsigned(Path path) { + TKit.assertTrue(findSpctlSignOrigin(SpctlType.EXEC, path).isEmpty(), + String.format("Check [%s] unsigned", path)); + } + + public static void assertPkgSigned(Path path, CertificateRequest certRequest, X509Certificate cert) { + final var expectedCertChain = List.of(new SignIdentity(certRequest.name(), CertificateHash.of(cert, SHA256))); + final var actualCertChain = getPkgCertificateChain(path); + TKit.assertStringListEquals( + expectedCertChain.stream().map(SignIdentity::toString).toList(), + actualCertChain.stream().map(SignIdentity::toString).toList(), + String.format("Check certificate chain of [%s] is as expected", path)); + TKit.assertEquals(certRequest.name(), findSpctlSignOrigin(SpctlType.INSTALL, path).orElse(null), + String.format("Check [%s] signed for installation", path)); + } + + public enum SpctlType { + EXEC("exec"), INSTALL("install"); + + SpctlType(String value) { + this.value = Objects.requireNonNull(value); + } + + public String value() { + return value; + } + + final private String value; + } + + public static final String ADHOC_SIGN_ORIGIN = "-"; + + public static Optional findSpctlSignOrigin(SpctlType type, Path path) { + final var exec = Executor.of("/usr/sbin/spctl", "-vv", "--raw", "--assess", "--type", type.value(), path.toString()).saveOutput().discardStderr(); + final var result = exec.executeWithoutExitCodeCheck(); + TKit.assertTrue(Set.of(0, 3).contains(result.exitCode()), + String.format("Check exit code of command %s is either 0 or 3", exec.getPrintableCommandLine())); + return toSupplier(() -> { + try { + return Optional.of(new PListReader(String.join("", result.getOutput()).getBytes()).queryValue("assessment:originator")); + } catch (NoSuchElementException ex) { + return Optional.empty(); + } + }).get(); + } + + public static Optional findCodesignSignOrigin(Path path) { + final var exec = Executor.of("/usr/bin/codesign", "--display", "--verbose=4", path.toString()).saveOutput(); + final var result = exec.executeWithoutExitCodeCheck(); + if (result.getExitCode() == 0) { + return Optional.of(result.getOutput().stream().map(line -> { + if (line.equals("Signature=adhoc")) { + return ADHOC_SIGN_ORIGIN; + } else if (line.startsWith("Authority=")) { + return line.substring("Authority=".length()); + } else { + return null; + } + }).filter(Objects::nonNull).reduce((x, y) -> { + throw new UnsupportedOperationException(String.format( + "Both adhoc [%s] and certificate [%s] signatures found in codesign output", x, y)); + }).orElseThrow(() -> { + final var msg = "Neither adhoc nor certificate signatures found in codesign output"; + TKit.trace(msg + ":"); + result.getOutput().forEach(TKit::trace); + TKit.trace("Done"); + return new UnsupportedOperationException(msg); + })); + } else if (result.getExitCode() == 1 && result.getFirstLineOfOutput().endsWith("code object is not signed at all")) { + return Optional.empty(); + } else { + reportUnexpectedCommandOutcome(exec.getPrintableCommandLine(), result); + return null; // Unreachable + } + } + + public static void assertSigned(Path path) { + final var verifier = TKit.assertTextStream(": valid on disk").predicate(String::endsWith).andThen(TKit.assertTextStream(": satisfies its Designated Requirement").predicate(String::endsWith)); + verifier.apply(Executor.of("/usr/bin/codesign", "--verify", "--deep", + "--strict", "--verbose=2", path.toString()).executeAndGetOutput().stream()); + } + + public static List getPkgCertificateChain(Path path) { + // + // Typical output of `/usr/sbin/pkgutil --check-signature`: + // Package "foo.pkg": + // Status: signed by a developer certificate issued by Apple for distribution + // Notarization: trusted by the Apple notary service + // Signed with a trusted timestamp on: 2022-05-10 19:54:56 +0000 + // Certificate Chain: + // 1. Developer ID Installer: Foo + // SHA256 Fingerprint: + // 4A A9 4A 85 20 2A DE 02 B2 9B 36 DA 45 00 B4 40 CF 31 43 4E 96 02 + // 60 6A 6D BC 02 F4 5D 3A 86 4A + // ------------------------------------------------------------------------ + // 2. Developer ID Certification Authority + // Expires: 2027-02-01 22:12:15 +0000 + // SHA256 Fingerprint: + // 7A FC 9D 01 A6 2F 03 A2 DE 96 37 93 6D 4A FE 68 09 0D 2D E1 8D 03 + // F2 9C 88 CF B0 B1 BA 63 58 7F + // ------------------------------------------------------------------------ + // 3. Apple Root CA + // Expires: 2035-02-09 21:40:36 +0000 + // SHA256 Fingerprint: + // B0 B1 73 0E CB C7 FF 45 05 14 2C 49 F1 29 5E 6E DA 6B CA ED 7E 2C + // 68 C5 BE 91 B5 A1 10 01 F0 24 + final var exec = Executor.of("/usr/sbin/pkgutil", "--check-signature", path.toString()).saveOutput(); + final var result = exec.executeWithoutExitCodeCheck(); + if (result.getExitCode() == 0) { + try { + final List signIdentities = new ArrayList<>(); + final var lineIt = result.getOutput().iterator(); + while (!lineIt.next().endsWith("Certificate Chain:")) { + + } + do { + final var m = SIGN_IDENTITY_NAME_REGEXP.matcher(lineIt.next()); + m.find(); + final var name = m.group(1); + while (!lineIt.next().endsWith("SHA256 Fingerprint:")) { + + } + final var digest = new StringBuilder(); + do { + final var line = lineIt.next().strip(); + if (line.endsWith("----") || line.isEmpty()) { + break; + } + digest.append(" " + line.strip()); + } while (lineIt.hasNext()); + final var fingerprint = new CertificateHash( + FINGERPRINT_FORMAT.parseHex(digest.substring(1)), SHA256); + signIdentities.add(new SignIdentity(name, fingerprint)); + } while (lineIt.hasNext()); + return signIdentities; + } catch (Throwable t) { + t.printStackTrace(); + reportUnexpectedCommandOutcome(exec.getPrintableCommandLine(), result); + return null; // Unreachable + } + } else if (result.getExitCode() == 1 && result.getOutput().getLast().endsWith("Status: no signature")) { + return List.of(); + } else { + reportUnexpectedCommandOutcome(exec.getPrintableCommandLine(), result); + return null; // Unreachable + } + } + + public record SignIdentity(String name, CertificateHash fingerprint) { + public SignIdentity { + Objects.requireNonNull(name); + Objects.requireNonNull(fingerprint); + } + } + + private static void reportUnexpectedCommandOutcome(String printableCommandLine, Executor.Result result) { + Objects.requireNonNull(printableCommandLine); + Objects.requireNonNull(result); + TKit.trace(String.format("Command %s exited with exit code %d and the following output:", + printableCommandLine, result.getExitCode())); + result.getOutput().forEach(TKit::trace); + TKit.trace("Done"); + TKit.assertUnexpected(String.format("Outcome of command %s", printableCommandLine)); + } + + private static final Pattern SIGN_IDENTITY_NAME_REGEXP = Pattern.compile("^\\s+\\d+\\.\\s+(.*)$"); + private static final HexFormat FINGERPRINT_FORMAT = HexFormat.ofDelimiter(" ").withUpperCase(); +} diff --git a/test/jdk/tools/jpackage/macosx/MacSignTest.java b/test/jdk/tools/jpackage/macosx/MacSignTest.java index 4313f1900e2..7b2e06dc7ca 100644 --- a/test/jdk/tools/jpackage/macosx/MacSignTest.java +++ b/test/jdk/tools/jpackage/macosx/MacSignTest.java @@ -24,12 +24,23 @@ import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Stream; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.CannedFormattedString; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JPackageStringBundle; import jdk.jpackage.test.MacHelper; +import jdk.jpackage.test.MacSign; +import jdk.jpackage.test.MacSign.CertificateRequest; +import jdk.jpackage.test.MacSignVerify; +import jdk.jpackage.test.PackageType; import jdk.jpackage.test.TKit; /* @@ -64,23 +75,173 @@ public class MacSignTest { expectedStrings.add(xcodeWarning); } - // --app-content and --type app-image - // Expect `message.codesign.failed.reason.app.content` message in the log. - // This is not a fatal error, just a warning. - // To make jpackage fail, specify bad additional content. - final var cmd = JPackageCommand.helloAppImage() - .ignoreDefaultVerbose(true) - .validateOutput(expectedStrings.toArray(CannedFormattedString[]::new)) - .addArguments("--app-content", appContent) - .addArguments("--mac-sign") - .addArguments("--mac-signing-keychain", SigningBase.StandardKeychain.MAIN.spec().keychain().name()) - .addArguments("--mac-app-image-sign-identity", SigningBase.StandardCertificateRequest.APP_IMAGE.spec().name()); + final var keychain = SigningBase.StandardKeychain.EXPIRED.spec().keychain(); - if (MacHelper.isXcodeDevToolsInstalled()) { - // Check there is no warning about missing xcode command line developer tools. - cmd.validateOutput(TKit.assertTextStream(xcodeWarning.getValue()).negate()); + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { + // --app-content and --type app-image + // Expect `message.codesign.failed.reason.app.content` message in the log. + // This is not a fatal error, just a warning. + // To make jpackage fail, specify bad additional content. + final var cmd = JPackageCommand.helloAppImage() + .ignoreDefaultVerbose(true) + .validateOutput(expectedStrings.toArray(CannedFormattedString[]::new)) + .addArguments("--app-content", appContent) + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) + .addArguments("--mac-app-image-sign-identity", SigningBase.StandardCertificateRequest.CODESIGN.spec().name()); + + if (MacHelper.isXcodeDevToolsInstalled()) { + // Check there is no warning about missing xcode command line developer tools. + cmd.validateOutput(TKit.assertTextStream(xcodeWarning.getValue()).negate()); + } + + cmd.execute(1); + }); + } + + @Test + @Parameter({"IMAGE", "EXPIRED_SIGNING_KEY_USER_NAME"}) + @Parameter({"MAC_DMG", "EXPIRED_SIGNING_KEY_USER_NAME"}) + @Parameter({"MAC_PKG", "EXPIRED_SIGNING_KEY_USER_NAME", "EXPIRED_SIGNING_KEY_USER_NAME_PKG"}) + + @Parameter({"IMAGE", "EXPIRED_SIGN_IDENTITY"}) + @Parameter({"MAC_DMG", "EXPIRED_SIGN_IDENTITY"}) + @Parameter({"MAC_PKG", "EXPIRED_SIGN_IDENTITY"}) + + @Parameter({"IMAGE", "EXPIRED_CODESIGN_SIGN_IDENTITY"}) + @Parameter({"MAC_DMG", "EXPIRED_CODESIGN_SIGN_IDENTITY"}) + @Parameter({"MAC_PKG", "EXPIRED_CODESIGN_SIGN_IDENTITY"}) + + @Parameter({"MAC_PKG", "GOOD_CODESIGN_SIGN_IDENTITY", "EXPIRED_PKG_SIGN_IDENTITY"}) + @Parameter({"MAC_PKG", "EXPIRED_CODESIGN_SIGN_IDENTITY", "GOOD_PKG_SIGN_IDENTITY"}) + public static void testExpiredCertificate(PackageType type, SignOption... options) { + + final var keychain = SigningBase.StandardKeychain.EXPIRED.spec().keychain(); + + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { + final var cmd = JPackageCommand.helloAppImage() + .ignoreDefaultVerbose(true) + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) + .addArguments(Stream.of(options).map(SignOption::args).flatMap(List::stream).toList()) + .setPackageType(type); + + SignOption.configureOutputValidation(cmd, Stream.of(options).filter(SignOption::expired).toList(), opt -> { + return JPackageStringBundle.MAIN.cannedFormattedString("error.certificate.expired", opt.identityName()); + }).execute(1); + }); + } + + @Test + @Parameter({"IMAGE", "GOOD_SIGNING_KEY_USER_NAME"}) + @Parameter({"MAC_DMG", "GOOD_SIGNING_KEY_USER_NAME"}) + @Parameter({"MAC_PKG", "GOOD_SIGNING_KEY_USER_NAME_PKG", "GOOD_SIGNING_KEY_USER_NAME"}) + + @Parameter({"IMAGE", "GOOD_CODESIGN_SIGN_IDENTITY"}) + @Parameter({"MAC_PKG", "GOOD_CODESIGN_SIGN_IDENTITY", "GOOD_PKG_SIGN_IDENTITY"}) + @Parameter({"MAC_PKG", "GOOD_PKG_SIGN_IDENTITY"}) + public static void testMultipleCertificates(PackageType type, SignOption... options) { + + final var keychain = SigningBase.StandardKeychain.DUPLICATE.spec().keychain(); + + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { + final var cmd = JPackageCommand.helloAppImage() + .ignoreDefaultVerbose(true) + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) + .addArguments(Stream.of(options).map(SignOption::args).flatMap(List::stream).toList()) + .setPackageType(type); + + SignOption.configureOutputValidation(cmd, List.of(options), opt -> { + return JPackageStringBundle.MAIN.cannedFormattedString("error.multiple.certs.found", opt.identityName(), keychain.name()); + }).execute(1); + }); + } + + @Test + @ParameterSupplier + public static void testSelectSigningIdentity(String signingKeyUserName, CertificateRequest certRequest) { + + final var keychain = SigningBase.StandardKeychain.MAIN.spec().keychain(); + + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { + final var cmd = JPackageCommand.helloAppImage() + .setFakeRuntime() + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) + .addArguments("--mac-signing-key-user-name", signingKeyUserName); + + cmd.executeAndAssertHelloAppImageCreated(); + + MacSignVerify.assertSigned(cmd.outputBundle(), certRequest); + }); + } + + public static Collection testSelectSigningIdentity() { + return Stream.of( + SigningBase.StandardCertificateRequest.CODESIGN, + SigningBase.StandardCertificateRequest.CODESIGN_UNICODE + ).map(SigningBase.StandardCertificateRequest::spec).mapMulti((certRequest, acc) -> { + acc.accept(new Object[] {certRequest.shortName(), certRequest}); + acc.accept(new Object[] {certRequest.name(), certRequest}); + }).toList(); + } + + enum SignOption { + EXPIRED_SIGNING_KEY_USER_NAME("--mac-signing-key-user-name", SigningBase.StandardCertificateRequest.CODESIGN_EXPIRED.spec(), true, false), + EXPIRED_SIGNING_KEY_USER_NAME_PKG("--mac-signing-key-user-name", SigningBase.StandardCertificateRequest.PKG_EXPIRED.spec(), true, false), + EXPIRED_SIGN_IDENTITY("--mac-signing-key-user-name", SigningBase.StandardCertificateRequest.CODESIGN_EXPIRED.spec(), false, false), + EXPIRED_CODESIGN_SIGN_IDENTITY("--mac-app-image-sign-identity", SigningBase.StandardCertificateRequest.CODESIGN_EXPIRED.spec(), false, true), + EXPIRED_PKG_SIGN_IDENTITY("--mac-installer-sign-identity", SigningBase.StandardCertificateRequest.PKG_EXPIRED.spec(), false, true), + GOOD_SIGNING_KEY_USER_NAME("--mac-signing-key-user-name", SigningBase.StandardCertificateRequest.CODESIGN.spec(), true, false), + GOOD_SIGNING_KEY_USER_NAME_PKG("--mac-signing-key-user-name", SigningBase.StandardCertificateRequest.PKG.spec(), true, false), + GOOD_CODESIGN_SIGN_IDENTITY("--mac-app-image-sign-identity", SigningBase.StandardCertificateRequest.CODESIGN.spec(), false, true), + GOOD_PKG_SIGN_IDENTITY("--mac-app-image-sign-identity", SigningBase.StandardCertificateRequest.PKG.spec(), false, true); + + SignOption(String option, MacSign.CertificateRequest cert, boolean shortName, boolean passThrough) { + this.option = Objects.requireNonNull(option); + this.cert = Objects.requireNonNull(cert); + this.shortName = shortName; + this.passThrough = passThrough; } - cmd.execute(1); + boolean passThrough() { + return passThrough; + } + + boolean expired() { + return cert.expired(); + } + + String identityName() { + return cert.name(); + } + + List args() { + return List.of(option, shortName ? cert.shortName() : cert.name()); + } + + static JPackageCommand configureOutputValidation(JPackageCommand cmd, List options, + Function conv) { + options.stream().filter(SignOption::passThrough) + .map(conv) + .map(CannedFormattedString::getValue) + .map(TKit::assertTextStream) + .map(TKit.TextStreamVerifier::negate) + .forEach(cmd::validateOutput); + + options.stream().filter(Predicate.not(SignOption::passThrough)) + .map(conv) + .map(CannedFormattedString::getValue) + .map(TKit::assertTextStream) + .forEach(cmd::validateOutput); + + return cmd; + } + + private final String option; + private final MacSign.CertificateRequest cert; + private final boolean shortName; + private final boolean passThrough; } } diff --git a/test/jdk/tools/jpackage/macosx/base/SigningBase.java b/test/jdk/tools/jpackage/macosx/base/SigningBase.java index e3237197c74..5484245f111 100644 --- a/test/jdk/tools/jpackage/macosx/base/SigningBase.java +++ b/test/jdk/tools/jpackage/macosx/base/SigningBase.java @@ -22,16 +22,18 @@ */ import java.nio.file.Path; +import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.stream.Stream; -import jdk.jpackage.test.Executor; -import jdk.jpackage.test.Executor.Result; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.MacSign; -import jdk.jpackage.test.MacSign.CertificateType; import jdk.jpackage.test.MacSign.CertificateRequest; +import jdk.jpackage.test.MacSign.CertificateType; import jdk.jpackage.test.MacSign.KeychainWithCertsSpec; +import jdk.jpackage.test.MacSign.ResolvedKeychain; +import jdk.jpackage.test.MacSignVerify; import jdk.jpackage.test.TKit; @@ -64,10 +66,14 @@ import jdk.jpackage.test.TKit; public class SigningBase { public enum StandardCertificateRequest { - APP_IMAGE(cert().userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), - INSTALLER(cert().type(CertificateType.INSTALLER).userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), - APP_IMAGE_UNICODE(cert().userName(DEV_NAMES[CertIndex.UNICODE_INDEX.value()])), - INSTALLER_UNICODE(cert().type(CertificateType.INSTALLER).userName(DEV_NAMES[CertIndex.UNICODE_INDEX.value()])); + CODESIGN(cert().userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), + CODESIGN_COPY(cert().days(100).userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), + PKG(cert().type(CertificateType.INSTALLER).userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), + PKG_COPY(cert().type(CertificateType.INSTALLER).days(100).userName(DEV_NAMES[CertIndex.ASCII_INDEX.value()])), + CODESIGN_UNICODE(cert().userName(DEV_NAMES[CertIndex.UNICODE_INDEX.value()])), + PKG_UNICODE(cert().type(CertificateType.INSTALLER).userName(DEV_NAMES[CertIndex.UNICODE_INDEX.value()])), + CODESIGN_EXPIRED(cert().expired().userName("expired jpackage test")), + PKG_EXPIRED(cert().expired().type(CertificateType.INSTALLER).userName("expired jpackage test")); StandardCertificateRequest(CertificateRequest.Builder specBuilder) { this.spec = specBuilder.create(); @@ -85,7 +91,21 @@ public class SigningBase { } public enum StandardKeychain { - MAIN(DEFAULT_KEYCHAIN, StandardCertificateRequest.values()); + MAIN(DEFAULT_KEYCHAIN, + StandardCertificateRequest.CODESIGN, + StandardCertificateRequest.PKG, + StandardCertificateRequest.CODESIGN_UNICODE, + StandardCertificateRequest.PKG_UNICODE), + EXPIRED("jpackagerTest-expired.keychain", + StandardCertificateRequest.CODESIGN, + StandardCertificateRequest.PKG, + StandardCertificateRequest.CODESIGN_EXPIRED, + StandardCertificateRequest.PKG_EXPIRED), + DUPLICATE("jpackagerTest-duplicate.keychain", + StandardCertificateRequest.CODESIGN, + StandardCertificateRequest.PKG, + StandardCertificateRequest.CODESIGN_COPY, + StandardCertificateRequest.PKG_COPY); StandardKeychain(String keychainName, StandardCertificateRequest... certs) { this(keychainName, certs[0].spec(), Stream.of(certs).skip(1).map(StandardCertificateRequest::spec).toArray(CertificateRequest[]::new)); @@ -94,11 +114,15 @@ public class SigningBase { StandardKeychain(String keychainName, CertificateRequest cert, CertificateRequest... otherCerts) { final var builder = keychain(keychainName).addCert(cert); List.of(otherCerts).forEach(builder::addCert); - this.spec = builder.create(); + this.spec = new ResolvedKeychain(builder.create()); } public KeychainWithCertsSpec spec() { - return spec; + return spec.spec(); + } + + public X509Certificate mapCertificateRequest(CertificateRequest certRequest) { + return Objects.requireNonNull(spec.mapCertificateRequests().get(certRequest)); } private static KeychainWithCertsSpec.Builder keychain(String name) { @@ -113,7 +137,7 @@ public class SigningBase { return Stream.of(values()).map(StandardKeychain::spec).toList(); } - private final KeychainWithCertsSpec spec; + private final ResolvedKeychain spec; } public static void setUp() { @@ -131,7 +155,7 @@ public class SigningBase { } private final class Inner { - private final static boolean SIGN_ENV_READY = MacSign.isDeployed(StandardKeychain.signingEnv()); + private static final boolean SIGN_ENV_READY = MacSign.isDeployed(StandardKeychain.signingEnv()); } enum CertIndex { @@ -199,140 +223,13 @@ public class SigningBase { return DEFAULT_KEYCHAIN; } - // Note: It is not clear if we can combine "--verify" and "--display", so - // we testing them separately. Since JDK-8298488 unsigned app images are - // actually signed with adhoc signature and it will pass "--verify", so in - // addition we will check certificate name which was used to sign. - private static enum CodesignCheckType { - VERIFY, // Runs codesign with "--verify" to check signature and 0 exit code - VERIFY_UNSIGNED, // Runs codesign with "--verify" to check signature and 1 exit code - DISPLAY // Runs codesign with "--display --verbose=4" to get info about signature - }; - - private static void checkString(List result, String lookupString) { - TKit.assertTextStream(lookupString).predicate( - (line, what) -> line.trim().contains(what)).apply(result.stream()); - } - - @SuppressWarnings("fallthrough") - private static List codesignResult(Path target, CodesignCheckType type) { - int exitCode = 0; - Executor executor = new Executor().setExecutable("/usr/bin/codesign"); - switch (type) { - case VERIFY_UNSIGNED: - exitCode = 1; - case VERIFY: - executor.addArguments("--verify", "--deep", "--strict", - "--verbose=2", target.toString()); - break; - case DISPLAY: - executor.addArguments("--display", "--verbose=4", target.toString()); - break; - default: - TKit.error("Unknown CodesignCheckType: " + type); - break; - } - return executor.saveOutput().execute(exitCode).getOutput(); - } - - private static void verifyCodesignResult(List result, Path target, - boolean signed, CodesignCheckType type, int certIndex) { - result.stream().forEachOrdered(TKit::trace); - String lookupString; - switch (type) { - case VERIFY: - lookupString = target.toString() + ": valid on disk"; - checkString(result, lookupString); - lookupString = target.toString() + ": satisfies its Designated Requirement"; - checkString(result, lookupString); - break; - case VERIFY_UNSIGNED: - lookupString = target.toString() + ": code object is not signed at all"; - checkString(result, lookupString); - break; - case DISPLAY: - if (signed) { - lookupString = "Authority=" + getAppCert(certIndex); - } else { - lookupString = "Signature=adhoc"; - } - checkString(result, lookupString); - break; - default: - TKit.error("Unknown CodesignCheckType: " + type); - break; - } - } - - private static Result spctlResult(Path target, String type) { - Result result = new Executor() - .setExecutable("/usr/sbin/spctl") - .addArguments("-vvv", "--assess", "--type", type, - target.toString()) - .saveOutput() - .executeWithoutExitCodeCheck(); - - // allow exit code 3 for not being notarized - if (result.getExitCode() != 3) { - result.assertExitCodeIsZero(); - } - return result; - } - - private static void verifySpctlResult(List output, Path target, - String type, int exitCode, int certIndex) { - output.stream().forEachOrdered(TKit::trace); - String lookupString; - - if (exitCode == 0) { - lookupString = target.toString() + ": accepted"; - checkString(output, lookupString); - } else if (exitCode == 3) { - // allow failure purely for not being notarized - lookupString = target.toString() + ": rejected"; - checkString(output, lookupString); - } - - if (type.equals("install")) { - lookupString = "origin=" + getInstallerCert(certIndex); - } else { - lookupString = "origin=" + getAppCert(certIndex); - } - checkString(output, lookupString); - } - - private static List pkgutilResult(Path target, boolean signed) { - List result = new Executor() - .setExecutable("/usr/sbin/pkgutil") - .addArguments("--check-signature", - target.toString()) - .saveOutput() - .execute(signed ? 0 : 1) - .getOutput(); - - return result; - } - - private static void verifyPkgutilResult(List result, boolean signed, - int certIndex) { - result.stream().forEachOrdered(TKit::trace); - if (signed) { - String lookupString = "Status: signed by"; - checkString(result, lookupString); - lookupString = "1. " + getInstallerCert(certIndex); - checkString(result, lookupString); - } else { - String lookupString = "Status: no signature"; - checkString(result, lookupString); - } - } - public static void verifyCodesign(Path target, boolean signed, int certIndex) { - List result = codesignResult(target, CodesignCheckType.VERIFY); - verifyCodesignResult(result, target, signed, CodesignCheckType.VERIFY, certIndex); - - result = codesignResult(target, CodesignCheckType.DISPLAY); - verifyCodesignResult(result, target, signed, CodesignCheckType.DISPLAY, certIndex); + if (signed) { + final var certRequest = getCertRequest(certIndex); + MacSignVerify.assertSigned(target, certRequest); + } else { + MacSignVerify.assertAdhocSigned(target); + } } // Since we no longer have unsigned app image, but we need to check @@ -341,23 +238,45 @@ public class SigningBase { // Should not be used to validated anything else. public static void verifyDMG(Path target) { if (!target.toString().toLowerCase().endsWith(".dmg")) { - TKit.error("Unexpected target: " + target); + throw new IllegalArgumentException("Unexpected target: " + target); } - List result = codesignResult(target, CodesignCheckType.VERIFY_UNSIGNED); - verifyCodesignResult(result, target, false, CodesignCheckType.VERIFY_UNSIGNED, -1); + MacSignVerify.assertUnsigned(target); } public static void verifySpctl(Path target, String type, int certIndex) { - Result result = spctlResult(target, type); - List output = result.getOutput(); + final var standardCertIndex = Stream.of(CertIndex.values()).filter(v -> { + return v.value() == certIndex; + }).findFirst().orElseThrow(); - verifySpctlResult(output, target, type, result.getExitCode(), certIndex); + final var standardType = Stream.of(MacSignVerify.SpctlType.values()).filter(v -> { + return v.value().equals(type); + }).findFirst().orElseThrow(); + + final String expectedSignOrigin; + if (standardCertIndex == CertIndex.INVALID_INDEX) { + expectedSignOrigin = null; + } else if (standardType == MacSignVerify.SpctlType.EXEC) { + expectedSignOrigin = getCertRequest(certIndex).name(); + } else if (standardType == MacSignVerify.SpctlType.INSTALL) { + expectedSignOrigin = getPkgCertRequest(certIndex).name(); + } else { + throw new IllegalArgumentException(); + } + + final var signOrigin = MacSignVerify.findSpctlSignOrigin(standardType, target).orElse(null); + + TKit.assertEquals(signOrigin, expectedSignOrigin, + String.format("Check [%s] has sign origin as expected", target)); } public static void verifyPkgutil(Path target, boolean signed, int certIndex) { - List result = pkgutilResult(target, signed); - verifyPkgutilResult(result, signed, certIndex); + if (signed) { + final var certRequest = getPkgCertRequest(certIndex); + MacSignVerify.assertPkgSigned(target, certRequest, StandardKeychain.MAIN.mapCertificateRequest(certRequest)); + } else { + MacSignVerify.assertUnsigned(target); + } } public static void verifyAppImageSignature(JPackageCommand appImageCmd, @@ -378,4 +297,31 @@ public class SigningBase { } } + private static CertificateRequest getCertRequest(int certIndex) { + switch (CertIndex.values()[certIndex]) { + case ASCII_INDEX -> { + return StandardCertificateRequest.CODESIGN.spec(); + } + case UNICODE_INDEX -> { + return StandardCertificateRequest.CODESIGN_UNICODE.spec(); + } + default -> { + throw new IllegalArgumentException(); + } + } + } + + private static CertificateRequest getPkgCertRequest(int certIndex) { + switch (CertIndex.values()[certIndex]) { + case ASCII_INDEX -> { + return StandardCertificateRequest.PKG.spec(); + } + case UNICODE_INDEX -> { + return StandardCertificateRequest.PKG_UNICODE.spec(); + } + default -> { + throw new IllegalArgumentException(); + } + } + } } From 7a72f0fac9a0704c4a0ada781f1cadd7c4903b3e Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 01:03:45 +0000 Subject: [PATCH 273/843] 8354465: Open some JTable bugs 8 Reviewed-by: serb, kizune --- .../swing/JTable/CheckBoxFirstClick.java | 185 +++++++++++++++++ .../swing/JTable/IllegalStateException.java | 187 ++++++++++++++++++ test/jdk/javax/swing/JTable/bug4139910.java | 68 +++++++ test/jdk/javax/swing/JTable/bug4226181.java | 87 ++++++++ test/jdk/javax/swing/JTable/bug4239157.java | 85 ++++++++ 5 files changed, 612 insertions(+) create mode 100644 test/jdk/javax/swing/JTable/CheckBoxFirstClick.java create mode 100644 test/jdk/javax/swing/JTable/IllegalStateException.java create mode 100644 test/jdk/javax/swing/JTable/bug4139910.java create mode 100644 test/jdk/javax/swing/JTable/bug4226181.java create mode 100644 test/jdk/javax/swing/JTable/bug4239157.java diff --git a/test/jdk/javax/swing/JTable/CheckBoxFirstClick.java b/test/jdk/javax/swing/JTable/CheckBoxFirstClick.java new file mode 100644 index 00000000000..91f8930103e --- /dev/null +++ b/test/jdk/javax/swing/JTable/CheckBoxFirstClick.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4115930 + * @summary Verify checkboxes in the table respond to first click. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual CheckBoxFirstClick + */ + +public class CheckBoxFirstClick { + private static final String INSTRUCTIONS = """ + Click over the checkbox in the table. It should change state + on the first click. If not - press 'fail'. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(CheckBoxFirstClick::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("ListSizeBug"); + + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { + return names.length; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) { + return names[column]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer) headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number) value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/IllegalStateException.java b/test/jdk/javax/swing/JTable/IllegalStateException.java new file mode 100644 index 00000000000..427b81ab2d9 --- /dev/null +++ b/test/jdk/javax/swing/JTable/IllegalStateException.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4133143 + * @summary Illegal State exception in ComboBox editor in table + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual IllegalStateException + */ + +public class IllegalStateException { + private static final String INSTRUCTIONS = """ + Click on a cell in the first column, delete the contents but leave the editor with focus. + Click on the third column popping up a combo box. + Verify that the text editor loses focus. + If it does, press "pass", otherwise press "fail". + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(IllegalStateException::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("IllegalStateException"); + + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { + return names.length; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) { + return names[column]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer) headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number) value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4139910.java b/test/jdk/javax/swing/JTable/bug4139910.java new file mode 100644 index 00000000000..c9d6d62cf0c --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4139910.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; + +/* + * @test + * @bug 4139910 + * @summary Column resize mouse pointer doesn't display in non-resizable JTable. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4139910 + */ + +public class bug4139910 { + private static final String INSTRUCTIONS = """ + Move mouse pointer to the position between "A" and "B" headers. + If mouse pointer does not change its shape then test passes. If + it does then test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4139910::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4139910"); + + String[] colName = {"A", "B"}; + JTable tbl = new JTable(new DefaultTableModel(colName, 6)); + tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + tbl.getTableHeader().setReorderingAllowed(false); + tbl.getTableHeader().setResizingAllowed(false); + JScrollPane sp = new JScrollPane(tbl); + frame.add(sp); + + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4226181.java b/test/jdk/javax/swing/JTable/bug4226181.java new file mode 100644 index 00000000000..70749cf5d55 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4226181.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +/* + * @test + * @bug 4226181 + * @summary Tests that JTable setModel() correctly re-sizes and counts columns + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4226181 + */ + +public class bug4226181 { + private static final String INSTRUCTIONS = """ + Take a look at the table and remember the number of columns you see. + Now press the "setModel" button. If the number of columns has changed, + then test fails, otherwise it passes. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4226181::createTestUI) + .build() + .awaitAndCheck(); + } + + static class TestModel extends AbstractTableModel { + public int getRowCount() { + return 5; + } + + public int getColumnCount() { + return 7; + } + + public Object getValueAt(int row, int column) { + return row + ":" + column; + } + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4226181"); + TestModel testModel = new TestModel(); + final JTable t = new JTable(testModel); + JButton b = new JButton("setModel"); + b.addActionListener(ae -> t.setModel(new TestModel())); + t.setCellSelectionEnabled(true); + JPanel p1 = new JPanel(new GridLayout(1, 2)); + p1.add(new JLabel("dummy")); + p1.add(t); + frame.add(p1); + frame.add(b, BorderLayout.SOUTH); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4239157.java b/test/jdk/javax/swing/JTable/bug4239157.java new file mode 100644 index 00000000000..025af1615e0 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4239157.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.DefaultCellEditor; +import javax.swing.JFrame; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableColumn; + +/* + * @test + * @bug 4239157 + * @summary Tests that JTable performs cell validation properly + * (i.e. does not accept entries for which stopCellEditing() + * returns false) + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4239157 + */ + +public class bug4239157 { + private static final String INSTRUCTIONS = """ + You see a JTable having one row and two columns. + Click in the very first cell (where "click here" is displayed). + Edit its content (e.g. type some letters) and press right arrow key. + The edited cell should stay active, its content shouldn't change. + The right cell (that with text "inactive forever") shouldn't become active. + The same should be true when you press Tab key. + If it is so, test passes, otherwise it fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4239157::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4239157"); + JTable table = new JTable(new Object[][]{{"click here", + "inactive forever"}}, + new Object[]{"1", "2"}); + frame.add("Center", table); + TableColumn column = table.getColumn("1"); + TableCellEditor editor = new TestEditor(new JTextField()); + column.setCellEditor(editor); + + frame.pack(); + return frame; + } + + static class TestEditor extends DefaultCellEditor { + public TestEditor(JTextField tf) { + super(tf); + } + + public boolean stopCellEditing() { + return false; + } + } +} From ade67df0f363cb95434832f750ac901c1c75c29c Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 01:04:48 +0000 Subject: [PATCH 274/843] 8354233: Open some JTable bugs 6 Reviewed-by: kizune --- test/jdk/javax/swing/JTable/bug4129401.java | 87 ++++++++++++ test/jdk/javax/swing/JTable/bug4193727.java | 135 ++++++++++++++++++ test/jdk/javax/swing/JTable/bug4242631.java | 144 ++++++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 test/jdk/javax/swing/JTable/bug4129401.java create mode 100644 test/jdk/javax/swing/JTable/bug4193727.java create mode 100644 test/jdk/javax/swing/JTable/bug4242631.java diff --git a/test/jdk/javax/swing/JTable/bug4129401.java b/test/jdk/javax/swing/JTable/bug4129401.java new file mode 100644 index 00000000000..37765d34698 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4129401.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.TableColumn; + +/* + * @test + * @bug 4129401 + * @summary Tests that keystroking for combobox cell editor in JTable works + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4129401 + */ + +public class bug4129401 { + private static final String INSTRUCTIONS = """ + 1. Move the mouse cursor to the cell "CELL 2 1", + which contains JComboBox and click left mouse button + to drop down combobox list. + 2. Change selected item in the combobox list + using up and down arrows. + 3. Press Esc. JComboBox drop down list should hide. + If all was successful then test passes, else test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4129401::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + Object data[][] = new Object[4][2]; + JComboBox cb = new JComboBox(); + cb.addItem("Item1"); + cb.addItem("Item2"); + cb.addItem("Item3"); + cb.addItem("Item4"); + data[0][0] = "CELL 0 0"; + data[0][1] = "CELL 0 1"; + data[1][0] = "CELL 1 0"; + data[1][1] = "CELL 1 1"; + data[2][0] = "CELL 2 0"; + data[2][1] = "CELL 2 1"; + data[3][0] = "CELL 3 0"; + data[3][1] = "CELL 3 1"; + String[] str = {"Column 0", "Column 1"}; + JTable tbl = new JTable(data, str); + JScrollPane sp = new JScrollPane(tbl); + + TableColumn col = tbl.getColumn("Column 1"); + col.setCellEditor(new DefaultCellEditor(cb)); + + JFrame f = new JFrame("4129401 test"); + f.getContentPane().add(sp); + f.setBounds(100, 100, 300, 300); + return f; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4193727.java b/test/jdk/javax/swing/JTable/bug4193727.java new file mode 100644 index 00000000000..2ef4159e90c --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4193727.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.FontMetrics; +import java.util.Vector; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; + +/* + * @test + * @bug 4193727 + * @summary Tests that resizing JTable via TableColumn's + * setWidth(int) repaints correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4193727 + */ + +public class bug4193727 { + static EnhancedJTable tblResults; + static JButton bTest = new JButton("Resize"); + + private static final String INSTRUCTIONS = """ + Push button "Resize". + If either of the following happen, test fails: + 1) The size of the columns change + 2) The JTable is not repainted correctly + + Otherwise test passes. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4193727::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4193727"); + Vector v = new Vector(); + Vector data = new Vector(); + Vector cols = new Vector(); + + cols.add("Name"); + cols.add("Address"); + data.add("Steve"); + data.add("100 East Main Street"); + v.add(data); + + data.add("Richard"); + data.add("99 Main Road"); + v.add(data); + + frame.setLayout(new BorderLayout()); + tblResults = new EnhancedJTable(v, cols); + MyTableHeader mth = new MyTableHeader(); + for (int i = 0; i < tblResults.getColumnCount(); i++) + tblResults.getColumnModel().getColumn(i).setHeaderRenderer(mth.getTHR()); + tblResults.setAutoResizeMode(EnhancedJTable.AUTO_RESIZE_OFF); + + JScrollPane pane = new JScrollPane(tblResults); + frame.add(pane, BorderLayout.CENTER); + JPanel panel = new JPanel(); + panel.add(bTest); + frame.add(panel, BorderLayout.EAST); + bTest.addActionListener(e -> tblResults.autoSizeColumns()); + frame.setSize(300, 200); + return frame; + } +} + +class MyTableHeader extends TableColumn { + public TableCellRenderer getTHR() { + return createDefaultHeaderRenderer(); + } +} + +class EnhancedJTable extends JTable { + public EnhancedJTable(Vector data, Vector colNames) { + super(data, colNames); + } + + public synchronized void autoSizeColumns() { + setAutoResizeMode(AUTO_RESIZE_OFF); + int colcnt = getColumnCount(); + int rowcnt = getRowCount(); + + for (int i = 0; i < colcnt; i++) { + // get the max column width needed + Component cell = getColumnModel().getColumn(i).getHeaderRenderer() + .getTableCellRendererComponent(this, null, false, false, -1, i); + FontMetrics fm = cell.getFontMetrics(cell.getFont()); + int max = SwingUtilities.computeStringWidth(fm, getColumnModel().getColumn(i).getHeaderValue() + .toString() + " "); + for (int j = 0; j < rowcnt; j++) { + // add 2 spaces to account for gutter + int width = SwingUtilities.computeStringWidth(fm, getValueAt(j, i).toString() + " "); + if (max < width) max = width; + } + // set the new column width + getColumnModel().getColumn(i).setWidth(max); + } + } +} diff --git a/test/jdk/javax/swing/JTable/bug4242631.java b/test/jdk/javax/swing/JTable/bug4242631.java new file mode 100644 index 00000000000..6e9d1eddc32 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4242631.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.util.ArrayList; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +/* + * @test + * @bug 4242631 + * @summary Tests that JTable repaints itself correctly after a record + * has been removed and added to the table model. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4242631 + */ + +public class bug4242631 { + private static JButton addButton; + private static JButton removeButton; + private static JButton bothButton; + private static SimpleTableModel tableModel; + + private static final String INSTRUCTIONS = """ + Press Add button to add a record to the table. The record added should + have number 0. Then press Remove/Add button some times. The record number + should increase as you press. If it does not, test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4242631::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4242631"); + GridBagLayout grid = new GridBagLayout(); + + frame.setLayout(grid); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(2, 2, 2, 2); + + // Add button. + c.gridx = 0; + c.gridy = 0; + grid.setConstraints(addButton = new JButton("Add"), c); + frame.add(addButton); + + // Edit button. + c.gridx = 1; + c.gridy = 0; + grid.setConstraints(removeButton = new JButton("Remove"), c); + frame.add(removeButton); + + // Remove button. + c.gridx = 2; + c.gridy = 0; + grid.setConstraints(bothButton = new JButton("Remove/Add"), c); + frame.add(bothButton); + + // Table. + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 6; + c.gridheight = 0; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1.0; + c.weighty = 1.0; + JScrollPane scroll = null; + tableModel = new SimpleTableModel(); + grid.setConstraints(scroll = new JScrollPane(new JTable(tableModel)), c); + frame.add(scroll); + + // Create some action listeners. + addButton.addActionListener(event -> tableModel.addRow()); + removeButton.addActionListener(event -> tableModel.removeRow()); + bothButton.addActionListener(event -> tableModel.removeThenAddRow()); + + frame.pack(); + return frame; + } + + static class SimpleTableModel extends AbstractTableModel { + int counter = 0; + ArrayList list = new ArrayList(); + + public SimpleTableModel() {} + public int getColumnCount() { return 1; } + public int getRowCount() { return list.size(); } + + public Object getValueAt(int row, int col) { + String str = (String) list.get(row); + return str;// + "." + col; + } + + public void addRow() { + list.add("" + counter++); + fireTableRowsInserted(list.size() - 1, list.size() - 1); + } + + public void removeRow() { + if (list.size() == 0) return; + list.remove(list.size() - 1); + fireTableRowsDeleted(list.size(), list.size()); + } + + public void removeThenAddRow() { + if (list.size() == 0) return; + removeRow(); + addRow(); + } + } +} From f880fa91dce7b8844cfa4e95caa3a982e280165a Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Tue, 22 Apr 2025 03:09:45 +0000 Subject: [PATCH 275/843] 8352793: Open source several AWT TextComponent tests - Batch 1 Reviewed-by: prr, serb --- .../awt/TextComponent/BackgroundTest.java | 127 ++++++++++++++++++ .../java/awt/TextComponent/DisableTest.java | 98 ++++++++++++++ .../java/awt/TextComponent/ModifiersTest.java | 85 ++++++++++++ .../awt/TextComponent/TextFieldMargin.java | 67 +++++++++ 4 files changed, 377 insertions(+) create mode 100644 test/jdk/java/awt/TextComponent/BackgroundTest.java create mode 100644 test/jdk/java/awt/TextComponent/DisableTest.java create mode 100644 test/jdk/java/awt/TextComponent/ModifiersTest.java create mode 100644 test/jdk/java/awt/TextComponent/TextFieldMargin.java diff --git a/test/jdk/java/awt/TextComponent/BackgroundTest.java b/test/jdk/java/awt/TextComponent/BackgroundTest.java new file mode 100644 index 00000000000..543f2cfd893 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/BackgroundTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4258667 4405602 + * @summary Make sure TextComponents are grayed out when non-editable + * if the background color has not been set by client code. + * Make sure TextComponents are not grayed out when non-editable + * if the background color has been set by client code. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual BackgroundTest + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.TextField; + +public class BackgroundTest { + private static final String enableString = "EnableText"; + private static final String disableString = "DisableText"; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. When the frame appears, it should have a blue background. + 2. The first TextField and TextArea will be the default color. + The second TextField and TextArea will be green. + 3. Press the "DisableText" button. + The first TextField and TextArea should change colors to the + default disabled color. On Windows, this is usually gray. + On linux and macos it will match the environment settings. + If the TextField or the TextArea do not change colors as described, + the test FAILS. + 4. The second TextField and TextArea should still be green. + If either of them are not green, the test FAILS. + Press the "EnableText" button (same button as before). + The first TextField and TextArea should return to their + original colors as described in the first paragraph. If they + do not, the test FAILS. + 5. The second TextField and TextArea should still be green. + If either of them are not green, the test FAILS. + Otherwise, the test PASSES. + """; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(BackgroundTest::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Background Test"); + frame.setLayout(new FlowLayout()); + TextField tf = new TextField(30); + TextArea ta = new TextArea(4, 30); + TextField setTf = new TextField(30); + TextArea setTa = new TextArea(4, 30); + Button enableButton = new Button(disableString); + + enableButton.setBackground(Color.red); + frame.setSize(500, 250); + + frame.setBackground(Color.blue); + + tf.setText("Background not set - should be default"); + tf.setEditable(true); + frame.add(tf); + ta.setText("Background not set - should be default"); + ta.setEditable(true); + frame.add(ta); + + setTf.setText("Background is set - should be Green"); + setTf.setBackground(Color.green); + setTf.setEditable(true); + frame.add(setTf); + setTa.setText("Background is set - should be Green"); + setTa.setBackground(Color.green); + setTa.setEditable(true); + frame.add(setTa); + + enableButton.addActionListener(e -> { + boolean currentlyEditable = tf.isEditable(); + + if (currentlyEditable) { + tf.setEditable(false); + ta.setEditable(false); + setTf.setEditable(false); + setTa.setEditable(false); + enableButton.setLabel(enableString); + } else { + tf.setEditable(true); + ta.setEditable(true); + setTf.setEditable(true); + setTa.setEditable(true); + enableButton.setLabel(disableString); + } + }); + frame.add(enableButton); + return frame; + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/TextComponent/DisableTest.java b/test/jdk/java/awt/TextComponent/DisableTest.java new file mode 100644 index 00000000000..820b9c8bd30 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/DisableTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5042122 + * @summary Verifies the TextComponent is grayed out when disabled + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual DisableTest + */ + +import javax.swing.BoxLayout; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Component; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.event.ActionListener; +import java.util.Vector; +import java.util.Iterator; + +public class DisableTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Click "Enable" and "Disable" buttons and verify the text + components are disabled and enabled correctly. + 2. Verify that the disabled text components are grayed + out and are uneditable. + 3. Click PASS or FAIL accordingly. + """; + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(DisableTest::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("TextComponent Disabled test"); + frame.setLayout(new BorderLayout()); + frame.setSize(200, 200); + final Vector comps = new Vector(); + comps.add(new TextField("TextField")); + TextArea ta = new TextArea("TextArea", 2, 100, TextArea.SCROLLBARS_NONE); + comps.add(ta); + Panel pc = new Panel(); + pc.setLayout(new BoxLayout(pc, BoxLayout.Y_AXIS)); + Iterator iter = comps.iterator(); + while (iter.hasNext()) { + Component c = (Component) iter.next(); + c.setEnabled(false); + pc.add(c); + } + frame.add(pc, BorderLayout.CENTER); + Panel p = new Panel(); + final Button be = new Button("Enable"); + final Button bd = new Button("Disable"); + p.add(be); + p.add(bd); + ActionListener al = ev -> { + boolean enable = (ev.getSource() == be); + Iterator iterator = comps.iterator(); + while (iterator.hasNext()) { + Component c = (Component) iterator.next(); + c.setEnabled(enable); + } + }; + be.addActionListener(al); + bd.addActionListener(al); + frame.add(p, BorderLayout.SOUTH); + return frame; + } +} diff --git a/test/jdk/java/awt/TextComponent/ModifiersTest.java b/test/jdk/java/awt/TextComponent/ModifiersTest.java new file mode 100644 index 00000000000..e9e76a9b694 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/ModifiersTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4035364 + * @summary Checks that Caps Lock key works + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ModifiersTest + */ + +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.TextArea; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +public class ModifiersTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Type some text in the TextArea in upper and lowercase, + using the Caps Lock ON/OFF. + 2. If Caps Lock toggles correctly and you are able to type in + both cases, the test PASS. Else Test FAILS. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ModifiersTest::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Modifiers Test"); + frame.setLayout(new GridLayout(1, 1)); + frame.addKeyListener(new KeyChecker()); + frame.setLayout(new GridLayout(2, 1)); + Label label = new Label("See if you can type in upper and lowercase using Caps Lock:"); + frame.add(label); + TextArea ta = new TextArea(); + frame.add(ta); + ta.addKeyListener(new KeyChecker()); + ta.requestFocus(); + frame.setSize(400, 300); + return frame; + } +} + +// a KeyListener for debugging purposes +class KeyChecker extends KeyAdapter { + public void keyPressed(KeyEvent ev) { + System.out.println(ev); + } + + public void keyReleased(KeyEvent ev) { + System.out.println(ev); + } + + public void keyTyped(KeyEvent ev) { + System.out.println(ev); + } +} diff --git a/test/jdk/java/awt/TextComponent/TextFieldMargin.java b/test/jdk/java/awt/TextComponent/TextFieldMargin.java new file mode 100644 index 00000000000..6baf144254c --- /dev/null +++ b/test/jdk/java/awt/TextComponent/TextFieldMargin.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4129511 + * @summary Tests that TextField margins are not exceedingly wide + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TextFieldMargin + */ + +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.TextArea; +import java.awt.TextField; + +public class TextFieldMargin { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Examine the TextField, Label, and TextArea to see + that the text is vertically aligned along the left + 2. If all are aligned along the left, then test PASS, + else test FAILS. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(TextFieldMargin::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Frame with a text field & a label"); + frame.setLayout(new GridLayout(5, 1)); + TextField text_field = new TextField("Left Textfield"); + frame.add(text_field); + Label label = new Label("Left Label"); + frame.add(label); + TextArea text_area = new TextArea("Left Textfield"); + frame.add(text_area); + frame.setBounds(50, 50, 300, 300); + return frame; + } +} From 0be3f163ed12db305673928d97f975d6f6bb6b1c Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Tue, 22 Apr 2025 03:29:59 +0000 Subject: [PATCH 276/843] 8341608: jdeps in JDK 23 crashes when parsing signatures while jdeps in JDK 22 works fine Reviewed-by: jpai, henryjen --- .../com/sun/tools/jdeps/ClassFileReader.java | 190 +++++------------- .../com/sun/tools/jdeps/Dependencies.java | 2 +- .../com/sun/tools/jdeps/DependencyFinder.java | 12 +- .../tools/jdeps/MalformedClassesTest.java | 129 ++++++++++++ test/langtools/tools/jdeps/TEST.properties | 2 + .../com/sun/tools/jdeps/JdepsAccess.java | 34 ++++ .../lib/compiler/InMemoryJavaCompiler.java | 8 +- test/lib/jdk/test/lib/util/JarUtils.java | 20 +- 8 files changed, 241 insertions(+), 156 deletions(-) create mode 100644 test/langtools/tools/jdeps/MalformedClassesTest.java create mode 100644 test/langtools/tools/jdeps/TEST.properties create mode 100644 test/langtools/tools/jdeps/jdk.jdeps/com/sun/tools/jdeps/JdepsAccess.java diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java index fc1bf5302d6..72dc4e72899 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,10 +41,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; -import java.util.NoSuchElementException; import java.util.Set; +import java.util.function.Consumer; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; @@ -102,6 +101,10 @@ public class ClassFileReader implements Closeable { return skippedEntries; } + protected void skipEntry(Throwable ex, String entryPath) { + skippedEntries.add(String.format("%s: %s", ex.toString(), entryPath)); + } + /** * Returns all entries in this archive. */ @@ -135,8 +138,15 @@ public class ClassFileReader implements Closeable { return null; } - public Iterable getClassFiles() throws IOException { - return FileIterator::new; + public void forEachClassFile(Consumer handler) throws IOException { + if (baseFileName.endsWith(".class")) { + // propagate ClassFileError for single file + try { + handler.accept(readClassFile(path)); + } catch (ClassFileError ex) { + skipEntry(ex, path.toString()); + } + } } protected ClassModel readClassFile(Path p) throws IOException { @@ -167,33 +177,6 @@ public class ClassFileReader implements Closeable { public void close() throws IOException { } - class FileIterator implements Iterator { - int count; - FileIterator() { - this.count = 0; - } - public boolean hasNext() { - return count == 0 && baseFileName.endsWith(".class"); - } - - public ClassModel next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - try { - ClassModel cf = readClassFile(path); - count++; - return cf; - } catch (IOException e) { - throw new ClassFileError(e); - } - } - - public void remove() { - throw new UnsupportedOperationException("Not supported yet."); - } - } - public String toString() { return path.toString(); } @@ -241,42 +224,17 @@ public class ClassFileReader implements Closeable { return null; } - public Iterable getClassFiles() throws IOException { - final Iterator iter = new DirectoryIterator(); - return () -> iter; - } - - class DirectoryIterator implements Iterator { - private final List entries; - private int index = 0; - DirectoryIterator() throws IOException { - List paths = null; - try (Stream stream = Files.walk(path, Integer.MAX_VALUE)) { - paths = stream.filter(ClassFileReader::isClass).toList(); - - } - this.entries = paths; - this.index = 0; - } - - public boolean hasNext() { - return index != entries.size(); - } - - public ClassModel next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - Path path = entries.get(index++); - try { - return readClassFile(path); - } catch (IOException e) { - throw new ClassFileError(e); - } - } - - public void remove() { - throw new UnsupportedOperationException("Not supported yet."); + @Override + public void forEachClassFile(Consumer handler) throws IOException { + try (Stream stream = Files.walk(path, Integer.MAX_VALUE)) { + stream.filter(ClassFileReader::isClass) + .forEach(e -> { + try { + handler.accept(readClassFile(e)); + } catch (ClassFileError | IOException ex) { + skipEntry(ex, e.toString()); + } + }); } } } @@ -314,14 +272,15 @@ public class ClassFileReader implements Closeable { return jf; } + private static boolean isJarEntryClass(JarEntry e) { + return e.getName().endsWith(".class"); + } + protected Set scan() { - try (JarFile jf = openJarFile(path.toFile(), version)) { - return jf.versionedStream().map(JarEntry::getName) - .filter(n -> n.endsWith(".class")) - .collect(Collectors.toSet()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + return jarfile.versionedStream() + .filter(JarFileReader::isJarEntryClass) + .map(JarEntry::getName) + .collect(Collectors.toSet()); } public ClassModel getClassFile(String name) throws IOException { @@ -358,76 +317,17 @@ public class ClassFileReader implements Closeable { } } - public Iterable getClassFiles() throws IOException { - final Iterator iter = new JarFileIterator(this, jarfile); - return () -> iter; - } - } - - class JarFileIterator implements Iterator { - protected final JarFileReader reader; - protected Iterator entries; - protected JarFile jf; - protected JarEntry nextEntry; - protected ClassModel cf; - JarFileIterator(JarFileReader reader) { - this(reader, null); - } - JarFileIterator(JarFileReader reader, JarFile jarfile) { - this.reader = reader; - setJarFile(jarfile); - } - - void setJarFile(JarFile jarfile) { - if (jarfile == null) return; - - this.jf = jarfile; - this.entries = jarfile.versionedStream().iterator(); - this.nextEntry = nextEntry(); - } - - public boolean hasNext() { - if (nextEntry != null && cf != null) { - return true; - } - while (nextEntry != null) { - try { - cf = reader.readClassFile(jf, nextEntry); - return true; - } catch (ClassFileError | IOException ex) { - skippedEntries.add(String.format("%s: %s (%s)", - ex.getMessage(), - nextEntry.getName(), - jf.getName())); - } - nextEntry = nextEntry(); - } - return false; - } - - public ClassModel next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - ClassModel classFile = cf; - cf = null; - nextEntry = nextEntry(); - return classFile; - } - - protected JarEntry nextEntry() { - while (entries.hasNext()) { - JarEntry e = entries.next(); - String name = e.getName(); - if (name.endsWith(".class")) { - return e; - } - } - return null; - } - - public void remove() { - throw new UnsupportedOperationException("Not supported yet."); + @Override + public void forEachClassFile(Consumer handler) throws IOException { + jarfile.versionedStream() + .filter(JarFileReader::isJarEntryClass) + .forEach(e -> { + try { + handler.accept(readClassFile(jarfile, e)); + } catch (ClassFileError | IOException ex) { + skipEntry(ex, e.getName() + " (" + jarfile.getName() + ")"); + } + }); } } } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java index 90682c478c7..d7df5ba77c2 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Dependencies.java @@ -79,7 +79,7 @@ public class Dependencies { private static final long serialVersionUID = 4111110813961313203L; public ClassFileError(Throwable cause) { - initCause(cause); + super(cause.getMessage(), cause); } } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java index 179043bc578..d2bf83a50b0 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,9 +173,9 @@ class DependencyFinder { trace("parsing %s %s%n", archive.getName(), archive.getPathName()); FutureTask> task = new FutureTask<>(() -> { Set targets = new HashSet<>(); - for (var cf : archive.reader().getClassFiles()) { + archive.reader().forEachClassFile(cf -> { if (cf.isModuleInfo()) - continue; + return; String classFileName; try { @@ -187,11 +187,11 @@ class DependencyFinder { // filter source class/archive String cn = classFileName.replace('/', '.'); if (!finder.accept(archive, cn, cf.flags())) - continue; + return; // tests if this class matches the -include if (!filter.matches(cn)) - continue; + return; for (Dependency d : finder.findDependencies(cf)) { if (filter.accepts(d)) { @@ -203,7 +203,7 @@ class DependencyFinder { } parsedClasses.putIfAbsent(d.getOrigin(), archive); } - } + }); return targets; }); tasks.add(task); diff --git a/test/langtools/tools/jdeps/MalformedClassesTest.java b/test/langtools/tools/jdeps/MalformedClassesTest.java new file mode 100644 index 00000000000..baa94ad78e2 --- /dev/null +++ b/test/langtools/tools/jdeps/MalformedClassesTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341608 + * @summary Tests for jdeps tool with jar files with malformed classes + * @library lib /test/lib + * @build jdk.jdeps/com.sun.tools.jdeps.* + * @run junit MalformedClassesTest + */ + +import java.io.IOException; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.attribute.SignatureAttribute; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +import com.sun.tools.jdeps.JdepsAccess; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.util.JarUtils; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class MalformedClassesTest { + + static Stream invalidArchives() throws Exception { + var jarPath = Path.of("malformed-signature.jar"); + var compiledClasses = InMemoryJavaCompiler.compile(Map.ofEntries( + Map.entry("one.One", """ + package one; + + import java.util.Optional; + + class One { + Optional st = Optional.empty(); + } + """), + Map.entry("two.Two", """ + package two; + + import java.lang.invoke.*; + + class Two { + int i; + static final VarHandle I; + + static { + try { + I = MethodHandles.lookup().findVarHandle(Two.class, "i", int.class); + } catch (ReflectiveOperationException ex) { + throw new ExceptionInInitializerError(ex); + } + } + } + """) + )); + var updated = ClassFile.of().transformClass(ClassFile.of().parse(compiledClasses.get("one.One")), + ClassTransform.transformingFields((fb, fe) -> { + if (fe instanceof SignatureAttribute) { + fb.with(SignatureAttribute.of(fb.constantPool().utf8Entry("Invalid string"))); + } else { + fb.with(fe); + } + })); + var classes = new HashMap<>(compiledClasses); + classes.put("one.One", updated); + JarUtils.createJarFromClasses(jarPath, classes); + + Path flatDir = Path.of("flatDir"); + Files.createDirectories(flatDir); + for (var entry : classes.entrySet()) { + ClassFileInstaller.writeClassToDisk(entry.getKey(), entry.getValue(), flatDir.toString()); + } + + return Stream.of( + Arguments.of("directory", flatDir, "One.class"), + Arguments.of("jar", jarPath, "one/One.class (malformed-signature.jar)") + ); + } + + @ParameterizedTest + @MethodSource("invalidArchives") + public void testMalformedSignature(String kind, Path path, String entryName) throws IOException { + try (var jdeps = JdepsUtil.newCommand("jdeps")) { + jdeps.addRoot(path); + var analyzer = jdeps.getDepsAnalyzer(); + analyzer.run(); + var archives = JdepsAccess.depsAnalyzerArchives(analyzer); + assertEquals(1, archives.size(), archives::toString); + var archive = archives.iterator().next(); + var skippedEntries = archive.reader().skippedEntries(); + assertEquals(1, skippedEntries.size(), skippedEntries::toString); + var message = skippedEntries.getFirst(); + assertTrue(message.contains("ClassFileError"), message); + assertTrue(message.contains("Invalid string"), message); + assertTrue(message.contains(entryName), "\"" + message + "\" does not contain \"" + entryName + "\""); + } + } +} diff --git a/test/langtools/tools/jdeps/TEST.properties b/test/langtools/tools/jdeps/TEST.properties new file mode 100644 index 00000000000..56b5043d3c1 --- /dev/null +++ b/test/langtools/tools/jdeps/TEST.properties @@ -0,0 +1,2 @@ +modules = \ + jdk.jdeps/com.sun.tools.jdeps diff --git a/test/langtools/tools/jdeps/jdk.jdeps/com/sun/tools/jdeps/JdepsAccess.java b/test/langtools/tools/jdeps/jdk.jdeps/com/sun/tools/jdeps/JdepsAccess.java new file mode 100644 index 00000000000..16229153e13 --- /dev/null +++ b/test/langtools/tools/jdeps/jdk.jdeps/com/sun/tools/jdeps/JdepsAccess.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.jdeps; + +import java.util.Set; + +public final class JdepsAccess { + public static Set depsAnalyzerArchives(DepsAnalyzer analyzer) { + return analyzer.archives; + } + + private JdepsAccess() {} +} diff --git a/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java b/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java index 4722ef3b67a..7a289bbcce5 100644 --- a/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java +++ b/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,8 +208,10 @@ public class InMemoryJavaCompiler { } /** - * Compiles the list of classes with the given map of name and source code. - * This overloaded version of compile is useful for batch compile use cases. + * Compiles the list of classes with the given map of binary name and source code. + * This overloaded version of compile is useful for batch compile use cases, or + * if a compilation unit produces multiple class files. Returns a map from + * class binary names to class file content. * * @param inputMap The map containing the name of the class and corresponding source code * @throws RuntimeException if the compilation did not succeed diff --git a/test/lib/jdk/test/lib/util/JarUtils.java b/test/lib/jdk/test/lib/util/JarUtils.java index 3aa4ada5197..9a3d73ee410 100644 --- a/test/lib/jdk/test/lib/util/JarUtils.java +++ b/test/lib/jdk/test/lib/util/JarUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,6 +131,24 @@ public final class JarUtils { createJarFile(jarfile, dir, paths); } + + /** + * Creates a JAR file from a map of class binary name to class bytes. + * + * @see jdk.test.lib.compiler.InMemoryJavaCompiler#compile(Map) + */ + public static void createJarFromClasses(Path jarfile, Map classes) throws IOException { + try (OutputStream out = Files.newOutputStream(jarfile); + JarOutputStream jos = new JarOutputStream(out)) { + for (var entry : classes.entrySet()) { + String name = entry.getKey().replace('.', '/') + ".class"; + jos.putNextEntry(new JarEntry(name)); + jos.write(entry.getValue()); + jos.closeEntry(); + } + } + } + /** * Updates a JAR file. * From e2cb64674f5b6b4f000ab1e903fbb75416218bb3 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Tue, 22 Apr 2025 05:56:07 +0000 Subject: [PATCH 277/843] 8343977: Convert java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest to main Reviewed-by: prr, achung --- .../HoveringAndDraggingTest.html | 43 --- .../HoveringAndDraggingTest.java | 285 ++++++------------ 2 files changed, 99 insertions(+), 229 deletions(-) delete mode 100644 test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html diff --git a/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html b/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html deleted file mode 100644 index 9fc7f55ceba..00000000000 --- a/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - HoveringAndDraggingTest - - - -

HoveringAndDraggingTest
Bug ID: 6497109

- -

See the dialog box (usually in upper left corner) for instructions

- - - - diff --git a/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java b/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java index 753fc490967..646bc6aa6b9 100644 --- a/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java +++ b/test/jdk/java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 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 @@ -21,71 +21,122 @@ * questions. */ -/* - test - @bug 6497109 - @summary Mouse cursor icons for TextArea should be correct in case of hovering or dragging mouse over different subcomponents. - @author Konstantin Voloshin: area=awt.TextArea - @run applet/manual=yesno HoveringAndDraggingTest.html -*/ +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.TextArea; +import java.util.concurrent.CountDownLatch; -/** - * HoveringAndDraggingTest.java - * - * summary: Mouse cursor icons for TextArea should be correct in case - * of hovering or dragging mouse over different subcomponents. +/* + * @test + * @bug 6497109 + * @summary Mouse cursor icons for TextArea should be correct in case of + * hovering or dragging mouse over different subcomponents. + * @run main/manual HoveringAndDraggingTest */ -import java.awt.Frame; -import java.awt.Panel; -import java.awt.GridLayout; -import java.awt.TextArea; -import java.awt.Dialog; +public class HoveringAndDraggingTest { + static Frame frame; + static Frame instructionsFrame; + static CountDownLatch countDownLatch; + public static CountDownLatch createCountDownLatch() { + return new CountDownLatch(1); + } -public class HoveringAndDraggingTest extends java.applet.Applet { - public void start() { - String[] instructions = new String[] { - "1. Notice components in test window: main-panel, box-for-text," - +" 2 scroll-sliders, and 4 scroll-buttons.", - "2. Hover mouse over box-for-text." - +" Make sure, that mouse cursor is TextCursor (a.k.a. \"beam\").", - "3. Hover mouse over each of components (see item 1), except for box-for-text." - +" Make sure, that cursor is DefaultCursor (arrow).", - "4. Drag mouse (using any mouse button) from box-for-text to every" - +" component in item 1, and also outside application window." - +" Make sure, that cursor remains TextCursor while mouse button is pressed.", - "5. Repeat item 4 for each other component in item 1, except for box-for-text," - +" _but_ now make sure that cursor is DefaultCursor.", - "6. If cursor behaves as described in items 2-3-4-5, then test passed; otherwise it failed." - }; - Sysout.createDialogWithInstructions( instructions ); + public static void main(String[] args) throws Exception { + countDownLatch = createCountDownLatch(); + EventQueue.invokeAndWait(() -> { + initialize(); + showInstructionFrame(); + }); + countDownLatch.await(); + System.out.println("Test Pass"); + } + public static void initialize() { Panel panel = new Panel(); - panel.setLayout( new GridLayout(3,3) ); + panel.setLayout(new GridLayout(3, 3)); - for( int y=0; y<3; ++y ) { - for( int x=0; x<3; ++x ) { - if( x==1 && y==1 ) { - panel.add( new TextArea( bigString() ) ); + for (int y = 0; y < 3; ++y) { + for (int x = 0; x < 3; ++x) { + if (x == 1 && y == 1) { + panel.add(new TextArea(bigString())); } else { - panel.add( new Panel() ); + panel.add(new Panel()); } } } - Frame frame = new Frame( "TextArea cursor icon test" ); - frame.setSize( 300, 300 ); - frame.add( panel ); - frame.setVisible( true ); + frame = new Frame("TextArea cursor icon test"); + frame.setSize(300, 300); + frame.setLocation(450, 400); + frame.add(panel); + frame.setVisible(true); + } + + static void showInstructionFrame() { + String INSTRUCTIONS = """ + 1. Notice components in test window: main-panel,box-for-text, + 2 scroll-sliders, and 4 scroll-buttons. + 2. Hover mouse over box-for-text. + Make sure, that mouse cursor is TextCursor(a.k.a. \"beam\"). + 3. Hover mouse over each of components (see item 1), + except for box-for-text. + Make sure, that cursor is DefaultCursor (arrow). + 4. Drag mouse (using any mouse button) from box-for-text to every" + component in item 1, and also outside application window." + Make sure, that cursor remains TextCursor + while mouse button is pressed. + 5. Repeat item 4 for each other component in item 1, + except for box-for-text + _but_ now make sure that cursor is DefaultCursor. + 6. If cursor behaves as described in items 2-3-4-5, + then test is PASS otherwise it FAILED. + """; + TextArea textArea = new TextArea(INSTRUCTIONS, 16, 65, TextArea.SCROLLBARS_NONE); + Button passBtn = new Button("PASS"); + Button failBtn = new Button("FAIL"); + Panel btnPanel = new Panel(new GridBagLayout()); + Panel panel = new Panel(new GridBagLayout()); + instructionsFrame = new Frame("Test Instructions"); + passBtn.setMaximumSize(new Dimension(100, 30)); + failBtn.setMaximumSize(new Dimension(100, 30)); + btnPanel.add(passBtn); + btnPanel.add(failBtn); + passBtn.addActionListener(e -> disposeFrames()); + failBtn.addActionListener(e -> { + disposeFrames(); + throw new RuntimeException("Test Failed"); + }); + panel.add(textArea); + panel.add(btnPanel); + instructionsFrame.add(panel); + instructionsFrame.pack(); + instructionsFrame.setLocation(300, 100); + instructionsFrame.setVisible(true); + } + + static void disposeFrames() { + countDownLatch.countDown(); + if (frame != null) { + frame.dispose(); + } + if (instructionsFrame != null) { + instructionsFrame.dispose(); + } } static String bigString() { String s = ""; - for( int lines=0; ; ++lines ) { - for( int symbols=0; symbols<100; ++symbols ) { + for (int lines = 0; ; ++lines) { + for (int symbols = 0; symbols < 100; ++symbols) { s += "0"; } - if( lines<50 ) { + if (lines < 50) { s += "\n"; } else { break; @@ -94,141 +145,3 @@ public class HoveringAndDraggingTest extends java.applet.Applet { return s; } } - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class From d1d7d2569c1745aef778c9b5a62c1bd50735e8a7 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Tue, 22 Apr 2025 06:23:24 +0000 Subject: [PATCH 278/843] 8353957: Open source several AWT ScrollPane tests - Batch 1 Reviewed-by: psadhukhan --- test/jdk/ProblemList.txt | 1 + .../awt/ScrollPane/ScrollPaneFlicker.java | 215 ++++++++++++++++++ .../java/awt/ScrollPane/ScrollPanePaint.java | 132 +++++++++++ .../awt/ScrollPane/ScrollPositionTest.java | 100 ++++++++ .../ScrollPane/ScrollbarsAsNeededTest.java | 72 ++++++ 5 files changed, 520 insertions(+) create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPaneFlicker.java create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPanePaint.java create mode 100644 test/jdk/java/awt/ScrollPane/ScrollPositionTest.java create mode 100644 test/jdk/java/awt/ScrollPane/ScrollbarsAsNeededTest.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index e1e0a695ebc..3fe0bcf8cdc 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -443,6 +443,7 @@ java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java 8203004 linux-all +java/awt/ScrollPane/ScrollPositionTest.java 8040070 linux-all java/awt/ScrollPane/ScrollPaneScrollType/ScrollPaneEventType.java 8296516 macosx-all java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneFlicker.java b/test/jdk/java/awt/ScrollPane/ScrollPaneFlicker.java new file mode 100644 index 00000000000..3594ff50f54 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneFlicker.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4073822 + * @summary ScrollPane repaints entire window when scrolling fast + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPaneFlicker + */ + +import java.awt.Button; +import java.awt.Canvas; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Label; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.ScrollPane; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +public class ScrollPaneFlicker { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + When scrolling a ScrollPane fast(i.e. holding the down/up arrow + down for a while), the ScrollPane would inexplicably refresh + the entire window. + + 1. Select a type of ScrollPane content from the content menu. + 2. Scroll the content using the up/down/left/right arrows on + the scroll bar. Try scrolling the entire content area using + the scroll arrows-- from top to bottom and left to right. + 3. Verify that the entire pane does not refresh when scrolling + - only the newly exposed areas should be repainting. + 4. Repeat for all content types. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollPaneFlicker::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + return new FlickerFrame(); + } +} + +class FlickerFrame extends Frame { + ScrollPane pane; + + public FlickerFrame() { + super("ScrollPane Flicker Test"); + TextPanel textPanel = new TextPanel(); + GradientPanel gradientPanel = new GradientPanel(); + ComponentPanel componentPanel = new ComponentPanel(); + SwingPanel swingPanel = new SwingPanel(); + MenuBar menubar = new MenuBar(); + Menu testMenu = new Menu("Test Options"); + + pane = new ScrollPane(); + pane.getHAdjustable().setUnitIncrement(8); + pane.getVAdjustable().setUnitIncrement(16); + pane.add(textPanel); + add(pane); + + testMenu.add(makeContentItem("Text Lines", textPanel)); + testMenu.add(makeContentItem("Gradient Fill", gradientPanel)); + testMenu.add(makeContentItem("AWT Components", componentPanel)); + testMenu.add(makeContentItem("Swing Components", swingPanel)); + menubar.add(testMenu); + + setMenuBar(menubar); + setSize(400, 300); + } + + public MenuItem makeContentItem(String title, final Component content) { + MenuItem menuItem = new MenuItem(title); + menuItem.addActionListener( + ev -> { + pane.add(content); + pane.validate(); + } + ); + return menuItem; + } +} + +class GradientPanel extends Canvas { + public void paint(Graphics g) { + // just paint something that'll take a while + int x, y; + int width = getSize().width; + int height = getSize().height; + int step = 8; + + for (x = 0; x < width; x += step) { + for (y = 0; y < height; y += step) { + int red = (255 * y) / height; + int green = (255 * x * y) / (width * height); + int blue = (255 * x) / width; + Rectangle bounds = g.getClipBounds(); + Rectangle fbounds = new Rectangle(x, y, x + step, y + step); + if (bounds.intersects(fbounds)) { + Color color = new Color(red, green, blue); + g.setColor(color); + g.fillRect(x, y, x + step, y + step); + } + } + } + } + + public Dimension getPreferredSize() { + return new Dimension(200, 1000); + } +} + +class TextPanel extends Canvas { + public void paint(Graphics g) { + Font font = new Font("SanSerif", Font.ITALIC, 12); + + g.setFont(font); + // just paint something that'll take a while + int x, y; + int width = getWidth(); + int height = getHeight(); + int step = 16; + + for (x = y = 0; y < height; y += step) { + Rectangle bounds = g.getClipBounds(); + Rectangle tbounds = new Rectangle(x, y - 16, x + width, y); + if (bounds.intersects(tbounds)) { + g.drawString(y + " : The quick brown fox jumps over the lazy dog. " + + "The rain in Spain falls mainly on the plain.", x, y); + } + } + } + + public Dimension getPreferredSize() { + return new Dimension(640, 1000); + } +} + +class ComponentPanel extends Panel { + ComponentPanel() { + add(new Label("Label")); + add(new Button("Button")); + add(new Checkbox("Checkbox")); + Choice c = new Choice(); + c.add("choice"); + java.awt.List l = new java.awt.List(); + l.add("list"); + add(new Scrollbar()); + add(new TextField("TextField")); + add(new TextArea("TextArea")); + add(new Panel()); + add(new Canvas()); + } +} + +class SwingPanel extends JPanel { + SwingPanel() { + add(new JLabel("JLabel")); + add(new JButton("JButton")); + add(new JCheckBox("JCheckBox")); + JComboBox c = new JComboBox(); + JList l = new JList(); + add(new JScrollBar()); + add(new JTextField("This is a JTextField with some text in it to make it longer.")); + add(new JTextArea("This is a JTextArea with some text in it to make it longer.")); + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPanePaint.java b/test/jdk/java/awt/ScrollPane/ScrollPanePaint.java new file mode 100644 index 00000000000..0d7b7779018 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPanePaint.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +/* + * Licensed Materials - Property of IBM + * + * (C) Copyright IBM Corporation 1998 All Rights Reserved. + * + * US Government Users Restricted Rights - Use, duplication or disclosure + * restricted by GSA ADP Schedule Contract with IBM Corp. + */ + +/* + * @test + * @bug 4160721 + * @summary AWT ScrollPane painting problem + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollPanePaint + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +public class ScrollPanePaint { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Press the button marked "Toggle" a few times. + 2. The contents of the frame should alternate between + a red panel and a scroll pane containing a green panel. + If this does not happen (specifically, if the scroll + pane does not consistently contain a green panel), + then the test has FAILED. + """; + ScrollPaintTest scrollPaintTest = new ScrollPaintTest(); + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(scrollPaintTest::initialize) + .positionTestUI(WindowLayouts::rightOneColumn) + .build() + .awaitAndCheck(); + } + + private static class ScrollPaintTest implements ActionListener { + static Frame f; + static boolean showScroll; + + public List initialize() { + Frame frame = new Frame("Scrollpane paint test"); + frame.setLayout(new BorderLayout()); + f = new Frame("Scrollpane paint test"); + f.setLayout(new GridLayout(0, 1)); + + Button b = new Button("Toggle"); + b.addActionListener(this); + + frame.add(b, BorderLayout.CENTER); + frame.pack(); + + showScroll = false; + actionPerformed(null); + return List.of(frame, f); + } + + public void actionPerformed(ActionEvent e) { + Container c; + if (!showScroll) { + c = (Container) new TestPanel(new Dimension(100, 100)); + c.setBackground(Color.red); + } else { + c = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); + Panel p = new TestPanel(new Dimension(20, 20)); + p.setBackground(Color.green); + c.add(p); + } + + f.removeAll(); + f.add("Center", c); + f.pack(); + showScroll = !showScroll; + } + } + + private static class TestPanel extends Panel { + Dimension dim; + + TestPanel(Dimension d) { + dim = d; + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getPreferredSize() { + return dim; + } + } + +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollPositionTest.java b/test/jdk/java/awt/ScrollPane/ScrollPositionTest.java new file mode 100644 index 00000000000..9c082a8dfc9 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPositionTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4008152 + * @summary ScrollPane position does not return correct values + * @key headful + * @run main ScrollPositionTest + */ + +import java.awt.Adjustable; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; + +public class ScrollPositionTest { + static Frame frame; + static int i = 0; + static Point p; + static ScrollPane sp; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("Scroll Position Test"); + frame.setLayout(new BorderLayout()); + frame.setSize(200, 200); + sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); + Canvas canvas = new Canvas(); + canvas.setSize(300, 300); + sp.add(canvas); + frame.add("Center", sp); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + EventQueue.invokeAndWait(() -> { + Adjustable saH = sp.getHAdjustable(); + saH.addAdjustmentListener(new TestAdjustmentListener()); + }); + for (i = 0; i < 1000; i++) { + EventQueue.invokeAndWait(() -> { + p = new Point(i % 100, i % 100); + sp.setScrollPosition(p); + }); + + robot.waitForIdle(); + robot.delay(10); + EventQueue.invokeAndWait(() -> { + if (!sp.getScrollPosition().equals(p)) { + throw new RuntimeException("Test failed. " + i + " : " + + "Expected " + p + ", but Returned: " + sp.getScrollPosition()); + } + }); + } + System.out.println("Test Passed."); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static class TestAdjustmentListener implements AdjustmentListener { + public void adjustmentValueChanged(AdjustmentEvent e) { + System.out.println("AdjEvent caught:" + e); + } + } +} diff --git a/test/jdk/java/awt/ScrollPane/ScrollbarsAsNeededTest.java b/test/jdk/java/awt/ScrollPane/ScrollbarsAsNeededTest.java new file mode 100644 index 00000000000..c5f48f80007 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollbarsAsNeededTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4094248 + * @summary Test initial appearance of SCROLLBARS_AS_NEEDED policy + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollbarsAsNeededTest + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.ScrollPane; + +public class ScrollbarsAsNeededTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. A Frame window with a ScrollPane that is + initially created with the SCROLLBARS_AS_NEEDED policy. + 2. If there are no scrollbars around the ScrollPane then + the test PASS. Otherwise the test FAILS. + """; + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ScrollbarsAsNeededTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame frame = new Frame("Scrollbar as needed test"); + ScrollPane scrollPane = new ScrollPane() { + @Override + public void paint(Graphics g) { + super.paint(g); + g.drawString("ScrollPane", 10, 50); + } + }; + scrollPane.setBackground(Color.WHITE); + frame.setBackground(Color.GRAY); + frame.setSize(200, 200); + frame.setLayout(new FlowLayout()); + frame.add(scrollPane); + return frame; + } +} From 33bdc807b18914bb57ca7853ab45d4fa8fdefd47 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 22 Apr 2025 06:51:18 +0000 Subject: [PATCH 279/843] 8355241: Move NativeDialogToFrontBackTest.java PL test to manual category Reviewed-by: psadhukhan --- test/jdk/ProblemList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 3fe0bcf8cdc..841b1110506 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -392,7 +392,6 @@ java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665 macosx-all -java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326 macosx-all java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021 macosx-all java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all @@ -820,3 +819,4 @@ java/awt/Checkbox/CheckboxBoxSizeTest.java 8340870 windows-all java/awt/Checkbox/CheckboxIndicatorSizeTest.java 8340870 windows-all java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all java/awt/dnd/WinMoveFileToShellTest.java 8341665 windows-all +java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all From a55ccd267cdfbb7a52c0647fa3b2f93b36b1805f Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 07:04:26 +0000 Subject: [PATCH 280/843] 8352905: Open some JComboBox bugs 1 Reviewed-by: honkar, psadhukhan --- .../jdk/javax/swing/JComboBox/bug4166593.java | 98 ++++++++++++ .../jdk/javax/swing/JComboBox/bug4180054.java | 112 +++++++++++++ .../jdk/javax/swing/JComboBox/bug4530952.java | 147 ++++++++++++++++++ .../jdk/javax/swing/JComboBox/bug4530953.java | 98 ++++++++++++ 4 files changed, 455 insertions(+) create mode 100644 test/jdk/javax/swing/JComboBox/bug4166593.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4180054.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4530952.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4530953.java diff --git a/test/jdk/javax/swing/JComboBox/bug4166593.java b/test/jdk/javax/swing/JComboBox/bug4166593.java new file mode 100644 index 00000000000..850aab2261f --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4166593.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Robot; +import java.awt.event.ActionListener; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4166593 + * @summary Tests that JComboBox fires action events every time the user does an action + * @key headful + * @run main bug4166593 + */ + +public class bug4166593 { + static JFrame frame; + static JComboBox comboBox; + static volatile int numberOfActionEvents = 0; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(250); + + // change selected index 3 times + SwingUtilities.invokeAndWait(() -> { + comboBox.setSelectedIndex(1); + comboBox.setSelectedIndex(3); + comboBox.setSelectedIndex(2); + }); + robot.waitForIdle(); + robot.delay(250); + + if (numberOfActionEvents != 3) { + throw new RuntimeException("Unexpected number of Action Events!\n" + + "Expected: 3\nActual: " + numberOfActionEvents); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + comboBox = new JComboBox(new Object[]{ + "Bob", "Fred", "Hank", "Joe", "Mildred", "Agatha", "Buffy" + }); + JPanel panel = new JPanel(); + JLabel label = new JLabel("0"); + frame = new JFrame("bug4166593"); + comboBox.setEditable(true); + + ActionListener actionCounter = e -> { + ++numberOfActionEvents; + label.setText(Integer.toString(numberOfActionEvents)); + }; + + comboBox.addActionListener(actionCounter); + + panel.add(comboBox); + panel.add(label); + + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4180054.java b/test/jdk/javax/swing/JComboBox/bug4180054.java new file mode 100644 index 00000000000..cee68dfcb9c --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4180054.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Robot; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +/* + * @test + * @bug 4180054 + * @summary Tests that DefaultComboBoxModel doesn't fire a "contents changed" unnecessarily + * @key headful + * @run main bug4180054 + */ + +public class bug4180054 { + static JFrame frame; + static JComboBox comboBox; + static volatile int numberOfContentsChangedEvents = 0; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(250); + + // change selected index 3 times + SwingUtilities.invokeAndWait(() -> { + comboBox.setSelectedIndex(1); + comboBox.setSelectedIndex(3); + comboBox.setSelectedIndex(2); + comboBox.setSelectedIndex(2); + }); + robot.waitForIdle(); + robot.delay(250); + + if (numberOfContentsChangedEvents != 3) { + throw new RuntimeException("Unexpected number of Contents Changed Events!\n" + + "Expected: 3\nActual: " + numberOfContentsChangedEvents); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4180054"); + JPanel panel = new JPanel(); + JLabel label = new JLabel("0"); + + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (int i = 0; i < 100; ++i) { + model.addElement(Integer.toString(i)); + } + comboBox = new JComboBox(model); + comboBox.setEditable(true); + + ListDataListener contentsCounter = new ListDataListener() { + public void contentsChanged(ListDataEvent e) { + ++numberOfContentsChangedEvents; + label.setText(Integer.toString(numberOfContentsChangedEvents)); + } + + public void intervalAdded(ListDataEvent e) { + } + + public void intervalRemoved(ListDataEvent e) { + } + }; + + comboBox.getModel().addListDataListener(contentsCounter); + + panel.add(comboBox); + panel.add(label); + + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4530952.java b/test/jdk/javax/swing/JComboBox/bug4530952.java new file mode 100644 index 00000000000..cf960d64c9a --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4530952.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +/* + * @test + * @bug 4530952 + * @summary Tests that double mouse clicks invoke Event + * @key headful + * @run main bug4530952 + */ + +public class bug4530952 { + static JFrame frame; + static JButton btnAction; + static JComboBox cmbAction; + static volatile Point loc; + static volatile Dimension btnSize; + + private static volatile boolean flag; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(1000); + + // enter some text in combo box + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); + robot.delay(250); + + // find and click action button + SwingUtilities.invokeAndWait(() -> { + loc = btnAction.getLocationOnScreen(); + btnSize = btnAction.getSize(); + }); + robot.waitForIdle(); + robot.delay(250); + + robot.mouseMove(loc.x + btnSize.width / 2, + loc.y + btnSize.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(1000); + + if (!flag) { + throw new RuntimeException("Failed: button action was not fired"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4530952"); + frame.setLayout(new FlowLayout()); + + btnAction = new JButton("Action"); + cmbAction = new JComboBox(); + + flag = false; + + ActionListener al = e -> flag = true; + DocumentListener dl = new DocumentListener() { + @Override + public void changedUpdate(DocumentEvent evt) { + resetButtons(); + } + + @Override + public void insertUpdate(DocumentEvent evt) { + resetButtons(); + } + + @Override + public void removeUpdate(DocumentEvent evt) { + resetButtons(); + } + }; + + // Add an editable combo box + cmbAction.setEditable(true); + frame.add(cmbAction); + + btnAction.setEnabled(false); + frame.add(btnAction); + + btnAction.addActionListener(al); + ((JTextField) cmbAction.getEditor().getEditorComponent()). + getDocument().addDocumentListener(dl); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void resetButtons() { + int length = ((JTextField) cmbAction.getEditor().getEditorComponent()). + getDocument().getLength(); + btnAction.setEnabled(length > 0); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4530953.java b/test/jdk/javax/swing/JComboBox/bug4530953.java new file mode 100644 index 00000000000..a9f0c70b9bc --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4530953.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.FlowLayout; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4530953 + * @summary Tests that highlighted Item appears after automatically scrolling to the item + * @key headful + * @run main bug4530953 + */ + +public class bug4530953 { + static JFrame frame; + static JComboBox combo; + static String[] data = {"Apple", "Orange", "Cherry"}; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(250); + + // enter some text in combo box editor + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + robot.delay(250); + + // select orange in combo box + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + robot.delay(250); + + String currSelection = (String) combo.getEditor().getItem(); + if (!currSelection.equals("Orange")) { + throw new RuntimeException("Unexpected Selection.\n" + + "Expected: Orange\nActual: " + currSelection); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4530953"); + combo = new JComboBox(data); + combo.setEditable(true); + combo.setSelectedIndex(1); + frame.setLayout(new FlowLayout()); + frame.add(combo); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} From 2f7806ffe5b5b4b2f7caa14d4559943968c34678 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Tue, 22 Apr 2025 07:07:31 +0000 Subject: [PATCH 281/843] 8355034: [JVMCI] assert(static_cast(_jvmci_data_size) == align_up(compiler->is_jvmci() ? jvmci_data->size() : 0, oopSize)) failed: failed: 104 != 16777320 Reviewed-by: never, yzheng, cslucas --- src/hotspot/share/code/nmethod.cpp | 2 +- .../share/jvmci/jvmciCodeInstaller.cpp | 8 ++- .../classes/jdk/vm/ci/code/InstalledCode.java | 19 ++++++- .../vm/ci/code/test/InstalledCodeTest.java | 57 +++++++++++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InstalledCodeTest.java diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 01ace66f4de..56ba76a806e 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -112,7 +112,7 @@ // 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); + guarantee(static_cast(result) == thing, "failed: %d != %d", static_cast(result), thing); //--------------------------------------------------------------------------------- // NMethod statistics diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 79aaacec809..3a9fbc54bf9 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -825,7 +825,13 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, // Since this compilation didn't pass through the broker it wasn't logged yet. if (PrintCompilation) { ttyLocker ttyl; - CompileTask::print(tty, nm, "(hosted JVMCI compilation)"); + if (name != nullptr) { + stringStream st; + st.print_cr("(hosted JVMCI compilation: %s)", name); + CompileTask::print(tty, nm, st.as_string()); + } else { + CompileTask::print(tty, nm, "(hosted JVMCI compilation)"); + } } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/InstalledCode.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/InstalledCode.java index 489cca81c7b..62c0b609146 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/InstalledCode.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/InstalledCode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,24 @@ public class InstalledCode { protected final String name; + /** + * The maximum length of an InstalledCode name. This name is typically installed into + * the code cache so it should have a reasonable limit. + */ + public static final int MAX_NAME_LENGTH = 2048; + + /** + * @param name the name to be associated with the installed code. Can be null and + * must be no longer than {@link #MAX_NAME_LENGTH}. + * + * @throws IllegalArgumentException if {@code name.length >} {@link #MAX_NAME_LENGTH} + */ public InstalledCode(String name) { + if (name != null && name.length() > MAX_NAME_LENGTH) { + String msg = String.format("name length (%d) is greater than %d (name[0:%s] = %s)", + name.length(), MAX_NAME_LENGTH, MAX_NAME_LENGTH, name.substring(0, MAX_NAME_LENGTH)); + throw new IllegalArgumentException(msg); + } this.name = name; } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InstalledCodeTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InstalledCodeTest.java new file mode 100644 index 00000000000..f7e68043da7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InstalledCodeTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test 8355034 + * @requires vm.jvmci + * @modules jdk.internal.vm.ci/jdk.vm.ci.code + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.code.test.InstalledCodeTest + */ + +package jdk.vm.ci.code.test; + +import jdk.vm.ci.code.InstalledCode; +import org.junit.Assert; +import org.junit.Test; + +public class InstalledCodeTest { + + @Test + public void testNullName() { + new InstalledCode(null); + } + + @Test + public void testTooLongName() { + String longName = new String(new char[InstalledCode.MAX_NAME_LENGTH]).replace('\0', 'A'); + new InstalledCode(longName); + try { + String tooLongName = longName + "X"; + new InstalledCode(tooLongName); + } catch (IllegalArgumentException iae) { + // Threw IllegalArgumentException as expected. + return; + } + Assert.fail("expected IllegalArgumentException"); + } +} From 17b080b2c90f7fd9986fe38daebb76363d012469 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Tue, 22 Apr 2025 07:44:44 +0000 Subject: [PATCH 282/843] 8353446: Open source several AWT Menu tests - Batch 2 Reviewed-by: abhiscxk --- .../Menu/DestroyMenuTest/DestroyMenuTest.java | 139 ++++++++++++++ .../awt/Menu/DestroyMenuTest/MenuTest.java | 172 ++++++++++++++++++ .../jdk/java/awt/Menu/MenuAddRemoveCrash.java | 102 +++++++++++ test/jdk/java/awt/Menu/MenuZOrderTest.java | 80 ++++++++ .../java/awt/Menu/OnFlyRepaintMenuTest.java | 103 +++++++++++ 5 files changed, 596 insertions(+) create mode 100644 test/jdk/java/awt/Menu/DestroyMenuTest/DestroyMenuTest.java create mode 100644 test/jdk/java/awt/Menu/DestroyMenuTest/MenuTest.java create mode 100644 test/jdk/java/awt/Menu/MenuAddRemoveCrash.java create mode 100644 test/jdk/java/awt/Menu/MenuZOrderTest.java create mode 100644 test/jdk/java/awt/Menu/OnFlyRepaintMenuTest.java diff --git a/test/jdk/java/awt/Menu/DestroyMenuTest/DestroyMenuTest.java b/test/jdk/java/awt/Menu/DestroyMenuTest/DestroyMenuTest.java new file mode 100644 index 00000000000..b75ba047dfb --- /dev/null +++ b/test/jdk/java/awt/Menu/DestroyMenuTest/DestroyMenuTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4209511 + * @summary Regression test DestroyMenuTest.java Failing + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual DestroyMenuTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Canvas; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Scrollbar; +import java.awt.TextField; + +public class DestroyMenuTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Create many windows by randomly clicking 'Show Menu Test 1', + 'Show Menu Test 2', 'Show Menu Test 3' buttons. + 2. Ignore the contents of the windows. + Go to the windows created and select menu items inside the menus. + 3. Close the windows by selecting menu item File--> Quit. + 4. Do the above menu item selections as quickly as possible. + If the program crashes when you select File--> Quit, + then the test FAILS. Otherwise the test is PASS. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(38) + .testUI(DestroyMenuTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame f = new Frame("Destroy Menu Test"); + Button launchButton = new Button("Show Menu Test 1..."); + Button launchButton2 = new Button("Show Menu Test 2..."); + Button launchButton3 = new Button("Show Menu Test 3..."); + f.setLayout(new FlowLayout()); + f.add(launchButton); + f.add(launchButton2); + f.add(launchButton3); + + launchButton.addActionListener(event -> { + MenuTest frame = new MenuTest("Menu Test 1"); + frame.setBounds(300, 300, 300, 300); + frame.setVisible(true); + }); + + launchButton2.addActionListener(event -> { + MenuTest frame = new MenuTest("Menu Test 2"); + + Button closeButton = new Button("Close"); + + Panel X = new Panel(); + X.setLayout(new BorderLayout()); + + Panel topPanel = new Panel(); + Panel bottomPanel = new Panel(); + + bottomPanel.add(closeButton); + + Scrollbar vScrollbar = new Scrollbar(Scrollbar.VERTICAL); + Scrollbar hScrollbar = new Scrollbar(Scrollbar.HORIZONTAL); + hScrollbar.setValues(hScrollbar.getValue(), 0, 0, 50); + vScrollbar.setValues(vScrollbar.getValue(), 0, 0, 50); + topPanel.setLayout(new BorderLayout()); + topPanel.add(vScrollbar, BorderLayout.EAST); + topPanel.add(hScrollbar, BorderLayout.SOUTH); + + X.add(topPanel, BorderLayout.NORTH); + X.add(bottomPanel, BorderLayout.SOUTH); + frame.add(X, BorderLayout.SOUTH); + frame.setBounds(350, 350, 300, 250); + frame.setVisible(true); + }); + + launchButton3.addActionListener(event -> { + MenuTest frame = new MenuTest("Menu Test 3"); + frame.setBounds(400, 400, 300, 300); + + mySimpleCanvas clock = new mySimpleCanvas(); + frame.add(clock, BorderLayout.CENTER); + + Panel p = new Panel(); + Button closeButton = new Button("Close"); + p.add(closeButton); + + p.add(new Label("Label")); + TextField textField = new TextField(8); + p.add(textField); + f.add(p, BorderLayout.EAST); + + frame.add(p, BorderLayout.SOUTH); + frame.setVisible(true); + }); + f.pack(); + return f; + } + + static class mySimpleCanvas extends Canvas { + @Override + public void paint(Graphics g) { + g.drawOval(0, 0, 100, 100); + g.drawOval(2, 2, 100, 100); + g.drawOval(4, 4, 100, 100); + } + } +} diff --git a/test/jdk/java/awt/Menu/DestroyMenuTest/MenuTest.java b/test/jdk/java/awt/Menu/DestroyMenuTest/MenuTest.java new file mode 100644 index 00000000000..95569f13fa2 --- /dev/null +++ b/test/jdk/java/awt/Menu/DestroyMenuTest/MenuTest.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Canvas; +import java.awt.CardLayout; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Label; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Panel; + +public class MenuTest extends Frame { + private MenuItem quitItem; + private final Panel cards; + private final CardLayout layout; + + public MenuTest(String s) { + super(s); + MenuBar mbar = new MenuBar(); + createMenus(mbar); + setMenuBar(mbar); + + cards = new Panel(); + layout = new CardLayout(); + cards.setLayout(layout); + + cards.add(new MyPanelOne("Options"), "Options"); + cards.add(new MyRectCanvas(), "MyRectCanvas"); + cards.add(new MycircleCanvas(), "MyCircleCanvas"); + + add(cards, "Center"); + } + + public void createMenus(MenuBar mbar) { + mbar.add(createFileMenu()); + mbar.add(createEditMenu()); + mbar.add(createOptionMenu1()); + mbar.add(createOptionMenu2()); + mbar.add(createOptionMenu3()); + mbar.add(createOptionMenu4()); + } + + private Menu createFileMenu() { + Menu fileMenu = new Menu("File"); + fileMenu.add(quitItem = new MenuItem("Quit")); + + quitItem.addActionListener(event -> { + MenuItem item = (MenuItem) event.getSource(); + if (item == quitItem) { + dispose(); + } + }); + return fileMenu; + } + + private Menu createEditMenu() { + Menu editMenu = new Menu("Edit"); + + editMenu.add("Cut"); + editMenu.add("Copy"); + editMenu.add("Paste"); + editMenu.addSeparator(); + editMenu.add("Select all"); + editMenu.addSeparator(); + editMenu.add("Find"); + editMenu.add("Find again"); + + return editMenu; + } + + private Menu createOptionMenu1() { + Menu optionMenu1 = new Menu("Option1"); + MenuItem item1, item2, item3; + optionMenu1.add(item1 = new MenuItem("Item1")); + optionMenu1.add(item2 = new MenuItem("Item2")); + optionMenu1.add(item3 = new MenuItem("Item3")); + + item1.addActionListener(event -> { + MenuItem mItem = (MenuItem) event.getSource(); + if (mItem == item1) { + layout.show(cards, "Options"); + } + }); + item2.addActionListener(event -> { + MenuItem mItem = (MenuItem) event.getSource(); + if (mItem == item2) { + layout.show(cards, "MyRectCanvas"); + } + }); + item3.addActionListener(event -> { + MenuItem mItem = (MenuItem) event.getSource(); + if (mItem == item3) { + layout.show(cards, "MyCircleCanvas"); + } + }); + return optionMenu1; + } + + private Menu createOptionMenu2() { + Menu optionMenu2 = new Menu("Option2"); + + optionMenu2.add("Item1"); + optionMenu2.add("Item2"); + + return optionMenu2; + } + + private Menu createOptionMenu3() { + Menu optionMenu3 = new Menu("Option3"); + + optionMenu3.add("Item1"); + optionMenu3.add("Item2"); + optionMenu3.add("Item3"); + optionMenu3.add("Item4"); + + return optionMenu3; + } + + private Menu createOptionMenu4() { + Menu optionMenu4 = new Menu("Option3"); + + optionMenu4.add("Item1"); + optionMenu4.add("Item2"); + optionMenu4.add("Item3"); + + return optionMenu4; + } +} + +class MyRectCanvas extends Canvas { + @Override + public void paint(Graphics g) { + g.drawRect(0, 0, 100, 100); + } +} + +class MyPanelOne extends Panel { + MyPanelOne(String name) { + add(new Label(name + " panel goes here")); + } +} + +class MycircleCanvas extends Canvas { + @Override + public void paint(Graphics g) { + g.drawOval(0, 0, 100, 100); + g.drawOval(2, 2, 100, 100); + g.drawOval(4, 4, 100, 100); + } +} diff --git a/test/jdk/java/awt/Menu/MenuAddRemoveCrash.java b/test/jdk/java/awt/Menu/MenuAddRemoveCrash.java new file mode 100644 index 00000000000..d5c80c27a4f --- /dev/null +++ b/test/jdk/java/awt/Menu/MenuAddRemoveCrash.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4410477 + * @summary Tests that menu does not crash during simultaneous drawing + * and removal of items. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MenuAddRemoveCrash + */ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; + +public class MenuAddRemoveCrash { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Move and resize the frame. + 2. If the test crashes the test is FAILED. + Otherwise it is PASSED. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(MenuAddRemoveCrash::initialize) + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + final TestGui myTestGui = new TestGui(); + Thread test = new Thread() { + public void run() { + while (!Thread.interrupted()) { + myTestGui.changeMenuItems(); + } + } + }; + test.setDaemon(true); + test.start(); + return myTestGui; + } +} + +class TestGui extends Frame { + Menu myMenu1; + Menu myMenu2; + + public TestGui() { + this.setTitle("Try to resize this frame!"); + + this.setSize(300, 300); + this.setVisible(true); + + MenuBar myMenuBar = new MenuBar(); + myMenu1 = new Menu("DemoMenu1"); + myMenu2 = new Menu("DemoMenu2"); + + myMenuBar.add(myMenu1); + myMenuBar.add(myMenu2); + + this.setMenuBar(myMenuBar); + } + + public void changeMenuItems() { + myMenu1.removeAll(); + + for (int i = 0; i < 10; i++) { + MenuItem myMenuItem1 = new MenuItem("DemoMenuItem" + i); + myMenu1.add(myMenuItem1); + } + try { + Thread.sleep(100); + } catch (Exception e) { + throw new RuntimeException("Failed :" + e); + } + } +} diff --git a/test/jdk/java/awt/Menu/MenuZOrderTest.java b/test/jdk/java/awt/Menu/MenuZOrderTest.java new file mode 100644 index 00000000000..fefd3d64c28 --- /dev/null +++ b/test/jdk/java/awt/Menu/MenuZOrderTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6267182 + * @summary Menu is not visible after showing and disposing a file dialog. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MenuZOrderTest + */ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class MenuZOrderTest { + static class Listener implements ActionListener { + @Override + public void actionPerformed(ActionEvent e) { + Frame f = new Frame("Menu Z order test frame"); + f.setBounds(200, 200, 200, 200); + f.setVisible(true); + } + } + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Choose Menu 1 --> Menu Item 1 several times. + 2. If menu window is shown correctly and each click + creates new frame - press PASS. + 3. If menu window is obscured by frame - press FAIL. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(MenuZOrderTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame mf = new Frame("Menu Z order test"); + Listener l = new Listener(); + MenuBar mb = new MenuBar(); + Menu m1 = new Menu("Menu 1"); + MenuItem mi1 = new MenuItem("Menu Item 1"); + + mf.setSize(200, 200); + mi1.addActionListener(l); + m1.add(mi1); + mb.add(m1); + mf.setMenuBar(mb); + mf.setVisible(true); + return mf; + } +} diff --git a/test/jdk/java/awt/Menu/OnFlyRepaintMenuTest.java b/test/jdk/java/awt/Menu/OnFlyRepaintMenuTest.java new file mode 100644 index 00000000000..617d640d907 --- /dev/null +++ b/test/jdk/java/awt/Menu/OnFlyRepaintMenuTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5024051 + * @summary Tests if menu is repainted in enabling/disabling it and + * changing its label while it is visible, either on MenuBar + * or in other Menu. Menu items are covered as well + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual OnFlyRepaintMenuTest + */ + +import java.awt.Button; +import java.awt.CheckboxMenuItem; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; + +public class OnFlyRepaintMenuTest { + static boolean menuEnabled = true; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Click the button 'Change state' and wait for 5 secs. + 2. If menu is repainted correctly after its setLabel() + and setEnabled() methods called test PASSED, else FAILED. + (During a 5 secs delay you may select the menu to see + the effect for menu items and submenu) + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(OnFlyRepaintMenuTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame f = new Frame("OnFly Menu Repaint Test"); + + f.setSize(200, 100); + + MenuBar mb = new MenuBar(); + Menu menu = new Menu("Menu"); + MenuItem menuItem = new MenuItem("MenuItem"); + menu.add(menuItem); + Menu submenu = new Menu("SubMenu"); + MenuItem submenuItem = new MenuItem("SubmenuItem"); + submenu.add(submenuItem); + CheckboxMenuItem checkMenuItem = new CheckboxMenuItem("CheckboxmenuItem"); + checkMenuItem.setState(true); + menu.add(checkMenuItem); + menu.add(submenu); + mb.add(menu); + f.setMenuBar(mb); + + Button b = new Button("Change state"); + b.addActionListener(ev -> new Thread(() -> { + try { + Thread.sleep(5000); + } catch (Exception e) { + } + menuEnabled = !menuEnabled; + String label = menuEnabled ? "Enabled" : "Disabled"; + menu.setLabel(label); + menuItem.setLabel(label); + submenu.setLabel(label); + submenuItem.setLabel(label); + checkMenuItem.setLabel(label); + checkMenuItem.setEnabled(menuEnabled); + checkMenuItem.setState(menuEnabled); + submenuItem.setEnabled(menuEnabled); + submenu.setEnabled(menuEnabled); + menuItem.setEnabled(menuEnabled); + menu.setEnabled(menuEnabled); + }).start()); + f.add(b); + return f; + } +} From 0b2a2f38d0b0133a562a898836d7a1b2dbd73a5e Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 07:45:56 +0000 Subject: [PATCH 283/843] 8353685: Open some JComboBox bugs 4 Reviewed-by: honkar, kizune --- .../jdk/javax/swing/JComboBox/bug4212498.java | 86 +++++++++++++++++ .../jdk/javax/swing/JComboBox/bug4459267.java | 75 +++++++++++++++ .../jdk/javax/swing/JComboBox/bug4519269.java | 94 +++++++++++++++++++ 3 files changed, 255 insertions(+) create mode 100644 test/jdk/javax/swing/JComboBox/bug4212498.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4459267.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4519269.java diff --git a/test/jdk/javax/swing/JComboBox/bug4212498.java b/test/jdk/javax/swing/JComboBox/bug4212498.java new file mode 100644 index 00000000000..b60470fdd32 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4212498.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/* + * @test + * @bug 4212498 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4212498 + */ + +public class bug4212498 { + static JPanel panel = new JPanel(); + static JComboBox comboBox = new JComboBox(new Object[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea"}); + + private static final String INSTRUCTIONS = """ + Edit the value in the text field (without using the popup) + and then press the tab key. If the number doesn't increase, + then test fails. + + Also, try tabbing out without making a change. The number + should NOT increase unless the user changes something. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4212498::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4212498"); + comboBox.setEditable(true); + + final JLabel label = new JLabel("0"); + + ActionListener actionListener = + e -> label.setText("" + (Integer.parseInt(label.getText()) + 1)); + + comboBox.addActionListener(actionListener); + + panel.add(comboBox); + panel.add(label); + panel.add(new JButton("B")); + + frame.getContentPane().add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + return frame; + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4459267.java b/test/jdk/javax/swing/JComboBox/bug4459267.java new file mode 100644 index 00000000000..85049936ea7 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4459267.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.BorderLayout; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4459267 + * @summary Tests that pressing PageUp in combo popup list doesn't cause + * stack overflow + * @key headful + * @run main bug4459267 + */ + +public class bug4459267 { + static JFrame frame; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(1000); + + robot.keyPress(KeyEvent.VK_PAGE_UP); + robot.keyRelease(KeyEvent.VK_PAGE_UP); + robot.waitForIdle(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4459267"); + JComboBox jcmb = new JComboBox(); + jcmb.addItem("JComobo1"); + jcmb.addItem("Item2"); + jcmb.addItem("Item3"); + frame.getContentPane().add(jcmb, BorderLayout.NORTH); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4519269.java b/test/jdk/javax/swing/JComboBox/bug4519269.java new file mode 100644 index 00000000000..29147998d0a --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4519269.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4519269 + * @summary Tests that DefaultKeySelectionManager doesn't throw NPE + * @key headful + * @run main bug4519269 + */ + +public class bug4519269 { + static JFrame frame; + static JComboBox combo; + static Point p; + static Object[] data = {new CustomString("Item 1"), new CustomString("Item 2"), + new CustomString("Item 3"), new CustomString("Item 4")}; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> p = combo.getLocationOnScreen()); + robot.mouseMove(p.x + 5, p.y + 5); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.waitForIdle(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4519269"); + combo = new JComboBox(data); + frame.getContentPane().add(combo); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + static class CustomString { + String string; + + public CustomString(String s) { + string = s; + } + + public String toString() { + return null; + } + } +} From 7eab2d9f9140a27f7a5c5e0a57b9e6a256558690 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 07:58:30 +0000 Subject: [PATCH 284/843] 8354095: Open some JTable bugs 5 Reviewed-by: kizune, honkar --- .../swing/JTable/InternationalCharacters.java | 172 +++++++++++++++++ .../javax/swing/JTable/NullTableHeader.java | 44 +++++ test/jdk/javax/swing/JTable/bug4118307.java | 182 ++++++++++++++++++ test/jdk/javax/swing/JTable/bug4138158.java | 62 ++++++ 4 files changed, 460 insertions(+) create mode 100644 test/jdk/javax/swing/JTable/InternationalCharacters.java create mode 100644 test/jdk/javax/swing/JTable/NullTableHeader.java create mode 100644 test/jdk/javax/swing/JTable/bug4118307.java create mode 100644 test/jdk/javax/swing/JTable/bug4138158.java diff --git a/test/jdk/javax/swing/JTable/InternationalCharacters.java b/test/jdk/javax/swing/JTable/InternationalCharacters.java new file mode 100644 index 00000000000..1d8fc2c4576 --- /dev/null +++ b/test/jdk/javax/swing/JTable/InternationalCharacters.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4179066 + * @summary Tests that JTable prints AltGr characters (~\@|{}[]²µ³) + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual InternationalCharacters + */ + +public class InternationalCharacters { + private static final String INSTRUCTIONS = """ + Double-click an entry in the JTable. + Press Alt-Gr or Option with any key to type an international character. + Verify that the international character appears in the table. + If it does, press "pass", otherwise press "fail". + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(InternationalCharacters::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("InternationalCharacters test"); + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { return names.length; } + public int getRowCount() { return data.length;} + public Object getValueAt(int row, int col) {return data[row][col];} + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) {return names[column];} + public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} + public boolean isCellEditable(int row, int col) {return true;} + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer)headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number)value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/NullTableHeader.java b/test/jdk/javax/swing/JTable/NullTableHeader.java new file mode 100644 index 00000000000..dc62b975d04 --- /dev/null +++ b/test/jdk/javax/swing/JTable/NullTableHeader.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.JTable; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4129409 + * @summary Tests that JTable.setTableHeader(null) doesn't break AutoResize + * @key headful + * @run main NullTableHeader + */ + +public class NullTableHeader { + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + JTable tableView = new JTable(); + tableView.setTableHeader(null); + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + }); + } +} diff --git a/test/jdk/javax/swing/JTable/bug4118307.java b/test/jdk/javax/swing/JTable/bug4118307.java new file mode 100644 index 00000000000..537e92176ef --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4118307.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4118307 + * @summary Tests that JTable's cell editor for Number and Date work correctly + * @key headful + * @run main bug4118307 + */ + +public class bug4118307 { + static JFrame frame; + static MyTable tbl; + static Point tableLoc; + static Point p; + private static volatile boolean flag; + static final String[] columnNames = {"Integer", "Double"}; + static final Object[][] data = { + {5, 3.14}, + {10, 2.71}, + {70, 3.14}, + {200, 2.71}, + }; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + tableLoc = tbl.getLocationOnScreen(); + p = tbl.getCellRect(0, 0, true).getLocation(); + }); + robot.waitForIdle(); + + robot.mouseMove(tableLoc.x + p.x + 10, tableLoc.y + p.y + 10); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> + p = tbl.getCellRect(1, 1, true).getLocation()); + robot.waitForIdle(); + + robot.mouseMove(tableLoc.x + p.x + 10, tableLoc.y + p.y + 10); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> + p = tbl.getCellRect(1, 0, true).getLocation()); + robot.waitForIdle(); + + robot.mouseMove(tableLoc.x + p.x + 10, tableLoc.y + p.y + 10); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(5000); + + if (!flag) { + throw new RuntimeException("Test Failed."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4118307"); + MyTableModel myModel = new MyTableModel(); + tbl = new MyTable(myModel); + JScrollPane sp = new JScrollPane(tbl); + flag = true; + + frame.add(sp, BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + static class MyTable extends JTable { + public MyTable(TableModel tm) { + super(tm); + } + + public Component prepareRenderer(TableCellRenderer rend, int row, int col) { + try { + return super.prepareRenderer(rend, row, col); + } catch (Exception e) { + e.printStackTrace(); + flag = false; + return null; + } + } + } + + static class MyTableModel extends AbstractTableModel { + public int getColumnCount() { + return columnNames.length; + } + + public int getRowCount() { + return data.length; + } + + @Override + public String getColumnName(int col) { + return columnNames[col]; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + @Override + public boolean isCellEditable(int row, int col) { + return true; + } + + @Override + public void setValueAt(Object value, int row, int col) { + data[row][col] = value; + } + } +} diff --git a/test/jdk/javax/swing/JTable/bug4138158.java b/test/jdk/javax/swing/JTable/bug4138158.java new file mode 100644 index 00000000000..400b8b1952e --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4138158.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +/* + * @test + * @bug 4138158 + * @summary Tests that setAutoscrolls(false) locks autoscroll + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4138158 + */ + +public class bug4138158 { + private static final String INSTRUCTIONS = """ + Move mouse to beginning of table, press left mouse button and drag mouse down + below the frame. If the table isn't scrolled down then test passes. + If the table is scrolled then test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4138158::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4138158"); + JTable table = new JTable(20, 3); + table.setAutoscrolls(false); + JScrollPane sp = new JScrollPane(table); + frame.add(sp); + frame.setSize(200, 200); + return frame; + } +} From 367bcc5df83722231106b635068a17f92404477b Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Tue, 22 Apr 2025 07:59:45 +0000 Subject: [PATCH 285/843] 8353445: Open source several AWT Menu tests - Batch 1 Reviewed-by: abhiscxk, prr --- test/jdk/ProblemList.txt | 1 + .../java/awt/Menu/MenuActionEventTest.java | 98 +++++++++++ .../jdk/java/awt/Menu/MenuVisibilityTest.java | 71 ++++++++ test/jdk/java/awt/Menu/RmInHideTest.java | 152 ++++++++++++++++++ test/jdk/java/awt/Menu/SetShortCutTest.java | 132 +++++++++++++++ 5 files changed, 454 insertions(+) create mode 100644 test/jdk/java/awt/Menu/MenuActionEventTest.java create mode 100644 test/jdk/java/awt/Menu/MenuVisibilityTest.java create mode 100644 test/jdk/java/awt/Menu/RmInHideTest.java create mode 100644 test/jdk/java/awt/Menu/SetShortCutTest.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 841b1110506..fe0657ff165 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -819,4 +819,5 @@ java/awt/Checkbox/CheckboxBoxSizeTest.java 8340870 windows-all java/awt/Checkbox/CheckboxIndicatorSizeTest.java 8340870 windows-all java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all java/awt/dnd/WinMoveFileToShellTest.java 8341665 windows-all +java/awt/Menu/MenuVisibilityTest.java 8161110 macosx-all java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all diff --git a/test/jdk/java/awt/Menu/MenuActionEventTest.java b/test/jdk/java/awt/Menu/MenuActionEventTest.java new file mode 100644 index 00000000000..70fcc81ac86 --- /dev/null +++ b/test/jdk/java/awt/Menu/MenuActionEventTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4094620 + * @summary MenuItem.enableEvents does not work + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MenuActionEventTest + */ + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.event.ActionEvent; + +public class MenuActionEventTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Click on the Menu and then on Menuitem on the frame. + 2. If you find the following message being printed in + the test log area:, + _MenuItem: action event", + click PASS, else click FAIL" + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(MenuActionEventTest::initialize) + .logArea() + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame f = new Frame("Menu Action Event Test"); + f.setLayout(new BorderLayout()); + f.setMenuBar(new MenuBar()); + Menu m = new _Menu("Menu"); + MenuBar mb = f.getMenuBar(); + mb.add(m); + MenuItem mi = new _MenuItem("Menuitem"); + m.add(mi); + f.setBounds(204, 152, 396, 300); + return f; + } + + static class _Menu extends Menu { + public _Menu(String text) { + super(text); + enableEvents(AWTEvent.ACTION_EVENT_MASK); + } + + @Override + protected void processActionEvent(ActionEvent e) { + PassFailJFrame.log("_Menu: action event"); + super.processActionEvent(e); + } + } + + static class _MenuItem extends MenuItem { + public _MenuItem(String text) { + super(text); + enableEvents(AWTEvent.ACTION_EVENT_MASK); + } + + @Override + protected void processActionEvent(ActionEvent e) { + PassFailJFrame.log("_MenuItem: action event"); + super.processActionEvent(e); + } + } + +} diff --git a/test/jdk/java/awt/Menu/MenuVisibilityTest.java b/test/jdk/java/awt/Menu/MenuVisibilityTest.java new file mode 100644 index 00000000000..cb74cd56e1a --- /dev/null +++ b/test/jdk/java/awt/Menu/MenuVisibilityTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5046491 6423258 + * @summary CheckboxMenuItem: menu text is missing from test frame + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MenuVisibilityTest +*/ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; + +public class MenuVisibilityTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Press on a MenuBar with a long name. + 2. Select "First item" in an opened menu. + If you see that "First menu item was pressed" in + the test log area, press PASS + Otherwise press FAIL" + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(MenuVisibilityTest::initialize) + .logArea() + .build() + .awaitAndCheck(); + } + + public static Frame initialize() { + Frame frame = new Frame("Menu visibility test"); + String menuTitle = "I_have_never_seen_so_long_Menu_Title_" + + "!_ehe-eha-ehu-ehi_ugu-gu!!!_;)_BANG_BANG..."; + MenuBar menubar = new MenuBar(); + Menu menu = new Menu(menuTitle); + MenuItem menuItem = new MenuItem("First item"); + menuItem.addActionListener(e -> + PassFailJFrame.log("First menu item was pressed.")); + menu.add(menuItem); + menubar.add(menu); + frame.setMenuBar(menubar); + frame.setSize(100, 200); + return frame; + } +} diff --git a/test/jdk/java/awt/Menu/RmInHideTest.java b/test/jdk/java/awt/Menu/RmInHideTest.java new file mode 100644 index 00000000000..b2d68400647 --- /dev/null +++ b/test/jdk/java/awt/Menu/RmInHideTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4039387 + * @summary Checks that calling Frame.remove() within hide() doesn't + * cause SEGV + * @key headful + * @run main RmInHideTest + */ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; + +public class RmInHideTest { + static volatile Point point; + static RmInHideTestFrame frame; + static volatile Dimension dimension; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new RmInHideTestFrame(); + frame.setSize(200, 200); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + EventQueue.invokeAndWait(() -> { + point = frame.getButtonLocation(); + dimension = frame.getButtonDimension(); + }); + robot.mouseMove(point.x + dimension.width / 2, point.y + dimension.height / 2); + robot.mousePress(MouseEvent.BUTTON2_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON2_DOWN_MASK); + robot.waitForIdle(); + robot.delay(100); + System.out.println("Test pass"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class RmInHideTestFrame extends Frame implements ActionListener { + MenuBar menubar = null; + Button b; + + public RmInHideTestFrame() { + super("RmInHideTest"); + b = new Button("Hide"); + b.setActionCommand("hide"); + b.addActionListener(this); + add("Center", b); + + MenuBar bar = new MenuBar(); + + Menu menu = new Menu("Test1", true); + menu.add(new MenuItem("Test1A")); + menu.add(new MenuItem("Test1B")); + menu.add(new MenuItem("Test1C")); + bar.add(menu); + + menu = new Menu("Test2", true); + menu.add(new MenuItem("Test2A")); + menu.add(new MenuItem("Test2B")); + menu.add(new MenuItem("Test2C")); + bar.add(menu); + setMenuBar(bar); + } + + @Override + public Dimension minimumSize() { + return new Dimension(200, 200); + } + + @Override + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + if (cmd.equals("hide")) { + hide(); + try { + Thread.currentThread().sleep(2000); + } catch (InterruptedException ex) { + // do nothing + } + show(); + } + } + + @Override + public void hide() { + menubar = getMenuBar(); + if (menubar != null) { + remove(menubar); + } + super.hide(); + } + + + @Override + public void show() { + if (menubar != null) { + setMenuBar(menubar); + } + super.show(); + } + + public Point getButtonLocation() { + return b.getLocationOnScreen(); + } + + public Dimension getButtonDimension() { + return b.getSize(); + } + } +} diff --git a/test/jdk/java/awt/Menu/SetShortCutTest.java b/test/jdk/java/awt/Menu/SetShortCutTest.java new file mode 100644 index 00000000000..b60b83dff9a --- /dev/null +++ b/test/jdk/java/awt/Menu/SetShortCutTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4203208 + * @summary setShortcut method does not display proper text on Menu component + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SetShortCutTest + */ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.MenuShortcut; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +import static java.awt.event.KeyEvent.VK_META; +import static java.awt.event.KeyEvent.VK_SHIFT; + +public class SetShortCutTest { + public static void main(String[] args) throws Exception { + boolean isMac = System.getProperty("os.name").startsWith("Mac"); + String shortcut = "Ctrl+Shift+"; + if (isMac) { + shortcut = KeyEvent.getKeyText(VK_SHIFT) + "+" + KeyEvent.getKeyText(VK_META); + } + + String INSTRUCTIONS = """ + 1. Select menuitem 'Stuff -> Second' once to remove 'File -> First'. + 2. Select menuitem 'Stuff -> Second' again to add 'File -> First'. + 3. If menuitem 'File -> First' reads First """ + shortcut + """ + 'C', press PASS. Otherwise press FAIL. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(SetShortCutTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + return new TestMenuShortCut(); + } + + static class TestMenuShortCut extends Frame implements ActionListener { + Menu menu1; + MenuItem item1; + MenuItem item2; + boolean beenHere; + + public TestMenuShortCut() { + setTitle("Set ShortCut test"); + beenHere = false; + MenuBar mTopMenu = buildMenu(); + setSize(300, 300); + this.setMenuBar(mTopMenu); + } + + public MenuBar buildMenu() { + MenuBar bar; + bar = new MenuBar(); + menu1 = new Menu("File"); + item1 = new MenuItem("First"); + menu1.add(item1); + item1.setShortcut(new MenuShortcut(KeyEvent.VK_C, true)); + bar.add(menu1); + + // Stuff menu + item2 = new MenuItem("Second"); + Menu menu2 = new Menu("Stuff"); + menu2.add(item2); + item2.setShortcut(new MenuShortcut(KeyEvent.VK_C, false)); + bar.add(menu2); + + item1.addActionListener(this); + item2.addActionListener(this); + return bar; + } + + @Override + public void actionPerformed(ActionEvent event) { + if (event.getSource() == item1) { + Frame temp = new Frame("Accelerator key is working for 'First'"); + temp.setSize(300, 50); + temp.setVisible(true); + } + + // Click on the "Stuff" menu to remove the "first" menu item + else if (event.getSource() == item2) { + // If the item has not been removed from the menu, + // then remove "First" from the "File" menu + if (beenHere == false) { + item1.removeActionListener(this); + menu1.remove(item1); + beenHere = true; + } else { + item1 = new MenuItem("First"); + menu1.add(item1); + item1.addActionListener(this); + item1.setShortcut(new MenuShortcut(KeyEvent.VK_C, true)); + beenHere = false; + } + } + } + } +} From 50358d1ca49c26d100c5c658de29c75f864fdc60 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Tue, 22 Apr 2025 08:00:01 +0000 Subject: [PATCH 286/843] 8354929: ZGC: Update collection stats while holding page allocator lock Reviewed-by: stefank, tschatzl, aboldtch --- src/hotspot/share/gc/z/zGeneration.cpp | 5 +-- src/hotspot/share/gc/z/zPageAllocator.cpp | 49 ++++++++++++----------- src/hotspot/share/gc/z/zPageAllocator.hpp | 6 ++- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index f3cd3393fc5..e74d7a8e9f3 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -279,7 +279,6 @@ void ZGeneration::reset_statistics() { _freed = 0; _promoted = 0; _compacted = 0; - _page_allocator->reset_statistics(_id); } size_t ZGeneration::freed() const { @@ -860,7 +859,7 @@ void ZGenerationYoung::mark_start() { _remembered.flip(); // Update statistics - stat_heap()->at_mark_start(_page_allocator->stats(this)); + stat_heap()->at_mark_start(_page_allocator->update_and_stats(this)); } void ZGenerationYoung::mark_roots() { @@ -1209,7 +1208,7 @@ void ZGenerationOld::mark_start() { _mark.start(); // Update statistics - stat_heap()->at_mark_start(_page_allocator->stats(this)); + stat_heap()->at_mark_start(_page_allocator->update_and_stats(this)); // Note that we start a marking cycle. // Unlike other GCs, the color switch implicitly changes the nmethods diff --git a/src/hotspot/share/gc/z/zPageAllocator.cpp b/src/hotspot/share/gc/z/zPageAllocator.cpp index a0d2c46c414..7bb1dcdcf81 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.cpp +++ b/src/hotspot/share/gc/z/zPageAllocator.cpp @@ -1373,9 +1373,25 @@ size_t ZPageAllocator::unused() const { return unused > 0 ? (size_t)unused : 0; } -ZPageAllocatorStats ZPageAllocator::stats(ZGeneration* generation) const { - ZLocker locker(&_lock); +void ZPageAllocator::update_collection_stats(ZGenerationId id) { + assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); +#ifdef ASSERT + size_t total_used = 0; + + ZPartitionIterator iter(&_partitions); + for (ZPartition* partition; iter.next(&partition);) { + total_used += partition->_used; + } + + assert(total_used == _used, "Must be consistent %zu == %zu", total_used, _used); +#endif + + _collection_stats[(int)id]._used_high = _used; + _collection_stats[(int)id]._used_low = _used; +} + +ZPageAllocatorStats ZPageAllocator::stats_inner(ZGeneration* generation) const { return ZPageAllocatorStats(_min_capacity, _max_capacity, soft_max_capacity(), @@ -1390,29 +1406,16 @@ ZPageAllocatorStats ZPageAllocator::stats(ZGeneration* generation) const { _stalled.size()); } -void ZPageAllocator::reset_statistics(ZGenerationId id) { - assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); -#ifdef ASSERT - { - // We may free without safepoint synchronization, take the lock to get - // consistent values. - ZLocker locker(&_lock); - size_t total_used = 0; +ZPageAllocatorStats ZPageAllocator::stats(ZGeneration* generation) const { + ZLocker locker(&_lock); + return stats_inner(generation); +} - ZPartitionIterator iter(&_partitions); - for (ZPartition* partition; iter.next(&partition);) { - total_used += partition->_used; - } +ZPageAllocatorStats ZPageAllocator::update_and_stats(ZGeneration* generation) { + ZLocker locker(&_lock); - assert(total_used == _used, "Must be consistent at safepoint %zu == %zu", total_used, _used); - } -#endif - - // Read once, we may have concurrent writers. - const size_t used = Atomic::load(&_used); - - _collection_stats[(int)id]._used_high = used; - _collection_stats[(int)id]._used_low = used; + update_collection_stats(generation->id()); + return stats_inner(generation); } void ZPageAllocator::increase_used_generation(ZGenerationId id, size_t size) { diff --git a/src/hotspot/share/gc/z/zPageAllocator.hpp b/src/hotspot/share/gc/z/zPageAllocator.hpp index 05b0d6774d9..5cd08aee94c 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.hpp +++ b/src/hotspot/share/gc/z/zPageAllocator.hpp @@ -235,6 +235,9 @@ private: void notify_out_of_memory(); void restart_gc() const; + void update_collection_stats(ZGenerationId id); + ZPageAllocatorStats stats_inner(ZGeneration* generation) const; + void print_on_inner(outputStream* st) const; public: @@ -262,8 +265,7 @@ public: void promote_used(const ZPage* from, const ZPage* to); ZPageAllocatorStats stats(ZGeneration* generation) const; - - void reset_statistics(ZGenerationId id); + ZPageAllocatorStats update_and_stats(ZGeneration* generation); ZPage* alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age); void safe_destroy_page(ZPage* page); From bcc33d5ef3bdbfaee51c45014851c54028da03f1 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Tue, 22 Apr 2025 08:32:03 +0000 Subject: [PATCH 287/843] 8352504: RISC-V: implement and enable CMoveI/L 8346786: RISC-V: Reconsider ConditionalMoveLimit when adding conditional move Reviewed-by: fyang, fjiang --- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 30 ++++ .../cpu/riscv/c2_MacroAssembler_riscv.hpp | 4 + src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 2 +- .../cpu/riscv/macroAssembler_riscv.cpp | 124 ++++++++++++++ .../cpu/riscv/macroAssembler_riscv.hpp | 5 + src/hotspot/cpu/riscv/riscv.ad | 103 ++++++++++-- src/hotspot/cpu/riscv/vm_version_riscv.cpp | 8 - .../os_cpu/linux_riscv/riscv_hwprobe.cpp | 5 +- .../c2/irTests/ModINodeIdealizationTests.java | 6 +- .../c2/irTests/ModLNodeIdealizationTests.java | 6 +- .../c2/irTests/TestConv2BExpansion.java | 8 + .../compiler/c2/irTests/TestFPComparison.java | 1 - .../compiler/c2/irTests/TestIfMinMax.java | 17 +- .../lib/ir_framework/TestFramework.java | 1 + .../compiler/vectorapi/TestVectorTest.java | 3 +- .../bench/java/lang/ClassComparison.java | 101 +++++++++++ .../openjdk/bench/java/lang/FPComparison.java | 159 +++++++++++++++++- .../bench/java/lang/IntegerComparison.java | 153 +++++++++++++++++ .../bench/java/lang/LongComparison.java | 152 +++++++++++++++++ .../bench/java/lang/PointerComparison.java | 101 +++++++++++ 20 files changed, 940 insertions(+), 49 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/lang/ClassComparison.java create mode 100644 test/micro/org/openjdk/bench/java/lang/IntegerComparison.java create mode 100644 test/micro/org/openjdk/bench/java/lang/LongComparison.java create mode 100644 test/micro/org/openjdk/bench/java/lang/PointerComparison.java diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index 39a49f8f1eb..0dc39744741 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -2156,6 +2156,36 @@ void C2_MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Regis } } +void C2_MacroAssembler::enc_cmove_cmp_fp(int cmpFlag, FloatRegister op1, FloatRegister op2, Register dst, Register src, bool is_single) { + int op_select = cmpFlag & (~unsigned_branch_mask); + + switch (op_select) { + case BoolTest::eq: + cmov_cmp_fp_eq(op1, op2, dst, src, is_single); + break; + case BoolTest::ne: + cmov_cmp_fp_ne(op1, op2, dst, src, is_single); + break; + case BoolTest::le: + cmov_cmp_fp_le(op1, op2, dst, src, is_single); + break; + case BoolTest::ge: + assert(false, "Should go to BoolTest::le case"); + ShouldNotReachHere(); + break; + case BoolTest::lt: + cmov_cmp_fp_lt(op1, op2, dst, src, is_single); + break; + case BoolTest::gt: + assert(false, "Should go to BoolTest::lt case"); + ShouldNotReachHere(); + break; + default: + assert(false, "unsupported compare condition"); + ShouldNotReachHere(); + } +} + // Set dst to NaN if any NaN input. void C2_MacroAssembler::minmax_fp(FloatRegister dst, FloatRegister src1, FloatRegister src2, FLOAT_TYPE ft, bool is_min) { diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp index a650174d90f..73fceea3805 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp @@ -129,6 +129,10 @@ Register op1, Register op2, Register dst, Register src); + void enc_cmove_cmp_fp(int cmpFlag, + FloatRegister op1, FloatRegister op2, + Register dst, Register src, bool is_single); + void spill(Register r, bool is64, int offset) { is64 ? sd(r, Address(sp, offset)) : sw(r, Address(sp, offset)); diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp index de3c1b17c8e..79bdc4917c9 100644 --- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp @@ -43,7 +43,7 @@ define_pd_global(bool, TieredCompilation, COMPILER1_PRESENT(true) NOT define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, OnStackReplacePercentage, 140); -define_pd_global(intx, ConditionalMoveLimit, 0); +define_pd_global(intx, ConditionalMoveLimit, 3); define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, MinJumpTableSize, 10); define_pd_global(intx, InteriorEntryAlignment, 16); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index c6393be0714..218da7cde03 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -1267,6 +1267,130 @@ void MacroAssembler::cmov_gtu(Register cmp1, Register cmp2, Register dst, Regist bind(no_set); } +// ----------- cmove, compare float ----------- + +// Move src to dst only if cmp1 == cmp2, +// otherwise leave dst unchanged, including the case where one of them is NaN. +// Clarification: +// java code : cmp1 != cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 eq cmp2), dst, src +void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { + if (UseZicond) { + if (is_single) { + feq_s(t0, cmp1, cmp2); + } else { + feq_d(t0, cmp1, cmp2); + } + czero_nez(dst, dst, t0); + czero_eqz(t0 , src, t0); + orr(dst, dst, t0); + return; + } + Label no_set; + if (is_single) { + // jump if cmp1 != cmp2, including the case of NaN + // not jump (i.e. move src to dst) if cmp1 == cmp2 + float_bne(cmp1, cmp2, no_set); + } else { + double_bne(cmp1, cmp2, no_set); + } + mv(dst, src); + bind(no_set); +} + +// Keep dst unchanged only if cmp1 == cmp2, +// otherwise move src to dst, including the case where one of them is NaN. +// Clarification: +// java code : cmp1 == cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 ne cmp2), dst, src +void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { + if (UseZicond) { + if (is_single) { + feq_s(t0, cmp1, cmp2); + } else { + feq_d(t0, cmp1, cmp2); + } + czero_eqz(dst, dst, t0); + czero_nez(t0 , src, t0); + orr(dst, dst, t0); + return; + } + Label no_set; + if (is_single) { + // jump if cmp1 == cmp2 + // not jump (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN + float_beq(cmp1, cmp2, no_set); + } else { + double_beq(cmp1, cmp2, no_set); + } + mv(dst, src); + bind(no_set); +} + +// When cmp1 <= cmp2 or any of them is NaN then dst = src, otherwise, dst = dst +// Clarification +// scenario 1: +// java code : cmp2 < cmp1 ? dst : src +// transformed to : CMove dst, (cmp1 le cmp2), dst, src +// scenario 2: +// java code : cmp1 > cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 le cmp2), dst, src +void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { + if (UseZicond) { + if (is_single) { + flt_s(t0, cmp2, cmp1); + } else { + flt_d(t0, cmp2, cmp1); + } + czero_eqz(dst, dst, t0); + czero_nez(t0 , src, t0); + orr(dst, dst, t0); + return; + } + Label no_set; + if (is_single) { + // jump if cmp1 > cmp2 + // not jump (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN + float_bgt(cmp1, cmp2, no_set); + } else { + double_bgt(cmp1, cmp2, no_set); + } + mv(dst, src); + bind(no_set); +} + +// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst +// Clarification +// scenario 1: +// java code : cmp2 <= cmp1 ? dst : src +// transformed to : CMove dst, (cmp1 lt cmp2), dst, src +// scenario 2: +// java code : cmp1 >= cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 lt cmp2), dst, src +void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { + if (UseZicond) { + if (is_single) { + fle_s(t0, cmp2, cmp1); + } else { + fle_d(t0, cmp2, cmp1); + } + czero_eqz(dst, dst, t0); + czero_nez(t0 , src, t0); + orr(dst, dst, t0); + return; + } + Label no_set; + if (is_single) { + // jump if cmp1 >= cmp2 + // not jump (i.e. move src to dst) if cmp1 < cmp2 or either is NaN + float_bge(cmp1, cmp2, no_set); + } else { + double_bge(cmp1, cmp2, no_set); + } + mv(dst, src); + bind(no_set); +} + // Float compare branch instructions #define INSN(NAME, FLOATCMP, BRANCH) \ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index b390fb236c2..c47200579c7 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -657,6 +657,11 @@ class MacroAssembler: public Assembler { void cmov_gt(Register cmp1, Register cmp2, Register dst, Register src); void cmov_gtu(Register cmp1, Register cmp2, Register dst, Register src); + void cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); + void cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); + void cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); + void cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); + public: // We try to follow risc-v asm menomics. // But as we don't layout a reachable GOT, diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 1eb1464e7d9..2e9d25c8156 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1933,6 +1933,12 @@ bool Matcher::match_rule_supported(int opcode) { case Op_SubHF: case Op_SqrtHF: return UseZfh; + + case Op_CMoveF: + case Op_CMoveD: + case Op_CMoveP: + case Op_CMoveN: + return false; } return true; // Per default match rules are supported. @@ -9938,12 +9944,15 @@ instruct far_cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN op1, immP0 zero, la // ============================================================================ // Conditional Move Instructions + +// --------- CMoveI --------- + instruct cmovI_cmpI(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOp cop) %{ match(Set dst (CMoveI (Binary cop (CmpI op1 op2)) (Binary dst src))); ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpI\n\t" + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpI\n\t" %} ins_encode %{ @@ -9960,7 +9969,7 @@ instruct cmovI_cmpU(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOpU cop) ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpU\n\t" + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpU\n\t" %} ins_encode %{ @@ -9977,7 +9986,7 @@ instruct cmovI_cmpL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOp cop) % ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpL\n\t" + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpL\n\t" %} ins_encode %{ @@ -9994,7 +10003,7 @@ instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop) ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpUL\n\t" + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpUL\n\t" %} ins_encode %{ @@ -10006,12 +10015,46 @@ instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop) ins_pipe(pipe_class_compare); %} +instruct cmovI_cmpF(iRegINoSp dst, iRegI src, fRegF op1, fRegF op2, cmpOp cop) %{ + match(Set dst (CMoveI (Binary cop (CmpF op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpF\n\t" + %} + + ins_encode %{ + __ enc_cmove_cmp_fp($cop$$cmpcode, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovI_cmpD(iRegINoSp dst, iRegI src, fRegD op1, fRegD op2, cmpOp cop) %{ + match(Set dst (CMoveI (Binary cop (CmpD op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpD\n\t" + %} + + ins_encode %{ + __ enc_cmove_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + instruct cmovI_cmpN(iRegINoSp dst, iRegI src, iRegN op1, iRegN op2, cmpOpU cop) %{ match(Set dst (CMoveI (Binary cop (CmpN op1 op2)) (Binary dst src))); ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpN\n\t" + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpN\n\t" %} ins_encode %{ @@ -10028,7 +10071,7 @@ instruct cmovI_cmpP(iRegINoSp dst, iRegI src, iRegP op1, iRegP op2, cmpOpU cop) ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpP\n\t" + "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpP\n\t" %} ins_encode %{ @@ -10040,12 +10083,14 @@ instruct cmovI_cmpP(iRegINoSp dst, iRegI src, iRegP op1, iRegP op2, cmpOpU cop) ins_pipe(pipe_class_compare); %} +// --------- CMoveL --------- + instruct cmovL_cmpL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOp cop) %{ match(Set dst (CMoveL (Binary cop (CmpL op1 op2)) (Binary dst src))); ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpL\n\t" + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpL\n\t" %} ins_encode %{ @@ -10062,7 +10107,7 @@ instruct cmovL_cmpUL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOpU cop) ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpUL\n\t" + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpUL\n\t" %} ins_encode %{ @@ -10079,7 +10124,7 @@ instruct cmovL_cmpI(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOp cop) % ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpI\n\t" + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpI\n\t" %} ins_encode %{ @@ -10096,7 +10141,7 @@ instruct cmovL_cmpU(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOpU cop) ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpU\n\t" + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpU\n\t" %} ins_encode %{ @@ -10108,12 +10153,46 @@ instruct cmovL_cmpU(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOpU cop) ins_pipe(pipe_class_compare); %} +instruct cmovL_cmpF(iRegLNoSp dst, iRegL src, fRegF op1, fRegF op2, cmpOp cop) %{ + match(Set dst (CMoveL (Binary cop (CmpF op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpF\n\t" + %} + + ins_encode %{ + __ enc_cmove_cmp_fp($cop$$cmpcode, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovL_cmpD(iRegLNoSp dst, iRegL src, fRegD op1, fRegD op2, cmpOp cop) %{ + match(Set dst (CMoveL (Binary cop (CmpD op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpD\n\t" + %} + + ins_encode %{ + __ enc_cmove_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + instruct cmovL_cmpN(iRegLNoSp dst, iRegL src, iRegN op1, iRegN op2, cmpOpU cop) %{ match(Set dst (CMoveL (Binary cop (CmpN op1 op2)) (Binary dst src))); ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpN\n\t" + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpN\n\t" %} ins_encode %{ @@ -10130,7 +10209,7 @@ instruct cmovL_cmpP(iRegLNoSp dst, iRegL src, iRegP op1, iRegP op2, cmpOpU cop) ins_cost(ALU_COST + BRANCH_COST); format %{ - "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpP\n\t" + "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpP\n\t" %} ins_encode %{ diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index a0de9d767bf..8dcffc9c646 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -248,14 +248,6 @@ void VM_Version::common_initialize() { #ifdef COMPILER2 void VM_Version::c2_initialize() { - if (UseCMoveUnconditionally) { - FLAG_SET_DEFAULT(UseCMoveUnconditionally, false); - } - - if (ConditionalMoveLimit > 0) { - FLAG_SET_DEFAULT(ConditionalMoveLimit, 0); - } - if (!UseRVV) { FLAG_SET_DEFAULT(MaxVectorSize, 0); } else { diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index 06d6aaf109f..d19128cafc2 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -233,10 +233,13 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZACAS)) { VM_Version::ext_Zacas.enable_feature(); } -#endif + // Currently tests shows that cmove using Zicond instructions will bring + // performance regression, but to get a test coverage all the time, will + // still prefer to enabling it in debug version. if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) { VM_Version::ext_Zicond.enable_feature(); } +#endif if (is_valid(RISCV_HWPROBE_KEY_CPUPERF_0)) { VM_Version::unaligned_access.enable_feature( query[RISCV_HWPROBE_KEY_CPUPERF_0].value & RISCV_HWPROBE_MISALIGNED_MASK); diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java index dffafea7ea8..d19e2562779 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java @@ -121,10 +121,8 @@ public class ModINodeIdealizationTests { } @Test - @IR(applyIfPlatform = {"riscv64", "false"}, - failOn = {IRNode.MOD_I}) - @IR(applyIfPlatform = {"riscv64", "false"}, - counts = {IRNode.AND_I, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_I, "2"}) + @IR(failOn = {IRNode.MOD_I}) + @IR(counts = {IRNode.AND_I, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_I, "2"}) // Special optimization for the case 2^k-1 for bigger k public int powerOf2Minus1(int x) { return x % 127; diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java index e931ff87c09..fc08ef60603 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java @@ -105,10 +105,8 @@ public class ModLNodeIdealizationTests { } @Test - @IR(applyIfPlatform = {"riscv64", "false"}, - failOn = {IRNode.MOD_L}) - @IR(applyIfPlatform = {"riscv64", "false"}, - counts = {IRNode.AND_L, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_L, "2"}) + @IR(failOn = {IRNode.MOD_L}) + @IR(counts = {IRNode.AND_L, ">=1", IRNode.RSHIFT, ">=1", IRNode.CMP_L, "2"}) // Special optimization for the case 2^k-1 for bigger k public long powerOf2Minus1(long x) { return x % ((1L << 33) - 1); diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestConv2BExpansion.java b/test/hotspot/jtreg/compiler/c2/irTests/TestConv2BExpansion.java index de32b7b21f6..35d676b6ddb 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestConv2BExpansion.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestConv2BExpansion.java @@ -42,6 +42,14 @@ public class TestConv2BExpansion { TestFramework.run(); } + // These IR checks do not apply on riscv64, as riscv64 supports Conv2B, e.g. for `return x == 0`, + // the graph looks like: + // Return (XorI (Conv2B ConI(#int: 1))) + // On other platforms, e.g. x86_64 which does not supports Conv2B, the graph looks like: + // Return (CMoveI (Bool (CompI (Param1 ConI(#int: 0))) ConI(#int: 1) ConI(#int: 0))) + // On riscv64, current graph is more efficient than `CMoveI`, as it + // 1. generates less code + // 2. even when zicond is not supported, it does not introduce branches. @Test @IR(counts = {IRNode.CMOVE_I, "1"}, failOn = {IRNode.XOR}) public boolean testIntEquals0(int x) { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java index 8445c856b4e..a06cb45d59e 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java @@ -31,7 +31,6 @@ import jdk.test.lib.Asserts; * @summary Test that code generation for fp comparison works as intended * @library /test/lib / * @run driver compiler.c2.irTests.TestFPComparison - * @requires os.arch != "riscv64" */ public class TestFPComparison { static final double[] DOUBLES = new double[] { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java index e232895257a..bb0a1200a7f 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIfMinMax.java @@ -33,7 +33,6 @@ import jdk.test.lib.Utils; * @bug 8324655 8329797 8331090 * @key randomness * @summary Test that if expressions are properly folded into min/max nodes - * @requires os.arch != "riscv64" * @library /test/lib / * @run driver compiler.c2.irTests.TestIfMinMax */ @@ -228,7 +227,7 @@ public class TestIfMinMax { @Test @IR(applyIf = { "SuperWordReductions", "true" }, - applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, + applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"}, counts = { IRNode.MAX_REDUCTION_V, "> 0" }) @Arguments(setup = "setupIntArrays") public Object[] testMaxIntReduction(int[] a, int[] b) { @@ -262,7 +261,7 @@ public class TestIfMinMax { @Test @IR(applyIf = { "SuperWordReductions", "true" }, - applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, + applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"}, counts = { IRNode.MIN_REDUCTION_V, "> 0" }) @Arguments(setup = "setupIntArrays") public Object[] testMinIntReduction(int[] a, int[] b) { @@ -297,7 +296,7 @@ public class TestIfMinMax { @Test @IR(applyIf = { "SuperWordReductions", "true" }, - applyIfCPUFeatureOr = { "avx512", "true" }, + applyIfCPUFeatureOr = { "avx512", "true", "rvv", "true" }, counts = { IRNode.MAX_REDUCTION_V, "> 0" }) @Arguments(setup = "setupLongArrays") public Object[] testMaxLongReduction(long[] a, long[] b) { @@ -332,7 +331,7 @@ public class TestIfMinMax { @Test @IR(applyIf = { "SuperWordReductions", "true" }, - applyIfCPUFeatureOr = { "avx512", "true" }, + applyIfCPUFeatureOr = { "avx512", "true", "rvv", "true" }, counts = { IRNode.MIN_REDUCTION_V, "> 0" }) @Arguments(setup = "setupLongArrays") public Object[] testMinLongReduction(long[] a, long[] b) { @@ -366,7 +365,7 @@ public class TestIfMinMax { } @Test - @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, + @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"}, counts = { IRNode.MAX_VI, "> 0" }) @Arguments(setup = "setupIntArrays") public Object[] testMaxIntVector(int[] a, int[] b) { @@ -401,7 +400,7 @@ public class TestIfMinMax { } @Test - @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, + @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"}, counts = { IRNode.MIN_VI, "> 0" }) @Arguments(setup = "setupIntArrays") public Object[] testMinIntVector(int[] a, int[] b) { @@ -436,7 +435,7 @@ public class TestIfMinMax { } @Test - @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, + @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"}, counts = { IRNode.MAX_VL, "> 0" }) @Arguments(setup = "setupLongArrays") public Object[] testMaxLongVector(long[] a, long[] b) { @@ -471,7 +470,7 @@ public class TestIfMinMax { } @Test - @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true"}, + @IR(applyIfCPUFeatureOr = { "sse4.1", "true" , "asimd" , "true", "rvv", "true"}, counts = { IRNode.MIN_VL, "> 0" }) @Arguments(setup = "setupLongArrays") public Object[] testMinLongVector(long[] a, long[] b) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 8f70ad9b7d0..a6d738b3a09 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -146,6 +146,7 @@ public class TestFramework { "UseRVV", "UseZbb", "UseZfh", + "UseZicond", "UseZvbb" ) ); diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java index 35f357c22f2..c6329c70f65 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import jdk.incubator.vector.VectorMask; * @library /test/lib / * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*sse4.*" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) * | os.arch == "aarch64" + * | (os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*") * @run driver compiler.vectorapi.TestVectorTest */ public class TestVectorTest { diff --git a/test/micro/org/openjdk/bench/java/lang/ClassComparison.java b/test/micro/org/openjdk/bench/java/lang/ClassComparison.java new file mode 100644 index 00000000000..2a768f243e2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/ClassComparison.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025, Rivos Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.random.RandomGenerator; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(3) +public class ClassComparison { + static final int INVOCATIONS = 1024; + + Class[] c1; + Class[] c2; + int[] res; + long[] resLong; + Object[] resObject; + Object ro1; + Object ro2; + Object[] resClass; + Class rc1; + Class rc2; + + @Setup + public void setup() { + var random = RandomGenerator.getDefault(); + c1 = new Class[INVOCATIONS]; + c2 = new Class[INVOCATIONS]; + res = new int[INVOCATIONS]; + resLong = new long[INVOCATIONS]; + resObject = new Object[INVOCATIONS]; + ro1 = new Object(); + ro2 = new Object(); + resClass = new Class[INVOCATIONS]; + rc1 = Float.class; + rc2 = Double.class; + for (int i = 0; i < INVOCATIONS; i++) { + c1[i] = random.nextBoolean() ? Float.class : Double.class; + } + List list = Arrays.asList(c1); + Collections.shuffle(list); + list.toArray(c2); + } + + @Benchmark + public void equalClass() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (c1[i] == c2[i]) ? 1 : 2; + } + } + + @Benchmark + public void notEqualClass() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (c1[i] != c2[i]) ? 1 : 2; + } + } + + public void equalClassResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (c1[i] == c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void notEqualClassResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (c1[i] != c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/FPComparison.java b/test/micro/org/openjdk/bench/java/lang/FPComparison.java index 9fe88b934f8..8074ada3257 100644 --- a/test/micro/org/openjdk/bench/java/lang/FPComparison.java +++ b/test/micro/org/openjdk/bench/java/lang/FPComparison.java @@ -23,6 +23,7 @@ package org.openjdk.bench.java.lang; import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; import java.util.concurrent.TimeUnit; import java.util.random.RandomGenerator; @@ -41,6 +42,13 @@ public class FPComparison { float[] f2; double[] d2; int[] res; + long[] resLong; + Object[] resObject; + Object ro1; + Object ro2; + Class[] resClass; + Class rc1; + Class rc2; @Setup public void setup() { @@ -50,6 +58,13 @@ public class FPComparison { f2 = new float[INVOCATIONS]; d2 = new double[INVOCATIONS]; res = new int[INVOCATIONS]; + resLong = new long[INVOCATIONS]; + resObject = new Object[INVOCATIONS]; + ro1 = new Object(); + ro2 = new Object(); + resClass = new Class[INVOCATIONS]; + rc1 = Float.class; + rc2 = Double.class; for (int i = 0; i < INVOCATIONS; i++) { int type = random.nextInt(5); if (type == 1) { @@ -79,56 +94,184 @@ public class FPComparison { @Benchmark public void isNanFloat() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = Float.isNaN(f1[i]) ? 1 : 0; + res[i] = Float.isNaN(f1[i]) ? 1 : 2; } } @Benchmark public void isNanDouble() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = Double.isNaN(d1[i]) ? 1 : 0; + res[i] = Double.isNaN(d1[i]) ? 1 : 2; } } @Benchmark public void isInfiniteFloat() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = Float.isInfinite(f1[i]) ? 1 : 0; + res[i] = Float.isInfinite(f1[i]) ? 1 : 2; } } @Benchmark public void isInfiniteDouble() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = Double.isInfinite(d1[i]) ? 1 : 0; + res[i] = Double.isInfinite(d1[i]) ? 1 : 2; } } @Benchmark public void isFiniteFloat() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = Float.isFinite(f1[i]) ? 1 : 0; + res[i] = Float.isFinite(f1[i]) ? 1 : 2; } } @Benchmark public void isFiniteDouble() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = Double.isFinite(d1[i]) ? 1 : 0; + res[i] = Double.isFinite(d1[i]) ? 1 : 2; } } @Benchmark public void equalFloat() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = (f1[i] == f2[i]) ? 1 : 0; + res[i] = (f1[i] == f2[i]) ? 1 : 2; } } @Benchmark public void equalDouble() { for (int i = 0; i < INVOCATIONS; i++) { - res[i] = (d1[i] == d2[i]) ? 1 : 0; + res[i] = (d1[i] == d2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (f1[i] < f2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (d1[i] < d2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessEqualFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (f1[i] <= f2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessEqualDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (d1[i] <= d2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (f1[i] > f2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (d1[i] > d2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterEqualFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (f1[i] >= f2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterEqualDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (d1[i] >= d2[i]) ? 1 : 2; + } + } + + // --------- result: long --------- + + @Benchmark + public void equalFloatResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (f1[i] == f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void equalDoubleResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (d1[i] == d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessFloatResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (f1[i] < f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessDoubleResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (d1[i] < d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessEqualFloatResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (f1[i] <= f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessEqualDoubleResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (d1[i] <= d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterFloatResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (f1[i] > f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterDoubleResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (d1[i] > d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterEqualFloatResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (f1[i] >= f2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterEqualDoubleResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (d1[i] >= d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; } } } diff --git a/test/micro/org/openjdk/bench/java/lang/IntegerComparison.java b/test/micro/org/openjdk/bench/java/lang/IntegerComparison.java new file mode 100644 index 00000000000..1853be8497d --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/IntegerComparison.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2025, Rivos Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; +import java.util.random.RandomGenerator; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(3) +public class IntegerComparison { + static final int INVOCATIONS = 1024; + + int[] i1; + int[] i2; + int[] res; + long[] resLong; + Object[] resObject; + Object ro1; + Object ro2; + Object[] resClass; + Class rc1; + Class rc2; + + @Setup + public void setup() { + var random = RandomGenerator.getDefault(); + i1 = new int[INVOCATIONS]; + i2 = new int[INVOCATIONS]; + res = new int[INVOCATIONS]; + resLong = new long[INVOCATIONS]; + resObject = new Object[INVOCATIONS]; + ro1 = new Object(); + ro2 = new Object(); + resClass = new Class[INVOCATIONS]; + rc1 = Float.class; + rc2 = Double.class; + for (int i = 0; i < INVOCATIONS; i++) { + i1[i] = random.nextInt(INVOCATIONS); + i2[i] = random.nextInt(INVOCATIONS); + } + } + + @Benchmark + public void equalInteger() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (i1[i] == i2[i]) ? 1 : 2; + } + } + + @Benchmark + public void notEqualInteger() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (i1[i] != i2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessInteger() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (i1[i] < i2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessEqualInteger() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (i1[i] <= i2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterInteger() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (i1[i] > i2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterEqualInteger() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (i1[i] >= i2[i]) ? 1 : 2; + } + } + + // --------- result: long --------- + + public void equalIntegerResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (i1[i] == i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void notEqualIntegerResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (i1[i] != i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + public void lessIntegerResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (i1[i] < i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessEqualIntegerResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (i1[i] <= i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + public void greaterIntegerResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (i1[i] > i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterEqualIntegerResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (i1[i] >= i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/LongComparison.java b/test/micro/org/openjdk/bench/java/lang/LongComparison.java new file mode 100644 index 00000000000..bed5ee245b2 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/LongComparison.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2025, Rivos Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.*; + +import java.util.concurrent.TimeUnit; +import java.util.random.RandomGenerator; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(3) +public class LongComparison { + static final int INVOCATIONS = 1024; + + long[] l1; + long[] l2; + int[] res; + long[] resLong; + Object[] resObject; + Object ro1; + Object ro2; + Object[] resClass; + Class rc1; + Class rc2; + + @Setup + public void setup() { + var random = RandomGenerator.getDefault(); + l1 = new long[INVOCATIONS]; + l2 = new long[INVOCATIONS]; + res = new int[INVOCATIONS]; + resLong = new long[INVOCATIONS]; + resObject = new Object[INVOCATIONS]; + ro1 = new Object(); + ro2 = new Object(); + resClass = new Class[INVOCATIONS]; + rc1 = Float.class; + rc2 = Double.class; + for (int i = 0; i < INVOCATIONS; i++) { + l1[i] = random.nextLong(INVOCATIONS); + l2[i] = random.nextLong(INVOCATIONS); + } + } + + @Benchmark + public void equalLong() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (l1[i] == l2[i]) ? 1 : 2; + } + } + + @Benchmark + public void notEqualLong() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (l1[i] != l2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessLong() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (l1[i] < l2[i]) ? 1 : 2; + } + } + + @Benchmark + public void lessEqualLong() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (l1[i] <= l2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterLong() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (l1[i] > l2[i]) ? 1 : 2; + } + } + + @Benchmark + public void greaterEqualLong() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (l1[i] >= l2[i]) ? 1 : 2; + } + } + + // --------- result: long --------- + + public void equalLongResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (l1[i] == l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void notEqualLongResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (l1[i] != l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + public void lessLongResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (l1[i] < l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessEqualLongResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (l1[i] <= l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + public void greaterLongResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (l1[i] > l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterEqualLongResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (l1[i] >= l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/PointerComparison.java b/test/micro/org/openjdk/bench/java/lang/PointerComparison.java new file mode 100644 index 00000000000..b6bcf008619 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/PointerComparison.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025, Rivos Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.random.RandomGenerator; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(3) +public class PointerComparison { + static final int INVOCATIONS = 1024; + + Object[] o1; + Object[] o2; + int[] res; + long[] resLong; + Object[] resObject; + Object ro1; + Object ro2; + Object[] resClass; + Class rc1; + Class rc2; + + @Setup + public void setup() { + var random = RandomGenerator.getDefault(); + o1 = new Object[INVOCATIONS]; + o2 = new Object[INVOCATIONS]; + res = new int[INVOCATIONS]; + resLong = new long[INVOCATIONS]; + resObject = new Object[INVOCATIONS]; + ro1 = new Object(); + ro2 = new Object(); + resClass = new Class[INVOCATIONS]; + rc1 = Float.class; + rc2 = Double.class; + for (int i = 0; i < INVOCATIONS; i++) { + o1[i] = new Object(); + } + List list = Arrays.asList(o1); + Collections.shuffle(list); + list.toArray(o2); + } + + @Benchmark + public void equalObject() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (o1[i] == o2[i]) ? 1 : 2; + } + } + + @Benchmark + public void notEqualObject() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = (o1[i] != o2[i]) ? 1 : 2; + } + } + + public void equalObjectResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (o1[i] == o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void notEqualObjectResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = (o1[i] != o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } +} From 7cd084cf350f66fd6ed5b6f5ba9fda71072963fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C5=A0ipka?= Date: Tue, 22 Apr 2025 08:46:52 +0000 Subject: [PATCH 288/843] 8350442: Update copyright Reviewed-by: naoto, jlu --- test/jdk/sun/nio/cs/Test6392804.java | 2 +- test/jdk/sun/nio/cs/TestUTF_32.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/sun/nio/cs/Test6392804.java b/test/jdk/sun/nio/cs/Test6392804.java index a98428c3e7f..63da96162c4 100644 --- a/test/jdk/sun/nio/cs/Test6392804.java +++ b/test/jdk/sun/nio/cs/Test6392804.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/sun/nio/cs/TestUTF_32.java b/test/jdk/sun/nio/cs/TestUTF_32.java index ba042494fd2..10de9084b00 100644 --- a/test/jdk/sun/nio/cs/TestUTF_32.java +++ b/test/jdk/sun/nio/cs/TestUTF_32.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 9eeb86d972ac4cc38d923b2b868b426bbd27a4e8 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 08:58:42 +0000 Subject: [PATCH 289/843] 8354341: Open some JTable bugs 7 Reviewed-by: kizune, serb --- test/jdk/javax/swing/JTable/ShiftClick.java | 187 ++++++++++++++++++++ test/jdk/javax/swing/JTable/bug4128506.java | 84 +++++++++ test/jdk/javax/swing/JTable/bug4190222.java | 103 +++++++++++ test/jdk/javax/swing/JTable/bug4224179.java | 74 ++++++++ 4 files changed, 448 insertions(+) create mode 100644 test/jdk/javax/swing/JTable/ShiftClick.java create mode 100644 test/jdk/javax/swing/JTable/bug4128506.java create mode 100644 test/jdk/javax/swing/JTable/bug4190222.java create mode 100644 test/jdk/javax/swing/JTable/bug4224179.java diff --git a/test/jdk/javax/swing/JTable/ShiftClick.java b/test/jdk/javax/swing/JTable/ShiftClick.java new file mode 100644 index 00000000000..4d617b5eeda --- /dev/null +++ b/test/jdk/javax/swing/JTable/ShiftClick.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Color; +import java.awt.Dimension; +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4201917 + * @summary Shift Click in table before making selection + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ShiftClick + */ + +public class ShiftClick { + private static final String INSTRUCTIONS = """ + Shift click in the table. Check that all cells + from the first through where you clicked are selected. + If the cells are selected, press pass, otherwise fail. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(ShiftClick::createTestUI) + .logArea(6) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("ShiftClick"); + + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", 2, true}, + {"Tom", "Ball", "Blue", 99, false}, + {"Alan", "Chung", "Green", 838, false}, + {"Jeff", "Dinkins", "Turquois", 8, true}, + {"Amy", "Fowler", "Yellow", 3, false}, + {"Brian", "Gerhold", "Green", 0, false}, + {"James", "Gosling", "Pink", 21, false}, + {"David", "Karlton", "Red", 1, false}, + {"Dave", "Kloba", "Yellow", 14, false}, + {"Peter", "Korn", "Purple", 12, false}, + {"Phil", "Milne", "Purple", 3, false}, + {"Dave", "Moore", "Green", 88, false}, + {"Hans", "Muller", "Maroon", 5, false}, + {"Rick", "Levenson", "Blue", 2, false}, + {"Tim", "Prinzing", "Blue", 22, false}, + {"Chester", "Rose", "Black", 0, false}, + {"Ray", "Ryan", "Gray", 77, false}, + {"Georges", "Saab", "Red", 4, false}, + {"Willie", "Walker", "Phthalo Blue", 4, false}, + {"Kathy", "Walrath", "Blue", 8, false}, + {"Arnaud", "Weber", "Green", 44, false} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { + return names.length; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) { + return names[column]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer) headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number) value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + frame.add(scrollpane); + frame.setSize(500, 200); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4128506.java b/test/jdk/javax/swing/JTable/bug4128506.java new file mode 100644 index 00000000000..21273c6f318 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4128506.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableModel; + +/* + * @test + * @bug 4128506 + * @summary Tests that JTable with AUTO_RESIZE_ALL_COLUMNS correctly compute width of columns + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4128506 + */ + +public class bug4128506 { + private static final String INSTRUCTIONS = """ + If the columns of JTable have the same width the test passes, else test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4128506::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + final Object[][] data = { + {"cell_1_1", "cell_1_2", "cell_1_3"}, + {"cell_2_1", "cell_2_2", "cell_2_3"}, + {"cell_3_1", "cell_3_2", "cell_3_3"}, + {"cell_4_1", "cell_4_2", "cell_4_3"}, + }; + + TableModel dataModel = new AbstractTableModel() { + public int getColumnCount() { + return 3; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + }; + + JFrame frame = new JFrame("bug4128506"); + JTable tableView = new JTable(dataModel); + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + tableView.getColumnModel().getColumn(1).setMinWidth(5); + JScrollPane scrollpane = new JScrollPane(tableView); + frame.add(scrollpane); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JTable/bug4190222.java b/test/jdk/javax/swing/JTable/bug4190222.java new file mode 100644 index 00000000000..5d6fcd2b0cc --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4190222.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Dimension; +import java.awt.Robot; +import java.util.Vector; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; + +/* + * @test + * @bug 4190222 + * @summary Setting data vector on the model correctly repaint table + * @key headful + * @run main bug4190222 + */ + +public class bug4190222 { + static JFrame frame; + static DefaultTableModel dtm; + static JTable tbl; + + static Vector data; + static Vector colNames; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + Dimension preResize = tbl.getSize(); + dtm.setDataVector(data, colNames); + + if (!preResize.equals(tbl.getSize())) { + throw new RuntimeException("Size of table changed after resizing."); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4190222"); + + data = new Vector(1, 1); + colNames = new Vector(3); + for (int i = 1; i < 4; i++) { + Vector row = new Vector(1, 1); + row.addElement("Row " + i + ", Col 1"); + row.addElement("Row " + i + ", Col 2"); + row.addElement("Row " + i + ", Col 3"); + data.addElement(row); + } + colNames.addElement("Col 1"); + colNames.addElement("Col 2"); + colNames.addElement("Col 3"); + + dtm = new DefaultTableModel(data, colNames); + tbl = new JTable(dtm); + JScrollPane scrollPane = new JScrollPane(tbl); + frame.add("Center", scrollPane); + JPanel panel = new JPanel(); + frame.add("South", panel); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JTable/bug4224179.java b/test/jdk/javax/swing/JTable/bug4224179.java new file mode 100644 index 00000000000..b223f3f4716 --- /dev/null +++ b/test/jdk/javax/swing/JTable/bug4224179.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.BorderLayout; +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; + +/* + * @test + * @bug 4224179 + * @summary Tests if Table default cell editor doesn't handle % (percent) character correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4224179 + */ + +public class bug4224179 { + private static final String INSTRUCTIONS = """ + 1. Click ONCE on the center cell ("Huml") + 2. Type the following symbols one after another: a%b + + If the center cell doesn't read "Humla%b" the test fails. + + 3. After the above, press the ESCAPE key and note that the cell + reverts back to "Huml" + 4. Do the stuff in part 1 again + 5. Press the ESCAPE key + + If the center cell now reads "Huml" as it initially was, + the test passed and fails otherwise. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4224179::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4224179"); + JTable table = new JTable(3, 3); + table.setValueAt("Huml", 1, 1); + table.setPreferredScrollableViewportSize(new Dimension(500, 70)); + JScrollPane scrollPane = new JScrollPane(table); + frame.add(scrollPane, BorderLayout.CENTER); + frame.pack(); + return frame; + } +} From 0f1c448ca15485cd7270cf0607acfceacdcefaff Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 22 Apr 2025 11:23:40 +0000 Subject: [PATCH 290/843] 8354922: ZGC: Use MAP_FIXED_NOREPLACE when reserving memory Reviewed-by: aboldtch, eosterlund --- src/hotspot/os/linux/gc/z/zSyscall_linux.hpp | 4 ++++ src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp b/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp index 1e1becf5a14..e5978c8d93a 100644 --- a/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp +++ b/src/hotspot/os/linux/gc/z/zSyscall_linux.hpp @@ -35,6 +35,10 @@ #define MPOL_F_ADDR (1<<1) #endif +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE 0x100000 +#endif + class ZSyscall : public AllStatic { public: static int memfd_create(const char* name, unsigned int flags); diff --git a/src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp b/src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp index 4eea35c8a2e..89bde0557ec 100644 --- a/src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp +++ b/src/hotspot/os/posix/gc/z/zVirtualMemoryManager_posix.cpp @@ -24,6 +24,9 @@ #include "gc/z/zAddress.inline.hpp" #include "gc/z/zVirtualMemoryManager.hpp" #include "logging/log.hpp" +#ifdef LINUX +#include "gc/z/zSyscall_linux.hpp" +#endif #include @@ -32,7 +35,9 @@ void ZVirtualMemoryReserver::pd_register_callbacks(ZVirtualMemoryRegistry* regis } bool ZVirtualMemoryReserver::pd_reserve(zaddress_unsafe addr, size_t size) { - void* const res = mmap((void*)untype(addr), size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + const int flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE LINUX_ONLY(|MAP_FIXED_NOREPLACE); + + void* const res = mmap((void*)untype(addr), size, PROT_NONE, flags, -1, 0); if (res == MAP_FAILED) { // Failed to reserve memory return false; From f2587d9bd2e86c46c49ad972790c60ec394848da Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 22 Apr 2025 11:48:46 +0000 Subject: [PATCH 291/843] 8354938: ZGC: Disable UseNUMA when ZFakeNUMA is used Reviewed-by: aboldtch, jsikstro --- src/hotspot/share/gc/z/zArguments.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/z/zArguments.cpp b/src/hotspot/share/gc/z/zArguments.cpp index 67b9f6f0bb9..2c70d8417c9 100644 --- a/src/hotspot/share/gc/z/zArguments.cpp +++ b/src/hotspot/share/gc/z/zArguments.cpp @@ -121,9 +121,19 @@ void ZArguments::select_max_gc_threads() { void ZArguments::initialize() { GCArguments::initialize(); - // Enable NUMA by default - if (FLAG_IS_DEFAULT(UseNUMA) && FLAG_IS_DEFAULT(ZFakeNUMA)) { - FLAG_SET_DEFAULT(UseNUMA, true); + // NUMA settings + if (FLAG_IS_DEFAULT(ZFakeNUMA)) { + // Enable NUMA by default + if (FLAG_IS_DEFAULT(UseNUMA)) { + FLAG_SET_DEFAULT(UseNUMA, true); + } + } else { + if (UseNUMA) { + if (!FLAG_IS_DEFAULT(UseNUMA)) { + warning("ZFakeNUMA is enabled; turning off UseNUMA"); + } + FLAG_SET_ERGO(UseNUMA, false); + } } select_max_gc_threads(); From 5264d80bea25a1ef98dae4633b04b16e8de6120f Mon Sep 17 00:00:00 2001 From: Martin Balao Date: Tue, 22 Apr 2025 14:37:10 +0000 Subject: [PATCH 292/843] 8350661: PKCS11 HKDF throws ProviderException when requesting a 31-byte AES key Reviewed-by: fferrari, valeriep, djelinski --- .../classes/sun/security/pkcs11/P11HKDF.java | 43 ++++-- .../sun/security/pkcs11/P11KeyGenerator.java | 38 ++--- .../security/pkcs11/P11SecretKeyFactory.java | 136 ++++++++++++------ .../pkcs11/wrapper/PKCS11Constants.java | 4 - .../jdk/sun/security/pkcs11/KDF/TestHKDF.java | 49 +++++++ 5 files changed, 199 insertions(+), 71 deletions(-) diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11HKDF.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11HKDF.java index 43a036da6f3..e8bef222d88 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11HKDF.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11HKDF.java @@ -38,6 +38,7 @@ import java.util.List; import static sun.security.pkcs11.TemplateManager.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.CKR_KEY_SIZE_RANGE; final class P11HKDF extends KDFSpi { private final Token token; @@ -157,6 +158,15 @@ final class P11HKDF extends KDFSpi { " instance, instead of " + derivationSpec.getClass()); } + P11SecretKeyFactory.KeyInfo ki = P11SecretKeyFactory.getKeyInfo(alg); + if (ki == null) { + throw new InvalidAlgorithmParameterException("A PKCS #11 key " + + "type (CKK_*) was not found for a key of the algorithm '" + + alg + "'."); + } + checkDerivedKeyType(ki, alg); + P11KeyGenerator.checkKeySize(ki.keyGenMech, outLen * 8, token); + P11Key p11BaseKey = convertKey(baseKey, (isExtract ? "IKM" : "PRK") + " could not be converted to a token key for HKDF derivation."); @@ -174,17 +184,10 @@ final class P11HKDF extends KDFSpi { "token as service."; } - P11SecretKeyFactory.KeyInfo ki = P11SecretKeyFactory.getKeyInfo(alg); - if (ki == null) { - throw new InvalidAlgorithmParameterException("A PKCS #11 key " + - "type (CKK_*) was not found for a key of the algorithm '" + - alg + "'."); - } - long derivedKeyType = ki.keyType; long derivedKeyClass = isData ? CKO_DATA : CKO_SECRET_KEY; CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_CLASS, derivedKeyClass), - new CK_ATTRIBUTE(CKA_KEY_TYPE, derivedKeyType), + new CK_ATTRIBUTE(CKA_KEY_TYPE, ki.keyType), new CK_ATTRIBUTE(CKA_VALUE_LEN, outLen) }; Session session = null; @@ -195,7 +198,7 @@ final class P11HKDF extends KDFSpi { svcKi.hmacMech, saltType, saltBytes, p11SaltKey != null ? p11SaltKey.getKeyID() : 0L, info); attrs = token.getAttributes(O_GENERATE, derivedKeyClass, - derivedKeyType, attrs); + ki.keyType, attrs); long derivedObjectID = token.p11.C_DeriveKey(session.id(), new CK_MECHANISM(mechanism, params), baseKeyID, attrs); Object ret; @@ -216,6 +219,11 @@ final class P11HKDF extends KDFSpi { } return retType.cast(ret); } catch (PKCS11Exception e) { + if (e.match(CKR_KEY_SIZE_RANGE)) { + throw new InvalidAlgorithmParameterException("Invalid key " + + "size (" + outLen + " bytes) for algorithm '" + alg + + "'.", e); + } throw new ProviderException("HKDF derivation for algorithm '" + alg + "' failed.", e); } finally { @@ -227,6 +235,23 @@ final class P11HKDF extends KDFSpi { } } + private static boolean canDeriveKeyInfoType(long t) { + return (t == CKK_DES || t == CKK_DES3 || t == CKK_AES || + t == CKK_RC4 || t == CKK_BLOWFISH || t == CKK_CHACHA20 || + t == CKK_GENERIC_SECRET); + } + + private void checkDerivedKeyType(P11SecretKeyFactory.KeyInfo ki, String alg) + throws InvalidAlgorithmParameterException { + Class kiClass = ki.getClass(); + if (!kiClass.equals(P11SecretKeyFactory.TLSKeyInfo.class) && + !(kiClass.equals(P11SecretKeyFactory.KeyInfo.class) && + canDeriveKeyInfoType(ki.keyType))) { + throw new InvalidAlgorithmParameterException("A key of algorithm " + + "'" + alg + "' is not valid for derivation."); + } + } + private P11Key.P11SecretKey convertKey(SecretKey key, String errorMessage) { try { return (P11Key.P11SecretKey) P11SecretKeyFactory.convertKey(token, diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java index 3ec2cfba655..9bfe55b2509 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,9 +75,10 @@ final class P11KeyGenerator extends KeyGeneratorSpi { // java-specific lower limit; returned values are in bits private static CK_MECHANISM_INFO getSupportedRange(Token token, long mech) throws ProviderException { - // No need to query for fix-length algorithms - if (mech == CKM_DES_KEY_GEN || mech == CKM_DES2_KEY_GEN || - mech == CKM_DES3_KEY_GEN) { + // No need to query if the mechanism is not available or for + // fix-length algorithms + if (mech == CK_UNAVAILABLE_INFORMATION || mech == CKM_DES_KEY_GEN || + mech == CKM_DES2_KEY_GEN || mech == CKM_DES3_KEY_GEN) { return null; } @@ -115,7 +116,7 @@ final class P11KeyGenerator extends KeyGeneratorSpi { * and within the supported range. Return the significant key size * upon successful validation. * @param keyGenMech the PKCS#11 key generation mechanism. - * @param keySize the to-be-checked key size for this mechanism. + * @param keySize the to-be-checked key size (in bits) for this mechanism. * @param token token which provides this mechanism. * @return the significant key size (in bits) corresponding to the * specified key size. @@ -123,7 +124,7 @@ final class P11KeyGenerator extends KeyGeneratorSpi { * @throws ProviderException if this mechanism isn't supported by SunPKCS11 * or underlying native impl. */ - // called by P11SecretKeyFactory to check key size + // called by P11SecretKeyFactory and P11HKDF to check key size static int checkKeySize(long keyGenMech, int keySize, Token token) throws InvalidAlgorithmParameterException, ProviderException { CK_MECHANISM_INFO range = getSupportedRange(token, keyGenMech); @@ -136,8 +137,8 @@ final class P11KeyGenerator extends KeyGeneratorSpi { switch ((int)keyGenMech) { case (int)CKM_DES_KEY_GEN: if ((keySize != 64) && (keySize != 56)) { - throw new InvalidAlgorithmParameterException - ("DES key length must be 56 bits"); + throw new InvalidAlgorithmParameterException("DES key " + + "length was " + keySize + " but must be 56 bits"); } sigKeySize = 56; break; @@ -148,23 +149,26 @@ final class P11KeyGenerator extends KeyGeneratorSpi { } else if ((keySize == 168) || (keySize == 192)) { sigKeySize = 168; } else { - throw new InvalidAlgorithmParameterException - ("DESede key length must be 112, or 168 bits"); + throw new InvalidAlgorithmParameterException("DESede key " + + "length was " + keySize + " but must be 112, or " + + "168 bits"); } break; default: // Handle all variable-key-length algorithms here - if (range != null && keySize < range.iMinKeySize - || keySize > range.iMaxKeySize) { - throw new InvalidAlgorithmParameterException - ("Key length must be between " + range.iMinKeySize + - " and " + range.iMaxKeySize + " bits"); + if (range != null && (keySize < range.iMinKeySize + || keySize > range.iMaxKeySize)) { + throw new InvalidAlgorithmParameterException("Key length " + + "was " + keySize + " but must be between " + + range.iMinKeySize + " and " + range.iMaxKeySize + + " bits"); } if (keyGenMech == CKM_AES_KEY_GEN) { if ((keySize != 128) && (keySize != 192) && (keySize != 256)) { - throw new InvalidAlgorithmParameterException - ("AES key length must be 128, 192, or 256 bits"); + throw new InvalidAlgorithmParameterException("AES key" + + " length was " + keySize + " but must be 128," + + " 192, or 256 bits"); } } sigKeySize = keySize; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java index 6c67e641438..bc0a7d10cf1 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java @@ -103,13 +103,37 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { keyInfo.put(ki.algo.toUpperCase(Locale.ENGLISH), ki); } - static sealed class KeyInfo permits PBEKeyInfo, HMACKeyInfo, HKDFKeyInfo { + /* + * The KeyInfo class represents information about a symmetric PKCS #11 key + * type or about the output of a key-based computation (e.g. HMAC). A + * KeyInfo instance may describe the key/output itself, or the type of + * key/output that a service accepts/produces. Used by P11SecretKeyFactory, + * P11PBECipher, P11Mac, and P11HKDF. + */ + static sealed class KeyInfo permits PBEKeyInfo, HMACKeyInfo, HKDFKeyInfo, + TLSKeyInfo { + // Java Standard Algorithm Name. public final String algo; + + // Key type (CKK_*). public final long keyType; + // Mechanism for C_GenerateKey to generate a key of this type (CKM_*). + // While keys may be generated with other APIs and mechanisms (e.g. AES + // key generated with C_DeriveKey and CKM_HKDF_DERIVE instead of + // C_GenerateKey and CKM_AES_KEY_GEN), this information is used by + // P11KeyGenerator::checkKeySize in a best-effort attempt to validate + // that the key size is within a valid range (see CK_MECHANISM_INFO). + public final long keyGenMech; + KeyInfo(String algo, long keyType) { + this(algo, keyType, CK_UNAVAILABLE_INFORMATION); + } + + KeyInfo(String algo, long keyType, long keyGenMech) { this.algo = algo; this.keyType = keyType; + this.keyGenMech = keyGenMech; } // The P11SecretKeyFactory::convertKey method needs to know if a service @@ -134,8 +158,26 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { } } + /* + * KeyInfo specialization for keys that are either input or result of a TLS + * key derivation. Keys of this type are typically handled by JSSE and their + * algorithm name start with "Tls". Used by P11HKDF. + */ + static final class TLSKeyInfo extends KeyInfo { + TLSKeyInfo(String algo) { + super(algo, CKK_GENERIC_SECRET); + } + } + + /* + * KeyInfo specialization for outputs of a HMAC computation. Used by + * P11SecretKeyFactory and P11Mac. + */ static final class HMACKeyInfo extends KeyInfo { + // HMAC mechanism (CKM_*) to generate the output. public final long mech; + + // HMAC output length (in bits). public final int keyLen; HMACKeyInfo(String algo, long mech, int keyLen) { @@ -145,6 +187,10 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { } } + /* + * KeyInfo specialization for HKDF key derivation. Used by + * P11SecretKeyFactory and P11HKDF. + */ static final class HKDFKeyInfo extends KeyInfo { public static final long UNKNOWN_KEY_TYPE = -1; public final long hmacMech; @@ -157,6 +203,10 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { } } + /* + * KeyInfo specialization for PBE key derivation. Used by + * P11SecretKeyFactory, P11PBECipher and P11Mac. + */ abstract static sealed class PBEKeyInfo extends KeyInfo permits AESPBEKeyInfo, PBKDF2KeyInfo, P12MacPBEKeyInfo { public static final long INVALID_PRF = -1; @@ -204,24 +254,39 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { } static { - putKeyInfo(new KeyInfo("RC4", CKK_RC4)); - putKeyInfo(new KeyInfo("ARCFOUR", CKK_RC4)); - putKeyInfo(new KeyInfo("DES", CKK_DES)); - putKeyInfo(new KeyInfo("DESede", CKK_DES3)); - putKeyInfo(new KeyInfo("AES", CKK_AES)); - putKeyInfo(new KeyInfo("Blowfish", CKK_BLOWFISH)); - putKeyInfo(new KeyInfo("ChaCha20", CKK_CHACHA20)); - putKeyInfo(new KeyInfo("ChaCha20-Poly1305", CKK_CHACHA20)); + putKeyInfo(new KeyInfo("RC4", CKK_RC4, CKM_RC4_KEY_GEN)); + putKeyInfo(new KeyInfo("ARCFOUR", CKK_RC4, CKM_RC4_KEY_GEN)); + putKeyInfo(new KeyInfo("DES", CKK_DES, CKM_DES_KEY_GEN)); + putKeyInfo(new KeyInfo("DESede", CKK_DES3, CKM_DES3_KEY_GEN)); + putKeyInfo(new KeyInfo("AES", CKK_AES, CKM_AES_KEY_GEN)); + putKeyInfo(new KeyInfo("Blowfish", CKK_BLOWFISH, CKM_BLOWFISH_KEY_GEN)); + putKeyInfo(new KeyInfo("ChaCha20", CKK_CHACHA20, CKM_CHACHA20_KEY_GEN)); + putKeyInfo(new KeyInfo("ChaCha20-Poly1305", CKK_CHACHA20, + CKM_CHACHA20_KEY_GEN)); // we don't implement RC2 or IDEA, but we want to be able to generate // keys for those SSL/TLS ciphersuites. - putKeyInfo(new KeyInfo("RC2", CKK_RC2)); - putKeyInfo(new KeyInfo("IDEA", CKK_IDEA)); + putKeyInfo(new KeyInfo("RC2", CKK_RC2, CKM_RC2_KEY_GEN)); + putKeyInfo(new KeyInfo("IDEA", CKK_IDEA, CKM_IDEA_KEY_GEN)); - putKeyInfo(new KeyInfo("TlsPremasterSecret", PCKK_TLSPREMASTER)); - putKeyInfo(new KeyInfo("TlsRsaPremasterSecret", PCKK_TLSRSAPREMASTER)); - putKeyInfo(new KeyInfo("TlsMasterSecret", PCKK_TLSMASTER)); - putKeyInfo(new KeyInfo("Generic", CKK_GENERIC_SECRET)); + putKeyInfo(new TLSKeyInfo("TlsPremasterSecret")); + putKeyInfo(new TLSKeyInfo("TlsRsaPremasterSecret")); + putKeyInfo(new TLSKeyInfo("TlsMasterSecret")); + putKeyInfo(new TLSKeyInfo("TlsBinderKey")); + putKeyInfo(new TLSKeyInfo("TlsClientAppTrafficSecret")); + putKeyInfo(new TLSKeyInfo("TlsClientHandshakeTrafficSecret")); + putKeyInfo(new TLSKeyInfo("TlsEarlySecret")); + putKeyInfo(new TLSKeyInfo("TlsFinishedSecret")); + putKeyInfo(new TLSKeyInfo("TlsHandshakeSecret")); + putKeyInfo(new TLSKeyInfo("TlsKey")); + putKeyInfo(new TLSKeyInfo("TlsResumptionMasterSecret")); + putKeyInfo(new TLSKeyInfo("TlsSaltSecret")); + putKeyInfo(new TLSKeyInfo("TlsServerAppTrafficSecret")); + putKeyInfo(new TLSKeyInfo("TlsServerHandshakeTrafficSecret")); + putKeyInfo(new TLSKeyInfo("TlsUpdateNplus1")); + + putKeyInfo(new KeyInfo("Generic", CKK_GENERIC_SECRET, + CKM_GENERIC_SECRET_KEY_GEN)); HMACKeyInfo hmacSHA1 = new HMACKeyInfo("HmacSHA1", CKM_SHA_1_HMAC, 160); @@ -549,34 +614,23 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi { long keyType = ki.keyType; try { switch ((int) keyType) { - case (int) CKK_DES -> { - keyLength = - P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token); - fixDESParity(encoded, 0); - } - case (int) CKK_DES3 -> { - keyLength = - P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token); - fixDESParity(encoded, 0); - fixDESParity(encoded, 8); - if (keyLength == 112) { - keyType = CKK_DES2; - } else { - keyType = CKK_DES3; - fixDESParity(encoded, 16); + case (int) CKK_DES, (int) CKK_DES3, (int) CKK_AES, (int) CKK_RC4, + (int) CKK_BLOWFISH, (int) CKK_CHACHA20 -> { + keyLength = P11KeyGenerator.checkKeySize(ki.keyGenMech, n, + token); + if (keyType == CKK_DES || keyType == CKK_DES3) { + fixDESParity(encoded, 0); + if (keyType == CKK_DES3) { + fixDESParity(encoded, 8); + if (keyLength == 112) { + keyType = CKK_DES2; + } else { + fixDESParity(encoded, 16); + } + } } } - case (int) CKK_AES -> keyLength = - P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token); - case (int) CKK_RC4 -> keyLength = - P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token); - case (int) CKK_BLOWFISH -> keyLength = - P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n, - token); - case (int) CKK_CHACHA20 -> keyLength = P11KeyGenerator.checkKeySize( - CKM_CHACHA20_KEY_GEN, n, token); - case (int) CKK_GENERIC_SECRET, (int) PCKK_TLSPREMASTER, (int) PCKK_TLSRSAPREMASTER, (int) PCKK_TLSMASTER -> - keyType = CKK_GENERIC_SECRET; + case (int) CKK_GENERIC_SECRET -> {} default -> throw new InvalidKeyException("Unknown algorithm " + algorithm); } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java index 3cd1ca12563..924bfbcc226 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java @@ -311,10 +311,6 @@ public interface PKCS11Constants { // pseudo key type ANY (for template manager) public static final long PCKK_ANY = 0x7FFFFF22L; - public static final long PCKK_TLSPREMASTER = 0x7FFFFF25L; - public static final long PCKK_TLSRSAPREMASTER = 0x7FFFFF26L; - public static final long PCKK_TLSMASTER = 0x7FFFFF27L; - /* Uncomment when actually used public static final long CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0L; public static final long CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1L; diff --git a/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java b/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java index 5a3e8163600..638d4aa2bb1 100644 --- a/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java +++ b/test/jdk/sun/security/pkcs11/KDF/TestHKDF.java @@ -302,6 +302,23 @@ public final class TestHKDF extends PKCS11Test { executeDerivation(ctx, KdfParamSpecType.EXPAND); } + private static void executeInvalidKeyDerivationTest(String testHeader, + String keyAlg, int keySize, String errorMsg) { + printTestHeader(testHeader); + try { + KDF k = KDF.getInstance("HKDF-SHA256", p11Provider); + k.deriveKey(keyAlg, HKDFParameterSpec.ofExtract() + .thenExpand(null, keySize)); + throw new Exception("No exception thrown."); + } catch (InvalidAlgorithmParameterException iape) { + // Expected. + } catch (Exception e) { + reportTestFailure(new Exception(errorMsg + " expected to throw " + + "InvalidAlgorithmParameterException for key algorithm '" + + keyAlg + "'.", e)); + } + } + private static void printTestHeader(String testHeader) { debugPrinter.println(); debugPrinter.println("=".repeat(testHeader.length())); @@ -610,6 +627,38 @@ public final class TestHKDF extends PKCS11Test { "6e09"); } + private static void test_unknown_key_algorithm_derivation() { + executeInvalidKeyDerivationTest( + "Test derivation of an unknown key algorithm", + "UnknownAlgorithm", + 32, + "Derivation of an unknown key algorithm"); + } + + private static void test_invalid_key_algorithm_derivation() { + executeInvalidKeyDerivationTest( + "Test derivation of an invalid key algorithm", + "PBKDF2WithHmacSHA1", + 32, + "Derivation of an invalid key algorithm"); + } + + private static void test_invalid_aes_key_algorithm_derivation() { + executeInvalidKeyDerivationTest( + "Test derivation of an invalid AES key", + "PBEWithHmacSHA224AndAES_256", + 32, + "Derivation of an invalid AES key"); + } + + private static void test_invalid_AES_key_size() { + executeInvalidKeyDerivationTest( + "Test derivation of an invalid AES key size", + "AES", + 31, + "Derivation of an AES key of invalid size (31 bytes)"); + } + public void main(Provider p) throws Exception { p11Provider = p; p11GenericSkf = SecretKeyFactory.getInstance("Generic", p11Provider); From 072b8273a4c7bd75bce440e5f1184e2926ed0f78 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 22 Apr 2025 15:10:26 +0000 Subject: [PATCH 293/843] 8354300: Mark String.hash field @Stable Reviewed-by: liach, shade, vlivanov --- .../share/classes/java/lang/String.java | 7 +- .../bench/java/lang/StringHashCodeStatic.java | 93 +++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/lang/StringHashCodeStatic.java diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 033d32611b0..0632785d899 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,11 +173,14 @@ public final class String private final byte coder; /** Cache the hash code for the string */ + @Stable private int hash; // Default to 0 /** * Cache if the hash has been calculated as actually being zero, enabling - * us to avoid recalculating this. + * us to avoid recalculating this. This field is _not_ annotated @Stable as + * the `hashCode()` method reads the field `hash` first anyhow and if `hash` + * is the default zero value, is not trusted. */ private boolean hashIsZero; // Default to false; diff --git a/test/micro/org/openjdk/bench/java/lang/StringHashCodeStatic.java b/test/micro/org/openjdk/bench/java/lang/StringHashCodeStatic.java new file mode 100644 index 00000000000..8f4d22a1d86 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/StringHashCodeStatic.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * Performance test of String.hashCode() function with constant folding. + * The tests are using a Map that holds a MethodHandle to better expose + * any potential lack of constant folding. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 3) +public class StringHashCodeStatic { + + private static final String HASHCODE = "abcdefghijkl"; + private static final String HASHCODE_0 = new String(new char[]{72, 90, 100, 89, 105, 2, 72, 90, 100, 89, 105, 2}); + private static final String EMPTY = new String(); + + private static final Map MAP = Map.of( + HASHCODE, mh(HASHCODE.hashCode()), + HASHCODE_0, mh(HASHCODE_0.hashCode()), + EMPTY, mh(EMPTY.hashCode())); + + /** + * Benchmark testing String.hashCode() with a regular 12 char string with + * the result possibly cached in String + */ + @Benchmark + public int nonZero() throws Throwable { + return (int)MAP.get(HASHCODE).invokeExact(); + } + + /** + * Benchmark testing String.hashCode() with a 12 char string with the + * hashcode = 0. + */ + @Benchmark + public int zero() throws Throwable { + return (int)MAP.get(HASHCODE_0).invokeExact(); + } + + /** + * Benchmark testing String.hashCode() with the empty string. an + * empty String has hashCode = 0. + */ + @Benchmark + public int empty() throws Throwable { + return (int)MAP.get(EMPTY).invokeExact(); + } + + static MethodHandle mh(int value) { + return MethodHandles.constant(int.class, value); + } + +} \ No newline at end of file From da16c839735bbf79ece4967f95a98208f74b7f73 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 15:26:59 +0000 Subject: [PATCH 294/843] 8354466: Open some misc Swing bugs 9 Reviewed-by: kizune, honkar --- .../swing/JPasswordField/bug4382819.java | 86 +++++++++++++++++ .../javax/swing/JSplitPane/bug4820080.java | 94 +++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 test/jdk/javax/swing/JPasswordField/bug4382819.java create mode 100644 test/jdk/javax/swing/JSplitPane/bug4820080.java diff --git a/test/jdk/javax/swing/JPasswordField/bug4382819.java b/test/jdk/javax/swing/JPasswordField/bug4382819.java new file mode 100644 index 00000000000..3a8799a2d52 --- /dev/null +++ b/test/jdk/javax/swing/JPasswordField/bug4382819.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.FlowLayout; +import java.awt.event.ItemListener; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPasswordField; + +/* + * @test + * @bug 4382819 + * @summary Tests the correctness of color used for the disabled passwordField. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4382819 + */ + +public class bug4382819 { + static JCheckBox enabledCheckBox; + static JPasswordField passwordField; + + private static final String INSTRUCTIONS = """ + Clear the "enabled" checkbox. + If the JPasswordField's foreground color changes to + light gray press Pass. If it stays black press Fail. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4382819::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame mainFrame = new JFrame("bug4382819"); + enabledCheckBox = new javax.swing.JCheckBox(); + enabledCheckBox.setSelected(true); + enabledCheckBox.setText("enabled"); + enabledCheckBox.setActionCommand("enabled"); + mainFrame.add(enabledCheckBox); + + passwordField = new javax.swing.JPasswordField(); + passwordField.setText("blahblahblah"); + mainFrame.add(passwordField); + SymItem lSymItem = new SymItem(); + enabledCheckBox.addItemListener(lSymItem); + + mainFrame.setSize(300, 100); + mainFrame.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + return mainFrame; + } + + static class SymItem implements ItemListener { + public void itemStateChanged(java.awt.event.ItemEvent event) { + Object object = event.getSource(); + if (object == enabledCheckBox) { + passwordField.setEnabled(enabledCheckBox.isSelected()); + } + } + } +} + diff --git a/test/jdk/javax/swing/JSplitPane/bug4820080.java b/test/jdk/javax/swing/JSplitPane/bug4820080.java new file mode 100644 index 00000000000..0702a3a2f59 --- /dev/null +++ b/test/jdk/javax/swing/JSplitPane/bug4820080.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Panel; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JSplitPane; +import javax.swing.UIManager; + +/* + * @test + * @bug 4820080 7175397 + * @summary RFE: Cannot Change the JSplitPane Divider Color while dragging + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4820080 + */ + +public class bug4820080 { + private static final String INSTRUCTIONS = """ + Drag the dividers of the splitpanes (both top and bottom). If the divider + color is green while dragging then test passes, otherwise test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4820080::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4820080"); + UIManager.put("SplitPaneDivider.draggingColor", Color.GREEN); + + Box box = new Box(BoxLayout.Y_AXIS); + frame.add(box); + + JPanel jleft = new JPanel(); + jleft.setBackground(Color.DARK_GRAY); + jleft.setPreferredSize(new Dimension(100, 100)); + JPanel jright = new JPanel(); + jright.setBackground(Color.DARK_GRAY); + jright.setPreferredSize(new Dimension(100, 100)); + + JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jleft, jright); + jsp.setContinuousLayout(false); + box.add(jsp); + + box.add(Box.createVerticalStrut(5)); + box.add(new JSeparator()); + box.add(Box.createVerticalStrut(5)); + + Panel left = new Panel(); + left.setBackground(Color.DARK_GRAY); + left.setPreferredSize(new Dimension(100, 100)); + Panel right = new Panel(); + right.setBackground(Color.DARK_GRAY); + right.setPreferredSize(new Dimension(100, 100)); + + JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right); + sp.setContinuousLayout(false); + box.add(sp); + frame.pack(); + return frame; + } +} From a4c5ed8144376f7ba0d2cb992da63b3e53d51f8b Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Tue, 22 Apr 2025 15:46:04 +0000 Subject: [PATCH 295/843] 8354561: Open source several swing tests batch0 Reviewed-by: prr, psadhukhan --- .../jdk/javax/swing/JComboBox/bug4139900.java | 119 +++++++++++++++++ .../jdk/javax/swing/JComboBox/bug4174876.java | 78 +++++++++++ .../jdk/javax/swing/JComboBox/bug4474400.java | 78 +++++++++++ .../swing/border/TransparentTitleTest.java | 122 ++++++++++++++++++ 4 files changed, 397 insertions(+) create mode 100644 test/jdk/javax/swing/JComboBox/bug4139900.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4174876.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4474400.java create mode 100644 test/jdk/javax/swing/border/TransparentTitleTest.java diff --git a/test/jdk/javax/swing/JComboBox/bug4139900.java b/test/jdk/javax/swing/JComboBox/bug4139900.java new file mode 100644 index 00000000000..a9ed685d5ab --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4139900.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4139900 + * @summary height of combobox may differ + * @key headful + * @run main bug4139900 +*/ + +import java.awt.Dimension; +import java.awt.Robot; +import java.awt.event.ActionListener; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +public class bug4139900 { + static JButton button; + static JFrame frame; + static JComboBox comboBox; + static int initialHeight; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(bug4139900::init); + test(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void test() throws Exception { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + SwingUtilities.invokeAndWait(() -> initialHeight = comboBox.getHeight()); + + for (int i = 0; i < 10; i++) { + SwingUtilities.invokeAndWait(() -> button.doClick()); + robot.waitForIdle(); + robot.delay(200); + SwingUtilities.invokeAndWait(() -> { + if (comboBox.getHeight() != initialHeight) { + throw new RuntimeException( + "Test failed: height differs from initial %d != %d" + .formatted(comboBox.getHeight(), initialHeight) + ); + } + }); + } + } + + public static void init() { + frame = new JFrame("bug4139900"); + + DefaultComboBoxModel model = + new DefaultComboBoxModel<>(new String[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea" + }); + + comboBox = new JComboBox<>(); + comboBox.setEditable(true); + + button = new JButton("Add/Remove Items"); + + ActionListener actionListener = e -> { + if (comboBox.getModel() == model) { + comboBox.setModel(new DefaultComboBoxModel<>()); + } else { + comboBox.setModel(model); + } + }; + + button.addActionListener(actionListener); + + JPanel panel = new JPanel(); + panel.setPreferredSize(new Dimension(300, 100)); + panel.add(comboBox); + panel.add(button); + + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4174876.java b/test/jdk/javax/swing/JComboBox/bug4174876.java new file mode 100644 index 00000000000..349dfa4b159 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4174876.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4174876 + * @summary JComboBox tooltips do not work properly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4174876 + */ + +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPanel; + +public class bug4174876 { + private static final String INSTRUCTIONS = """ + Hold the mouse over both combo boxes. + A tool tip should appear over every area of both of them. + Notably, if you hold the mouse over the button on the right one, + a tool tip should appear. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("TransparentTitleTest Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .splitUIBottom(bug4174876::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JComboBox comboBox1 = new JComboBox<>(new String[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea" + }); + JComboBox comboBox2 = new JComboBox<>(new String[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea" + }); + + comboBox1.setToolTipText("Combo Box #1"); + comboBox2.setToolTipText("Combo Box #2"); + comboBox2.setEditable(true); + + JPanel panel = new JPanel(); + panel.add(comboBox1); + panel.add(comboBox2); + return panel; + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4474400.java b/test/jdk/javax/swing/JComboBox/bug4474400.java new file mode 100644 index 00000000000..ea52d0c71b5 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4474400.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4474400 + * @summary Tests JTextArea wrapping with font change + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4474400 + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +public class bug4474400 { + private static final String INSTRUCTIONS = """ + Press the "Change Font" button. The two lines of text should be + properly drawn using the larger font, there should be empty line + between them. If display is garbled, test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4474400 Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .splitUIRight(bug4474400::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + Font smallFont = new Font("SansSerif", Font.PLAIN, 12); + Font largeFont = new Font("SansSerif", Font.PLAIN, 36); + + JTextArea textArea = new JTextArea("This is the first line\n\nThis is the third line"); + textArea.setFont(smallFont); + textArea.setEditable(false); + textArea.setLineWrap(true); + textArea.setWrapStyleWord(true); + + JButton b = new JButton("Change Font"); + b.addActionListener((e) -> textArea.setFont(largeFont)); + + JPanel panel = new JPanel(new BorderLayout()); + panel.setPreferredSize(new Dimension(200, 300)); + panel.add(textArea, BorderLayout.CENTER); + panel.add(b, BorderLayout.SOUTH); + + return panel; + } +} diff --git a/test/jdk/javax/swing/border/TransparentTitleTest.java b/test/jdk/javax/swing/border/TransparentTitleTest.java new file mode 100644 index 00000000000..49a32a5890c --- /dev/null +++ b/test/jdk/javax/swing/border/TransparentTitleTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4154572 + * @summary Tests that the area behind a TitledBorder's title string is transparent, + * allowing the component's background to show through + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TransparentTitleTest + */ + +import java.awt.GridLayout; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Color; +import java.awt.image.BufferedImage; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.border.TitledBorder; +import javax.swing.border.LineBorder; + +public class TransparentTitleTest { + private static final String INSTRUCTIONS = """ + If all panels are correctly painted such that the title of the + border allows the underlying panel image (green rectangle) + to show through the background of the text, + then this test passes; else it fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("TransparentTitleTest Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(TransparentTitleTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("TransparentTitleTest"); + + frame.setLayout(new GridLayout(3, 6, 5, 5)); + + frame.add(new ImagePanel(TitledBorder.TOP, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.TOP, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.TOP, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_TOP, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_TOP, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.ABOVE_TOP, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.BELOW_TOP, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.BELOW_TOP, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.BELOW_TOP, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.BOTTOM, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.BOTTOM, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.BOTTOM, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_BOTTOM, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.ABOVE_BOTTOM, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.ABOVE_BOTTOM, TitledBorder.RIGHT)); + frame.add(new ImagePanel(TitledBorder.BELOW_BOTTOM, TitledBorder.LEFT)); + frame.add(new ImagePanel(TitledBorder.BELOW_BOTTOM, TitledBorder.CENTER)); + frame.add(new ImagePanel(TitledBorder.BELOW_BOTTOM, TitledBorder.RIGHT)); + + frame.pack(); + return frame; + } +} + +class ImagePanel extends JPanel { + + private final ImageIcon imageIcon; + + private static final BufferedImage bufferedImage = + new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB); + + static { + Graphics g = bufferedImage.getGraphics(); + g.setColor(Color.GREEN); + g.fillRect(0, 0, 128, 128); + } + + public ImagePanel(int titlePos, int titleJust) { + imageIcon = new ImageIcon(bufferedImage); + + TitledBorder b = new TitledBorder(new LineBorder(Color.black,3), "title text"); + b.setTitlePosition(titlePos); + b.setTitleJustification(titleJust); + b.setTitleColor(Color.black); + setBorder(b); + } + + public Dimension getPreferredSize() { + return new Dimension(imageIcon.getIconWidth(), imageIcon.getIconHeight()); + } + + public void paintComponent(Graphics g) { + imageIcon.paintIcon(this, g, 0, 0); + } +} From 477da161e62040d77079196ea27d24b27de75b64 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 22 Apr 2025 15:50:58 +0000 Subject: [PATCH 296/843] 8352638: Enhance code consistency: java.desktop/windows Reviewed-by: prr --- .../plaf/windows/AnimationController.java | 9 ++- .../sun/java/swing/plaf/windows/TMSchema.java | 3 + .../swing/plaf/windows/WindowsBorders.java | 17 +++-- .../swing/plaf/windows/WindowsButtonUI.java | 9 ++- .../windows/WindowsCheckBoxMenuItemUI.java | 5 +- .../swing/plaf/windows/WindowsCheckBoxUI.java | 5 +- .../windows/WindowsClassicLookAndFeel.java | 3 +- .../swing/plaf/windows/WindowsComboBoxUI.java | 32 +++++++--- .../plaf/windows/WindowsDesktopIconUI.java | 8 ++- .../plaf/windows/WindowsDesktopManager.java | 3 +- .../plaf/windows/WindowsDesktopPaneUI.java | 5 +- .../plaf/windows/WindowsEditorPaneUI.java | 3 +- .../plaf/windows/WindowsFileChooserUI.java | 62 ++++++++++++++++--- .../plaf/windows/WindowsGraphicsUtils.java | 2 +- .../plaf/windows/WindowsIconFactory.java | 56 +++++++++++++---- .../WindowsInternalFrameTitlePane.java | 24 ++++++- .../plaf/windows/WindowsInternalFrameUI.java | 12 +++- .../swing/plaf/windows/WindowsLabelUI.java | 4 +- .../plaf/windows/WindowsLookAndFeel.java | 58 ++++++++++++----- .../swing/plaf/windows/WindowsMenuBarUI.java | 5 +- .../swing/plaf/windows/WindowsMenuItemUI.java | 5 +- .../swing/plaf/windows/WindowsMenuUI.java | 13 +++- .../plaf/windows/WindowsOptionPaneUI.java | 2 +- .../plaf/windows/WindowsPasswordFieldUI.java | 3 +- .../windows/WindowsPopupMenuSeparatorUI.java | 4 +- .../plaf/windows/WindowsPopupMenuUI.java | 7 ++- .../plaf/windows/WindowsPopupWindow.java | 5 +- .../plaf/windows/WindowsProgressBarUI.java | 11 +++- .../windows/WindowsRadioButtonMenuItemUI.java | 5 +- .../plaf/windows/WindowsRadioButtonUI.java | 5 ++ .../swing/plaf/windows/WindowsRootPaneUI.java | 5 +- .../plaf/windows/WindowsScrollBarUI.java | 17 ++++- .../plaf/windows/WindowsScrollPaneUI.java | 2 +- .../plaf/windows/WindowsSeparatorUI.java | 2 +- .../swing/plaf/windows/WindowsSliderUI.java | 17 ++++- .../swing/plaf/windows/WindowsSpinnerUI.java | 5 +- .../plaf/windows/WindowsSplitPaneDivider.java | 3 +- .../plaf/windows/WindowsSplitPaneUI.java | 3 +- .../plaf/windows/WindowsTabbedPaneUI.java | 8 ++- .../plaf/windows/WindowsTableHeaderUI.java | 13 +++- .../swing/plaf/windows/WindowsTextAreaUI.java | 3 +- .../plaf/windows/WindowsTextFieldUI.java | 11 +++- .../swing/plaf/windows/WindowsTextPaneUI.java | 3 +- .../swing/plaf/windows/WindowsTextUI.java | 8 ++- .../plaf/windows/WindowsToggleButtonUI.java | 9 ++- .../windows/WindowsToolBarSeparatorUI.java | 5 +- .../swing/plaf/windows/WindowsToolBarUI.java | 7 ++- .../swing/plaf/windows/WindowsTreeUI.java | 11 +++- .../sun/java/swing/plaf/windows/XPStyle.java | 26 ++++++-- .../classes/sun/awt/PlatformGraphicsInfo.java | 2 +- .../classes/sun/awt/Win32ColorModel24.java | 4 +- .../classes/sun/awt/Win32FontManager.java | 5 ++ .../classes/sun/awt/Win32GraphicsConfig.java | 1 + .../classes/sun/awt/Win32GraphicsDevice.java | 2 +- .../sun/awt/Win32GraphicsEnvironment.java | 4 ++ .../sun/awt/shell/Win32ShellFolder2.java | 27 +++++++- .../awt/shell/Win32ShellFolderManager2.java | 8 ++- .../awt/windows/TranslucentWindowPainter.java | 4 +- .../sun/awt/windows/WComponentPeer.java | 1 + .../sun/awt/windows/WDataTransferer.java | 2 +- .../sun/awt/windows/WDefaultFontCharset.java | 2 +- .../sun/awt/windows/WDesktopProperties.java | 5 +- .../awt/windows/WDragSourceContextPeer.java | 3 + .../sun/awt/windows/WEmbeddedFrame.java | 7 ++- .../sun/awt/windows/WEmbeddedFramePeer.java | 2 +- .../classes/sun/awt/windows/WLabelPeer.java | 7 +++ .../awt/windows/WLightweightFramePeer.java | 3 +- .../sun/awt/windows/WMenuItemPeer.java | 4 ++ .../sun/awt/windows/WMouseInfoPeer.java | 2 + .../sun/awt/windows/WPopupMenuPeer.java | 1 + .../classes/sun/awt/windows/WPrinterJob.java | 4 +- .../sun/awt/windows/WScrollPanePeer.java | 4 +- .../sun/awt/windows/WScrollbarPeer.java | 7 +++ .../classes/sun/awt/windows/WToolkit.java | 2 +- .../sun/awt/windows/WTrayIconPeer.java | 2 +- .../classes/sun/awt/windows/WWindowPeer.java | 4 +- .../classes/sun/awt/windows/WingDings.java | 2 +- .../windows/classes/sun/font/NativeFont.java | 11 +++- .../classes/sun/font/NativeStrike.java | 8 +++ .../java2d/WindowsSurfaceManagerFactory.java | 3 +- .../classes/sun/java2d/d3d/D3DBlitLoops.java | 51 +++++++++------ .../classes/sun/java2d/d3d/D3DBufImgOps.java | 2 +- .../classes/sun/java2d/d3d/D3DContext.java | 2 +- .../classes/sun/java2d/d3d/D3DDrawImage.java | 2 +- .../sun/java2d/d3d/D3DGraphicsConfig.java | 4 +- .../sun/java2d/d3d/D3DGraphicsDevice.java | 4 +- .../classes/sun/java2d/d3d/D3DMaskBlit.java | 2 +- .../classes/sun/java2d/d3d/D3DMaskFill.java | 2 +- .../classes/sun/java2d/d3d/D3DPaints.java | 8 +-- .../sun/java2d/d3d/D3DRenderQueue.java | 4 +- .../classes/sun/java2d/d3d/D3DRenderer.java | 15 ++++- .../java2d/d3d/D3DScreenUpdateManager.java | 3 +- .../sun/java2d/d3d/D3DSurfaceData.java | 17 ++++- .../sun/java2d/d3d/D3DSurfaceDataProxy.java | 2 +- .../sun/java2d/d3d/D3DTextRenderer.java | 3 +- .../java2d/d3d/D3DVolatileSurfaceManager.java | 5 +- .../sun/java2d/opengl/WGLGraphicsConfig.java | 14 ++--- .../sun/java2d/opengl/WGLSurfaceData.java | 11 +++- .../opengl/WGLVolatileSurfaceManager.java | 4 +- .../sun/java2d/windows/GDIBlitLoops.java | 3 +- .../sun/java2d/windows/GDIRenderer.java | 29 ++++++++- .../java2d/windows/GDIWindowSurfaceData.java | 8 ++- .../sun/java2d/windows/WindowsFlags.java | 2 +- .../sun/print/PlatformPrinterJobProxy.java | 2 +- .../sun/print/PrintServiceLookupProvider.java | 6 +- .../classes/sun/print/Win32MediaTray.java | 4 +- .../classes/sun/print/Win32PrintJob.java | 10 ++- .../classes/sun/print/Win32PrintService.java | 33 ++++++++-- .../plaf/windows/ClassicSortArrowIcon.java | 5 +- 109 files changed, 743 insertions(+), 200 deletions(-) diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java index a71b3b8367f..a91e1a97ee1 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/AnimationController.java @@ -62,7 +62,7 @@ import sun.awt.AppContext; * * @author Igor Kushnirskiy */ -class AnimationController implements ActionListener, PropertyChangeListener { +final class AnimationController implements ActionListener, PropertyChangeListener { private static final boolean VISTA_ANIMATION_DISABLED = Boolean.getBoolean("swing.disablevistaanimation"); @@ -253,6 +253,7 @@ class AnimationController implements ActionListener, PropertyChangeListener { } } + @Override public synchronized void propertyChange(PropertyChangeEvent e) { if ("lookAndFeel" == e.getPropertyName() && ! (e.getNewValue() instanceof WindowsLookAndFeel) ) { @@ -260,6 +261,7 @@ class AnimationController implements ActionListener, PropertyChangeListener { } } + @Override public synchronized void actionPerformed(ActionEvent e) { java.util.List componentsToRemove = null; java.util.List partsToRemove = null; @@ -319,7 +321,7 @@ class AnimationController implements ActionListener, PropertyChangeListener { } } - private static class AnimationState { + private static final class AnimationState { private final State startState; //animation duration in nanoseconds @@ -407,7 +409,7 @@ class AnimationController implements ActionListener, PropertyChangeListener { } } - private static class PartUIClientPropertyKey + private static final class PartUIClientPropertyKey implements UIClientPropertyKey { private static final Map map = @@ -426,6 +428,7 @@ class AnimationController implements ActionListener, PropertyChangeListener { private PartUIClientPropertyKey(Part part) { this.part = part; } + @Override public String toString() { return part.toString(); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/TMSchema.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/TMSchema.java index 90c7f797043..93628d85766 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/TMSchema.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/TMSchema.java @@ -221,6 +221,7 @@ public final class TMSchema { return str + control.toString(); } + @Override public String toString() { return control.toString()+"."+name(); } @@ -531,6 +532,7 @@ public final class TMSchema { return value; } + @Override public String toString() { return name()+"["+type.getName()+"] = "+value; } @@ -559,6 +561,7 @@ public final class TMSchema { private final String enumName; private final int value; + @Override public String toString() { return prop+"="+enumName+"="+value; } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java index 1e10ccce1bf..31a490bebcc 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java @@ -43,7 +43,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; * @author Rich Schiavi */ -public class WindowsBorders { +public final class WindowsBorders { /** * Returns a border instance for a Windows Progress Bar @@ -115,7 +115,7 @@ public class WindowsBorders { } @SuppressWarnings("serial") // Superclass is not serializable across versions - public static class ProgressBarBorder extends AbstractBorder implements UIResource { + public static final class ProgressBarBorder extends AbstractBorder implements UIResource { protected Color shadow; protected Color highlight; @@ -124,6 +124,7 @@ public class WindowsBorders { this.shadow = shadow; } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { g.setColor(shadow); @@ -134,6 +135,7 @@ public class WindowsBorders { g.drawLine(width-1,y, width-1,height-1); // draw right } + @Override public Insets getBorderInsets(Component c, Insets insets) { insets.set(1,1,1,1); return insets; @@ -146,7 +148,7 @@ public class WindowsBorders { * @since 1.4 */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { + public static final class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { protected Color shadow; protected Color highlight; @@ -155,6 +157,7 @@ public class WindowsBorders { this.shadow = shadow; } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { if (!(c instanceof JToolBar)) { @@ -224,6 +227,7 @@ public class WindowsBorders { g.translate(-x, -y); } + @Override public Insets getBorderInsets(Component c, Insets insets) { insets.set(1,1,1,1); if (!(c instanceof JToolBar)) { @@ -259,6 +263,7 @@ public class WindowsBorders { super(color, thickness); } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Color oldColor = g.getColor(); int i; @@ -276,7 +281,7 @@ public class WindowsBorders { * of the component's background color. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - static class ComplementDashedBorder extends LineBorder implements UIResource { + static final class ComplementDashedBorder extends LineBorder implements UIResource { private Color origColor; private Color paintColor; @@ -284,6 +289,7 @@ public class WindowsBorders { super(null); } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Color color = c.getBackground(); @@ -302,7 +308,7 @@ public class WindowsBorders { * @since 1.4 */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public static class InternalFrameLineBorder extends LineBorder implements + public static final class InternalFrameLineBorder extends LineBorder implements UIResource { protected Color activeColor; protected Color inactiveColor; @@ -315,6 +321,7 @@ public class WindowsBorders { inactiveColor = inactiveBorderColor; } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java index b1f7f3902e2..33dea2b3b08 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java @@ -58,7 +58,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; * * @author Jeff Dinkins */ -public class WindowsButtonUI extends BasicButtonUI +public final class WindowsButtonUI extends BasicButtonUI { protected int dashedRectGapX; protected int dashedRectGapY; @@ -89,6 +89,7 @@ public class WindowsButtonUI extends BasicButtonUI // ******************************** // Defaults // ******************************** + @Override protected void installDefaults(AbstractButton b) { super.installDefaults(b); if(!defaults_initialized) { @@ -108,6 +109,7 @@ public class WindowsButtonUI extends BasicButtonUI } } + @Override protected void uninstallDefaults(AbstractButton b) { super.uninstallDefaults(b); defaults_initialized = false; @@ -124,10 +126,12 @@ public class WindowsButtonUI extends BasicButtonUI /** * Overridden method to render the text without the mnemonic */ + @Override protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { WindowsGraphicsUtils.paintText(g, b, textRect, text, getTextShiftOffset()); } + @Override protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect){ // focus painted same color as text on Basic?? @@ -138,6 +142,7 @@ public class WindowsButtonUI extends BasicButtonUI width - dashedRectGapWidth, height - dashedRectGapHeight); } + @Override protected void paintButtonPressed(Graphics g, AbstractButton b){ setTextShiftOffset(); } @@ -145,6 +150,7 @@ public class WindowsButtonUI extends BasicButtonUI // ******************************** // Layout Methods // ******************************** + @Override public Dimension getPreferredSize(JComponent c) { Dimension d = super.getPreferredSize(c); @@ -167,6 +173,7 @@ public class WindowsButtonUI extends BasicButtonUI */ private Rectangle viewRect = new Rectangle(); + @Override public void paint(Graphics g, JComponent c) { if (XPStyle.getXP() != null) { WindowsButtonUI.paintXPButtonBackground(g, c); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java index c7007bec3db..6b85a88e50c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java @@ -41,11 +41,12 @@ import com.sun.java.swing.plaf.windows.TMSchema.State; /** * Windows check box menu item. */ -public class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { +public final class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { final WindowsMenuItemUIAccessor accessor = new WindowsMenuItemUIAccessor() { + @Override public JMenuItem getMenuItem() { return menuItem; } @@ -54,6 +55,7 @@ public class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { return WindowsMenuItemUI.getState(this, menuItem); } + @Override public Part getPart(JMenuItem menuItem) { return WindowsMenuItemUI.getPart(this, menuItem); } @@ -80,6 +82,7 @@ public class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { * @param text String to render * @since 1.4 */ + @Override protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { if (WindowsMenuItemUI.isVistaPainting()) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java index f94b58c5610..3ead1228b0e 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java @@ -37,7 +37,7 @@ import sun.awt.AppContext; * * @author Jeff Dinkins */ -public class WindowsCheckBoxUI extends WindowsRadioButtonUI +public final class WindowsCheckBoxUI extends WindowsRadioButtonUI { // NOTE: WindowsCheckBoxUI inherits from WindowsRadioButtonUI instead // of BasicCheckBoxUI because we want to pick up all the @@ -64,6 +64,7 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI } + @Override public String getPropertyPrefix() { return propertyPrefix; } @@ -71,6 +72,7 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI // ******************************** // Defaults // ******************************** + @Override public void installDefaults(AbstractButton b) { super.installDefaults(b); if(!defaults_initialized) { @@ -79,6 +81,7 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI } } + @Override public void uninstallDefaults(AbstractButton b) { super.uninstallDefaults(b); defaults_initialized = false; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java index 6a2c9eeae31..59eace01a4c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java @@ -31,7 +31,8 @@ package com.sun.java.swing.plaf.windows; * @since 1.5 */ @SuppressWarnings("serial") // Superclass is not serializable across versions -public class WindowsClassicLookAndFeel extends WindowsLookAndFeel { +public final class WindowsClassicLookAndFeel extends WindowsLookAndFeel { + @Override public String getName() { return "Windows Classic"; } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java index 1a601f40332..f37ce17d876 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java @@ -75,7 +75,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; * @author Tom Santos * @author Igor Kushnirskiy */ -public class WindowsComboBoxUI extends BasicComboBoxUI { +public final class WindowsComboBoxUI extends BasicComboBoxUI { private static final MouseListener rolloverListener = new MouseAdapter() { @@ -162,6 +162,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { return new WindowsComboBoxUI(); } + @Override public void installUI( JComponent c ) { super.installUI( c ); isRollover = false; @@ -176,6 +177,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { } } + @Override public void uninstallUI(JComponent c ) { comboBox.removeMouseListener(rolloverListener); if(arrowButton != null) { @@ -215,6 +217,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * {@inheritDoc} * @since 1.6 */ + @Override protected void configureEditor() { super.configureEditor(); if (XPStyle.getXP() != null) { @@ -226,6 +229,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * {@inheritDoc} * @since 1.6 */ + @Override protected void unconfigureEditor() { super.unconfigureEditor(); editor.removeMouseListener(rolloverListener); @@ -235,6 +239,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * {@inheritDoc} * @since 1.6 */ + @Override public void paint(Graphics g, JComponent c) { if (XPStyle.getXP() != null) { paintXPComboBoxBackground(g, c); @@ -283,6 +288,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * @throws NullPointerException if any of the arguments are null. * @since 1.5 */ + @Override public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) { XPStyle xp = XPStyle.getXP(); @@ -347,6 +353,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * {@inheritDoc} * @since 1.6 */ + @Override public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) { if (XPStyle.getXP() == null) { @@ -354,6 +361,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { } } + @Override public Dimension getMinimumSize( JComponent c ) { Dimension d = super.getMinimumSize(c); if (XPStyle.getXP() != null) { @@ -380,6 +388,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * * @return an instance of a layout manager */ + @Override protected LayoutManager createLayoutManager() { return new BasicComboBoxUI.ComboBoxLayoutManager() { public void layoutContainer(Container parent) { @@ -407,10 +416,12 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { }; } + @Override protected void installKeyboardActions() { super.installKeyboardActions(); } + @Override protected ComboPopup createPopup() { return new WinComboPopUp(comboBox); } @@ -423,6 +434,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * @return a ComboBoxEditor used for the combo box * @see javax.swing.JComboBox#setEditor */ + @Override protected ComboBoxEditor createEditor() { return new WindowsComboBoxEditor(); } @@ -447,6 +459,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * * @return a button which represents the popup control */ + @Override protected JButton createArrowButton() { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -457,7 +470,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private class XPComboBoxButton extends XPStyle.GlyphButton { + private final class XPComboBoxButton extends XPStyle.GlyphButton { private State prevState = null; public XPComboBoxButton(XPStyle xp) { @@ -504,6 +517,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { return rv; } + @Override public Dimension getPreferredSize() { return new Dimension(17, 21); } @@ -518,7 +532,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { } @SuppressWarnings("serial") // Same-version serialization only - protected class WinComboPopUp extends BasicComboPopup { + protected final class WinComboPopUp extends BasicComboPopup { private Skin listBoxBorder = null; private XPStyle xp; @@ -531,16 +545,18 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { } } + @Override protected KeyListener createKeyListener() { return new InvocationKeyHandler(); } - protected class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler { + protected final class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler { protected InvocationKeyHandler() { WinComboPopUp.this.super(); } } + @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (this.listBoxBorder != null) { @@ -554,13 +570,14 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { /** * Subclassed to highlight selected item in an editable combo box. */ - public static class WindowsComboBoxEditor + public static final class WindowsComboBoxEditor extends BasicComboBoxEditor.UIResource { /** * {@inheritDoc} * @since 1.6 */ + @Override protected JTextField createEditorComponent() { JTextField editor = super.createEditorComponent(); Border border = (Border)UIManager.get("ComboBox.editorBorder"); @@ -572,6 +589,7 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { return editor; } + @Override public void setItem(Object item) { super.setItem(item); Object focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); @@ -586,14 +604,14 @@ public class WindowsComboBoxUI extends BasicComboBoxUI { * and to show border for focused cells. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - private static class WindowsComboBoxRenderer + private static final class WindowsComboBoxRenderer extends BasicComboBoxRenderer.UIResource { private static final Object BORDER_KEY = new StringUIClientPropertyKey("BORDER_KEY"); private static final Border NULL_BORDER = new EmptyBorder(0, 0, 0, 0); // Create own version of DashedBorder with more space on left side - private static class WindowsComboBoxDashedBorder extends DashedBorder { + private static final class WindowsComboBoxDashedBorder extends DashedBorder { public WindowsComboBoxDashedBorder(Color color, int thickness) { super(color, thickness); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java index 564ae5b9f71..8da4bd7921b 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopIconUI.java @@ -36,18 +36,20 @@ import javax.swing.plaf.basic.BasicDesktopIconUI; /** * Windows icon for a minimized window on the desktop. */ -public class WindowsDesktopIconUI extends BasicDesktopIconUI { +public final class WindowsDesktopIconUI extends BasicDesktopIconUI { private int width; public static ComponentUI createUI(JComponent c) { return new WindowsDesktopIconUI(); } + @Override public void installDefaults() { super.installDefaults(); width = UIManager.getInt("DesktopIcon.width"); } + @Override public void installUI(JComponent c) { super.installUI(c); @@ -55,6 +57,7 @@ public class WindowsDesktopIconUI extends BasicDesktopIconUI { } // Uninstall the listeners added by the WindowsInternalFrameTitlePane + @Override public void uninstallUI(JComponent c) { WindowsInternalFrameTitlePane thePane = (WindowsInternalFrameTitlePane)iconPane; @@ -62,6 +65,7 @@ public class WindowsDesktopIconUI extends BasicDesktopIconUI { thePane.uninstallListeners(); } + @Override protected void installComponents() { iconPane = new WindowsInternalFrameTitlePane(frame); desktopIcon.setLayout(new BorderLayout()); @@ -72,6 +76,7 @@ public class WindowsDesktopIconUI extends BasicDesktopIconUI { } } + @Override public Dimension getPreferredSize(JComponent c) { // Windows desktop icons can not be resized. Therefore, we should // always return the minimum size of the desktop icon. See @@ -83,6 +88,7 @@ public class WindowsDesktopIconUI extends BasicDesktopIconUI { * Windows desktop icons are restricted to a width of 160 pixels by * default. This value is retrieved by the DesktopIcon.width property. */ + @Override public Dimension getMinimumSize(JComponent c) { Dimension dim = super.getMinimumSize(c); dim.width = width; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java index 82708f571e5..355f70b4607 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java @@ -52,7 +52,7 @@ import java.lang.ref.WeakReference; * @author Thomas Ball */ @SuppressWarnings("serial") // JDK-implementation class -public class WindowsDesktopManager extends DefaultDesktopManager +public final class WindowsDesktopManager extends DefaultDesktopManager implements java.io.Serializable, javax.swing.plaf.UIResource { /* The frame which is currently selected/activated. @@ -60,6 +60,7 @@ public class WindowsDesktopManager extends DefaultDesktopManager */ private WeakReference currentFrameRef; + @Override public void activateFrame(JInternalFrame f) { JInternalFrame currentFrame = currentFrameRef != null ? currentFrameRef.get() : null; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java index 3ceea2d31dc..49ab809dddd 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopPaneUI.java @@ -34,12 +34,13 @@ import javax.swing.plaf.basic.BasicDesktopPaneUI; * * @author David Kloba */ -public class WindowsDesktopPaneUI extends BasicDesktopPaneUI +public final class WindowsDesktopPaneUI extends BasicDesktopPaneUI { public static ComponentUI createUI(JComponent c) { return new WindowsDesktopPaneUI(); } + @Override protected void installDesktopManager() { desktopManager = desktop.getDesktopManager(); if(desktopManager == null) { @@ -48,10 +49,12 @@ public class WindowsDesktopPaneUI extends BasicDesktopPaneUI } } + @Override protected void installDefaults() { super.installDefaults(); } + @Override @SuppressWarnings("deprecation") protected void installKeyboardActions() { super.installKeyboardActions(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java index 2f5c45633d4..abccb6b9a48 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsEditorPaneUI.java @@ -33,7 +33,7 @@ import javax.swing.text.Caret; /** * Windows rendition of the component. */ -public class WindowsEditorPaneUI extends BasicEditorPaneUI +public final class WindowsEditorPaneUI extends BasicEditorPaneUI { /** @@ -54,6 +54,7 @@ public class WindowsEditorPaneUI extends BasicEditorPaneUI * * @return the caret object */ + @Override protected Caret createCaret() { return new WindowsTextUI.WindowsCaret(); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java index 7065e3db19b..37d45bbf902 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java @@ -101,7 +101,7 @@ import sun.swing.WindowsPlacesBar; * * @author Jeff Dinkins */ -public class WindowsFileChooserUI extends BasicFileChooserUI { +public final class WindowsFileChooserUI extends BasicFileChooserUI { // The following are private because the implementation of the // Windows FileChooser L&F is not complete yet. @@ -194,61 +194,75 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { super(filechooser); } + @Override public void installUI(JComponent c) { super.installUI(c); } + @Override public void uninstallComponents(JFileChooser fc) { fc.removeAll(); } - private class WindowsFileChooserUIAccessor implements FilePane.FileChooserUIAccessor { + private final class WindowsFileChooserUIAccessor implements FilePane.FileChooserUIAccessor { + @Override public JFileChooser getFileChooser() { return WindowsFileChooserUI.this.getFileChooser(); } + @Override public BasicDirectoryModel getModel() { return WindowsFileChooserUI.this.getModel(); } + @Override public JPanel createList() { return WindowsFileChooserUI.this.createList(getFileChooser()); } + @Override public JPanel createDetailsView() { return WindowsFileChooserUI.this.createDetailsView(getFileChooser()); } + @Override public boolean isDirectorySelected() { return WindowsFileChooserUI.this.isDirectorySelected(); } + @Override public File getDirectory() { return WindowsFileChooserUI.this.getDirectory(); } + @Override public Action getChangeToParentDirectoryAction() { return WindowsFileChooserUI.this.getChangeToParentDirectoryAction(); } + @Override public Action getApproveSelectionAction() { return WindowsFileChooserUI.this.getApproveSelectionAction(); } + @Override public Action getNewFolderAction() { return WindowsFileChooserUI.this.getNewFolderAction(); } + @Override public MouseListener createDoubleClickListener(JList list) { return WindowsFileChooserUI.this.createDoubleClickListener(getFileChooser(), list); } + @Override public ListSelectionListener createListSelectionListener() { return WindowsFileChooserUI.this.createListSelectionListener(getFileChooser()); } } + @Override public void installComponents(JFileChooser fc) { filePane = new FilePane(new WindowsFileChooserUIAccessor()); fc.addPropertyChangeListener(filePane); @@ -584,6 +598,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { return bottomPanel; } + @Override protected void installStrings(JFileChooser fc) { super.installStrings(fc); @@ -615,6 +630,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { return SwingUtilities2.getUIDefaultsInt(key, l); } + @Override protected void installListeners(JFileChooser fc) { super.installListeners(fc); ActionMap actionMap = getActionMap(); @@ -645,10 +661,12 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { * @param fc a JFileChooser * @return a ListSelectionListener */ + @Override public ListSelectionListener createListSelectionListener(JFileChooser fc) { return super.createListSelectionListener(fc); } + @Override public void uninstallUI(JComponent c) { // Remove listeners c.removePropertyChangeListener(filterComboBoxModel); @@ -859,6 +877,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { * Listen for filechooser property changes, such as * the selected file changing, or the type of the dialog changing. */ + @Override public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) { return new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { @@ -913,14 +932,17 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { getBottomPanel().add(getButtonPanel()); } + @Override public void ensureFileIsVisible(JFileChooser fc, File f) { filePane.ensureFileIsVisible(fc, f); } + @Override public void rescanCurrentDirectory(JFileChooser fc) { filePane.rescanCurrentDirectory(); } + @Override public String getFileName() { if(filenameTextField != null) { return filenameTextField.getText(); @@ -929,6 +951,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { } } + @Override public void setFileName(String filename) { if(filenameTextField != null) { filenameTextField.setText(filename); @@ -942,6 +965,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { * @param directorySelected if a directory is currently selected. * @since 1.4 */ + @Override protected void setDirectorySelected(boolean directorySelected) { super.setDirectorySelected(directorySelected); JFileChooser chooser = getFileChooser(); @@ -956,11 +980,13 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { } } + @Override public String getDirectoryName() { // PENDING(jeff) - get the name from the directory combobox return null; } + @Override public void setDirectoryName(String dirname) { // PENDING(jeff) - set the name in the directory combobox } @@ -1032,8 +1058,9 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { // Renderer for DirectoryComboBox // @SuppressWarnings("serial") // Superclass is not serializable across versions - class DirectoryComboBoxRenderer extends DefaultListCellRenderer { + final class DirectoryComboBoxRenderer extends DefaultListCellRenderer { IndentIcon ii = new IndentIcon(); + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { @@ -1056,11 +1083,12 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { } static final int space = 10; - static class IndentIcon implements Icon { + static final class IndentIcon implements Icon { Icon icon = null; int depth = 0; + @Override public void paintIcon(Component c, Graphics g, int x, int y) { if (c.getComponentOrientation().isLeftToRight()) { icon.paintIcon(c, g, x+depth*space, y); @@ -1069,10 +1097,12 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { } } + @Override public int getIconWidth() { return icon.getIconWidth() + depth*space; } + @Override public int getIconHeight() { return icon.getIconHeight(); } @@ -1090,7 +1120,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { * Data model for a type-face selection combo-box. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { + protected final class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { Vector directories = new Vector(); int[] depths = null; File selectedDirectory = null; @@ -1187,19 +1217,23 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0; } + @Override public void setSelectedItem(Object selectedDirectory) { this.selectedDirectory = (File)selectedDirectory; fireContentsChanged(this, -1, -1); } + @Override public Object getSelectedItem() { return selectedDirectory; } + @Override public int getSize() { return directories.size(); } + @Override public File getElementAt(int index) { return directories.elementAt(index); } @@ -1216,7 +1250,8 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { * Render different type sizes and styles. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public class FilterComboBoxRenderer extends DefaultListCellRenderer { + public final class FilterComboBoxRenderer extends DefaultListCellRenderer { + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { @@ -1242,7 +1277,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { * Data model for a type-face selection combo-box. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, + protected final class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener { protected FileFilter[] filters; protected FilterComboBoxModel() { @@ -1250,6 +1285,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { filters = getFileChooser().getChoosableFileFilters(); } + @Override public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { @@ -1260,6 +1296,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { } } + @Override public void setSelectedItem(Object filter) { if(filter != null) { getFileChooser().setFileFilter((FileFilter) filter); @@ -1267,6 +1304,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { } } + @Override public Object getSelectedItem() { // Ensure that the current filter is in the list. // NOTE: we shouldn't have to do this, since JFileChooser adds @@ -1288,6 +1326,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { return getFileChooser().getFileFilter(); } + @Override public int getSize() { if(filters != null) { return filters.length; @@ -1296,6 +1335,7 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { } } + @Override public FileFilter getElementAt(int index) { if(index > getSize() - 1) { // This shouldn't happen. Try to recover gracefully. @@ -1320,21 +1360,24 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { /** * Acts when DirectoryComboBox has changed the selected item. */ - protected class DirectoryComboBoxAction implements ActionListener { + protected final class DirectoryComboBoxAction implements ActionListener { + @Override public void actionPerformed(ActionEvent e) { File f = (File)directoryComboBox.getSelectedItem(); getFileChooser().setCurrentDirectory(f); } } + @Override protected JButton getApproveButton(JFileChooser fc) { return approveButton; } + @Override public FileView getFileView(JFileChooser fc) { return fileView; } @@ -1342,9 +1385,10 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { // *********************** // * FileView operations * // *********************** - protected class WindowsFileView extends BasicFileView { + protected final class WindowsFileView extends BasicFileView { /* FileView type descriptions */ + @Override public Icon getIcon(File f) { Icon icon = getCachedIcon(f); if (icon != null) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java index cb4b5caa86d..b5859b08ea8 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java @@ -58,7 +58,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.TypeEnum; * @author Mark Davidson * @since 1.4 */ -public class WindowsGraphicsUtils { +public final class WindowsGraphicsUtils { /** * Renders a text String in Windows without the mnemonic. diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java index 072ff606b5b..cf2fd119423 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java @@ -63,7 +63,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; * @author Rich Schiavi */ @SuppressWarnings("serial") // Same-version serialization only -public class WindowsIconFactory implements Serializable +public final class WindowsIconFactory implements Serializable { private static Icon frame_closeIcon; private static Icon frame_iconifyIcon; @@ -173,13 +173,14 @@ public class WindowsIconFactory implements Serializable @SuppressWarnings("serial") // Same-version serialization only - private static class FrameButtonIcon implements Icon, Serializable { + private static final class FrameButtonIcon implements Icon, Serializable { private final Part part; private FrameButtonIcon(Part part) { this.part = part; } + @Override public void paintIcon(Component c, Graphics g, int x0, int y0) { int width = getIconWidth(); int height = getIconHeight(); @@ -281,6 +282,7 @@ public class WindowsIconFactory implements Serializable } } + @Override public int getIconWidth() { int width; if (XPStyle.getXP() != null) { @@ -293,6 +295,7 @@ public class WindowsIconFactory implements Serializable return width; } + @Override public int getIconHeight() { int height = UIManager.getInt("InternalFrame.titleButtonHeight")-4; return height; @@ -302,7 +305,8 @@ public class WindowsIconFactory implements Serializable @SuppressWarnings("serial") // Same-version serialization only - private static class ResizeIcon implements Icon, Serializable { + private static final class ResizeIcon implements Icon, Serializable { + @Override public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(UIManager.getColor("InternalFrame.resizeIconHighlight")); g.drawLine(0, 11, 11, 0); @@ -317,14 +321,17 @@ public class WindowsIconFactory implements Serializable g.drawLine(9, 11, 11, 9); g.drawLine(10, 11, 11, 10); } + @Override public int getIconWidth() { return 13; } + @Override public int getIconHeight() { return 13; } } @SuppressWarnings("serial") // Same-version serialization only - private static class CheckBoxIcon implements Icon, Serializable + private static final class CheckBoxIcon implements Icon, Serializable { static final int csize = 13; + @Override public void paintIcon(Component c, Graphics g, int x, int y) { JCheckBox cb = (JCheckBox) c; ButtonModel model = cb.getModel(); @@ -425,6 +432,7 @@ public class WindowsIconFactory implements Serializable } } + @Override public int getIconWidth() { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -434,6 +442,7 @@ public class WindowsIconFactory implements Serializable } } + @Override public int getIconHeight() { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -445,8 +454,9 @@ public class WindowsIconFactory implements Serializable } @SuppressWarnings("serial") // Same-version serialization only - private static class RadioButtonIcon implements Icon, UIResource, Serializable + private static final class RadioButtonIcon implements Icon, UIResource, Serializable { + @Override public void paintIcon(Component c, Graphics g, int x, int y) { AbstractButton b = (AbstractButton) c; ButtonModel model = b.getModel(); @@ -579,6 +589,7 @@ public class WindowsIconFactory implements Serializable } } + @Override public int getIconWidth() { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -588,6 +599,7 @@ public class WindowsIconFactory implements Serializable } } + @Override public int getIconHeight() { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -600,8 +612,9 @@ public class WindowsIconFactory implements Serializable @SuppressWarnings("serial") // Same-version serialization only - private static class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable + private static final class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable { + @Override public void paintIcon(Component c, Graphics g, int x, int y) { AbstractButton b = (AbstractButton) c; ButtonModel model = b.getModel(); @@ -619,15 +632,18 @@ public class WindowsIconFactory implements Serializable g.drawLine(x+3, y+6, x+4, y+6); } } + @Override public int getIconWidth() { return 9; } + @Override public int getIconHeight() { return 9; } } // End class CheckBoxMenuItemIcon @SuppressWarnings("serial") // Same-version serialization only - private static class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable + private static final class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable { + @Override public void paintIcon(Component c, Graphics g, int x, int y) { AbstractButton b = (AbstractButton) c; ButtonModel model = b.getModel(); @@ -636,14 +652,17 @@ public class WindowsIconFactory implements Serializable 4, 4); } } + @Override public int getIconWidth() { return 12; } + @Override public int getIconHeight() { return 12; } } // End class RadioButtonMenuItemIcon @SuppressWarnings("serial") // Same-version serialization only - private static class MenuItemCheckIcon implements Icon, UIResource, Serializable{ + private static final class MenuItemCheckIcon implements Icon, UIResource, Serializable{ + @Override public void paintIcon(Component c, Graphics g, int x, int y) { /* For debugging: Color oldColor = g.getColor(); @@ -652,13 +671,16 @@ public class WindowsIconFactory implements Serializable g.setColor(oldColor); */ } + @Override public int getIconWidth() { return 9; } + @Override public int getIconHeight() { return 9; } } // End class MenuItemCheckIcon @SuppressWarnings("serial") // Same-version serialization only - private static class MenuItemArrowIcon implements Icon, UIResource, Serializable { + private static final class MenuItemArrowIcon implements Icon, UIResource, Serializable { + @Override public void paintIcon(Component c, Graphics g, int x, int y) { /* For debugging: Color oldColor = g.getColor(); @@ -667,13 +689,16 @@ public class WindowsIconFactory implements Serializable g.setColor(oldColor); */ } + @Override public int getIconWidth() { return 4; } + @Override public int getIconHeight() { return 8; } } // End class MenuItemArrowIcon @SuppressWarnings("serial") // Same-version serialization only - private static class MenuArrowIcon implements Icon, UIResource, Serializable { + private static final class MenuArrowIcon implements Icon, UIResource, Serializable { + @Override public void paintIcon(Component c, Graphics g, int x, int y) { XPStyle xp = XPStyle.getXP(); if (WindowsMenuItemUI.isVistaPainting(xp)) { @@ -708,6 +733,7 @@ public class WindowsIconFactory implements Serializable g.translate(-x,-y); } } + @Override public int getIconWidth() { XPStyle xp = XPStyle.getXP(); if (WindowsMenuItemUI.isVistaPainting(xp)) { @@ -717,6 +743,7 @@ public class WindowsIconFactory implements Serializable return 4; } } + @Override public int getIconHeight() { XPStyle xp = XPStyle.getXP(); if (WindowsMenuItemUI.isVistaPainting(xp)) { @@ -728,14 +755,16 @@ public class WindowsIconFactory implements Serializable } } // End class MenuArrowIcon - static class VistaMenuItemCheckIconFactory + static final class VistaMenuItemCheckIconFactory implements MenuItemCheckIconFactory { private static final int OFFSET = 3; + @Override public Icon getIcon(JMenuItem component) { return new VistaMenuItemCheckIcon(component); } + @Override public boolean isCompatible(Object icon, String prefix) { return icon instanceof VistaMenuItemCheckIcon && ((VistaMenuItemCheckIcon) icon).type == getType(prefix); @@ -788,7 +817,7 @@ public class WindowsIconFactory implements Serializable * Note: to be used on Vista only. */ @SuppressWarnings("serial") // Same-version serialization only - private static class VistaMenuItemCheckIcon + private static final class VistaMenuItemCheckIcon implements Icon, UIResource, Serializable { private final JMenuItem menuItem; @@ -803,6 +832,7 @@ public class WindowsIconFactory implements Serializable this.menuItem = null; } + @Override public int getIconHeight() { Icon lafIcon = getLaFIcon(); if (lafIcon != null) { @@ -825,6 +855,7 @@ public class WindowsIconFactory implements Serializable return height; } + @Override public int getIconWidth() { Icon lafIcon = getLaFIcon(); if (lafIcon != null) { @@ -840,6 +871,7 @@ public class WindowsIconFactory implements Serializable return width; } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { Icon lafIcon = getLaFIcon(); if (lafIcon != null) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java index 083563b4464..ba4bde12122 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java @@ -83,6 +83,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { super(f); } + @Override protected void addSubComponents() { add(systemLabel); add(iconButton); @@ -90,6 +91,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { add(closeButton); } + @Override protected void installDefaults() { super.installDefaults(); @@ -117,11 +119,13 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { UIManager.getColor("InternalFrame.inactiveTitleGradient"); } + @Override protected void uninstallListeners() { // Get around protected method in superclass super.uninstallListeners(); } + @Override protected void createButtons() { super.createButtons(); if (XPStyle.getXP() != null) { @@ -131,6 +135,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } } + @Override protected void setButtonIcons() { super.setButtonIcons(); @@ -142,6 +147,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } + @Override public void paintComponent(Graphics g) { XPStyle xp = XPStyle.getXP(); @@ -224,10 +230,12 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } } + @Override public Dimension getPreferredSize() { return getMinimumSize(); } + @Override public Dimension getMinimumSize() { Dimension d = new Dimension(super.getMinimumSize()); d.height = titlePaneHeight + 2; @@ -245,6 +253,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { return d; } + @Override protected void paintTitleBackground(Graphics g) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -285,6 +294,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } } + @Override protected void assembleSystemMenu() { systemPopupMenu = new JPopupMenu(); addSystemMenuItems(systemPopupMenu); @@ -372,6 +382,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } } + @Override protected void showSystemMenu(){ showSystemPopupMenu(systemLabel); } @@ -397,15 +408,17 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } } + @Override protected PropertyChangeListener createPropertyChangeListener() { return new WindowsPropertyChangeHandler(); } + @Override protected LayoutManager createLayout() { return new WindowsTitlePaneLayout(); } - public class WindowsTitlePaneLayout extends BasicInternalFrameTitlePane.TitlePaneLayout { + public final class WindowsTitlePaneLayout extends BasicInternalFrameTitlePane.TitlePaneLayout { private Insets captionMargin = null; private Insets contentMargin = null; private XPStyle xp = XPStyle.getXP(); @@ -439,6 +452,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { return x; } + @Override public void layoutContainer(Container c) { boolean leftToRight = WindowsGraphicsUtils.isLeftToRight(frame); int x, y; @@ -492,7 +506,8 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } } // end WindowsTitlePaneLayout - public class WindowsPropertyChangeHandler extends PropertyChangeHandler { + public final class WindowsPropertyChangeHandler extends PropertyChangeHandler { + @Override public void propertyChange(PropertyChangeEvent evt) { String prop = evt.getPropertyName(); @@ -515,7 +530,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { *

* Note: We assume here that icons are square. */ - public static class ScalableIconUIResource implements Icon, UIResource { + public static final class ScalableIconUIResource implements Icon, UIResource { // We can use an arbitrary size here because we scale to it in paintIcon() private static final int SIZE = 16; @@ -562,6 +577,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { } } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D g2d = (Graphics2D)g.create(); // Calculate how big our drawing area is in pixels @@ -580,10 +596,12 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { g2d.dispose(); } + @Override public int getIconWidth() { return SIZE; } + @Override public int getIconHeight() { return SIZE; } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java index 19169f6e424..5c331533af9 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameUI.java @@ -45,10 +45,11 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; /** * Windows rendition of the component. */ -public class WindowsInternalFrameUI extends BasicInternalFrameUI +public final class WindowsInternalFrameUI extends BasicInternalFrameUI { XPStyle xp = XPStyle.getXP(); + @Override public void installDefaults() { super.installDefaults(); @@ -59,6 +60,7 @@ public class WindowsInternalFrameUI extends BasicInternalFrameUI } } + @Override public void installUI(JComponent c) { super.installUI(c); @@ -66,6 +68,7 @@ public class WindowsInternalFrameUI extends BasicInternalFrameUI xp == null? Boolean.TRUE : Boolean.FALSE); } + @Override public void uninstallDefaults() { frame.setBorder(null); super.uninstallDefaults(); @@ -79,17 +82,19 @@ public class WindowsInternalFrameUI extends BasicInternalFrameUI super(w); } + @Override protected DesktopManager createDesktopManager(){ return new WindowsDesktopManager(); } + @Override protected JComponent createNorthPane(JInternalFrame w) { titlePane = new WindowsInternalFrameTitlePane(w); return titlePane; } @SuppressWarnings("serial") // Superclass is not serializable across versions - private class XPBorder extends AbstractBorder { + private final class XPBorder extends AbstractBorder { private Skin leftSkin = xp.getSkin(frame, Part.WP_FRAMELEFT); private Skin rightSkin = xp.getSkin(frame, Part.WP_FRAMERIGHT); private Skin bottomSkin = xp.getSkin(frame, Part.WP_FRAMEBOTTOM); @@ -100,6 +105,7 @@ public class WindowsInternalFrameUI extends BasicInternalFrameUI * @param width the width of the painted border * @param height the height of the painted border */ + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { State state = ((JInternalFrame)c).isSelected() ? State.ACTIVE : State.INACTIVE; int topBorderHeight = (titlePane != null) ? titlePane.getSize().height : 0; @@ -118,6 +124,7 @@ public class WindowsInternalFrameUI extends BasicInternalFrameUI } + @Override public Insets getBorderInsets(Component c, Insets insets) { insets.top = 4; insets.left = leftSkin.getWidth(); @@ -127,6 +134,7 @@ public class WindowsInternalFrameUI extends BasicInternalFrameUI return insets; } + @Override public boolean isBorderOpaque() { return true; } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java index 6266772dcf4..d10f3f47c3c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java @@ -41,7 +41,7 @@ import sun.swing.SwingUtilities2; /** * Windows rendition of the component. */ -public class WindowsLabelUI extends BasicLabelUI { +public final class WindowsLabelUI extends BasicLabelUI { private static final Object WINDOWS_LABEL_UI_KEY = new Object(); @@ -59,6 +59,7 @@ public class WindowsLabelUI extends BasicLabelUI { return windowsLabelUI; } + @Override protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY) { int mnemonicIndex = l.getDisplayedMnemonicIndex(); @@ -72,6 +73,7 @@ public class WindowsLabelUI extends BasicLabelUI { textX, textY); } + @Override protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY) { int mnemonicIndex = l.getDisplayedMnemonicIndex(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java index 72ad51535ff..d1ee714f362 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java @@ -145,26 +145,32 @@ public class WindowsLookAndFeel extends BasicLookAndFeel */ private int baseUnitY; + @Override public String getName() { return "Windows"; } + @Override public String getDescription() { return "The Microsoft Windows Look and Feel"; } + @Override public String getID() { return "Windows"; } + @Override public boolean isNativeLookAndFeel() { return OSInfo.getOSType() == OSInfo.OSType.WINDOWS; } + @Override public boolean isSupportedLookAndFeel() { return isNativeLookAndFeel(); } + @Override public void initialize() { super.initialize(); @@ -206,6 +212,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * * @see BasicLookAndFeel#getDefaults */ + @Override protected void initClassDefaults(UIDefaults table) { super.initClassDefaults(table); @@ -260,6 +267,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * values, otherwise we create color objects whose values match * the defaults Windows95 colors. */ + @Override protected void initSystemColorDefaults(UIDefaults table) { String[] defaultSystemColors = { @@ -310,6 +318,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel // XXX - there are probably a lot of redundant values that could be removed. // ie. Take a look at RadioButtonBorder, etc... + @Override protected void initComponentDefaults(UIDefaults table) { super.initComponentDefaults( table ); @@ -1893,6 +1902,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel return lazyDefaults; } + @Override public void uninitialize() { super.uninitialize(); @@ -1944,6 +1954,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * * @see javax.swing.LookAndFeel#provideErrorFeedback */ + @Override public void provideErrorFeedback(Component component) { super.provideErrorFeedback(component); } @@ -1951,6 +1962,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel /** * {@inheritDoc} */ + @Override public LayoutStyle getLayoutStyle() { LayoutStyle style = this.style; if (style == null) { @@ -1981,6 +1993,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * @see #playSound(Action) * @since 1.4 */ + @Override protected Action createAudioAction(Object key) { if (key != null) { String audioKey = (String)key; @@ -2018,7 +2031,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * @since 1.4 */ @SuppressWarnings("serial") // Superclass is not serializable across versions - private static class AudioAction extends AbstractAction { + private static final class AudioAction extends AbstractAction { private Runnable audioRunnable; private String audioResource; /** @@ -2029,6 +2042,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel super(name); audioResource = resource; } + @Override public void actionPerformed(ActionEvent e) { if (audioRunnable == null) { audioRunnable = (Runnable)Toolkit.getDefaultToolkit().getDesktopProperty(audioResource); @@ -2045,7 +2059,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * Gets an Icon from the native libraries if available, * otherwise gets it from an image resource file. */ - private static class LazyWindowsIcon implements UIDefaults.LazyValue { + private static final class LazyWindowsIcon implements UIDefaults.LazyValue { private String nativeImage; private String resource; @@ -2054,6 +2068,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel this.resource = resource; } + @Override public Object createValue(UIDefaults table) { if (nativeImage != null) { Image image = (Image)ShellFolder.get(nativeImage); @@ -2072,7 +2087,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * Gets an Icon from the native libraries if available. * A desktop property is used to trigger reloading the icon when needed. */ - private static class ActiveWindowsIcon implements UIDefaults.ActiveValue { + private static final class ActiveWindowsIcon implements UIDefaults.ActiveValue { private Icon icon; private String nativeImageName; private String fallbackName; @@ -2117,7 +2132,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel /** * Icon backed-up by XP Skin. */ - private static class SkinIcon implements Icon, UIResource { + private static final class SkinIcon implements Icon, UIResource { private final Part part; private final State state; SkinIcon(Part part, State state) { @@ -2130,6 +2145,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * may use the Component argument to get properties useful for * painting, e.g. the foreground or background color. */ + @Override public void paintIcon(Component c, Graphics g, int x, int y) { XPStyle xp = XPStyle.getXP(); assert xp != null; @@ -2144,6 +2160,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * * @return an int specifying the fixed width of the icon. */ + @Override public int getIconWidth() { int width = 0; XPStyle xp = XPStyle.getXP(); @@ -2160,6 +2177,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * * @return an int specifying the fixed height of the icon. */ + @Override public int getIconHeight() { int height = 0; XPStyle xp = XPStyle.getXP(); @@ -2176,11 +2194,12 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * WindowsDesktopProperty for fonts. If a font with the name 'MS Sans Serif' * is returned, it is mapped to 'Microsoft Sans Serif'. */ - private static class WindowsFontProperty extends WindowsDesktopProperty { + private static final class WindowsFontProperty extends WindowsDesktopProperty { WindowsFontProperty(String key, Object backup) { super(key, backup); } + @Override public void invalidate(LookAndFeel laf) { if ("win.defaultGUI.font.height".equals(getKey())) { ((WindowsLookAndFeel)laf).style = null; @@ -2188,6 +2207,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel super.invalidate(laf); } + @Override protected Object configureValue(Object value) { if (value instanceof Font) { Font font = (Font)value; @@ -2236,7 +2256,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * WindowsDesktopProperty for fonts that only gets sizes from the desktop, * font name and style are passed into the constructor */ - private static class WindowsFontSizeProperty extends + private static final class WindowsFontSizeProperty extends WindowsDesktopProperty { private String fontName; private int fontSize; @@ -2250,6 +2270,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel this.fontStyle = fontStyle; } + @Override protected Object configureValue(Object value) { if (value == null) { value = new FontUIResource(fontName, fontStyle, fontSize); @@ -2278,6 +2299,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel this.classicValue = classicValue; } + @Override public Object createValue(UIDefaults table) { Object value = null; if (XPStyle.getXP() != null) { @@ -2313,7 +2335,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel } } - private static class XPBorderValue extends XPValue { + private static final class XPBorderValue extends XPValue { private final Border extraMargin; XPBorderValue(Part xpValue, Object classicValue) { @@ -2325,6 +2347,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel this.extraMargin = extraMargin; } + @Override public Object getXPValue(UIDefaults table) { XPStyle xp = XPStyle.getXP(); Border xpBorder = xp != null ? xp.getBorder(null, (Part)xpValue) : null; @@ -2337,18 +2360,19 @@ public class WindowsLookAndFeel extends BasicLookAndFeel } } - private static class XPColorValue extends XPValue { + private static final class XPColorValue extends XPValue { XPColorValue(Part part, State state, Prop prop, Object classicValue) { super(new XPColorValueKey(part, state, prop), classicValue); } + @Override public Object getXPValue(UIDefaults table) { XPColorValueKey key = (XPColorValueKey)xpValue; XPStyle xp = XPStyle.getXP(); return xp != null ? xp.getColor(key.skin, key.prop, null) : null; } - private static class XPColorValueKey { + private static final class XPColorValueKey { Skin skin; Prop prop; @@ -2359,7 +2383,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel } } - private class XPDLUValue extends XPValue { + private final class XPDLUValue extends XPValue { private int direction; XPDLUValue(int xpdlu, int classicdlu, int direction) { @@ -2367,11 +2391,13 @@ public class WindowsLookAndFeel extends BasicLookAndFeel this.direction = direction; } + @Override public Object getXPValue(UIDefaults table) { int px = dluToPixels(((Integer)xpValue).intValue(), direction); return Integer.valueOf(px); } + @Override public Object getClassicValue(UIDefaults table) { int px = dluToPixels(((Integer)classicValue).intValue(), direction); return Integer.valueOf(px); @@ -2387,6 +2413,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel getValueFromDesktop(); } + @Override protected void updateUI() { super.updateUI(); @@ -2395,11 +2422,12 @@ public class WindowsLookAndFeel extends BasicLookAndFeel } } - private static class FontDesktopProperty extends TriggerDesktopProperty { + private static final class FontDesktopProperty extends TriggerDesktopProperty { FontDesktopProperty(String key) { super(key); } + @Override protected void updateUI() { UIDefaults defaults = UIManager.getLookAndFeelDefaults(); SwingUtilities2.putAATextInfo(true, defaults); @@ -2410,7 +2438,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel // Windows LayoutStyle. From: // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwue/html/ch14e.asp @SuppressWarnings("fallthrough") - private class WindowsLayoutStyle extends DefaultLayoutStyle { + private final class WindowsLayoutStyle extends DefaultLayoutStyle { @Override public int getPreferredGap(JComponent component1, JComponent component2, ComponentPlacement type, int position, @@ -2504,6 +2532,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel * * @since 1.6 */ + @Override public Icon getDisabledIcon(JComponent component, Icon icon) { // if the component has a HI_RES_DISABLED_ICON_CLIENT_KEY // client property set to Boolean.TRUE, then use the new @@ -2525,10 +2554,11 @@ public class WindowsLookAndFeel extends BasicLookAndFeel return super.getDisabledIcon(component, icon); } - private static class RGBGrayFilter extends RGBImageFilter { + private static final class RGBGrayFilter extends RGBImageFilter { public RGBGrayFilter() { canFilterIndexColorModel = true; } + @Override public int filterRGB(int x, int y, int rgb) { // find the average of red, green, and blue float avg = (((rgb >> 16) & 0xff) / 255f + @@ -2547,7 +2577,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel } } - private static class FocusColorProperty extends WindowsDesktopProperty { + private static final class FocusColorProperty extends WindowsDesktopProperty { public FocusColorProperty () { // Fallback value is never used because of the configureValue method doesn't return null super("win.3d.backgroundColor", Color.BLACK); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java index 8c6cbdff541..f663d8d1e90 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java @@ -57,7 +57,7 @@ import sun.swing.MnemonicHandler; /** * Windows rendition of the component. */ -public class WindowsMenuBarUI extends BasicMenuBarUI +public final class WindowsMenuBarUI extends BasicMenuBarUI { /* to be accessed on the EDT only */ private WindowListener windowListener = null; @@ -125,6 +125,7 @@ public class WindowsMenuBarUI extends BasicMenuBarUI super.installListeners(); } + @Override protected void installKeyboardActions() { super.installKeyboardActions(); ActionMap map = SwingUtilities.getUIActionMap(menuBar); @@ -140,7 +141,7 @@ public class WindowsMenuBarUI extends BasicMenuBarUI * Unlike BasicMenuBarUI.TakeFocus, this Action will not show menu popup. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - private static class TakeFocus extends AbstractAction { + private static final class TakeFocus extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { JMenuBar menuBar = (JMenuBar)e.getSource(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java index 2f76f929133..2ee1b2d119f 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java @@ -54,7 +54,7 @@ import sun.swing.SwingUtilities2; * * @author Igor Kushnirskiy */ -public class WindowsMenuItemUI extends BasicMenuItemUI { +public final class WindowsMenuItemUI extends BasicMenuItemUI { /** * The instance of {@code PropertyChangeListener}. */ @@ -63,6 +63,7 @@ public class WindowsMenuItemUI extends BasicMenuItemUI { final WindowsMenuItemUIAccessor accessor = new WindowsMenuItemUIAccessor() { + @Override public JMenuItem getMenuItem() { return menuItem; } @@ -71,6 +72,7 @@ public class WindowsMenuItemUI extends BasicMenuItemUI { return WindowsMenuItemUI.getState(this, menuItem); } + @Override public Part getPart(JMenuItem menuItem) { return WindowsMenuItemUI.getPart(this, menuItem); } @@ -141,6 +143,7 @@ public class WindowsMenuItemUI extends BasicMenuItemUI { * @param textRect Bounding rectangle to render the text. * @param text String to render */ + @Override protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { if (WindowsMenuItemUI.isVistaPainting()) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java index 4195b4e85ca..5562ce60388 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java @@ -50,13 +50,14 @@ import com.sun.java.swing.plaf.windows.TMSchema.State; /** * Windows rendition of the component. */ -public class WindowsMenuUI extends BasicMenuUI { +public final class WindowsMenuUI extends BasicMenuUI { protected Integer menuBarHeight; protected boolean hotTrackingOn; final WindowsMenuItemUIAccessor accessor = new WindowsMenuItemUIAccessor() { + @Override public JMenuItem getMenuItem() { return menuItem; } @@ -106,6 +107,7 @@ public class WindowsMenuUI extends BasicMenuUI { return state; } + @Override public Part getPart(JMenuItem menuItem) { return ((JMenu) menuItem).isTopLevelMenu() ? Part.MP_BARITEM : Part.MP_POPUPITEM; @@ -115,6 +117,7 @@ public class WindowsMenuUI extends BasicMenuUI { return new WindowsMenuUI(); } + @Override protected void installDefaults() { super.installDefaults(); if (!WindowsLookAndFeel.isClassicWindows()) { @@ -131,6 +134,7 @@ public class WindowsMenuUI extends BasicMenuUI { * Draws the background of the menu. * @since 1.4 */ + @Override protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { if (WindowsMenuItemUI.isVistaPainting()) { WindowsMenuItemUI.paintBackground(accessor, g, menuItem, bgColor); @@ -210,6 +214,7 @@ public class WindowsMenuUI extends BasicMenuUI { * @param text String to render * @since 1.4 */ + @Override protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { if (WindowsMenuItemUI.isVistaPainting()) { @@ -245,6 +250,7 @@ public class WindowsMenuUI extends BasicMenuUI { g.setColor(oldColor); } + @Override protected MouseInputListener createMouseInputListener(JComponent c) { return new WindowsMouseInputHandler(); } @@ -254,7 +260,8 @@ public class WindowsMenuUI extends BasicMenuUI { * true when the mouse enters the menu and false when it exits. * @since 1.4 */ - protected class WindowsMouseInputHandler extends BasicMenuUI.MouseInputHandler { + protected final class WindowsMouseInputHandler extends BasicMenuUI.MouseInputHandler { + @Override public void mouseEntered(MouseEvent evt) { super.mouseEntered(evt); @@ -265,6 +272,7 @@ public class WindowsMenuUI extends BasicMenuUI { } } + @Override public void mouseExited(MouseEvent evt) { super.mouseExited(evt); @@ -277,6 +285,7 @@ public class WindowsMenuUI extends BasicMenuUI { } } + @Override protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon, Icon arrowIcon, diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java index 2755cc76c96..5ced1659adf 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsOptionPaneUI.java @@ -30,5 +30,5 @@ import javax.swing.plaf.basic.BasicOptionPaneUI; /** * Windows rendition of the component. */ -public class WindowsOptionPaneUI extends BasicOptionPaneUI { +public final class WindowsOptionPaneUI extends BasicOptionPaneUI { } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java index baf0997ceff..1f64c18e61f 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPasswordFieldUI.java @@ -33,7 +33,7 @@ import javax.swing.text.Caret; /** * Windows rendition of the component. */ -public class WindowsPasswordFieldUI extends BasicPasswordFieldUI { +public final class WindowsPasswordFieldUI extends BasicPasswordFieldUI { /** * Creates a UI for a JPasswordField @@ -54,6 +54,7 @@ public class WindowsPasswordFieldUI extends BasicPasswordFieldUI { * * @return the caret object */ + @Override protected Caret createCaret() { return new WindowsTextUI.WindowsCaret(); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java index ed31f00a89b..9d67278526a 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java @@ -42,12 +42,13 @@ import com.sun.java.swing.plaf.windows.XPStyle.Skin; * @author Igor Kushnirskiy */ -public class WindowsPopupMenuSeparatorUI extends BasicPopupMenuSeparatorUI { +public final class WindowsPopupMenuSeparatorUI extends BasicPopupMenuSeparatorUI { public static ComponentUI createUI(JComponent c) { return new WindowsPopupMenuSeparatorUI(); } + @Override public void paint(Graphics g, JComponent c) { Dimension s = c.getSize(); XPStyle xp = XPStyle.getXP(); @@ -82,6 +83,7 @@ public class WindowsPopupMenuSeparatorUI extends BasicPopupMenuSeparatorUI { } } + @Override public Dimension getPreferredSize(JComponent c) { int fontHeight = 0; Font font = c.getFont(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java index 3bf214aff37..4df236115fb 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java @@ -57,7 +57,7 @@ import static sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET; * * @author Igor Kushnirskiy */ -public class WindowsPopupMenuUI extends BasicPopupMenuUI { +public final class WindowsPopupMenuUI extends BasicPopupMenuUI { static MnemonicListener mnemonicListener = null; static final Object GUTTER_OFFSET_KEY = @@ -67,6 +67,7 @@ public class WindowsPopupMenuUI extends BasicPopupMenuUI { return new WindowsPopupMenuUI(); } + @Override public void installListeners() { super.installListeners(); if (! UIManager.getBoolean("Button.showMnemonics") && @@ -88,14 +89,16 @@ public class WindowsPopupMenuUI extends BasicPopupMenuUI { * @return Popup that will show the JPopupMenu * @since 1.4 */ + @Override public Popup getPopup(JPopupMenu popupMenu, int x, int y) { PopupFactory popupFactory = PopupFactory.getSharedInstance(); return popupFactory.getPopup(popupMenu.getInvoker(), popupMenu, x, y); } - static class MnemonicListener implements ChangeListener { + static final class MnemonicListener implements ChangeListener { JRootPane repaintRoot = null; + @Override public void stateChanged(ChangeEvent ev) { MenuSelectionManager msm = (MenuSelectionManager)ev.getSource(); MenuElement[] path = msm.getSelectedPath(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java index f23cb31dff0..b58ad07a57b 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsPopupWindow.java @@ -45,7 +45,7 @@ import javax.swing.JWindow; * @author Amy Fowler */ @SuppressWarnings("serial") // Superclass is not serializable across versions -class WindowsPopupWindow extends JWindow { +final class WindowsPopupWindow extends JWindow { static final int UNDEFINED_WINDOW_TYPE = 0; static final int TOOLTIP_WINDOW_TYPE = 1; @@ -69,10 +69,12 @@ class WindowsPopupWindow extends JWindow { return windowType; } + @Override public void update(Graphics g) { paint(g); } + @Override @SuppressWarnings("deprecation") public void hide() { super.hide(); @@ -85,6 +87,7 @@ class WindowsPopupWindow extends JWindow { removeNotify(); } + @Override @SuppressWarnings("deprecation") public void show() { super.show(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java index 790dc85166b..9cc7d277ff1 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java @@ -51,7 +51,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; * * @author Michael C. Albers */ -public class WindowsProgressBarUI extends BasicProgressBarUI +public final class WindowsProgressBarUI extends BasicProgressBarUI { private Rectangle previousFullBox; @@ -62,6 +62,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI } + @Override protected void installDefaults() { super.installDefaults(); @@ -80,6 +81,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI * @see javax.swing.JComponent#getBaseline(int, int) * @since 1.6 */ + @Override public int getBaseline(JComponent c, int width, int height) { int baseline = super.getBaseline(c, width, height); if (XPStyle.getXP() != null && progressBar.isStringPainted() && @@ -102,6 +104,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI return baseline; } + @Override protected Dimension getPreferredInnerHorizontal() { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -113,6 +116,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI return super.getPreferredInnerHorizontal(); } + @Override protected Dimension getPreferredInnerVertical() { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -124,6 +128,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI return super.getPreferredInnerVertical(); } + @Override protected void paintDeterminate(Graphics g, JComponent c) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -218,6 +223,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI * {@inheritDoc} * @since 1.6 */ + @Override protected void setAnimationIndex(int newValue) { super.setAnimationIndex(newValue); XPStyle xp = XPStyle.getXP(); @@ -241,6 +247,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI * {@inheritDoc} * @since 1.6 */ + @Override protected int getBoxLength(int availableLength, int otherDimension) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -253,6 +260,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI * {@inheritDoc} * @since 1.6 */ + @Override protected Rectangle getBox(Rectangle r) { Rectangle rect = super.getBox(r); @@ -298,6 +306,7 @@ public class WindowsProgressBarUI extends BasicProgressBarUI } + @Override protected void paintIndeterminate(Graphics g, JComponent c) { XPStyle xp = XPStyle.getXP(); if (xp != null) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java index 584a0f1622b..f6f3d4f06d1 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java @@ -41,11 +41,12 @@ import com.sun.java.swing.plaf.windows.TMSchema.State; /** * Windows rendition of the component. */ -public class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { +public final class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { final WindowsMenuItemUIAccessor accessor = new WindowsMenuItemUIAccessor() { + @Override public JMenuItem getMenuItem() { return menuItem; } @@ -54,6 +55,7 @@ public class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { return WindowsMenuItemUI.getState(this, menuItem); } + @Override public Part getPart(JMenuItem menuItem) { return WindowsMenuItemUI.getPart(this, menuItem); } @@ -81,6 +83,7 @@ public class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { * @param text String to render * @since 1.4 */ + @Override protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { if (WindowsMenuItemUI.isVistaPainting()) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java index dd0a93c95a1..8fdc1a315c9 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java @@ -73,6 +73,7 @@ public class WindowsRadioButtonUI extends BasicRadioButtonUI // ******************************** // Defaults // ******************************** + @Override public void installDefaults(AbstractButton b) { super.installDefaults(b); if(!initialized) { @@ -88,6 +89,7 @@ public class WindowsRadioButtonUI extends BasicRadioButtonUI } } + @Override protected void uninstallDefaults(AbstractButton b) { super.uninstallDefaults(b); initialized = false; @@ -104,11 +106,13 @@ public class WindowsRadioButtonUI extends BasicRadioButtonUI /** * Overridden method to render the text without the mnemonic */ + @Override protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { WindowsGraphicsUtils.paintText(g, b, textRect, text, getTextShiftOffset()); } + @Override protected void paintFocus(Graphics g, Rectangle textRect, Dimension d){ g.setColor(getFocusColor()); BasicGraphicsUtils.drawDashedRect(g, textRect.x, textRect.y, textRect.width, textRect.height); @@ -117,6 +121,7 @@ public class WindowsRadioButtonUI extends BasicRadioButtonUI // ******************************** // Layout Methods // ******************************** + @Override public Dimension getPreferredSize(JComponent c) { Dimension d = super.getPreferredSize(c); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java index f05da909ac1..19bfad0a1da 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java @@ -70,7 +70,7 @@ import sun.swing.MnemonicHandler; * @author Mark Davidson * @since 1.4 */ -public class WindowsRootPaneUI extends BasicRootPaneUI { +public final class WindowsRootPaneUI extends BasicRootPaneUI { private static final WindowsRootPaneUI windowsRootPaneUI = new WindowsRootPaneUI(); static final AltProcessor altProcessor = new AltProcessor(); @@ -79,7 +79,7 @@ public class WindowsRootPaneUI extends BasicRootPaneUI { return windowsRootPaneUI; } - static class AltProcessor implements KeyEventPostProcessor { + static final class AltProcessor implements KeyEventPostProcessor { static boolean altKeyPressed = false; static boolean menuCanceledOnPress = false; static JRootPane root = null; @@ -166,6 +166,7 @@ public class WindowsRootPaneUI extends BasicRootPaneUI { } + @Override public boolean postProcessKeyEvent(KeyEvent ev) { if (ev.isConsumed()) { if (ev.getKeyCode() != KeyEvent.VK_ALT) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java index a3dd04362b9..c8d62e52834 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollBarUI.java @@ -55,7 +55,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; /** * Windows rendition of the component. */ -public class WindowsScrollBarUI extends BasicScrollBarUI { +public final class WindowsScrollBarUI extends BasicScrollBarUI { private Grid thumbGrid; private Grid highlightGrid; private Dimension horizontalThumbSize; @@ -71,6 +71,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { return new WindowsScrollBarUI(); } + @Override protected void installDefaults() { super.installDefaults(); @@ -100,11 +101,13 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { : verticalThumbSize; } + @Override public void uninstallUI(JComponent c) { super.uninstallUI(c); thumbGrid = highlightGrid = null; } + @Override protected void configureScrollBarColors() { super.configureScrollBarColors(); Color color = UIManager.getColor("ScrollBar.trackForeground"); @@ -118,6 +121,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { } } + @Override protected JButton createDecreaseButton(int orientation) { return new WindowsArrowButton(orientation, UIManager.getColor("ScrollBar.thumb"), @@ -126,6 +130,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { UIManager.getColor("ScrollBar.thumbHighlight")); } + @Override protected JButton createIncreaseButton(int orientation) { return new WindowsArrowButton(orientation, UIManager.getColor("ScrollBar.thumb"), @@ -161,6 +166,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { } } + @Override protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds){ boolean v = (scrollbar.getOrientation() == JScrollBar.VERTICAL); @@ -189,6 +195,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { } } + @Override protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { boolean v = (scrollbar.getOrientation() == JScrollBar.VERTICAL); @@ -231,6 +238,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { } + @Override protected void paintDecreaseHighlight(Graphics g) { if (highlightGrid == null) { super.paintDecreaseHighlight(g); @@ -257,6 +265,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { } + @Override protected void paintIncreaseHighlight(Graphics g) { if (highlightGrid == null) { super.paintDecreaseHighlight(g); @@ -304,7 +313,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { * preferred size is always a square. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - private class WindowsArrowButton extends BasicArrowButton { + private final class WindowsArrowButton extends BasicArrowButton { public WindowsArrowButton(int direction, Color background, Color shadow, Color darkShadow, Color highlight) { @@ -315,6 +324,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { super(direction); } + @Override public void paint(Graphics g) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -370,6 +380,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { } } + @Override public Dimension getPreferredSize() { int size = 16; if (scrollbar != null) { @@ -398,7 +409,7 @@ public class WindowsScrollBarUI extends BasicScrollBarUI { * a WeakRef so that it can be freed when no longer needed. As the * Grid is rather expensive to draw, it is drawn in a BufferedImage. */ - private static class Grid { + private static final class Grid { private static final int BUFFER_SIZE = 64; private static HashMap> map; diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java index 6c89eabc894..393f7595402 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsScrollPaneUI.java @@ -30,5 +30,5 @@ import javax.swing.plaf.basic.BasicScrollPaneUI; /** * Windows rendition of the component. */ -public class WindowsScrollPaneUI extends BasicScrollPaneUI +public final class WindowsScrollPaneUI extends BasicScrollPaneUI {} diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java index 65526a40c1b..9ce5db3b4ef 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java @@ -30,4 +30,4 @@ import javax.swing.plaf.basic.*; /** * Windows Separator. */ -public class WindowsSeparatorUI extends BasicSeparatorUI { } +public final class WindowsSeparatorUI extends BasicSeparatorUI { } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java index ceaf878cbca..88dc91d572b 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java @@ -44,7 +44,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; /** * Windows rendition of the component. */ -public class WindowsSliderUI extends BasicSliderUI +public final class WindowsSliderUI extends BasicSliderUI { private boolean rollover = false; private boolean pressed = false; @@ -63,32 +63,38 @@ public class WindowsSliderUI extends BasicSliderUI * the HOT, PRESSED, and FOCUSED states. * @since 1.6 */ + @Override protected TrackListener createTrackListener(JSlider slider) { return new WindowsTrackListener(); } - private class WindowsTrackListener extends TrackListener { + private final class WindowsTrackListener extends TrackListener { + @Override public void mouseMoved(MouseEvent e) { updateRollover(thumbRect.contains(e.getX(), e.getY())); super.mouseMoved(e); } + @Override public void mouseEntered(MouseEvent e) { updateRollover(thumbRect.contains(e.getX(), e.getY())); super.mouseEntered(e); } + @Override public void mouseExited(MouseEvent e) { updateRollover(false); super.mouseExited(e); } + @Override public void mousePressed(MouseEvent e) { updatePressed(thumbRect.contains(e.getX(), e.getY())); super.mousePressed(e); } + @Override public void mouseReleased(MouseEvent e) { updatePressed(false); super.mouseReleased(e); @@ -119,6 +125,7 @@ public class WindowsSliderUI extends BasicSliderUI } + @Override public void paintTrack(Graphics g) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -141,6 +148,7 @@ public class WindowsSliderUI extends BasicSliderUI } + @Override protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -149,6 +157,7 @@ public class WindowsSliderUI extends BasicSliderUI super.paintMinorTickForHorizSlider(g, tickBounds, x); } + @Override protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -157,6 +166,7 @@ public class WindowsSliderUI extends BasicSliderUI super.paintMajorTickForHorizSlider(g, tickBounds, x); } + @Override protected void paintMinorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -165,6 +175,7 @@ public class WindowsSliderUI extends BasicSliderUI super.paintMinorTickForVertSlider(g, tickBounds, y); } + @Override protected void paintMajorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -174,6 +185,7 @@ public class WindowsSliderUI extends BasicSliderUI } + @Override public void paintThumb(Graphics g) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -199,6 +211,7 @@ public class WindowsSliderUI extends BasicSliderUI } } + @Override protected Dimension getThumbSize() { XPStyle xp = XPStyle.getXP(); if (xp != null) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java index c17328e50cc..bad66ce3a04 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java @@ -37,7 +37,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.State; import static com.sun.java.swing.plaf.windows.XPStyle.Skin; -public class WindowsSpinnerUI extends BasicSpinnerUI { +public final class WindowsSpinnerUI extends BasicSpinnerUI { public static ComponentUI createUI(JComponent c) { return new WindowsSpinnerUI(); } @@ -46,6 +46,7 @@ public class WindowsSpinnerUI extends BasicSpinnerUI { * {@inheritDoc} * @since 1.6 */ + @Override public void paint(Graphics g, JComponent c) { if (XPStyle.getXP() != null) { paintXPBackground(g, c); @@ -71,6 +72,7 @@ public class WindowsSpinnerUI extends BasicSpinnerUI { skin.paintSkin(g, 0, 0, c.getWidth(), c.getHeight(), state); } + @Override protected Component createPreviousButton() { if (XPStyle.getXP() != null) { JButton xpButton = new XPStyle.GlyphButton(spinner, Part.SPNP_DOWN); @@ -83,6 +85,7 @@ public class WindowsSpinnerUI extends BasicSpinnerUI { return super.createPreviousButton(); } + @Override protected Component createNextButton() { if (XPStyle.getXP() != null) { JButton xpButton = new XPStyle.GlyphButton(spinner, Part.SPNP_UP); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java index 04eeb726f90..95062ef586f 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneDivider.java @@ -39,7 +39,7 @@ import javax.swing.plaf.basic.BasicSplitPaneUI; * @author Jeff Dinkins */ @SuppressWarnings("serial") // Superclass is not serializable across versions -public class WindowsSplitPaneDivider extends BasicSplitPaneDivider +public final class WindowsSplitPaneDivider extends BasicSplitPaneDivider { /** @@ -52,6 +52,7 @@ public class WindowsSplitPaneDivider extends BasicSplitPaneDivider /** * Paints the divider. */ + @Override public void paint(Graphics g) { Color bgColor = (splitPane.hasFocus()) ? UIManager.getColor("SplitPane.shadow") : diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java index 9305e46c36f..8c50e391164 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsSplitPaneUI.java @@ -33,7 +33,7 @@ import javax.swing.plaf.basic.BasicSplitPaneUI; /** * Windows rendition of the component. */ -public class WindowsSplitPaneUI extends BasicSplitPaneUI +public final class WindowsSplitPaneUI extends BasicSplitPaneUI { public WindowsSplitPaneUI() { @@ -50,6 +50,7 @@ public class WindowsSplitPaneUI extends BasicSplitPaneUI /** * Creates the default divider. */ + @Override public BasicSplitPaneDivider createDefaultDivider() { return new WindowsSplitPaneDivider(this); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java index 9b4e22102eb..86e2ee1fc52 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTabbedPaneUI.java @@ -48,7 +48,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; /** * Windows rendition of the component. */ -public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { +public final class WindowsTabbedPaneUI extends BasicTabbedPaneUI { /** * Keys to use for forward focus traversal when the JComponent is * managing focus. @@ -63,6 +63,7 @@ public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { private boolean contentOpaque = true; + @Override @SuppressWarnings("deprecation") protected void installDefaults() { super.installDefaults(); @@ -82,6 +83,7 @@ public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { tabPane.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, managingFocusBackwardTraversalKeys); } + @Override protected void uninstallDefaults() { // sets the focus forward and backward traversal keys to null // to restore the defaults @@ -94,6 +96,7 @@ public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { return new WindowsTabbedPaneUI(); } + @Override protected void setRolloverTab(int index) { // Rollover is only supported on XP if (XPStyle.getXP() != null) { @@ -119,6 +122,7 @@ public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { } } + @Override protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) { XPStyle xp = XPStyle.getXP(); if (xp != null && (contentOpaque || tabPane.isOpaque())) { @@ -155,6 +159,7 @@ public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { super.paintContentBorder(g, tabPlacement, selectedIndex); } + @Override protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected ) { if (XPStyle.getXP() == null) { @@ -162,6 +167,7 @@ public class WindowsTabbedPaneUI extends BasicTabbedPaneUI { } } + @Override protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected ) { XPStyle xp = XPStyle.getXP(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java index 507990812cc..b670bd294b0 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java @@ -50,13 +50,14 @@ import static com.sun.java.swing.plaf.windows.TMSchema.Part; import static com.sun.java.swing.plaf.windows.TMSchema.State; import static com.sun.java.swing.plaf.windows.XPStyle.Skin; -public class WindowsTableHeaderUI extends BasicTableHeaderUI { +public final class WindowsTableHeaderUI extends BasicTableHeaderUI { private TableCellRenderer originalHeaderRenderer; public static ComponentUI createUI(JComponent h) { return new WindowsTableHeaderUI(); } + @Override public void installUI(JComponent c) { super.installUI(c); @@ -68,6 +69,7 @@ public class WindowsTableHeaderUI extends BasicTableHeaderUI { } } + @Override public void uninstallUI(JComponent c) { if (header.getDefaultRenderer() instanceof XPDefaultRenderer) { header.setDefaultRenderer(originalHeaderRenderer); @@ -84,7 +86,7 @@ public class WindowsTableHeaderUI extends BasicTableHeaderUI { } @SuppressWarnings("serial") // JDK-implementation class - private class XPDefaultRenderer extends DefaultTableCellHeaderRenderer { + private final class XPDefaultRenderer extends DefaultTableCellHeaderRenderer { Skin skin; boolean isSelected, hasFocus, hasRollover; int column; @@ -93,6 +95,7 @@ public class WindowsTableHeaderUI extends BasicTableHeaderUI { setHorizontalAlignment(LEADING); } + @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { @@ -181,6 +184,7 @@ public class WindowsTableHeaderUI extends BasicTableHeaderUI { return this; } + @Override public void paint(Graphics g) { Dimension size = getSize(); State state = State.NORMAL; @@ -227,7 +231,7 @@ public class WindowsTableHeaderUI extends BasicTableHeaderUI { * A border with an Icon at the middle of the top side. * Outer insets can be provided for this border. */ - private static class IconBorder implements Border, UIResource{ + private static final class IconBorder implements Border, UIResource{ private final Icon icon; private final int top; private final int left; @@ -246,12 +250,15 @@ public class WindowsTableHeaderUI extends BasicTableHeaderUI { this.bottom = bottom; this.right = right; } + @Override public Insets getBorderInsets(Component c) { return new Insets(icon.getIconHeight() + top, left, bottom, right); } + @Override public boolean isBorderOpaque() { return false; } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { icon.paintIcon(c, g, diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java index 6aca81225ea..e695d9f6708 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextAreaUI.java @@ -33,7 +33,7 @@ import javax.swing.text.Caret; /** * Windows rendition of the component. */ -public class WindowsTextAreaUI extends BasicTextAreaUI { +public final class WindowsTextAreaUI extends BasicTextAreaUI { /** * Creates the object to use for a caret. By default an * instance of WindowsCaret is created. This method @@ -42,6 +42,7 @@ public class WindowsTextAreaUI extends BasicTextAreaUI { * * @return the caret object */ + @Override protected Caret createCaret() { return new WindowsTextUI.WindowsCaret(); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java index be3e6276161..508d260895c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextFieldUI.java @@ -62,7 +62,7 @@ import javax.swing.text.Position; * * @author Timothy Prinzing */ -public class WindowsTextFieldUI extends BasicTextFieldUI +public final class WindowsTextFieldUI extends BasicTextFieldUI { /** * Creates a UI for a JTextField. @@ -82,6 +82,7 @@ public class WindowsTextFieldUI extends BasicTextFieldUI * * @param g the graphics context */ + @Override protected void paintBackground(Graphics g) { super.paintBackground(g); } @@ -91,6 +92,7 @@ public class WindowsTextFieldUI extends BasicTextFieldUI * * @return the caret */ + @Override protected Caret createCaret() { return new WindowsFieldCaret(); } @@ -100,7 +102,7 @@ public class WindowsTextFieldUI extends BasicTextFieldUI * DefaultCaret. */ @SuppressWarnings("serial") // Superclass is not serializable across versions - static class WindowsFieldCaret extends DefaultCaret implements UIResource { + static final class WindowsFieldCaret extends DefaultCaret implements UIResource { public WindowsFieldCaret() { super(); @@ -112,6 +114,7 @@ public class WindowsTextFieldUI extends BasicTextFieldUI * caret out into the field by about a quarter of * a field length if not visible. */ + @Override protected void adjustVisibility(Rectangle r) { SwingUtilities.invokeLater(new SafeScroller(r)); } @@ -121,16 +124,18 @@ public class WindowsTextFieldUI extends BasicTextFieldUI * * @return the painter */ + @Override protected Highlighter.HighlightPainter getSelectionPainter() { return WindowsTextUI.WindowsPainter; } - private class SafeScroller implements Runnable { + private final class SafeScroller implements Runnable { SafeScroller(Rectangle r) { this.r = r; } + @Override @SuppressWarnings("deprecation") public void run() { JTextField field = (JTextField) getComponent(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java index 372563f74f4..7858a1195e8 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextPaneUI.java @@ -33,7 +33,7 @@ import javax.swing.text.Caret; /** * Windows rendition of the component. */ -public class WindowsTextPaneUI extends BasicTextPaneUI +public final class WindowsTextPaneUI extends BasicTextPaneUI { /** * Creates a UI for a JTextPane. @@ -53,6 +53,7 @@ public class WindowsTextPaneUI extends BasicTextPaneUI * * @return the caret object */ + @Override protected Caret createCaret() { return new WindowsTextUI.WindowsCaret(); } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextUI.java index b73b38385f2..89180ffdd5f 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTextUI.java @@ -55,6 +55,7 @@ public abstract class WindowsTextUI extends BasicTextUI { * * @return the caret object */ + @Override protected Caret createCaret() { return new WindowsCaret(); } @@ -64,20 +65,21 @@ public abstract class WindowsTextUI extends BasicTextUI { /* public */ @SuppressWarnings("serial") // Superclass is not serializable across versions - static class WindowsCaret extends DefaultCaret + static final class WindowsCaret extends DefaultCaret implements UIResource { /** * Gets the painter for the Highlighter. * * @return the painter */ + @Override protected Highlighter.HighlightPainter getSelectionPainter() { return WindowsTextUI.WindowsPainter; } } /* public */ - static class WindowsHighlightPainter extends + static final class WindowsHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter { WindowsHighlightPainter(Color c) { super(c); @@ -94,6 +96,7 @@ public abstract class WindowsTextUI extends BasicTextUI { * @param bounds the bounding box for the highlight * @param c the editor */ + @Override @SuppressWarnings("deprecation") public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) { Rectangle alloc = bounds.getBounds(); @@ -167,6 +170,7 @@ public abstract class WindowsTextUI extends BasicTextUI { * @param view View painting for * @return region drawing occurred in */ + @Override public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c, View view) { Color color = getColor(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java index feee0c0aaef..0f468fdf6b1 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java @@ -45,7 +45,7 @@ import sun.awt.AppContext; * * @author Jeff Dinkins */ -public class WindowsToggleButtonUI extends BasicToggleButtonUI +public final class WindowsToggleButtonUI extends BasicToggleButtonUI { protected int dashedRectGapX; protected int dashedRectGapY; @@ -73,6 +73,7 @@ public class WindowsToggleButtonUI extends BasicToggleButtonUI // ******************************** // Defaults // ******************************** + @Override protected void installDefaults(AbstractButton b) { super.installDefaults(b); if(!defaults_initialized) { @@ -93,6 +94,7 @@ public class WindowsToggleButtonUI extends BasicToggleButtonUI } } + @Override protected void uninstallDefaults(AbstractButton b) { super.uninstallDefaults(b); defaults_initialized = false; @@ -112,6 +114,7 @@ public class WindowsToggleButtonUI extends BasicToggleButtonUI private transient Color cachedBackgroundColor = null; private transient Color cachedHighlightColor = null; + @Override protected void paintButtonPressed(Graphics g, AbstractButton b) { if (XPStyle.getXP() == null && b.isContentAreaFilled()) { Color oldColor = g.getColor(); @@ -135,6 +138,7 @@ public class WindowsToggleButtonUI extends BasicToggleButtonUI } } + @Override public void paint(Graphics g, JComponent c) { if (XPStyle.getXP() != null) { WindowsButtonUI.paintXPButtonBackground(g, c); @@ -146,10 +150,12 @@ public class WindowsToggleButtonUI extends BasicToggleButtonUI /** * Overridden method to render the text without the mnemonic */ + @Override protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) { WindowsGraphicsUtils.paintText(g, b, textRect, text, getTextShiftOffset()); } + @Override protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { g.setColor(getFocusColor()); @@ -161,6 +167,7 @@ public class WindowsToggleButtonUI extends BasicToggleButtonUI // ******************************** // Layout Methods // ******************************** + @Override public Dimension getPreferredSize(JComponent c) { Dimension d = super.getPreferredSize(c); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java index ffd6daa3ad8..5350de9ae5c 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java @@ -40,12 +40,13 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; * * @author Mark Davidson */ -public class WindowsToolBarSeparatorUI extends BasicToolBarSeparatorUI { +public final class WindowsToolBarSeparatorUI extends BasicToolBarSeparatorUI { public static ComponentUI createUI( JComponent c ) { return new WindowsToolBarSeparatorUI(); } + @Override public Dimension getPreferredSize(JComponent c) { Dimension size = ((JToolBar.Separator)c).getSeparatorSize(); @@ -71,6 +72,7 @@ public class WindowsToolBarSeparatorUI extends BasicToolBarSeparatorUI { return size; } + @Override public Dimension getMaximumSize(JComponent c) { Dimension pref = getPreferredSize(c); if (((JSeparator)c).getOrientation() == SwingConstants.VERTICAL) { @@ -80,6 +82,7 @@ public class WindowsToolBarSeparatorUI extends BasicToolBarSeparatorUI { } } + @Override public void paint( Graphics g, JComponent c ) { boolean vertical = ((JSeparator)c).getOrientation() == SwingConstants.VERTICAL; Dimension size = c.getSize(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java index a34ce0cf6a5..68e077fa350 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsToolBarUI.java @@ -45,12 +45,13 @@ import javax.swing.plaf.basic.BasicToolBarUI; import static com.sun.java.swing.plaf.windows.TMSchema.Part; -public class WindowsToolBarUI extends BasicToolBarUI { +public final class WindowsToolBarUI extends BasicToolBarUI { public static ComponentUI createUI(JComponent c) { return new WindowsToolBarUI(); } + @Override protected void installDefaults() { if (XPStyle.getXP() != null) { setRolloverBorders(true); @@ -58,6 +59,7 @@ public class WindowsToolBarUI extends BasicToolBarUI { super.installDefaults(); } + @Override protected Border createRolloverBorder() { if (XPStyle.getXP() != null) { return new EmptyBorder(3, 3, 3, 3); @@ -66,6 +68,7 @@ public class WindowsToolBarUI extends BasicToolBarUI { } } + @Override protected Border createNonRolloverBorder() { if (XPStyle.getXP() != null) { return new EmptyBorder(3, 3, 3, 3); @@ -74,6 +77,7 @@ public class WindowsToolBarUI extends BasicToolBarUI { } } + @Override public void paint(Graphics g, JComponent c) { XPStyle xp = XPStyle.getXP(); if (xp != null) { @@ -88,6 +92,7 @@ public class WindowsToolBarUI extends BasicToolBarUI { * {@inheritDoc} * @since 1.6 */ + @Override protected Border getRolloverBorder(AbstractButton b) { XPStyle xp = XPStyle.getXP(); if (xp != null) { diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java index 5bef0e075a4..6ab2352641f 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsTreeUI.java @@ -60,6 +60,7 @@ public class WindowsTreeUI extends BasicTreeUI { * Ensures that the rows identified by beginRow through endRow are * visible. */ + @Override protected void ensureRowsAreVisible(int beginRow, int endRow) { if(tree != null && beginRow >= 0 && endRow < getRowCount(tree)) { Rectangle visRect = tree.getVisibleRect(); @@ -108,6 +109,7 @@ public class WindowsTreeUI extends BasicTreeUI { * Returns the default cell renderer that is used to do the * stamping of each node. */ + @Override protected TreeCellRenderer createDefaultCellRenderer() { return new WindowsTreeCellRenderer(); } @@ -127,6 +129,7 @@ public class WindowsTreeUI extends BasicTreeUI { return (xp != null) ? xp.getSkin(c, Part.TVP_GLYPH) : null; } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { Skin skin = getSkin(c); if (skin != null) { @@ -147,11 +150,13 @@ public class WindowsTreeUI extends BasicTreeUI { g.drawLine(x + 2, y + HALF_SIZE, x + (SIZE - 3), y + HALF_SIZE); } + @Override public int getIconWidth() { Skin skin = getSkin(null); return (skin != null) ? skin.getWidth() : SIZE; } + @Override public int getIconHeight() { Skin skin = getSkin(null); return (skin != null) ? skin.getHeight() : SIZE; @@ -162,11 +167,12 @@ public class WindowsTreeUI extends BasicTreeUI { * The plus sign button icon */ @SuppressWarnings("serial") // Superclass is not serializable across versions - public static class CollapsedIcon extends ExpandedIcon { + public static final class CollapsedIcon extends ExpandedIcon { public static Icon createCollapsedIcon() { return new CollapsedIcon(); } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { Skin skin = getSkin(c); if (skin != null) { @@ -179,7 +185,7 @@ public class WindowsTreeUI extends BasicTreeUI { } @SuppressWarnings("serial") // Superclass is not serializable across versions - public class WindowsTreeCellRenderer extends DefaultTreeCellRenderer { + public final class WindowsTreeCellRenderer extends DefaultTreeCellRenderer { /** * Configures the renderer based on the passed in components. @@ -189,6 +195,7 @@ public class WindowsTreeUI extends BasicTreeUI { * The foreground color is set based on the selection and the icon * is set based on on leaf and expanded. */ + @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java index f8f5e3628fb..89751f6dc94 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java @@ -90,7 +90,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.TypeEnum; * * @author Leif Samuelsson */ -class XPStyle { +final class XPStyle { // Singleton instance of this class private static XPStyle xp; @@ -331,6 +331,7 @@ class XPStyle { super(color, thickness); } + @Override public Insets getBorderInsets(Component c, Insets insets) { Insets margin = null; // @@ -355,7 +356,7 @@ class XPStyle { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private class XPStatefulFillBorder extends XPFillBorder { + private final class XPStatefulFillBorder extends XPFillBorder { private final Part part; private final Prop prop; XPStatefulFillBorder(Color color, int thickness, Part part, Prop prop) { @@ -364,6 +365,7 @@ class XPStyle { this.prop = prop; } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { State state = State.NORMAL; // special casing for comboboxes. @@ -383,18 +385,20 @@ class XPStyle { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private class XPImageBorder extends AbstractBorder implements UIResource { + private final class XPImageBorder extends AbstractBorder implements UIResource { Skin skin; XPImageBorder(Component c, Part part) { this.skin = getSkin(c, part); } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { skin.paintSkin(g, x, y, width, height, null); } + @Override public Insets getBorderInsets(Component c, Insets insets) { Insets margin = null; Insets borderInsets = skin.getContentMargin(); @@ -423,11 +427,12 @@ class XPStyle { } @SuppressWarnings("serial") // Superclass is not serializable across versions - private static class XPEmptyBorder extends EmptyBorder implements UIResource { + private static final class XPEmptyBorder extends EmptyBorder implements UIResource { XPEmptyBorder(Insets m) { super(m.top+2, m.left+2, m.bottom+2, m.right+2); } + @Override public Insets getBorderInsets(Component c, Insets insets) { insets = super.getBorderInsets(c, insets); @@ -494,7 +499,7 @@ class XPStyle { * (component type) and which provides methods for painting backgrounds * and glyphs */ - static class Skin { + static final class Skin { final Component component; final Part part; final State state; @@ -566,14 +571,17 @@ class XPStyle { return getHeight((state != null) ? state : State.NORMAL); } + @Override public String toString() { return string; } + @Override public boolean equals(Object obj) { return (obj instanceof Skin && ((Skin)obj).string.equals(string)); } + @Override public int hashCode() { return string.hashCode(); } @@ -675,16 +683,18 @@ class XPStyle { } } - private static class SkinPainter extends CachedPainter { + private static final class SkinPainter extends CachedPainter { SkinPainter() { super(30); flush(); } + @Override public void flush() { super.flush(); } + @Override protected void paintToImage(Component c, Image image, Graphics g, int w, int h, Object[] args) { Skin skin = (Skin)args[0]; @@ -717,6 +727,7 @@ class XPStyle { SunWritableRaster.markDirty(dbi); } + @Override protected Image createImage(Component c, int w, int h, GraphicsConfiguration config, Object[] args) { return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); @@ -737,6 +748,7 @@ class XPStyle { setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); } + @Override @SuppressWarnings("deprecation") public boolean isFocusTraversable() { return false; @@ -754,6 +766,7 @@ class XPStyle { return state; } + @Override public void paintComponent(Graphics g) { if (XPStyle.getXP() == null || skin == null) { return; @@ -769,6 +782,7 @@ class XPStyle { repaint(); } + @Override protected void paintBorder(Graphics g) { } diff --git a/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java b/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java index 642f98b0df2..c888106d779 100644 --- a/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java +++ b/src/java.desktop/windows/classes/sun/awt/PlatformGraphicsInfo.java @@ -30,7 +30,7 @@ import java.awt.Toolkit; import sun.awt.windows.WToolkit; -public class PlatformGraphicsInfo { +public final class PlatformGraphicsInfo { private static final boolean hasDisplays; diff --git a/src/java.desktop/windows/classes/sun/awt/Win32ColorModel24.java b/src/java.desktop/windows/classes/sun/awt/Win32ColorModel24.java index ec86bce8c69..fe55cacf833 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32ColorModel24.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32ColorModel24.java @@ -40,7 +40,7 @@ import java.awt.Transparency; * in the reverse order from the base ComponentColorModel to match * the ordering on a Windows 24-bit display. */ -public class Win32ColorModel24 extends ComponentColorModel { +public final class Win32ColorModel24 extends ComponentColorModel { public Win32ColorModel24() { super(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8, 8, 8}, false, false, @@ -53,6 +53,7 @@ public class Win32ColorModel24 extends ComponentColorModel { * @see WritableRaster * @see SampleModel */ + @Override public WritableRaster createCompatibleWritableRaster (int w, int h) { int[] bOffs = {2, 1, 0}; return Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, @@ -65,6 +66,7 @@ public class Win32ColorModel24 extends ComponentColorModel { * has a data layout compatible with this ColorModel. * @see SampleModel */ + @Override public SampleModel createCompatibleSampleModel(int w, int h) { int[] bOffs = {2, 1, 0}; return new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, diff --git a/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java b/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java index c2532ff38b3..5084d0bcabe 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java @@ -70,6 +70,7 @@ public final class Win32FontManager extends SunFontManager { */ private static native String getEUDCFontFile(); + @Override public TrueTypeFont getEUDCFont() { return eudcFont; } @@ -88,6 +89,7 @@ public final class Win32FontManager extends SunFontManager { * Whether registerFontFile expects absolute or relative * font file names. */ + @Override protected boolean useAbsoluteFontFileNames() { return false; } @@ -98,6 +100,7 @@ public final class Win32FontManager extends SunFontManager { * class reports these back to the GraphicsEnvironment, so these * are the componentFileNames of CompositeFonts. */ + @Override protected void registerFontFile(String fontFileName, String[] nativeNames, int fontRank, boolean defer) { @@ -175,6 +178,7 @@ public final class Win32FontManager extends SunFontManager { preferLocaleFonts,preferPropFonts); } + @Override protected void populateFontFileNameMap(HashMap fontToFileMap, HashMap fontToFamilyNameMap, @@ -194,6 +198,7 @@ public final class Win32FontManager extends SunFontManager { familyToFontListMap, Locale locale); + @Override protected synchronized native String getFontPath(boolean noType1Fonts); @Override diff --git a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java index 6e740de6a9b..31fc0847d3b 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java @@ -214,6 +214,7 @@ public class Win32GraphicsConfig extends GraphicsConfiguration return new AffineTransform(xscale, 0.0, 0.0, yscale, 0.0, 0.0); } + @Override public String toString() { return (super.toString()+"[dev="+device+",pixfmt="+visual+"]"); } diff --git a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java index 973eb916a5c..865fe480853 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java @@ -590,7 +590,7 @@ public class Win32GraphicsDevice extends GraphicsDevice implements * The listener restores the default display mode when window is iconified * and sets it back to the one set by the user on de-iconification. */ - private static class Win32FSWindowAdapter extends WindowAdapter { + private static final class Win32FSWindowAdapter extends WindowAdapter { private Win32GraphicsDevice device; private DisplayMode dm; diff --git a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java index cb7ab363cdf..09768148f3d 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsEnvironment.java @@ -92,9 +92,11 @@ public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment { public Win32GraphicsEnvironment() { } + @Override protected native int getNumScreens(); private native int getDefaultScreen(); + @Override public GraphicsDevice getDefaultScreenDevice() { GraphicsDevice[] screens = getScreenDevices(); if (screens.length == 0) { @@ -207,6 +209,7 @@ public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment { * ----END DISPLAY CHANGE SUPPORT---- */ + @Override protected GraphicsDevice makeScreenDevice(int screennum) { GraphicsDevice device = null; if (WindowsFlags.isD3DEnabled()) { @@ -218,6 +221,7 @@ public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment { return device; } + @Override public boolean isDisplayLocal() { return true; } diff --git a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java index c85c2d4ced9..1777e408ea6 100644 --- a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -212,7 +212,7 @@ final class Win32ShellFolder2 extends ShellFolder { static final List INSTANCE = getLibraries(); } - static class FolderDisposer implements sun.java2d.DisposerRecord { + static final class FolderDisposer implements sun.java2d.DisposerRecord { /* * This is cached as a concession to getFolderType(), which needs * an absolute PIDL. @@ -226,6 +226,7 @@ final class Win32ShellFolder2 extends ShellFolder { long relativePIDL; boolean disposed; + @Override public void dispose() { if (disposed) return; invoke(new Callable() { @@ -387,6 +388,7 @@ final class Win32ShellFolder2 extends ShellFolder { * is a not a normal directory, then returns the first non-removable * drive (normally "C:\"). */ + @Override @Serial protected Object writeReplace() throws java.io.ObjectStreamException { return invoke(new Callable() { @@ -541,6 +543,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * Check to see if two ShellFolder objects are the same */ + @Override public boolean equals(Object o) { if (!(o instanceof Win32ShellFolder2 rhs)) { // Short-circuit circuitous delegation path @@ -588,6 +591,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return Whether this is a file system shell folder */ + @Override public boolean isFileSystem() { if (cachedIsFileSystem == null) { cachedIsFileSystem = hasAttribute(ATTRIB_FILESYSTEM); @@ -682,10 +686,12 @@ final class Win32ShellFolder2 extends ShellFolder { * @return The parent shell folder of this shell folder, null if * there is no parent */ + @Override public File getParentFile() { return parent; } + @Override public boolean isDirectory() { if (isDir == null) { // Folders with SFGAO_BROWSABLE have "shell extension" handlers and are @@ -742,6 +748,7 @@ final class Win32ShellFolder2 extends ShellFolder { * object. The array will be empty if the folder is empty. Returns * {@code null} if this shellfolder does not denote a directory. */ + @Override public File[] listFiles(final boolean includeHiddenFiles) { try { @@ -851,6 +858,7 @@ final class Win32ShellFolder2 extends ShellFolder { * symbolic links and junctions. */ + @Override public boolean isLink() { if (cachedIsLink == null) { cachedIsLink = hasAttribute(ATTRIB_LINK) @@ -864,6 +872,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return Whether this shell folder is marked as hidden */ + @Override public boolean isHidden() { return hasAttribute(ATTRIB_HIDDEN); } @@ -878,6 +887,7 @@ final class Win32ShellFolder2 extends ShellFolder { * @return The shell folder linked to by this shell folder, or null * if this shell folder is not a link or is a broken or invalid link */ + @Override public ShellFolder getLinkLocation() { return getLinkLocation(true); } @@ -933,6 +943,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return The name used to display this shell folder */ + @Override public String getDisplayName() { if (displayName == null) { displayName = @@ -953,6 +964,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return The type of shell folder as a string */ + @Override public String getFolderType() { if (folderType == null) { final long absolutePIDL = getAbsolutePIDL(); @@ -972,6 +984,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return The executable type as a string */ + @Override public String getExecutableType() { if (!isFileSystem()) { return null; @@ -1047,6 +1060,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return The icon image used to display this shell folder */ + @Override public Image getIcon(final boolean getLargeIcon) { Image icon = getLargeIcon ? largeIcon : smallIcon; int size = getLargeIcon ? LARGE_ICON_SIZE : SMALL_ICON_SIZE; @@ -1140,6 +1154,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return The icon image of specified size used to display this shell folder */ + @Override public Image getIcon(int width, int height) { int size = Math.max(width, height); return invoke(() -> { @@ -1236,6 +1251,7 @@ final class Win32ShellFolder2 extends ShellFolder { * * @see java.io.File#getCanonicalFile */ + @Override public File getCanonicalFile() throws IOException { return this; } @@ -1252,6 +1268,7 @@ final class Win32ShellFolder2 extends ShellFolder { * * @see sun.awt.shell.ShellFolder#compareTo(File) */ + @Override public int compareTo(File file2) { if (!(file2 instanceof Win32ShellFolder2)) { if (isFileSystem() && !isSpecial()) { @@ -1268,6 +1285,7 @@ final class Win32ShellFolder2 extends ShellFolder { private static final int LVCFMT_RIGHT = 1; private static final int LVCFMT_CENTER = 2; + @Override public ShellFolderColumnInfo[] getFolderColumns() { ShellFolder library = resolveLibrary(); if (library != null) return library.getFolderColumns(); @@ -1300,6 +1318,7 @@ final class Win32ShellFolder2 extends ShellFolder { }); } + @Override public Object getFolderColumnValue(final int column) { if(!isLibrary()) { ShellFolder library = resolveLibrary(); @@ -1342,6 +1361,7 @@ final class Win32ShellFolder2 extends ShellFolder { private static native int compareIDsByColumn(long pParentIShellFolder, long pidl1, long pidl2, int columnIdx); + @Override public void sortChildren(final List files) { // To avoid loads of synchronizations with Invoker and improve performance we // synchronize the whole code of the sort method once @@ -1354,7 +1374,7 @@ final class Win32ShellFolder2 extends ShellFolder { }); } - private static class ColumnComparator implements Comparator { + private static final class ColumnComparator implements Comparator { private final Win32ShellFolder2 shellFolder; private final int columnIdx; @@ -1365,6 +1385,7 @@ final class Win32ShellFolder2 extends ShellFolder { } // compares 2 objects within this folder by the specified column + @Override public int compare(final File o, final File o1) { Integer result = invoke(new Callable() { public Integer call() { @@ -1405,7 +1426,7 @@ final class Win32ShellFolder2 extends ShellFolder { }); } - static class MultiResolutionIconImage extends AbstractMultiResolutionImage { + static final class MultiResolutionIconImage extends AbstractMultiResolutionImage { final int baseSize; final Map resolutionVariants = new HashMap<>(); diff --git a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index d8bb2146798..075e3d0db50 100644 --- a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -75,6 +75,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { sun.awt.windows.WToolkit.loadLibraries(); } + @Override public ShellFolder createShellFolder(File file) throws FileNotFoundException { try { return createShellFolder(getDesktop(), file); @@ -264,6 +265,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { * * @return An Object matching the key string. */ + @Override public Object get(String key) { if (key.equals("fileChooserDefaultFolder")) { File file = getPersonal(); @@ -408,6 +410,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { * Does {@code dir} represent a "computer" such as a node on the network, or * "My Computer" on the desktop. */ + @Override public boolean isComputerNode(final File dir) { if (dir != null && dir == getDrives()) { return true; @@ -418,6 +421,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { } } + @Override public boolean isFileSystemRoot(File dir) { //Note: Removable drives don't "exist" but are listed in "My Computer" if (dir != null) { @@ -498,7 +502,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { return new ComInvoker(); } - private static class ComInvoker extends ThreadPoolExecutor implements ThreadFactory, ShellFolder.Invoker { + private static final class ComInvoker extends ThreadPoolExecutor implements ThreadFactory, ShellFolder.Invoker { private static Thread comThread; private ComInvoker() { @@ -512,6 +516,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { Runtime.getRuntime().addShutdownHook(t); } + @Override public synchronized Thread newThread(final Runnable task) { final Runnable comRun = new Runnable() { public void run() { @@ -539,6 +544,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { return comThread; } + @Override public T invoke(Callable task) throws Exception { if (Thread.currentThread() == comThread) { // if it's already called from the COM diff --git a/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java b/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java index 6b9d54aaa28..94a2c4df0a9 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java @@ -355,7 +355,7 @@ abstract class TranslucentWindowPainter { } } - private static class VIOptD3DWindowPainter extends VIOptWindowPainter { + private static final class VIOptD3DWindowPainter extends VIOptWindowPainter { protected VIOptD3DWindowPainter(WWindowPeer peer) { super(peer); @@ -370,7 +370,7 @@ abstract class TranslucentWindowPainter { } } - private static class VIOptWGLWindowPainter extends VIOptWindowPainter { + private static final class VIOptWGLWindowPainter extends VIOptWindowPainter { protected VIOptWGLWindowPainter(WWindowPeer peer) { super(peer); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java index c07d116abfb..8b3218de667 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java @@ -789,6 +789,7 @@ public abstract class WComponentPeer extends WObjectPeer // Object overrides + @Override public String toString() { return getClass().getName() + "[" + target + "]"; } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java b/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java index 8aca12d268f..068d577995f 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDataTransferer.java @@ -541,7 +541,7 @@ enum EHTMLReadMode { * * on encode: static convertToHTMLFormat is responsible for HTML clipboard header creation */ -class HTMLCodec extends InputStream { +final class HTMLCodec extends InputStream { public static final String VERSION = "Version:"; public static final String START_HTML = "StartHTML:"; diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDefaultFontCharset.java b/src/java.desktop/windows/classes/sun/awt/windows/WDefaultFontCharset.java index 7632e172b73..09c317c81f2 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WDefaultFontCharset.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDefaultFontCharset.java @@ -46,7 +46,7 @@ final class WDefaultFontCharset extends AWTCharset return new Encoder(); } - private class Encoder extends AWTCharset.Encoder { + private final class Encoder extends AWTCharset.Encoder { @Override public boolean canEncode(char c){ return canConvert(c); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java b/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java index d9b169160b4..6e3de090ee8 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDesktopProperties.java @@ -198,7 +198,7 @@ final class WDesktopProperties { */ private native void playWindowsSound(String winEventName); - class WinPlaySound implements Runnable { + final class WinPlaySound implements Runnable { String winEventName; WinPlaySound(String winEventName) { @@ -210,10 +210,12 @@ final class WDesktopProperties { WDesktopProperties.this.playWindowsSound(winEventName); } + @Override public String toString() { return "WinPlaySound("+winEventName+")"; } + @Override public boolean equals(Object o) { if (o == this) { return true; @@ -225,6 +227,7 @@ final class WDesktopProperties { } } + @Override public int hashCode() { return winEventName.hashCode(); } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDragSourceContextPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WDragSourceContextPeer.java index f4ab5fe0a34..43a91c3c7ab 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WDragSourceContextPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDragSourceContextPeer.java @@ -54,9 +54,11 @@ import sun.awt.dnd.SunDragSourceContextPeer; */ final class WDragSourceContextPeer extends SunDragSourceContextPeer { + @Override public void startSecondaryEventLoop(){ WToolkit.startSecondaryEventLoop(); } + @Override public void quitSecondaryEventLoop(){ WToolkit.quitSecondaryEventLoop(); } @@ -168,6 +170,7 @@ final class WDragSourceContextPeer extends SunDragSourceContextPeer { int imgWidth, int imgHight, int offsetX, int offsetY); + @Override protected native void setNativeCursor(long nativeCtxt, Cursor c, int cType); } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java index e5db1d432cf..ad0745a2733 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFrame.java @@ -36,7 +36,7 @@ import sun.awt.image.ByteInterleavedRaster; import java.awt.peer.FramePeer; @SuppressWarnings("serial") // JDK-implementation class -public class WEmbeddedFrame extends EmbeddedFrame { +public final class WEmbeddedFrame extends EmbeddedFrame { static { initIDs(); @@ -79,6 +79,7 @@ public class WEmbeddedFrame extends EmbeddedFrame { } } + @Override public void addNotify() { if (!isDisplayable()) { WToolkit toolkit = (WToolkit)Toolkit.getDefaultToolkit(); @@ -224,6 +225,7 @@ public class WEmbeddedFrame extends EmbeddedFrame { public void activateEmbeddingTopLevel() { } + @Override public void synthesizeWindowActivation(final boolean activate) { final FramePeer peer = AWTAccessor.getComponentAccessor().getPeer(this); if (!activate || EventQueue.isDispatchThread()) { @@ -241,7 +243,9 @@ public class WEmbeddedFrame extends EmbeddedFrame { } } + @Override public void registerAccelerator(AWTKeyStroke stroke) {} + @Override public void unregisterAccelerator(AWTKeyStroke stroke) {} /** @@ -256,6 +260,7 @@ public class WEmbeddedFrame extends EmbeddedFrame { * NOTE: This method may be called by privileged threads. * DO NOT INVOKE CLIENT CODE ON THIS THREAD! */ + @Override public void notifyModalBlocked(Dialog blocker, boolean blocked) { try { ComponentPeer thisPeer = (ComponentPeer)WToolkit.targetToPeer(this); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java index 4d5219cf34e..bab79c38ff4 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java @@ -32,7 +32,7 @@ import java.awt.Rectangle; import sun.awt.EmbeddedFrame; import sun.awt.Win32GraphicsEnvironment; -public class WEmbeddedFramePeer extends WFramePeer { +public final class WEmbeddedFramePeer extends WFramePeer { public WEmbeddedFramePeer(EmbeddedFrame target) { super(target); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WLabelPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WLabelPeer.java index 259329d4f6d..c5267e52793 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WLabelPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WLabelPeer.java @@ -31,6 +31,7 @@ final class WLabelPeer extends WComponentPeer implements LabelPeer { // ComponentPeer overrides + @Override public Dimension getMinimumSize() { FontMetrics fm = getFontMetrics(((Label)target).getFont()); String label = ((Label)target).getText(); @@ -40,6 +41,7 @@ final class WLabelPeer extends WComponentPeer implements LabelPeer { } native void lazyPaint(); + @Override synchronized void start() { super.start(); // if need then paint label @@ -47,11 +49,14 @@ final class WLabelPeer extends WComponentPeer implements LabelPeer { } // LabelPeer implementation + @Override public boolean shouldClearRectBeforePaint() { return false; } + @Override public native void setText(String label); + @Override public native void setAlignment(int alignment); // Toolkit & peer internals @@ -60,8 +65,10 @@ final class WLabelPeer extends WComponentPeer implements LabelPeer { super(target); } + @Override native void create(WComponentPeer parent); + @Override void initialize() { Label l = (Label)target; diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WLightweightFramePeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WLightweightFramePeer.java index ff77a5c188c..994b81e372e 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WLightweightFramePeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WLightweightFramePeer.java @@ -36,7 +36,7 @@ import sun.awt.OverrideNativeWindowHandle; import sun.swing.JLightweightFrame; import sun.swing.SwingAccessor; -public class WLightweightFramePeer extends WFramePeer implements OverrideNativeWindowHandle { +public final class WLightweightFramePeer extends WFramePeer implements OverrideNativeWindowHandle { public WLightweightFramePeer(LightweightFrame target) { super(target); @@ -100,6 +100,7 @@ public class WLightweightFramePeer extends WFramePeer implements OverrideNativeW SwingAccessor.getJLightweightFrameAccessor().updateCursor((JLightweightFrame)getLwTarget()); } + @Override public boolean isLightweightFramePeer() { return true; } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java index 43d4d2b907a..f2961f79a04 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WMenuItemPeer.java @@ -46,11 +46,13 @@ class WMenuItemPeer extends WObjectPeer implements MenuItemPeer { // MenuItemPeer implementation private synchronized native void _dispose(); + @Override protected void disposeImpl() { WToolkit.targetDisposedPeer(target, this); _dispose(); } + @Override public void setEnabled(boolean b) { enable(b); } @@ -69,6 +71,7 @@ class WMenuItemPeer extends WObjectPeer implements MenuItemPeer { } } + @Override public void setLabel(String label) { //Fix for 6288578: PIT. Windows: Shortcuts displayed for the menuitems in a popup menu readShortcutLabel(); @@ -165,6 +168,7 @@ class WMenuItemPeer extends WObjectPeer implements MenuItemPeer { private native void _setFont(Font f); + @Override public void setFont(final Font f) { _setFont(f); } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WMouseInfoPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WMouseInfoPeer.java index e5bef4fe1b9..4b785aaba69 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WMouseInfoPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WMouseInfoPeer.java @@ -43,8 +43,10 @@ public final class WMouseInfoPeer implements MouseInfoPeer { WMouseInfoPeer() { } + @Override public native int fillPointWithCoords(Point point); + @Override public native boolean isWindowUnderMouse(Window w); } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java index 69b62325670..d89cbcfa53a 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WPopupMenuPeer.java @@ -70,6 +70,7 @@ final class WPopupMenuPeer extends WMenuPeer implements PopupMenuPeer { private native void createMenu(WComponentPeer parent); + @Override @SuppressWarnings("deprecation") public void show(Event e) { Component origin = (Component)e.target; diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java b/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java index d7efc54ffd4..e50cfcff33b 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java @@ -264,7 +264,7 @@ public final class WPrinterJob extends RasterPrinterJob /* The HandleRecord holds the native resources that need to be freed * when this WPrinterJob is GC'd. */ - static class HandleRecord implements DisposerRecord { + static final class HandleRecord implements DisposerRecord { /** * The Windows device context we will print into. * This variable is set after the Print dialog @@ -2269,7 +2269,7 @@ public final class WPrinterJob extends RasterPrinterJob } @SuppressWarnings("serial") // JDK-implementation class -static class PrintToFileErrorDialog extends Dialog implements ActionListener { +static final class PrintToFileErrorDialog extends Dialog implements ActionListener { public PrintToFileErrorDialog(Frame parent, String title, String message, String buttonText) { super(parent, title, true); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java index e305654d91f..3a0d7bf3a71 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WScrollPanePeer.java @@ -167,7 +167,7 @@ final class WScrollPanePeer extends WPanelPeer implements ScrollPanePeer { * operation. */ @SuppressWarnings("serial") // JDK-implementation class - static class ScrollEvent extends PeerEvent { + static final class ScrollEvent extends PeerEvent { ScrollEvent(Object source, Runnable runnable) { super(source, runnable, 0L); } @@ -187,7 +187,7 @@ final class WScrollPanePeer extends WPanelPeer implements ScrollPanePeer { /* * Runnable for the ScrollEvent that performs the adjustment. */ - class Adjustor implements Runnable { + final class Adjustor implements Runnable { int orient; // selects scrollbar int type; // adjustment type int pos; // new position (only used for absolute) diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WScrollbarPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WScrollbarPeer.java index 055f2523cea..cfc227d29d6 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WScrollbarPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WScrollbarPeer.java @@ -35,6 +35,7 @@ final class WScrollbarPeer extends WComponentPeer implements ScrollbarPeer { static native int getScrollbarSize(int orientation); // ComponentPeer overrides + @Override public Dimension getMinimumSize() { if (((Scrollbar)target).getOrientation() == Scrollbar.VERTICAL) { return new Dimension(getScrollbarSize(Scrollbar.VERTICAL), 50); @@ -46,9 +47,12 @@ final class WScrollbarPeer extends WComponentPeer implements ScrollbarPeer { // ScrollbarPeer implementation + @Override public native void setValues(int value, int visible, int minimum, int maximum); + @Override public native void setLineIncrement(int l); + @Override public native void setPageIncrement(int l); @@ -58,8 +62,10 @@ final class WScrollbarPeer extends WComponentPeer implements ScrollbarPeer { super(target); } + @Override native void create(WComponentPeer parent); + @Override void initialize() { Scrollbar sb = (Scrollbar)target; setValues(sb.getValue(), sb.getVisibleAmount(), @@ -136,6 +142,7 @@ final class WScrollbarPeer extends WComponentPeer implements ScrollbarPeer { }); } + @Override public boolean shouldClearRectBeforePaint() { return false; } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java index e151a69a0f1..0fdc4c6005b 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java @@ -186,7 +186,7 @@ public final class WToolkit extends SunToolkit implements Runnable { } } - static class ToolkitDisposer implements sun.java2d.DisposerRecord { + static final class ToolkitDisposer implements sun.java2d.DisposerRecord { @Override public void dispose() { WToolkit.postDispose(); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java index 90fbd880446..d6c311d3f48 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java @@ -199,7 +199,7 @@ final class WTrayIconPeer extends WObjectPeer implements TrayIconPeer { native void _displayMessage(String caption, String text, String messageType); - class IconObserver implements ImageObserver { + final class IconObserver implements ImageObserver { @Override public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height) { if (image != ((TrayIcon)target).getImage() || // if the image has been changed diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java index 997db36beac..0ba2217dde5 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java @@ -849,7 +849,7 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, * it removes the list of the active windows from the disposed AppContext and * unregisters ActiveWindowListener listener. */ - private static class GuiDisposedListener implements PropertyChangeListener { + private static final class GuiDisposedListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent e) { boolean isDisposed = (Boolean)e.getNewValue(); @@ -875,7 +875,7 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, * window is always at the end of the list. The list is stored in AppContext. */ @SuppressWarnings("unchecked") - private static class ActiveWindowListener implements PropertyChangeListener { + private static final class ActiveWindowListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent e) { Window w = (Window)e.getNewValue(); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WingDings.java b/src/java.desktop/windows/classes/sun/awt/windows/WingDings.java index 55c5236594c..ae7573ac4e2 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WingDings.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WingDings.java @@ -52,7 +52,7 @@ public final class WingDings extends Charset { return cs instanceof WingDings; } - private static class Encoder extends CharsetEncoder { + private static final class Encoder extends CharsetEncoder { public Encoder(Charset cs) { super(cs, 1.0f, 1.0f); } diff --git a/src/java.desktop/windows/classes/sun/font/NativeFont.java b/src/java.desktop/windows/classes/sun/font/NativeFont.java index 7a5c29c7c73..9b0e6492d67 100644 --- a/src/java.desktop/windows/classes/sun/font/NativeFont.java +++ b/src/java.desktop/windows/classes/sun/font/NativeFont.java @@ -37,7 +37,7 @@ import java.awt.geom.Rectangle2D; * and the font is ignored. */ -public class NativeFont extends PhysicalFont { +public final class NativeFont extends PhysicalFont { /** * Verifies native font is accessible. @@ -53,6 +53,7 @@ public class NativeFont extends PhysicalFont { return false; } + @Override public CharToGlyphMapper getMapper() { return null; } @@ -61,6 +62,7 @@ public class NativeFont extends PhysicalFont { return null; } + @Override FontStrike createStrike(FontStrikeDesc desc) { return null; } @@ -69,16 +71,19 @@ public class NativeFont extends PhysicalFont { return null; } + @Override StrikeMetrics getFontMetrics(long pScalerContext) { return null; } + @Override public GeneralPath getGlyphOutline(long pScalerContext, int glyphCode, float x, float y) { return null; } + @Override public GeneralPath getGlyphVectorOutline(long pScalerContext, int[] glyphs, int numGlyphs, float x, float y) { @@ -86,20 +91,24 @@ public class NativeFont extends PhysicalFont { } + @Override long getGlyphImage(long pScalerContext, int glyphCode) { return 0L; } + @Override void getGlyphMetrics(long pScalerContext, int glyphCode, Point2D.Float metrics) { } + @Override float getGlyphAdvance(long pScalerContext, int glyphCode) { return 0f; } + @Override Rectangle2D.Float getGlyphOutlineBounds(long pScalerContext, int glyphCode) { return new Rectangle2D.Float(0f, 0f, 0f, 0f); diff --git a/src/java.desktop/windows/classes/sun/font/NativeStrike.java b/src/java.desktop/windows/classes/sun/font/NativeStrike.java index a28c47911ed..7b2b947d722 100644 --- a/src/java.desktop/windows/classes/sun/font/NativeStrike.java +++ b/src/java.desktop/windows/classes/sun/font/NativeStrike.java @@ -48,9 +48,11 @@ public class NativeStrike extends PhysicalStrike { } + @Override void getGlyphImagePtrs(int[] glyphCodes, long[] images,int len) { } + @Override long getGlyphImagePtr(int glyphCode) { return 0L; } @@ -59,26 +61,32 @@ public class NativeStrike extends PhysicalStrike { return 0L; } + @Override void getGlyphImageBounds(int glyphcode, Point2D.Float pt, Rectangle result) { } + @Override Point2D.Float getGlyphMetrics(int glyphCode) { return null; } + @Override float getGlyphAdvance(int glyphCode) { return 0f; } + @Override Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) { return null; } + @Override GeneralPath getGlyphOutline(int glyphCode, float x, float y) { return null; } + @Override GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) { return null; } diff --git a/src/java.desktop/windows/classes/sun/java2d/WindowsSurfaceManagerFactory.java b/src/java.desktop/windows/classes/sun/java2d/WindowsSurfaceManagerFactory.java index 4512492350d..4abb8c823f6 100644 --- a/src/java.desktop/windows/classes/sun/java2d/WindowsSurfaceManagerFactory.java +++ b/src/java.desktop/windows/classes/sun/java2d/WindowsSurfaceManagerFactory.java @@ -38,7 +38,7 @@ import sun.java2d.opengl.WGLVolatileSurfaceManager; * The SurfaceManagerFactory that creates VolatileSurfaceManager * implementations for the Windows volatile images. */ -public class WindowsSurfaceManagerFactory extends SurfaceManagerFactory { +public final class WindowsSurfaceManagerFactory extends SurfaceManagerFactory { /** * Creates a new instance of a VolatileSurfaceManager given any @@ -49,6 +49,7 @@ public class WindowsSurfaceManagerFactory extends SurfaceManagerFactory { * For Windows platforms, this method returns a Windows-specific * VolatileSurfaceManager. */ + @Override public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg, Object context) { diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java index 8f4da91eef2..9aa9837b191 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java @@ -358,7 +358,7 @@ final class D3DBlitLoops { } } -class D3DSurfaceToSurfaceBlit extends Blit { +final class D3DSurfaceToSurfaceBlit extends Blit { D3DSurfaceToSurfaceBlit() { super(D3DSurfaceData.D3DSurface, @@ -366,6 +366,7 @@ class D3DSurfaceToSurfaceBlit extends Blit { D3DSurfaceData.D3DSurface); } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -380,7 +381,7 @@ class D3DSurfaceToSurfaceBlit extends Blit { } } -class D3DSurfaceToSurfaceScale extends ScaledBlit { +final class D3DSurfaceToSurfaceScale extends ScaledBlit { D3DSurfaceToSurfaceScale() { super(D3DSurfaceData.D3DSurface, @@ -388,6 +389,7 @@ class D3DSurfaceToSurfaceScale extends ScaledBlit { D3DSurfaceData.D3DSurface); } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -405,7 +407,7 @@ class D3DSurfaceToSurfaceScale extends ScaledBlit { } } -class D3DSurfaceToSurfaceTransform extends TransformBlit { +final class D3DSurfaceToSurfaceTransform extends TransformBlit { D3DSurfaceToSurfaceTransform() { super(D3DSurfaceData.D3DSurface, @@ -413,6 +415,7 @@ class D3DSurfaceToSurfaceTransform extends TransformBlit { D3DSurfaceData.D3DSurface); } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -428,7 +431,7 @@ class D3DSurfaceToSurfaceTransform extends TransformBlit { } } -class D3DRTTSurfaceToSurfaceBlit extends Blit { +final class D3DRTTSurfaceToSurfaceBlit extends Blit { D3DRTTSurfaceToSurfaceBlit() { super(D3DSurfaceData.D3DSurfaceRTT, @@ -436,6 +439,7 @@ class D3DRTTSurfaceToSurfaceBlit extends Blit { D3DSurfaceData.D3DSurface); } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -450,7 +454,7 @@ class D3DRTTSurfaceToSurfaceBlit extends Blit { } } -class D3DRTTSurfaceToSurfaceScale extends ScaledBlit { +final class D3DRTTSurfaceToSurfaceScale extends ScaledBlit { D3DRTTSurfaceToSurfaceScale() { super(D3DSurfaceData.D3DSurfaceRTT, @@ -458,6 +462,7 @@ class D3DRTTSurfaceToSurfaceScale extends ScaledBlit { D3DSurfaceData.D3DSurface); } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -475,7 +480,7 @@ class D3DRTTSurfaceToSurfaceScale extends ScaledBlit { } } -class D3DRTTSurfaceToSurfaceTransform extends TransformBlit { +final class D3DRTTSurfaceToSurfaceTransform extends TransformBlit { D3DRTTSurfaceToSurfaceTransform() { super(D3DSurfaceData.D3DSurfaceRTT, @@ -483,6 +488,7 @@ class D3DRTTSurfaceToSurfaceTransform extends TransformBlit { D3DSurfaceData.D3DSurface); } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -497,7 +503,7 @@ class D3DRTTSurfaceToSurfaceTransform extends TransformBlit { } } -class D3DSurfaceToSwBlit extends Blit { +final class D3DSurfaceToSwBlit extends Blit { private int typeval; private WeakReference srcTmp; @@ -567,6 +573,7 @@ class D3DSurfaceToSwBlit extends Blit { } } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, @@ -629,7 +636,7 @@ class D3DSurfaceToSwBlit extends Blit { } } -class D3DSwToSurfaceBlit extends Blit { +final class D3DSwToSurfaceBlit extends Blit { private int typeval; @@ -640,6 +647,7 @@ class D3DSwToSurfaceBlit extends Blit { this.typeval = typeval; } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -653,7 +661,7 @@ class D3DSwToSurfaceBlit extends Blit { } } -class D3DSwToSurfaceScale extends ScaledBlit { +final class D3DSwToSurfaceScale extends ScaledBlit { private int typeval; @@ -664,6 +672,7 @@ class D3DSwToSurfaceScale extends ScaledBlit { this.typeval = typeval; } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -680,7 +689,7 @@ class D3DSwToSurfaceScale extends ScaledBlit { } } -class D3DSwToSurfaceTransform extends TransformBlit { +final class D3DSwToSurfaceTransform extends TransformBlit { private int typeval; @@ -691,6 +700,7 @@ class D3DSwToSurfaceTransform extends TransformBlit { this.typeval = typeval; } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -704,7 +714,7 @@ class D3DSwToSurfaceTransform extends TransformBlit { } } -class D3DSwToTextureBlit extends Blit { +final class D3DSwToTextureBlit extends Blit { private int typeval; @@ -715,6 +725,7 @@ class D3DSwToTextureBlit extends Blit { this.typeval = typeval; } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -728,7 +739,7 @@ class D3DSwToTextureBlit extends Blit { } } -class D3DTextureToSurfaceBlit extends Blit { +final class D3DTextureToSurfaceBlit extends Blit { D3DTextureToSurfaceBlit() { super(D3DSurfaceData.D3DTexture, @@ -736,6 +747,7 @@ class D3DTextureToSurfaceBlit extends Blit { D3DSurfaceData.D3DSurface); } + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) @@ -750,7 +762,7 @@ class D3DTextureToSurfaceBlit extends Blit { } } -class D3DTextureToSurfaceScale extends ScaledBlit { +final class D3DTextureToSurfaceScale extends ScaledBlit { D3DTextureToSurfaceScale() { super(D3DSurfaceData.D3DTexture, @@ -758,6 +770,7 @@ class D3DTextureToSurfaceScale extends ScaledBlit { D3DSurfaceData.D3DSurface); } + @Override public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, @@ -775,7 +788,7 @@ class D3DTextureToSurfaceScale extends ScaledBlit { } } -class D3DTextureToSurfaceTransform extends TransformBlit { +final class D3DTextureToSurfaceTransform extends TransformBlit { D3DTextureToSurfaceTransform() { super(D3DSurfaceData.D3DTexture, @@ -783,6 +796,7 @@ class D3DTextureToSurfaceTransform extends TransformBlit { D3DSurfaceData.D3DSurface); } + @Override public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform at, int hint, @@ -804,7 +818,7 @@ class D3DTextureToSurfaceTransform extends TransformBlit { * IntArgbPre->D3DSurface/Texture loop to get the intermediate * (premultiplied) surface down to D3D using simple blit. */ -class D3DGeneralBlit extends Blit { +final class D3DGeneralBlit extends Blit { private final Blit performop; private WeakReference srcTmp; @@ -817,6 +831,7 @@ class D3DGeneralBlit extends Blit { this.performop = performop; } + @Override public synchronized void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, @@ -917,7 +932,7 @@ final class D3DGeneralTransformedBlit extends TransformBlit { * */ -class D3DSurfaceToGDIWindowSurfaceBlit extends Blit { +final class D3DSurfaceToGDIWindowSurfaceBlit extends Blit { D3DSurfaceToGDIWindowSurfaceBlit() { super(D3DSurfaceData.D3DSurface, @@ -935,7 +950,7 @@ class D3DSurfaceToGDIWindowSurfaceBlit extends Blit { } -class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit { +final class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit { D3DSurfaceToGDIWindowSurfaceScale() { super(D3DSurfaceData.D3DSurface, @@ -955,7 +970,7 @@ class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit { } } -class D3DSurfaceToGDIWindowSurfaceTransform extends TransformBlit { +final class D3DSurfaceToGDIWindowSurfaceTransform extends TransformBlit { D3DSurfaceToGDIWindowSurfaceTransform() { super(D3DSurfaceData.D3DSurface, diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBufImgOps.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBufImgOps.java index 890bb87d66b..7ca0130391b 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBufImgOps.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBufImgOps.java @@ -37,7 +37,7 @@ import sun.java2d.loops.CompositeType; import sun.java2d.pipe.BufferedBufImgOps; import static sun.java2d.d3d.D3DContext.D3DContextCaps.*; -class D3DBufImgOps extends BufferedBufImgOps { +final class D3DBufImgOps extends BufferedBufImgOps { /** * This method is called from D3DDrawImage.transformImage() only. It diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DContext.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DContext.java index 055e636bb69..5d9b6c30b5b 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DContext.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DContext.java @@ -106,7 +106,7 @@ final class D3DContext extends BufferedContext { return device; } - static class D3DContextCaps extends ContextCapabilities { + static final class D3DContextCaps extends ContextCapabilities { /** * Indicates the presence of pixel shaders (v2.0 or greater). * This cap will only be set if the hardware supports the minimum number diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DDrawImage.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DDrawImage.java index f814dc2f613..e847c7ba7cd 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DDrawImage.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DDrawImage.java @@ -37,7 +37,7 @@ import sun.java2d.loops.SurfaceType; import sun.java2d.loops.TransformBlit; import sun.java2d.pipe.DrawImage; -public class D3DDrawImage extends DrawImage { +public final class D3DDrawImage extends DrawImage { @Override protected void renderImageXform(SunGraphics2D sg, Image img, diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsConfig.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsConfig.java index 53d64017a3e..aab6b720d6a 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsConfig.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsConfig.java @@ -223,7 +223,7 @@ public final class D3DGraphicsConfig } } - private static class D3DBufferCaps extends BufferCapabilities { + private static final class D3DBufferCaps extends BufferCapabilities { public D3DBufferCaps() { // REMIND: should we indicate that the front-buffer // (the on-screen rendering) is not accelerated? @@ -244,7 +244,7 @@ public final class D3DGraphicsConfig return bufferCaps; } - private static class D3DImageCaps extends ImageCapabilities { + private static final class D3DImageCaps extends ImageCapabilities { private D3DImageCaps() { super(true); } diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java index e9f02a5d98c..1c838d0d32d 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java @@ -128,7 +128,7 @@ public final class D3DGraphicsDevice extends Win32GraphicsDevice { return d3dCaps != null ? d3dCaps : new D3DContextCaps(CAPS_EMPTY, null); } - public final boolean isCapPresent(int cap) { + public boolean isCapPresent(int cap) { return ((d3dCaps.getCaps() & cap) != 0); } @@ -234,7 +234,7 @@ public final class D3DGraphicsDevice extends Win32GraphicsDevice { * REMIND: we create an instance per each full-screen device while a single * instance would suffice (but requires more management). */ - private static class D3DFSWindowAdapter extends WindowAdapter { + private static final class D3DFSWindowAdapter extends WindowAdapter { @Override @SuppressWarnings("static") public void windowDeactivated(WindowEvent e) { diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskBlit.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskBlit.java index 835bcb733ad..6ba766d2b13 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskBlit.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskBlit.java @@ -36,7 +36,7 @@ import sun.java2d.pipe.BufferedMaskBlit; import static sun.java2d.loops.CompositeType.*; import static sun.java2d.loops.SurfaceType.*; -class D3DMaskBlit extends BufferedMaskBlit { +final class D3DMaskBlit extends BufferedMaskBlit { static void register() { GraphicsPrimitive[] primitives = { diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskFill.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskFill.java index fb78616a98f..d00e3fe2ee1 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskFill.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DMaskFill.java @@ -36,7 +36,7 @@ import sun.java2d.pipe.BufferedMaskFill; import static sun.java2d.loops.CompositeType.*; import static sun.java2d.loops.SurfaceType.*; -class D3DMaskFill extends BufferedMaskFill { +final class D3DMaskFill extends BufferedMaskFill { static void register() { GraphicsPrimitive[] primitives = { diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DPaints.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DPaints.java index 7d5bd4423ea..74b7cfc6967 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DPaints.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DPaints.java @@ -76,7 +76,7 @@ abstract class D3DPaints { /************************* GradientPaint support ****************************/ - private static class Gradient extends D3DPaints { + private static final class Gradient extends D3DPaints { private Gradient() {} /** @@ -96,7 +96,7 @@ abstract class D3DPaints { /************************** TexturePaint support ****************************/ - private static class Texture extends D3DPaints { + private static final class Texture extends D3DPaints { private Texture() {} /** @@ -201,7 +201,7 @@ abstract class D3DPaints { /********************** LinearGradientPaint support *************************/ - private static class LinearGradient extends MultiGradient { + private static final class LinearGradient extends MultiGradient { private LinearGradient() {} @Override @@ -228,7 +228,7 @@ abstract class D3DPaints { /********************** RadialGradientPaint support *************************/ - private static class RadialGradient extends MultiGradient { + private static final class RadialGradient extends MultiGradient { private RadialGradient() {} } } diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderQueue.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderQueue.java index d77e90456df..be20e1c4e4c 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderQueue.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderQueue.java @@ -33,7 +33,7 @@ import static sun.java2d.pipe.BufferedOpCodes.*; /** * D3D-specific implementation of RenderQueue. */ -public class D3DRenderQueue extends RenderQueue { +public final class D3DRenderQueue extends RenderQueue { private static D3DRenderQueue theInstance; private static Thread rqThread; @@ -132,11 +132,13 @@ public class D3DRenderQueue extends RenderQueue { } } + @Override public void flushNow() { // assert lock.isHeldByCurrentThread(); flushBuffer(null); } + @Override public void flushAndInvokeNow(Runnable r) { // assert lock.isHeldByCurrentThread(); flushBuffer(r); diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderer.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderer.java index fd63d758548..7361a09973b 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderer.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DRenderer.java @@ -87,6 +87,7 @@ class D3DRenderer extends BufferedRenderPipe { } } + @Override protected native void drawPoly(int[] xPoints, int[] yPoints, int nPoints, boolean isClosed, int transX, int transY); @@ -95,12 +96,13 @@ class D3DRenderer extends BufferedRenderPipe { return new Tracer(this); } - private static class Tracer extends D3DRenderer { + private static final class Tracer extends D3DRenderer { private D3DRenderer d3dr; Tracer(D3DRenderer d3dr) { super(d3dr.rq); this.d3dr = d3dr; } + @Override public ParallelogramPipe getAAParallelogramPipe() { final ParallelogramPipe realpipe = d3dr.getAAParallelogramPipe(); return new ParallelogramPipe() { @@ -133,19 +135,23 @@ class D3DRenderer extends BufferedRenderPipe { }; } + @Override protected void validateContext(SunGraphics2D sg2d) { d3dr.validateContext(sg2d); } + @Override public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { GraphicsPrimitive.tracePrimitive("D3DDrawLine"); d3dr.drawLine(sg2d, x1, y1, x2, y2); } + @Override public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("D3DDrawRect"); d3dr.drawRect(sg2d, x, y, w, h); } + @Override protected void drawPoly(SunGraphics2D sg2d, int[] xPoints, int[] yPoints, int nPoints, boolean isClosed) @@ -153,28 +159,33 @@ class D3DRenderer extends BufferedRenderPipe { GraphicsPrimitive.tracePrimitive("D3DDrawPoly"); d3dr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed); } + @Override public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) { GraphicsPrimitive.tracePrimitive("D3DFillRect"); d3dr.fillRect(sg2d, x, y, w, h); } + @Override protected void drawPath(SunGraphics2D sg2d, Path2D.Float p2df, int transx, int transy) { GraphicsPrimitive.tracePrimitive("D3DDrawPath"); d3dr.drawPath(sg2d, p2df, transx, transy); } + @Override protected void fillPath(SunGraphics2D sg2d, Path2D.Float p2df, int transx, int transy) { GraphicsPrimitive.tracePrimitive("D3DFillPath"); d3dr.fillPath(sg2d, p2df, transx, transy); } + @Override protected void fillSpans(SunGraphics2D sg2d, SpanIterator si, int transx, int transy) { GraphicsPrimitive.tracePrimitive("D3DFillSpans"); d3dr.fillSpans(sg2d, si, transx, transy); } + @Override public void fillParallelogram(SunGraphics2D sg2d, double ux1, double uy1, double ux2, double uy2, @@ -187,6 +198,7 @@ class D3DRenderer extends BufferedRenderPipe { ux1, uy1, ux2, uy2, x, y, dx1, dy1, dx2, dy2); } + @Override public void drawParallelogram(SunGraphics2D sg2d, double ux1, double uy1, double ux2, double uy2, @@ -200,6 +212,7 @@ class D3DRenderer extends BufferedRenderPipe { ux1, uy1, ux2, uy2, x, y, dx1, dy1, dx2, dy2, lw1, lw2); } + @Override public void copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index a1afb5cd4c4..58dfd17dea7 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -58,7 +58,7 @@ import sun.java2d.windows.WindowsFlags; * There are some restrictions to which windows we would use this for. * @see #createScreenSurface */ -public class D3DScreenUpdateManager extends ScreenUpdateManager +public final class D3DScreenUpdateManager extends ScreenUpdateManager implements Runnable { /** @@ -401,6 +401,7 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager } } + @Override public void run() { while (!done) { synchronized (runLock) { diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java index c8e082b59d6..374fce63db0 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java @@ -441,6 +441,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { * Returns the D3DContext for the GraphicsConfig associated with this * surface. */ + @Override public final D3DContext getContext() { return graphicsDevice.getContext(); } @@ -448,6 +449,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { /** * Returns one of the surface type constants defined above. */ + @Override public final int getType() { return type; } @@ -455,7 +457,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { private static native int dbGetPixelNative(long pData, int x, int y); private static native void dbSetPixelNative(long pData, int x, int y, int pixel); - static class D3DDataBufferNative extends DataBufferNative { + static final class D3DDataBufferNative extends DataBufferNative { int pixel; protected D3DDataBufferNative(SurfaceData sData, int type, int w, int h) @@ -463,6 +465,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { super(sData, type, w, h); } + @Override protected int getElem(final int x, final int y, final SurfaceData sData) { @@ -486,6 +489,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { return retPixel; } + @Override protected void setElem(final int x, final int y, final int pixel, final SurfaceData sData) { @@ -508,6 +512,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { } } + @Override public synchronized Raster getRaster(int x, int y, int w, int h) { if (wrn == null) { DirectColorModel dcm = (DirectColorModel)getColorModel(); @@ -541,6 +546,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { * - the source color is opaque * - and the destination is opaque */ + @Override public boolean canRenderLCDText(SunGraphics2D sg2d) { return graphicsDevice.isCapPresent(CAPS_LCD_SHADER) && @@ -564,6 +570,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { } } + @Override public void validatePipe(SunGraphics2D sg2d) { TextPipe textpipe; boolean validated = false; @@ -803,10 +810,12 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { /** * Returns destination Image associated with this SurfaceData. */ + @Override public Object getDestination() { return offscreenImage; } + @Override public Rectangle getBounds() { if (type == FLIP_BACKBUFFER || type == WINDOW) { double scaleX = getDefaultScaleX(); @@ -821,6 +830,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { } } + @Override public Rectangle getNativeBounds() { D3DRenderQueue rq = D3DRenderQueue.getInstance(); // need to lock to make sure nativeWidth and Height are consistent @@ -836,10 +846,12 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { } + @Override public GraphicsConfiguration getDeviceConfiguration() { return graphicsDevice.getDefaultConfiguration(); } + @Override public SurfaceData getReplacement() { return restoreContents(offscreenImage); } @@ -909,6 +921,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { * such resource doesn't exist or can not be retrieved. * @see sun.java2d.pipe.hw.AccelSurface#getNativeResource */ + @Override public long getNativeResource(int resType) { return getNativeResourceNative(getNativeOps(), resType); } @@ -920,7 +933,7 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface { * * @see D3DScreenUpdateManager */ - public static class D3DWindowSurfaceData extends D3DSurfaceData { + public static final class D3DWindowSurfaceData extends D3DSurfaceData { StateTracker dirtyTracker; public D3DWindowSurfaceData(WComponentPeer peer, diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceDataProxy.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceDataProxy.java index 66e98882a19..6ea095666b3 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceDataProxy.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceDataProxy.java @@ -38,7 +38,7 @@ import sun.java2d.loops.CompositeType; * SurfaceData with a cached D3D Texture and the code to create * the accelerated surfaces. */ -public class D3DSurfaceDataProxy extends SurfaceDataProxy { +public final class D3DSurfaceDataProxy extends SurfaceDataProxy { public static SurfaceDataProxy createProxy(SurfaceData srcData, D3DGraphicsConfig dstConfig) diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DTextRenderer.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DTextRenderer.java index b892ed4b10c..31b2cc207cd 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DTextRenderer.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DTextRenderer.java @@ -59,10 +59,11 @@ class D3DTextRenderer extends BufferedTextPipe { return new Tracer(this); } - private static class Tracer extends D3DTextRenderer { + private static final class Tracer extends D3DTextRenderer { Tracer(D3DTextRenderer d3dtr) { super(d3dtr.rq); } + @Override protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) { GraphicsPrimitive.tracePrimitive("D3DDrawGlyphs"); super.drawGlyphList(sg2d, gl); diff --git a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DVolatileSurfaceManager.java b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DVolatileSurfaceManager.java index 4aac1c248a6..0fedb478362 100644 --- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DVolatileSurfaceManager.java +++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DVolatileSurfaceManager.java @@ -48,7 +48,7 @@ import static sun.java2d.pipe.hw.AccelSurface.RT_TEXTURE; import static sun.java2d.pipe.hw.AccelSurface.TEXTURE; import static sun.java2d.pipe.hw.AccelSurface.UNDEFINED; -public class D3DVolatileSurfaceManager +public final class D3DVolatileSurfaceManager extends VolatileSurfaceManager { private boolean accelerationEnabled; @@ -75,6 +75,7 @@ public class D3DVolatileSurfaceManager gd.isCapPresent(CAPS_RT_TEXTURE_ALPHA))); } + @Override protected boolean isAccelerationEnabled() { return accelerationEnabled; } @@ -86,6 +87,7 @@ public class D3DVolatileSurfaceManager * Create a pbuffer-based SurfaceData object (or init the backbuffer * of an existing window if this is a double buffered GraphicsConfig). */ + @Override protected SurfaceData initAcceleratedSurface() { SurfaceData sData; Component comp = vImg.getComponent(); @@ -124,6 +126,7 @@ public class D3DVolatileSurfaceManager return sData; } + @Override protected boolean isConfigValid(GraphicsConfiguration gc) { return ((gc == null) || (gc == vImg.getGraphicsConfig())); } diff --git a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java index 768f2df08ad..c6658bf2914 100644 --- a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java +++ b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java @@ -158,7 +158,7 @@ public final class WGLGraphicsConfig * This is a small helper class that allows us to execute * getWGLConfigInfo() on the queue flushing thread. */ - private static class WGLGetConfigInfo implements Runnable { + private static final class WGLGetConfigInfo implements Runnable { private int screen; private int pixfmt; private long cfginfo; @@ -184,21 +184,21 @@ public final class WGLGraphicsConfig * See OGLContext.java for a list of supported capabilities. */ @Override - public final boolean isCapPresent(int cap) { + public boolean isCapPresent(int cap) { return ((oglCaps.getCaps() & cap) != 0); } @Override - public final long getNativeConfigInfo() { + public long getNativeConfigInfo() { return pConfigInfo; } @Override - public final OGLContext getContext() { + public OGLContext getContext() { return context; } - private static class WGLGCDisposerRecord implements DisposerRecord { + private static final class WGLGCDisposerRecord implements DisposerRecord { private long pCfgInfo; public WGLGCDisposerRecord(long pCfgInfo) { this.pCfgInfo = pCfgInfo; @@ -374,7 +374,7 @@ public final class WGLGraphicsConfig } } - private static class WGLBufferCaps extends BufferCapabilities { + private static final class WGLBufferCaps extends BufferCapabilities { public WGLBufferCaps(boolean dblBuf) { super(imageCaps, imageCaps, dblBuf ? FlipContents.UNDEFINED : null); @@ -390,7 +390,7 @@ public final class WGLGraphicsConfig return bufferCaps; } - private static class WGLImageCaps extends ImageCapabilities { + private static final class WGLImageCaps extends ImageCapabilities { private WGLImageCaps() { super(true); } diff --git a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java index fa4cb6a3cc2..8f97980811f 100644 --- a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java +++ b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java @@ -75,6 +75,7 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { return scaleY; } + @Override public GraphicsConfiguration getDeviceConfiguration() { return graphicsConfig; } @@ -151,7 +152,7 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { } } - public static class WGLWindowSurfaceData extends WGLSurfaceData { + public static final class WGLWindowSurfaceData extends WGLSurfaceData { public WGLWindowSurfaceData(WComponentPeer peer, WGLGraphicsConfig gc) @@ -159,10 +160,12 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { super(peer, gc, peer.getColorModel(), WINDOW); } + @Override public SurfaceData getReplacement() { return peer.getSurfaceData(); } + @Override public Rectangle getBounds() { Rectangle r = peer.getBounds(); r.x = r.y = 0; @@ -174,6 +177,7 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { /** * Returns destination Component associated with this SurfaceData. */ + @Override public Object getDestination() { return peer.getTarget(); } @@ -188,7 +192,7 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { * belongs to is showed, it is first copied to the real private * FLIP_BACKBUFFER, which is then flipped. */ - public static class WGLVSyncOffScreenSurfaceData extends + public static final class WGLVSyncOffScreenSurfaceData extends WGLOffScreenSurfaceData { private WGLOffScreenSurfaceData flipSurface; @@ -235,10 +239,12 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { initSurface(this.width, this.height); } + @Override public SurfaceData getReplacement() { return restoreContents(offscreenImage); } + @Override public Rectangle getBounds() { if (type == FLIP_BACKBUFFER) { Rectangle r = peer.getBounds(); @@ -254,6 +260,7 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { /** * Returns destination Image associated with this SurfaceData. */ + @Override public Object getDestination() { return offscreenImage; } diff --git a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java index 750bb94df08..c90f8102e7e 100644 --- a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java +++ b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java @@ -43,7 +43,7 @@ import static sun.java2d.pipe.hw.AccelSurface.*; import sun.java2d.pipe.hw.ExtendedBufferCapabilities; import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*; -public class WGLVolatileSurfaceManager extends VolatileSurfaceManager { +public final class WGLVolatileSurfaceManager extends VolatileSurfaceManager { private final boolean accelerationEnabled; @@ -62,6 +62,7 @@ public class WGLVolatileSurfaceManager extends VolatileSurfaceManager { && transparency != Transparency.BITMASK; } + @Override protected boolean isAccelerationEnabled() { return accelerationEnabled; } @@ -70,6 +71,7 @@ public class WGLVolatileSurfaceManager extends VolatileSurfaceManager { * Create a FBO-based SurfaceData object (or init the backbuffer * of an existing window if this is a double buffered GraphicsConfig). */ + @Override protected SurfaceData initAcceleratedSurface() { SurfaceData sData; Component comp = vImg.getComponent(); diff --git a/src/java.desktop/windows/classes/sun/java2d/windows/GDIBlitLoops.java b/src/java.desktop/windows/classes/sun/java2d/windows/GDIBlitLoops.java index 3f1996309cd..18d44ea6a49 100644 --- a/src/java.desktop/windows/classes/sun/java2d/windows/GDIBlitLoops.java +++ b/src/java.desktop/windows/classes/sun/java2d/windows/GDIBlitLoops.java @@ -43,7 +43,7 @@ import sun.java2d.SurfaceData; * that is faster than our current fallback (which creates * a temporary GDI DIB) */ -public class GDIBlitLoops extends Blit { +public final class GDIBlitLoops extends Blit { // Store these values to be passed to native code int rmask, gmask, bmask; @@ -134,6 +134,7 @@ public class GDIBlitLoops extends Blit { * Composite data because we only register these loops for * SrcNoEa composite operations. */ + @Override public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) diff --git a/src/java.desktop/windows/classes/sun/java2d/windows/GDIRenderer.java b/src/java.desktop/windows/classes/sun/java2d/windows/GDIRenderer.java index f08273c76fb..9bb3ba38b20 100644 --- a/src/java.desktop/windows/classes/sun/java2d/windows/GDIRenderer.java +++ b/src/java.desktop/windows/classes/sun/java2d/windows/GDIRenderer.java @@ -50,6 +50,7 @@ public class GDIRenderer implements Region clip, Composite comp, int color, int x1, int y1, int x2, int y2); + @Override public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { @@ -68,6 +69,7 @@ public class GDIRenderer implements Region clip, Composite comp, int color, int x, int y, int w, int h); + @Override public void drawRect(SunGraphics2D sg2d, int x, int y, int width, int height) { @@ -85,6 +87,7 @@ public class GDIRenderer implements int x, int y, int w, int h, int arcW, int arcH); + @Override public void drawRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) @@ -103,6 +106,7 @@ public class GDIRenderer implements Region clip, Composite comp, int color, int x, int y, int w, int h); + @Override public void drawOval(SunGraphics2D sg2d, int x, int y, int width, int height) { @@ -120,6 +124,7 @@ public class GDIRenderer implements int x, int y, int w, int h, int angleStart, int angleExtent); + @Override public void drawArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) @@ -140,6 +145,7 @@ public class GDIRenderer implements int[] xpoints, int[] ypoints, int npoints, boolean isclosed); + @Override public void drawPolyline(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) @@ -153,6 +159,7 @@ public class GDIRenderer implements } } + @Override public void drawPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) @@ -170,6 +177,7 @@ public class GDIRenderer implements Region clip, Composite comp, int color, int x, int y, int w, int h); + @Override public void fillRect(SunGraphics2D sg2d, int x, int y, int width, int height) { @@ -187,6 +195,7 @@ public class GDIRenderer implements int x, int y, int w, int h, int arcW, int arcH); + @Override public void fillRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight) @@ -205,6 +214,7 @@ public class GDIRenderer implements Region clip, Composite comp, int color, int x, int y, int w, int h); + @Override public void fillOval(SunGraphics2D sg2d, int x, int y, int width, int height) { @@ -222,6 +232,7 @@ public class GDIRenderer implements int x, int y, int w, int h, int angleStart, int angleExtent); + @Override public void fillArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle) @@ -242,6 +253,7 @@ public class GDIRenderer implements int[] xpoints, int[] ypoints, int npoints); + @Override public void fillPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints) @@ -303,6 +315,7 @@ public class GDIRenderer implements } } + @Override public void draw(SunGraphics2D sg2d, Shape s) { if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) { doShape(sg2d, s, false); @@ -318,6 +331,7 @@ public class GDIRenderer implements } } + @Override public void fill(SunGraphics2D sg2d, Shape s) { doShape(sg2d, s, true); } @@ -331,7 +345,8 @@ public class GDIRenderer implements return new Tracer(); } - public static class Tracer extends GDIRenderer { + public static final class Tracer extends GDIRenderer { + @Override void doDrawLine(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x1, int y1, int x2, int y2) @@ -339,6 +354,7 @@ public class GDIRenderer implements GraphicsPrimitive.tracePrimitive("GDIDrawLine"); super.doDrawLine(sData, clip, comp, color, x1, y1, x2, y2); } + @Override void doDrawRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) @@ -346,6 +362,7 @@ public class GDIRenderer implements GraphicsPrimitive.tracePrimitive("GDIDrawRect"); super.doDrawRect(sData, clip, comp, color, x, y, w, h); } + @Override void doDrawRoundRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, @@ -355,6 +372,7 @@ public class GDIRenderer implements super.doDrawRoundRect(sData, clip, comp, color, x, y, w, h, arcW, arcH); } + @Override void doDrawOval(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) @@ -362,6 +380,7 @@ public class GDIRenderer implements GraphicsPrimitive.tracePrimitive("GDIDrawOval"); super.doDrawOval(sData, clip, comp, color, x, y, w, h); } + @Override void doDrawArc(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, @@ -371,6 +390,7 @@ public class GDIRenderer implements super.doDrawArc(sData, clip, comp, color, x, y, w, h, angleStart, angleExtent); } + @Override void doDrawPoly(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, @@ -381,6 +401,7 @@ public class GDIRenderer implements super.doDrawPoly(sData, clip, comp, color, transx, transy, xpoints, ypoints, npoints, isclosed); } + @Override void doFillRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) @@ -388,6 +409,7 @@ public class GDIRenderer implements GraphicsPrimitive.tracePrimitive("GDIFillRect"); super.doFillRect(sData, clip, comp, color, x, y, w, h); } + @Override void doFillRoundRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, @@ -397,6 +419,7 @@ public class GDIRenderer implements super.doFillRoundRect(sData, clip, comp, color, x, y, w, h, arcW, arcH); } + @Override void doFillOval(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h) @@ -404,6 +427,7 @@ public class GDIRenderer implements GraphicsPrimitive.tracePrimitive("GDIFillOval"); super.doFillOval(sData, clip, comp, color, x, y, w, h); } + @Override void doFillArc(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, @@ -413,6 +437,7 @@ public class GDIRenderer implements super.doFillArc(sData, clip, comp, color, x, y, w, h, angleStart, angleExtent); } + @Override void doFillPoly(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, @@ -423,6 +448,7 @@ public class GDIRenderer implements super.doFillPoly(sData, clip, comp, color, transx, transy, xpoints, ypoints, npoints); } + @Override void doShape(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transX, int transY, @@ -434,6 +460,7 @@ public class GDIRenderer implements super.doShape(sData, clip, comp, color, transX, transY, p2df, isfill); } + @Override public void devCopyArea(GDIWindowSurfaceData sData, int srcx, int srcy, int dx, int dy, diff --git a/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java b/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java index 52e0d47c55d..38b57f77bce 100644 --- a/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java +++ b/src/java.desktop/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java @@ -51,7 +51,7 @@ import sun.java2d.loops.CompositeType; import sun.java2d.loops.RenderLoops; import sun.java2d.loops.XORComposite; -public class GDIWindowSurfaceData extends SurfaceData { +public final class GDIWindowSurfaceData extends SurfaceData { private WComponentPeer peer; private Win32GraphicsConfig graphicsConfig; private RenderLoops solidloops; @@ -139,6 +139,7 @@ public class GDIWindowSurfaceData extends SurfaceData { return SurfaceDataProxy.UNCACHED; } + @Override public Raster getRaster(int x, int y, int w, int h) { throw new InternalError("not implemented yet"); } @@ -155,6 +156,7 @@ public class GDIWindowSurfaceData extends SurfaceData { } + @Override public void validatePipe(SunGraphics2D sg2d) { if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && @@ -223,6 +225,7 @@ public class GDIWindowSurfaceData extends SurfaceData { } } + @Override public RenderLoops getRenderLoops(SunGraphics2D sg2d) { if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY) @@ -232,6 +235,7 @@ public class GDIWindowSurfaceData extends SurfaceData { return super.getRenderLoops(sg2d); } + @Override public GraphicsConfiguration getDeviceConfiguration() { return graphicsConfig; } @@ -299,6 +303,7 @@ public class GDIWindowSurfaceData extends SurfaceData { return mgr.getReplacementScreenSurface(peer, this); } + @Override public Rectangle getBounds() { Rectangle r = peer.getBounds(); r.x = r.y = 0; @@ -307,6 +312,7 @@ public class GDIWindowSurfaceData extends SurfaceData { return r; } + @Override public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { diff --git a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java index 7333eeda3dd..b5b1e6376e9 100644 --- a/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java +++ b/src/java.desktop/windows/classes/sun/java2d/windows/WindowsFlags.java @@ -28,7 +28,7 @@ package sun.java2d.windows; import sun.awt.windows.WToolkit; import sun.java2d.opengl.WGLGraphicsConfig; -public class WindowsFlags { +public final class WindowsFlags { /** * Description of command-line flags. All flags with [true|false] diff --git a/src/java.desktop/windows/classes/sun/print/PlatformPrinterJobProxy.java b/src/java.desktop/windows/classes/sun/print/PlatformPrinterJobProxy.java index f9ac7621aa4..677831a9245 100644 --- a/src/java.desktop/windows/classes/sun/print/PlatformPrinterJobProxy.java +++ b/src/java.desktop/windows/classes/sun/print/PlatformPrinterJobProxy.java @@ -27,7 +27,7 @@ package sun.print; import java.awt.print.PrinterJob; -public class PlatformPrinterJobProxy { +public final class PlatformPrinterJobProxy { public static PrinterJob getPrinterJob() { return new sun.awt.windows.WPrinterJob(); diff --git a/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java b/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java index 4dbcf3a4701..7af6f1b61f8 100644 --- a/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java +++ b/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java @@ -43,7 +43,7 @@ import javax.print.attribute.standard.PrinterName; import sun.awt.util.ThreadGroupUtils; -public class PrintServiceLookupProvider extends PrintServiceLookup { +public final class PrintServiceLookupProvider extends PrintServiceLookup { private PrintService defaultPrintService; private PrintService[] printServices; /* includes the default printer */ @@ -105,6 +105,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { * This isn't required by the API and there's a risk doing this will * lead people to assume its guaranteed. */ + @Override public synchronized PrintService[] getPrintServices() { if (printServices == null) { refreshServices(); @@ -199,6 +200,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { return true; } + @Override public PrintService[] getPrintServices(DocFlavor flavor, AttributeSet attributes) { @@ -260,6 +262,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { /* * return empty array as don't support multi docs */ + @Override public MultiDocPrintService[] getMultiDocPrintServices(DocFlavor[] flavors, AttributeSet attributes) { @@ -267,6 +270,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { } + @Override public synchronized PrintService getDefaultPrintService() { // Windows does not have notification for a change in default diff --git a/src/java.desktop/windows/classes/sun/print/Win32MediaTray.java b/src/java.desktop/windows/classes/sun/print/Win32MediaTray.java index 43ce6a19d6a..3cb8c858e39 100644 --- a/src/java.desktop/windows/classes/sun/print/Win32MediaTray.java +++ b/src/java.desktop/windows/classes/sun/print/Win32MediaTray.java @@ -35,7 +35,7 @@ import java.util.ArrayList; * It also implements driver-defined trays. **/ @SuppressWarnings("serial") // JDK implementation class -public class Win32MediaTray extends MediaTray { +public final class Win32MediaTray extends MediaTray { static final Win32MediaTray ENVELOPE_MANUAL = new Win32MediaTray(0, 6); //DMBIN_ENVMANUAL @@ -96,6 +96,7 @@ public class Win32MediaTray extends MediaTray { return (myStringTable.length+winStringTable.size()); } + @Override protected String[] getStringTable() { ArrayList completeList = new ArrayList<>(); for (int i=0; i < myStringTable.length; i++) { @@ -106,6 +107,7 @@ public class Win32MediaTray extends MediaTray { return completeList.toArray(nameTable); } + @Override protected EnumSyntax[] getEnumValueTable() { ArrayList completeList = new ArrayList<>(); for (int i=0; i < myEnumValueTable.length; i++) { diff --git a/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java b/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java index f8ee2d3db0b..cd4eec9926b 100644 --- a/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java +++ b/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java @@ -73,7 +73,7 @@ import javax.print.attribute.standard.PrinterStateReasons; import java.awt.print.*; -public class Win32PrintJob implements CancelablePrintJob { +public final class Win32PrintJob implements CancelablePrintJob { private transient ArrayList jobListeners; private transient ArrayList attrListeners; @@ -113,10 +113,12 @@ public class Win32PrintJob implements CancelablePrintJob { this.service = service; } + @Override public PrintService getPrintService() { return service; } + @Override public PrintJobAttributeSet getAttributes() { synchronized (this) { if (jobAttrSet == null) { @@ -129,6 +131,7 @@ public class Win32PrintJob implements CancelablePrintJob { } } + @Override public void addPrintJobListener(PrintJobListener listener) { synchronized (this) { if (listener == null) { @@ -141,6 +144,7 @@ public class Win32PrintJob implements CancelablePrintJob { } } + @Override public void removePrintJobListener(PrintJobListener listener) { synchronized (this) { if (listener == null || jobListeners == null ) { @@ -254,6 +258,7 @@ public class Win32PrintJob implements CancelablePrintJob { } } + @Override public void addPrintJobAttributeListener( PrintJobAttributeListener listener, PrintJobAttributeSet attributes) { @@ -273,6 +278,7 @@ public class Win32PrintJob implements CancelablePrintJob { } } + @Override public void removePrintJobAttributeListener( PrintJobAttributeListener listener) { synchronized (this) { @@ -293,6 +299,7 @@ public class Win32PrintJob implements CancelablePrintJob { } } + @Override public void print(Doc doc, PrintRequestAttributeSet attributes) throws PrintException { @@ -697,6 +704,7 @@ public class Win32PrintJob implements CancelablePrintJob { private native boolean endPrintRawData(); /* Cancel PrinterJob jobs that haven't yet completed. */ + @Override public void cancel() throws PrintException { synchronized (this) { if (!printing) { diff --git a/src/java.desktop/windows/classes/sun/print/Win32PrintService.java b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java index 7d85755bf0c..3bca5b581bb 100644 --- a/src/java.desktop/windows/classes/sun/print/Win32PrintService.java +++ b/src/java.desktop/windows/classes/sun/print/Win32PrintService.java @@ -78,7 +78,7 @@ import javax.print.attribute.standard.SheetCollate; import javax.print.event.PrintServiceAttributeListener; import sun.awt.windows.WPrinterJob; -public class Win32PrintService implements PrintService, AttributeUpdater, +public final class Win32PrintService implements PrintService, AttributeUpdater, SunPrinterJobService { public static MediaSize[] predefMedia = Win32MediaSize.getPredefMedia(); @@ -242,6 +242,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, isInvalid = true; } + @Override public String getName() { return printer; } @@ -857,6 +858,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return false; } + @Override public DocPrintJob createPrintJob() { return new Win32PrintJob(this); } @@ -868,6 +870,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return attrs; } + @Override public PrintServiceAttributeSet getUpdatedAttributes() { PrintServiceAttributeSet currSet = getDynamicAttributes(); if (lastSet == null) { @@ -896,6 +899,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } + @Override public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener) { synchronized (this) { @@ -909,6 +913,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } + @Override public void removePrintServiceAttributeListener( PrintServiceAttributeListener listener) { synchronized (this) { @@ -923,6 +928,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } + @Override @SuppressWarnings("unchecked") public T getAttribute(Class category) @@ -955,6 +961,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } + @Override public PrintServiceAttributeSet getAttributes() { PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); @@ -979,6 +986,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return AttributeSetUtilities.unmodifiableView(attrs); } + @Override public DocFlavor[] getSupportedDocFlavors() { int len = supportedFlavors.length; DocFlavor[] supportedDocFlavors; @@ -998,6 +1006,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return supportedDocFlavors; } + @Override public boolean isDocFlavorSupported(DocFlavor flavor) { /* To avoid a native query which may be time-consuming * do not invoke native unless postscript support is being queried. @@ -1017,6 +1026,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return false; } + @Override public Class[] getSupportedAttributeCategories() { ArrayList> categList = new ArrayList<>(otherAttrCats.length+3); for (int i=0; i < otherAttrCats.length; i++) { @@ -1049,6 +1059,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return categList.toArray(new Class[categList.size()]); } + @Override public boolean isAttributeCategorySupported(Class category) { @@ -1072,6 +1083,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return false; } + @Override public Object getDefaultAttributeValue(Class category) { @@ -1255,6 +1267,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } + @Override public Object getSupportedAttributeValues(Class category, DocFlavor flavor, @@ -1457,6 +1470,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } + @Override public boolean isAttributeValueSupported(Attribute attr, DocFlavor flavor, AttributeSet attributes) { @@ -1586,6 +1600,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return true; } + @Override public AttributeSet getUnsupportedAttributes(DocFlavor flavor, AttributeSet attributes) { @@ -1622,7 +1637,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, private Win32DocumentPropertiesUI docPropertiesUI = null; - private static class Win32DocumentPropertiesUI + private static final class Win32DocumentPropertiesUI extends DocumentPropertiesUI { Win32PrintService service; @@ -1631,6 +1646,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, service = s; } + @Override public PrintRequestAttributeSet showDocumentProperties(PrinterJob job, Window owner, @@ -1649,7 +1665,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return new Win32DocumentPropertiesUI(this); } - private static class Win32ServiceUIFactory extends ServiceUIFactory { + private static final class Win32ServiceUIFactory extends ServiceUIFactory { Win32PrintService service; @@ -1657,6 +1673,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, service = s; } + @Override public Object getUI(int role, String ui) { if (role <= ServiceUIFactory.MAIN_UIROLE) { return null; @@ -1669,6 +1686,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, throw new IllegalArgumentException("Unsupported role"); } + @Override public String[] getUIClassNamesForRole(int role) { if (role <= ServiceUIFactory.MAIN_UIROLE) { @@ -1685,6 +1703,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, private Win32ServiceUIFactory uiFactory = null; + @Override public synchronized ServiceUIFactory getServiceUIFactory() { if (uiFactory == null) { uiFactory = new Win32ServiceUIFactory(this); @@ -1692,20 +1711,24 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return uiFactory; } + @Override public String toString() { return "Win32 Printer : " + getName(); } + @Override public boolean equals(Object obj) { return (obj == this || (obj instanceof Win32PrintService && ((Win32PrintService)obj).getName().equals(getName()))); } + @Override public int hashCode() { return this.getClass().hashCode()+getName().hashCode(); } + @Override public boolean usesClass(Class c) { return (c == sun.awt.windows.WPrinterJob.class); } @@ -1727,7 +1750,7 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } @SuppressWarnings("serial") // JDK implementation class -class Win32MediaSize extends MediaSizeName { +final class Win32MediaSize extends MediaSizeName { private static ArrayList winStringTable = new ArrayList<>(); private static ArrayList winEnumTable = new ArrayList<>(); private static MediaSize[] predefMedia; @@ -1787,11 +1810,13 @@ class Win32MediaSize extends MediaSizeName { return dmPaperID; } + @Override protected String[] getStringTable() { String[] nameTable = new String[winStringTable.size()]; return winStringTable.toArray(nameTable); } + @Override protected EnumSyntax[] getEnumValueTable() { MediaSizeName[] enumTable = new MediaSizeName[winEnumTable.size()]; return winEnumTable.toArray(enumTable); diff --git a/src/java.desktop/windows/classes/sun/swing/plaf/windows/ClassicSortArrowIcon.java b/src/java.desktop/windows/classes/sun/swing/plaf/windows/ClassicSortArrowIcon.java index 6430a71f06e..f1180b3ae38 100644 --- a/src/java.desktop/windows/classes/sun/swing/plaf/windows/ClassicSortArrowIcon.java +++ b/src/java.desktop/windows/classes/sun/swing/plaf/windows/ClassicSortArrowIcon.java @@ -37,7 +37,7 @@ import javax.swing.plaf.UIResource; * */ @SuppressWarnings("serial") // JDK-implementation class -public class ClassicSortArrowIcon implements Icon, UIResource, Serializable{ +public final class ClassicSortArrowIcon implements Icon, UIResource, Serializable{ private static final int X_OFFSET = 9; private boolean ascending; @@ -45,6 +45,7 @@ public class ClassicSortArrowIcon implements Icon, UIResource, Serializable{ this.ascending = ascending; } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { x += X_OFFSET; if (ascending) { @@ -89,9 +90,11 @@ public class ClassicSortArrowIcon implements Icon, UIResource, Serializable{ g.fillRect(x, y, 1, 2); } + @Override public int getIconWidth() { return X_OFFSET + 8; } + @Override public int getIconHeight() { return 9; } From 1889dacb1981d3d15174bc5a201e683a6cdab725 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 16:01:34 +0000 Subject: [PATCH 297/843] 8353007: Open some JComboBox bugs 2 Reviewed-by: kizune, honkar --- .../jdk/javax/swing/JComboBox/bug4185024.java | 109 +++++++++++++++ .../jdk/javax/swing/JComboBox/bug4201964.java | 77 +++++++++++ .../jdk/javax/swing/JComboBox/bug4249732.java | 72 ++++++++++ .../jdk/javax/swing/JComboBox/bug4368848.java | 129 ++++++++++++++++++ 4 files changed, 387 insertions(+) create mode 100644 test/jdk/javax/swing/JComboBox/bug4185024.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4201964.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4249732.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4368848.java diff --git a/test/jdk/javax/swing/JComboBox/bug4185024.java b/test/jdk/javax/swing/JComboBox/bug4185024.java new file mode 100644 index 00000000000..da0360143d6 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4185024.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Point; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JPanel; + +/* + * @test + * @bug 4185024 + * @summary Tests that Heavyweight combo boxes on JDesktop work correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4185024 + */ + +public class bug4185024 { + private static final String INSTRUCTIONS = """ + Click on the JComboBox button inside the JInternalFrame to bring up the menu. + Select one of the menu items and verify that the choice is highlighted correctly. + Click and drag the menu's scroll bar down and verify that it causes the menu to scroll down. + + Inside JInternalFrame: + This test is for the JComboBox in the JInternalFrame. + To test, please click on the combobox and check the following: + Does the selection in the popup list follow the mouse? + Does the popup list respond to clicking and dragging the scroll bar? + If so, press PASS, otherwise, press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4185024::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4185024"); + JPanel p = new JPanel(); + p.setLayout(new BorderLayout()); + JDesktopPane desktop = new JDesktopPane(); + p.add(desktop); + frame.add(p); + + JComboBox months = new JComboBox(); + months.addItem("January"); + months.addItem("February"); + months.addItem("March"); + months.addItem("April"); + months.addItem("May"); + months.addItem("June"); + months.addItem("July"); + months.addItem("August"); + months.addItem("September"); + months.addItem("October"); + months.addItem("November"); + months.addItem("December"); + months.getAccessibleContext().setAccessibleName("Months"); + months.getAccessibleContext().setAccessibleDescription("Choose a month of the year"); + + // Set this to true and the popup works correctly... + months.setLightWeightPopupEnabled(false); + + addFrame("Months", desktop, months); + + frame.setSize(300, 300); + return frame; + } + + private static void addFrame(String title, JDesktopPane desktop, JComponent component) { + JInternalFrame jf = new JInternalFrame(title); + Point newPos = new Point(20, 20); + jf.setResizable(true); + jf.add(component); + jf.setLocation(newPos); + desktop.add(jf); + + jf.pack(); + jf.show(); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4201964.java b/test/jdk/javax/swing/JComboBox/bug4201964.java new file mode 100644 index 00000000000..5c3a0f30199 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4201964.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.UIManager; + +/* + * @test + * @bug 4201964 + * @summary Tests that JComboBox's arrow button isn't drawn too wide in Windows Look&Feel + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4201964 + */ + +public class bug4201964 { + private static final String INSTRUCTIONS = """ + Does the arrow look too large? If not, it passes. + """; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + PassFailJFrame.forceFail("Couldn't load the Windows look and feel."); + } + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(8) + .columns(30) + .testUI(bug4201964::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4201964"); + JPanel panel = new JPanel(); + JComboBox comboBox; + + comboBox = new JComboBox(new Object[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea"}); + + panel.add(comboBox); + + frame.add(panel); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4249732.java b/test/jdk/javax/swing/JComboBox/bug4249732.java new file mode 100644 index 00000000000..b8de7fa48b7 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4249732.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.BorderLayout; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.UIManager; + +/* + * @test + * @bug 4249732 + * @requires (os.family == "windows") + * @summary Tests that Windows editable combo box selects text picked from its list + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4249732 + */ + +public class bug4249732 { + private static final String INSTRUCTIONS = """ + Click on combo box arrow button to open its dropdown list, and + select an item from there. The text in the combo box editor should + be selected, otherwise test fails. + """; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + PassFailJFrame.forceFail("Couldn't load the Windows look and feel."); + } + + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .rows(8) + .columns(40) + .testUI(bug4249732::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4249732"); + + JComboBox cb = new JComboBox(new Object[]{"foo", "bar", "baz"}); + cb.setEditable(true); + + frame.add(cb, BorderLayout.NORTH); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4368848.java b/test/jdk/javax/swing/JComboBox/bug4368848.java new file mode 100644 index 00000000000..1673c458cac --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4368848.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +/* + * @test + * @bug 4368848 + * @summary Tests that mouse wheel events cancel popups + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4368848 + */ + +public class bug4368848 { + static final String[] names = {"First Name", "Last Name", "Veggy"}; + static Object[][] data = { + {"Mark", "Andrews", false}, + {"Tom", "Ball", false}, + {"Alan", "Chung", false}, + {"Jeff", "Dinkins", false}, + {"Amy", "Fowler", false}, + {"Brian", "Gerhold", false}, + {"James", "Gosling", false}, + {"David", "Karlton", false}, + {"Dave", "Kloba", false}, + {"Peter", "Korn", false}, + {"Phil", "Milne", false}, + {"Dave", "Moore", false}, + {"Hans", "Muller", false}, + {"Rick", "Levenson", false}, + {"Tim", "Prinzing", false}, + {"Chester", "Rose", false}, + {"Ray", "Ryan", false}, + {"Georges", "Saab", false}, + {"Willie", "Walker", false}, + {"Kathy", "Walrath", false}, + {"Arnaud", "Weber", false} + }; + + private static final String INSTRUCTIONS = """ + Click any cell in the 'Veggy' column, so that combo box appears. + Make sure mouse pointer is over the table, but _not_ over the combo + box. Try scrolling the table using the mouse wheel. The combo popup + should disappear. If it stays visible, test fails. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4368848::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4368848"); + ExampleTableModel dataModel = new ExampleTableModel(); + + JComboBox _editor = new JComboBox(); + _editor.addItem(false); + _editor.addItem(true); + + JTable tableView = new JTable(dataModel); + tableView.setDefaultEditor(Boolean.class, new DefaultCellEditor(_editor)); + + frame.add(new JScrollPane(tableView)); + frame.setSize(200, 200); + return frame; + } + + static class ExampleTableModel extends AbstractTableModel { + // These methods always need to be implemented. + @Override + public int getColumnCount() { + return names.length; + } + + @Override + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + @Override + public boolean isCellEditable(int row, int col) { + return true; + } + + @Override + public String getColumnName(int column) { + return names[column]; + } + + @Override + public Class getColumnClass(int col) { + return getValueAt(0, col).getClass(); + } + } +} From 6a310613392b9d619ae1bbe3e663cb4a022165d9 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Tue, 22 Apr 2025 16:11:55 +0000 Subject: [PATCH 298/843] 8354248: Open source several AWT GridBagLayout and List tests Reviewed-by: abhiscxk --- test/jdk/ProblemList.txt | 2 + .../awt/GridBagLayout/ComponentShortage.java | 99 +++++++++ .../awt/List/ListScrollbarCursorTest.java | 70 +++++++ test/jdk/java/awt/List/ListScrollbarTest.java | 197 ++++++++++++++++++ 4 files changed, 368 insertions(+) create mode 100644 test/jdk/java/awt/GridBagLayout/ComponentShortage.java create mode 100644 test/jdk/java/awt/List/ListScrollbarCursorTest.java create mode 100644 test/jdk/java/awt/List/ListScrollbarTest.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index fe0657ff165..56224181b0a 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -464,6 +464,7 @@ java/awt/TrayIcon/RightClickWhenBalloonDisplayed/RightClickWhenBalloonDisplayed. java/awt/PopupMenu/PopupMenuLocation.java 8259913,8315878 windows-all,macosx-aarch64 java/awt/GridLayout/ComponentPreferredSize/ComponentPreferredSize.java 8238720,8324782 windows-all,macosx-all java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java 8238720,8324782 windows-all,macosx-all +java/awt/GridBagLayout/ComponentShortage.java 8355280 windows-all,linux-all java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.java 8238720 windows-all # Several tests which fail sometimes on macos11 @@ -815,6 +816,7 @@ java/awt/PopupMenu/PopupHangTest.java 8340022 windows-all java/awt/Focus/MinimizeNonfocusableWindowTest.java 8024487 windows-all java/awt/Focus/InactiveFocusRace.java 8023263 linux-all java/awt/List/HandlingKeyEventIfMousePressedTest.java 6848358 macosx-all,windows-all +java/awt/List/ListScrollbarCursorTest.java 8066410 generic-all java/awt/Checkbox/CheckboxBoxSizeTest.java 8340870 windows-all java/awt/Checkbox/CheckboxIndicatorSizeTest.java 8340870 windows-all java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all diff --git a/test/jdk/java/awt/GridBagLayout/ComponentShortage.java b/test/jdk/java/awt/GridBagLayout/ComponentShortage.java new file mode 100644 index 00000000000..dd641bbf066 --- /dev/null +++ b/test/jdk/java/awt/GridBagLayout/ComponentShortage.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4238932 + * @summary JTextField in gridBagLayout does not properly set MinimumSize + * @key headful + * @run main ComponentShortage + */ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JTextField; + +public class ComponentShortage { + static final int WIDTH_REDUCTION = 50; + static JFrame frame; + static JTextField jtf; + static volatile Dimension size; + static volatile Dimension fSize; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new JFrame(); + frame.setLayout(new GridBagLayout()); + GridBagConstraints gBC = new GridBagConstraints(); + + gBC.gridx = 1; + gBC.gridy = 0; + gBC.gridwidth = 1; + gBC.gridheight = 1; + gBC.weightx = 1.0; + gBC.weighty = 0.0; + gBC.fill = GridBagConstraints.NONE; + gBC.anchor = GridBagConstraints.NORTHWEST; + jtf = new JTextField(16); + frame.add(jtf, gBC); + frame.pack(); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + size = jtf.getSize(); + }); + System.out.println("TextField size before Frame's width reduction : " + size); + + EventQueue.invokeAndWait(() -> { + frame.setSize(frame.getSize().width - WIDTH_REDUCTION, frame.getSize().height); + }); + frame.repaint(); + + EventQueue.invokeAndWait(() -> { + size = jtf.getSize(); + fSize = frame.getSize(); + }); + System.out.println("TextField size after Frame's width reduction : " + size); + + if (size.width < fSize.width - WIDTH_REDUCTION) { + throw new RuntimeException("Width of JTextField is too small to be visible."); + } + System.out.println("Test passed."); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/List/ListScrollbarCursorTest.java b/test/jdk/java/awt/List/ListScrollbarCursorTest.java new file mode 100644 index 00000000000..fc832029b13 --- /dev/null +++ b/test/jdk/java/awt/List/ListScrollbarCursorTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4290684 + * @summary Tests that cursor on the scrollbar of the list is set to default. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ListScrollbarCursorTest + */ + +import java.awt.Cursor; +import java.awt.Frame; +import java.awt.List; +import java.awt.Panel; + +public class ListScrollbarCursorTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. You see the list in the middle of the panel. + This list has two scrollbars. + 2. The cursor should have a shape of hand over the main area + and a shape of arrow over scrollbars. + 3. Move the mouse cursor to either horizontal or vertical scrollbar. + 4. Press PASS if you see the default arrow cursor else press FAIL. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ListScrollbarCursorTest::initialize) + .build() + .awaitAndCheck(); + } + + static Frame initialize() { + Frame frame = new Frame("List Scrollbar Cursor Test"); + Panel panel = new Panel(); + List list = new List(3); + list.add("List item with a very long name" + + "(just to make the horizontal scrollbar visible)"); + list.add("Item 2"); + list.add("Item 3"); + list.setCursor(new Cursor(Cursor.HAND_CURSOR)); + panel.add(list); + frame.add(panel); + frame.setSize(200, 200); + return frame; + } +} diff --git a/test/jdk/java/awt/List/ListScrollbarTest.java b/test/jdk/java/awt/List/ListScrollbarTest.java new file mode 100644 index 00000000000..b676303b927 --- /dev/null +++ b/test/jdk/java/awt/List/ListScrollbarTest.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4096445 + * @summary Test to verify List Scollbar appears/disappears automatically + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ListScrollbarTest + */ + +import java.awt.Button; +import java.awt.Component; +import java.awt.Event; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.List; + +public class ListScrollbarTest extends Frame { + static final int ITEMS = 10; + List ltList; + List rtList; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. There are two lists added to the Frame separated by + a column of buttons + 2. Double click on any item(s) on the left list, you would see + a '*' added at the end of the item + 3. Keep double clicking on the same item till the length of the + item exceeds the width of the list + 4. Now, if you don't get the horizontal scrollbar on + the left list click FAIL. + 5. If you get horizontal scrollbar, select the item + (that you double clicked) and press the '>' button + to move the item to the right list. + 6. If horizontal scroll bar appears on the right list + as well as disappears from the left list [only if both + happen] proceed with step 8 else click FAIL + 7. Now move the same item to the left list, by pressing + '<' button + 8. If the horizontal scrollbar appears on the left list + and disappears from the right list[only if both happen] + click PASS else click FAIL. + """; + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(ListScrollbarTest::new) + .build() + .awaitAndCheck(); + } + + public ListScrollbarTest() { + super("List scroll bar test"); + GridBagLayout gbl = new GridBagLayout(); + ltList = new List(ITEMS, true); + rtList = new List(0, true); + setLayout(gbl); + add(ltList, 0, 0, 1, 5, 1.0, 1.0); + add(rtList, 2, 0, 1, 5, 1.0, 1.0); + add(new Button(">"), 1, 0, 1, 1, 0, 1.0); + add(new Button(">>"), 1, 1, 1, 1, 0, 1.0); + add(new Button("<"), 1, 2, 1, 1, 0, 1.0); + add(new Button("<<"), 1, 3, 1, 1, 0, 1.0); + add(new Button("!"), 1, 4, 1, 1, 0, 1.0); + + for (int i = 0; i < ITEMS; i++) { + ltList.addItem("item " + i); + } + setSize(220, 250); + } + + void add(Component comp, int x, int y, int w, int h, double weightx, double weighty) { + GridBagLayout gbl = (GridBagLayout) getLayout(); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.gridx = x; + c.gridy = y; + c.gridwidth = w; + c.gridheight = h; + c.weightx = weightx; + c.weighty = weighty; + add(comp); + gbl.setConstraints(comp, c); + } + + void reverseSelections(List l) { + for (int i = 0; i < l.countItems(); i++) { + if (l.isSelected(i)) { + l.deselect(i); + } else { + l.select(i); + } + } + } + + void deselectAll(List l) { + for (int i = 0; i < l.countItems(); i++) { + l.deselect(i); + } + } + + void replaceItem(List l, String item) { + for (int i = 0; i < l.countItems(); i++) { + if (l.getItem(i).equals(item)) { + l.replaceItem(item + "*", i); + } + } + } + + void move(List l1, List l2, boolean all) { + + // if all the items are to be moved + if (all) { + for (int i = 0; i < l1.countItems(); i++) { + l2.addItem(l1.getItem(i)); + } + l1.delItems(0, l1.countItems() - 1); + } else { // else move the selected items + String[] items = l1.getSelectedItems(); + int[] itemIndexes = l1.getSelectedIndexes(); + + deselectAll(l2); + for (int i = 0; i < items.length; i++) { + l2.addItem(items[i]); + l2.select(l2.countItems() - 1); + if (i == 0) { + l2.makeVisible(l2.countItems() - 1); + } + } + for (int i = itemIndexes.length - 1; i >= 0; i--) { + l1.delItem(itemIndexes[i]); + } + } + } + + @Override + public boolean action(Event evt, Object arg) { + if (">".equals(arg)) { + move(ltList, rtList, false); + } else if (">>".equals(arg)) { + move(ltList, rtList, true); + } else if ("<".equals(arg)) { + move(rtList, ltList, false); + } else if ("<<".equals(arg)) { + move(rtList, ltList, true); + } else if ("!".equals(arg)) { + if (ltList.getSelectedItems().length > 0) { + reverseSelections(ltList); + } else if (rtList.getSelectedItems().length > 0) { + reverseSelections(rtList); + } + } else if (evt.target == rtList || evt.target == ltList) { + replaceItem((List) evt.target, (String) arg); + } else { + return false; + } + return true; + } + + @Override + public boolean handleEvent(Event evt) { + if (evt.id == Event.LIST_SELECT + || evt.id == Event.LIST_DESELECT) { + if (evt.target == ltList) { + deselectAll(rtList); + } else if (evt.target == rtList) { + deselectAll(ltList); + } + return true; + } + return super.handleEvent(evt); + } +} From d783a940988677dc91975f884adeaf9f047f7e07 Mon Sep 17 00:00:00 2001 From: Boris Ulasevich Date: Tue, 22 Apr 2025 16:46:44 +0000 Subject: [PATCH 299/843] 8332368: ubsan aarch64: immediate_aarch64.cpp:298:31: runtime error: shift exponent 32 is too large for 32-bit type 'int' Reviewed-by: adinn --- src/hotspot/share/adlc/output_h.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/adlc/output_h.cpp b/src/hotspot/share/adlc/output_h.cpp index a4ab29008f0..dd149064a5a 100644 --- a/src/hotspot/share/adlc/output_h.cpp +++ b/src/hotspot/share/adlc/output_h.cpp @@ -870,7 +870,8 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " void step(uint cycles) {\n"); fprintf(fp_hpp, " _used = 0;\n"); - fprintf(fp_hpp, " _mask <<= cycles;\n"); + fprintf(fp_hpp, " uint max_shift = 8 * sizeof(_mask) - 1;\n"); + fprintf(fp_hpp, " _mask <<= (cycles < max_shift) ? cycles : max_shift;\n"); fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " friend class Pipeline_Use;\n"); fprintf(fp_hpp, "};\n\n"); From 594b26516e5c01d7daa331db59bdbe8ab7dc0a6d Mon Sep 17 00:00:00 2001 From: Jamil Nimeh Date: Tue, 22 Apr 2025 16:49:29 +0000 Subject: [PATCH 300/843] 8350126: Regression ~3% on Crypto-ChaCha20Poly1305.encrypt for MacOSX aarch64 Reviewed-by: aph --- .../cpu/aarch64/macroAssembler_aarch64.hpp | 16 +- .../aarch64/macroAssembler_aarch64_chacha.cpp | 151 ++++--- .../cpu/aarch64/stubGenerator_aarch64.cpp | 386 +++++++++--------- 3 files changed, 305 insertions(+), 248 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 11d1985e50b..af09f97e938 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1611,11 +1611,15 @@ public: void aes_round(FloatRegister input, FloatRegister subkey); // ChaCha20 functions support block - void cc20_quarter_round(FloatRegister aVec, FloatRegister bVec, - FloatRegister cVec, FloatRegister dVec, FloatRegister scratch, - FloatRegister tbl); - void cc20_shift_lane_org(FloatRegister bVec, FloatRegister cVec, - FloatRegister dVec, bool colToDiag); + void cc20_qr_add4(FloatRegister (&addFirst)[4], + FloatRegister (&addSecond)[4]); + void cc20_qr_xor4(FloatRegister (&firstElem)[4], + FloatRegister (&secondElem)[4], FloatRegister (&result)[4]); + void cc20_qr_lrot4(FloatRegister (&sourceReg)[4], + FloatRegister (&destReg)[4], int bits, FloatRegister table); + void cc20_set_qr_registers(FloatRegister (&vectorSet)[4], + const FloatRegister (&stateVectors)[16], int idx1, int idx2, + int idx3, int idx4); // Place an ISB after code may have been modified due to a safepoint. void safepoint_isb(); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_chacha.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_chacha.cpp index 1f7bb8f46f6..083e81af5d9 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_chacha.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_chacha.cpp @@ -28,60 +28,119 @@ #include "runtime/stubRoutines.hpp" /** - * Perform the quarter round calculations on values contained within - * four SIMD registers. + * Perform the vectorized add for a group of 4 quarter round operations. + * In the ChaCha20 quarter round, there are two add ops: a += b and c += d. + * Each parameter is a set of 4 registers representing the 4 registers + * for the each addend in the add operation for each of the quarter rounds. + * (e.g. for "a" it would consist of v0/v1/v2/v3). The result of the add + * is placed into the vectors in the "addFirst" array. * - * @param aVec the SIMD register containing only the "a" values - * @param bVec the SIMD register containing only the "b" values - * @param cVec the SIMD register containing only the "c" values - * @param dVec the SIMD register containing only the "d" values - * @param scratch scratch SIMD register used for 12 and 7 bit left rotations - * @param table the SIMD register used as a table for 8 bit left rotations + * @param addFirst array of SIMD registers representing the first addend. + * @param addSecond array of SIMD registers representing the second addend. */ -void MacroAssembler::cc20_quarter_round(FloatRegister aVec, FloatRegister bVec, - FloatRegister cVec, FloatRegister dVec, FloatRegister scratch, - FloatRegister table) { +void MacroAssembler::cc20_qr_add4(FloatRegister (&addFirst)[4], + FloatRegister (&addSecond)[4]) { + for (int i = 0; i < 4; i++) { + addv(addFirst[i], T4S, addFirst[i], addSecond[i]); + } +} - // a += b, d ^= a, d <<<= 16 - addv(aVec, T4S, aVec, bVec); - eor(dVec, T16B, dVec, aVec); - rev32(dVec, T8H, dVec); - // c += d, b ^= c, b <<<= 12 - addv(cVec, T4S, cVec, dVec); - eor(scratch, T16B, bVec, cVec); - ushr(bVec, T4S, scratch, 20); - sli(bVec, T4S, scratch, 12); - - // a += b, d ^= a, d <<<= 8 - addv(aVec, T4S, aVec, bVec); - eor(dVec, T16B, dVec, aVec); - tbl(dVec, T16B, dVec, 1, table); - - // c += d, b ^= c, b <<<= 7 - addv(cVec, T4S, cVec, dVec); - eor(scratch, T16B, bVec, cVec); - ushr(bVec, T4S, scratch, 25); - sli(bVec, T4S, scratch, 7); +/** + * Perform the vectorized XOR for a group of 4 quarter round operations. + * In the ChaCha20 quarter round, there are two XOR ops: d ^= a and b ^= c + * Each parameter is a set of 4 registers representing the 4 registers + * for the each element in the xor operation for each of the quarter rounds. + * (e.g. for "a" it would consist of v0/v1/v2/v3) + * Note: because the b ^= c ops precede a non-byte-aligned left-rotation, + * there is a third parameter which can take a set of scratch registers + * for the result, which facilitates doing the subsequent operations for + * the left rotation. + * + * @param firstElem array of SIMD registers representing the first element. + * @param secondElem array of SIMD registers representing the second element. + * @param result array of SIMD registers representing the destination. + * May be the same as firstElem or secondElem, or a separate array. + */ +void MacroAssembler::cc20_qr_xor4(FloatRegister (&firstElem)[4], + FloatRegister (&secondElem)[4], FloatRegister (&result)[4]) { + for (int i = 0; i < 4; i++) { + eor(result[i], T16B, firstElem[i], secondElem[i]); + } } /** - * Shift the b, c, and d vectors between columnar and diagonal representations. - * Note that the "a" vector does not shift. + * Perform the vectorized left-rotation on 32-bit lanes for a group of + * 4 quarter round operations. + * Each parameter is a set of 4 registers representing the 4 registers + * for the each element in the source and destination for each of the quarter + * rounds (e.g. for "d" it would consist of v12/v13/v14/v15 on columns and + * v15/v12/v13/v14 on diagonal alignments). * - * @param bVec the SIMD register containing only the "b" values - * @param cVec the SIMD register containing only the "c" values - * @param dVec the SIMD register containing only the "d" values - * @param colToDiag true if moving columnar to diagonal, false if - * moving diagonal back to columnar. + * @param sourceReg array of SIMD registers representing the source + * @param destReg array of SIMD registers representing the destination + * @param bits the distance of the rotation in bits, must be 16/12/8/7 per + * the ChaCha20 specification. */ -void MacroAssembler::cc20_shift_lane_org(FloatRegister bVec, FloatRegister cVec, - FloatRegister dVec, bool colToDiag) { - int bShift = colToDiag ? 4 : 12; - int cShift = 8; - int dShift = colToDiag ? 12 : 4; +void MacroAssembler::cc20_qr_lrot4(FloatRegister (&sourceReg)[4], + FloatRegister (&destReg)[4], int bits, FloatRegister table) { + switch (bits) { + case 16: // reg <<<= 16, in-place swap of half-words + for (int i = 0; i < 4; i++) { + rev32(destReg[i], T8H, sourceReg[i]); + } + break; - ext(bVec, T16B, bVec, bVec, bShift); - ext(cVec, T16B, cVec, cVec, cShift); - ext(dVec, T16B, dVec, dVec, dShift); + case 7: // reg <<<= (12 || 7) + case 12: // r-shift src -> dest, l-shift src & ins to dest + for (int i = 0; i < 4; i++) { + ushr(destReg[i], T4S, sourceReg[i], 32 - bits); + } + + for (int i = 0; i < 4; i++) { + sli(destReg[i], T4S, sourceReg[i], bits); + } + break; + + case 8: // reg <<<= 8, simulate left rotation with table reorg + for (int i = 0; i < 4; i++) { + tbl(destReg[i], T16B, sourceReg[i], 1, table); + } + break; + + default: + // The caller shouldn't be sending bit rotation values outside + // of the 16/12/8/7 as defined in the specification. + ShouldNotReachHere(); + } +} + +/** + * Set the FloatRegisters for a 4-vector register set. These will be used + * during various quarter round transformations (adds, xors and left-rotations). + * This method itself does not result in the output of any assembly + * instructions. It just organizes the vectors so they can be in columnar or + * diagonal alignments. + * + * @param vectorSet a 4-vector array to be altered into a new alignment + * @param stateVectors the 16-vector array that represents the current + * working state. The indices of this array match up with the + * organization of the ChaCha20 state per RFC 7539 (e.g. stateVectors[12] + * would contain the vector that holds the 32-bit counter, etc.) + * @param idx1 the index of the stateVectors array to be assigned to the + * first vectorSet element. + * @param idx2 the index of the stateVectors array to be assigned to the + * second vectorSet element. + * @param idx3 the index of the stateVectors array to be assigned to the + * third vectorSet element. + * @param idx4 the index of the stateVectors array to be assigned to the + * fourth vectorSet element. + */ +void MacroAssembler::cc20_set_qr_registers(FloatRegister (&vectorSet)[4], + const FloatRegister (&stateVectors)[16], int idx1, int idx2, + int idx3, int idx4) { + vectorSet[0] = stateVectors[idx1]; + vectorSet[1] = stateVectors[idx2]; + vectorSet[2] = stateVectors[idx3]; + vectorSet[3] = stateVectors[idx4]; } diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 467505ed337..a6cc757f6a0 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -4405,89 +4405,44 @@ class StubGenerator: public StubCodeGenerator { return start; } - /** - * Arguments: - * - * Inputs: - * c_rarg0 - int crc - * c_rarg1 - byte* buf - * c_rarg2 - int length - * - * Output: - * rax - int crc result - */ - address generate_updateBytesCRC32() { - assert(UseCRC32Intrinsics, "what are we doing here?"); - - __ align(CodeEntryAlignment); - StubGenStubId stub_id = StubGenStubId::updateBytesCRC32_id; - StubCodeMark mark(this, stub_id); - - address start = __ pc(); - - const Register crc = c_rarg0; // crc - const Register buf = c_rarg1; // source java byte array address - const Register len = c_rarg2; // length - const Register table0 = c_rarg3; // crc_table address - const Register table1 = c_rarg4; - const Register table2 = c_rarg5; - const Register table3 = c_rarg6; - const Register tmp3 = c_rarg7; - - BLOCK_COMMENT("Entry:"); - __ enter(); // required for proper stackwalking of RuntimeStub frame - - __ kernel_crc32(crc, buf, len, - table0, table1, table2, table3, rscratch1, rscratch2, tmp3); - - __ leave(); // required for proper stackwalking of RuntimeStub frame - __ ret(lr); - - return start; - } - - // ChaCha20 block function. This version parallelizes 4 quarter - // round operations at a time. It uses 16 SIMD registers to - // produce 4 blocks of key stream. + // ChaCha20 block function. This version parallelizes the 32-bit + // state elements on each of 16 vectors, producing 4 blocks of + // keystream at a time. // // state (int[16]) = c_rarg0 // keystream (byte[256]) = c_rarg1 - // return - number of bytes of keystream (always 256) + // return - number of bytes of produced keystream (always 256) // - // In this approach, we load the 512-bit start state sequentially into - // 4 128-bit vectors. We then make 4 4-vector copies of that starting - // state, with each successive set of 4 vectors having a +1 added into - // the first 32-bit lane of the 4th vector in that group (the counter). - // By doing this, we can perform the block function on 4 512-bit blocks - // within one run of this intrinsic. - // The alignment of the data across the 4-vector group is such that at - // the start it is already aligned for the first round of each two-round - // loop iteration. In other words, the corresponding lanes of each vector - // will contain the values needed for that quarter round operation (e.g. - // elements 0/4/8/12, 1/5/9/13, 2/6/10/14, etc.). - // In between each full round, a lane shift must occur. Within a loop - // iteration, between the first and second rounds, the 2nd, 3rd, and 4th - // vectors are rotated left 32, 64 and 96 bits, respectively. The result - // is effectively a diagonal orientation in columnar form. After the - // second full round, those registers are left-rotated again, this time - // 96, 64, and 32 bits - returning the vectors to their columnar organization. - // After all 10 iterations, the original state is added to each 4-vector - // working state along with the add mask, and the 4 vector groups are - // sequentially written to the memory dedicated for the output key stream. - // - // For a more detailed explanation, see Goll and Gueron, "Vectorization of - // ChaCha Stream Cipher", 2014 11th Int. Conf. on Information Technology: - // New Generations, Las Vegas, NV, USA, April 2014, DOI: 10.1109/ITNG.2014.33 - address generate_chacha20Block_qrpar() { - Label L_Q_twoRounds, L_Q_cc20_const; + // This implementation takes each 32-bit integer from the state + // array and broadcasts it across all 4 32-bit lanes of a vector register + // (e.g. state[0] is replicated on all 4 lanes of v4, state[1] to all 4 lanes + // of v5, etc.). Once all 16 elements have been broadcast onto 16 vectors, + // the quarter round schedule is implemented as outlined in RFC 7539 section + // 2.3. However, instead of sequentially processing the 3 quarter round + // operations represented by one QUARTERROUND function, we instead stack all + // the adds, xors and left-rotations from the first 4 quarter rounds together + // and then do the same for the second set of 4 quarter rounds. This removes + // some latency that would otherwise be incurred by waiting for an add to + // complete before performing an xor (which depends on the result of the + // add), etc. An adjustment happens between the first and second groups of 4 + // quarter rounds, but this is done only in the inputs to the macro functions + // that generate the assembly instructions - these adjustments themselves are + // not part of the resulting assembly. + // The 4 registers v0-v3 are used during the quarter round operations as + // scratch registers. Once the 20 rounds are complete, these 4 scratch + // registers become the vectors involved in adding the start state back onto + // the post-QR working state. After the adds are complete, each of the 16 + // vectors write their first lane back to the keystream buffer, followed + // by the second lane from all vectors and so on. + address generate_chacha20Block_blockpar() { + Label L_twoRounds, L_cc20_const; // The constant data is broken into two 128-bit segments to be loaded - // onto SIMD registers. The first 128 bits are a counter add overlay - // that adds +1/+0/+0/+0 to the vectors holding replicated state[12]. + // onto FloatRegisters. The first 128 bits are a counter add overlay + // that adds +0/+1/+2/+3 to the vector holding replicated state[12]. // The second 128-bits is a table constant used for 8-bit left rotations. - // on 32-bit lanes within a SIMD register. - __ BIND(L_Q_cc20_const); - __ emit_int64(0x0000000000000001UL); - __ emit_int64(0x0000000000000000UL); + __ BIND(L_cc20_const); + __ emit_int64(0x0000000100000000UL); + __ emit_int64(0x0000000300000002UL); __ emit_int64(0x0605040702010003UL); __ emit_int64(0x0E0D0C0F0A09080BUL); @@ -4497,144 +4452,142 @@ class StubGenerator: public StubCodeGenerator { address start = __ pc(); __ enter(); + int i, j; const Register state = c_rarg0; const Register keystream = c_rarg1; const Register loopCtr = r10; const Register tmpAddr = r11; + const FloatRegister ctrAddOverlay = v28; + const FloatRegister lrot8Tbl = v29; - const FloatRegister aState = v0; - const FloatRegister bState = v1; - const FloatRegister cState = v2; - const FloatRegister dState = v3; - const FloatRegister a1Vec = v4; - const FloatRegister b1Vec = v5; - const FloatRegister c1Vec = v6; - const FloatRegister d1Vec = v7; - // Skip the callee-saved registers v8 - v15 - const FloatRegister a2Vec = v16; - const FloatRegister b2Vec = v17; - const FloatRegister c2Vec = v18; - const FloatRegister d2Vec = v19; - const FloatRegister a3Vec = v20; - const FloatRegister b3Vec = v21; - const FloatRegister c3Vec = v22; - const FloatRegister d3Vec = v23; - const FloatRegister a4Vec = v24; - const FloatRegister b4Vec = v25; - const FloatRegister c4Vec = v26; - const FloatRegister d4Vec = v27; - const FloatRegister scratch = v28; - const FloatRegister addMask = v29; - const FloatRegister lrot8Tbl = v30; + // Organize SIMD registers in an array that facilitates + // putting repetitive opcodes into loop structures. It is + // important that each grouping of 4 registers is monotonically + // increasing to support the requirements of multi-register + // instructions (e.g. ld4r, st4, etc.) + const FloatRegister workSt[16] = { + v4, v5, v6, v7, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27 + }; - // Load the initial state in the first 4 quadword registers, - // then copy the initial state into the next 4 quadword registers - // that will be used for the working state. - __ ld1(aState, bState, cState, dState, __ T16B, Address(state)); + // Pull in constant data. The first 16 bytes are the add overlay + // which is applied to the vector holding the counter (state[12]). + // The second 16 bytes is the index register for the 8-bit left + // rotation tbl instruction. + __ adr(tmpAddr, L_cc20_const); + __ ldpq(ctrAddOverlay, lrot8Tbl, Address(tmpAddr)); - // Load the index register for 2 constant 128-bit data fields. - // The first represents the +1/+0/+0/+0 add mask. The second is - // the 8-bit left rotation. - __ adr(tmpAddr, L_Q_cc20_const); - __ ldpq(addMask, lrot8Tbl, Address(tmpAddr)); + // Load from memory and interlace across 16 SIMD registers, + // With each word from memory being broadcast to all lanes of + // each successive SIMD register. + // Addr(0) -> All lanes in workSt[i] + // Addr(4) -> All lanes workSt[i + 1], etc. + __ mov(tmpAddr, state); + for (i = 0; i < 16; i += 4) { + __ ld4r(workSt[i], workSt[i + 1], workSt[i + 2], workSt[i + 3], __ T4S, + __ post(tmpAddr, 16)); + } + __ addv(workSt[12], __ T4S, workSt[12], ctrAddOverlay); // Add ctr overlay - __ mov(a1Vec, __ T16B, aState); - __ mov(b1Vec, __ T16B, bState); - __ mov(c1Vec, __ T16B, cState); - __ mov(d1Vec, __ T16B, dState); + // Before entering the loop, create 5 4-register arrays. These + // will hold the 4 registers that represent the a/b/c/d fields + // in the quarter round operation. For instance the "b" field + // for the first 4 quarter round operations is the set of v16/v17/v18/v19, + // but in the second 4 quarter rounds it gets adjusted to v17/v18/v19/v16 + // since it is part of a diagonal organization. The aSet and scratch + // register sets are defined at declaration time because they do not change + // organization at any point during the 20-round processing. + FloatRegister aSet[4] = { v4, v5, v6, v7 }; + FloatRegister bSet[4]; + FloatRegister cSet[4]; + FloatRegister dSet[4]; + FloatRegister scratch[4] = { v0, v1, v2, v3 }; - __ mov(a2Vec, __ T16B, aState); - __ mov(b2Vec, __ T16B, bState); - __ mov(c2Vec, __ T16B, cState); - __ addv(d2Vec, __ T4S, d1Vec, addMask); - - __ mov(a3Vec, __ T16B, aState); - __ mov(b3Vec, __ T16B, bState); - __ mov(c3Vec, __ T16B, cState); - __ addv(d3Vec, __ T4S, d2Vec, addMask); - - __ mov(a4Vec, __ T16B, aState); - __ mov(b4Vec, __ T16B, bState); - __ mov(c4Vec, __ T16B, cState); - __ addv(d4Vec, __ T4S, d3Vec, addMask); - - // Set up the 10 iteration loop + // Set up the 10 iteration loop and perform all 8 quarter round ops __ mov(loopCtr, 10); - __ BIND(L_Q_twoRounds); + __ BIND(L_twoRounds); - // The first set of operations on the vectors covers the first 4 quarter - // round operations: - // Qround(state, 0, 4, 8,12) - // Qround(state, 1, 5, 9,13) - // Qround(state, 2, 6,10,14) - // Qround(state, 3, 7,11,15) - __ cc20_quarter_round(a1Vec, b1Vec, c1Vec, d1Vec, scratch, lrot8Tbl); - __ cc20_quarter_round(a2Vec, b2Vec, c2Vec, d2Vec, scratch, lrot8Tbl); - __ cc20_quarter_round(a3Vec, b3Vec, c3Vec, d3Vec, scratch, lrot8Tbl); - __ cc20_quarter_round(a4Vec, b4Vec, c4Vec, d4Vec, scratch, lrot8Tbl); + // Set to columnar organization and do the following 4 quarter-rounds: + // QUARTERROUND(0, 4, 8, 12) + // QUARTERROUND(1, 5, 9, 13) + // QUARTERROUND(2, 6, 10, 14) + // QUARTERROUND(3, 7, 11, 15) + __ cc20_set_qr_registers(bSet, workSt, 4, 5, 6, 7); + __ cc20_set_qr_registers(cSet, workSt, 8, 9, 10, 11); + __ cc20_set_qr_registers(dSet, workSt, 12, 13, 14, 15); - // Shuffle the b1Vec/c1Vec/d1Vec to reorganize the state vectors to - // diagonals. The a1Vec does not need to change orientation. - __ cc20_shift_lane_org(b1Vec, c1Vec, d1Vec, true); - __ cc20_shift_lane_org(b2Vec, c2Vec, d2Vec, true); - __ cc20_shift_lane_org(b3Vec, c3Vec, d3Vec, true); - __ cc20_shift_lane_org(b4Vec, c4Vec, d4Vec, true); + __ cc20_qr_add4(aSet, bSet); // a += b + __ cc20_qr_xor4(dSet, aSet, dSet); // d ^= a + __ cc20_qr_lrot4(dSet, dSet, 16, lrot8Tbl); // d <<<= 16 - // The second set of operations on the vectors covers the second 4 quarter - // round operations, now acting on the diagonals: - // Qround(state, 0, 5,10,15) - // Qround(state, 1, 6,11,12) - // Qround(state, 2, 7, 8,13) - // Qround(state, 3, 4, 9,14) - __ cc20_quarter_round(a1Vec, b1Vec, c1Vec, d1Vec, scratch, lrot8Tbl); - __ cc20_quarter_round(a2Vec, b2Vec, c2Vec, d2Vec, scratch, lrot8Tbl); - __ cc20_quarter_round(a3Vec, b3Vec, c3Vec, d3Vec, scratch, lrot8Tbl); - __ cc20_quarter_round(a4Vec, b4Vec, c4Vec, d4Vec, scratch, lrot8Tbl); + __ cc20_qr_add4(cSet, dSet); // c += d + __ cc20_qr_xor4(bSet, cSet, scratch); // b ^= c (scratch) + __ cc20_qr_lrot4(scratch, bSet, 12, lrot8Tbl); // b <<<= 12 - // Before we start the next iteration, we need to perform shuffles - // on the b/c/d vectors to move them back to columnar organizations - // from their current diagonal orientation. - __ cc20_shift_lane_org(b1Vec, c1Vec, d1Vec, false); - __ cc20_shift_lane_org(b2Vec, c2Vec, d2Vec, false); - __ cc20_shift_lane_org(b3Vec, c3Vec, d3Vec, false); - __ cc20_shift_lane_org(b4Vec, c4Vec, d4Vec, false); + __ cc20_qr_add4(aSet, bSet); // a += b + __ cc20_qr_xor4(dSet, aSet, dSet); // d ^= a + __ cc20_qr_lrot4(dSet, dSet, 8, lrot8Tbl); // d <<<= 8 + + __ cc20_qr_add4(cSet, dSet); // c += d + __ cc20_qr_xor4(bSet, cSet, scratch); // b ^= c (scratch) + __ cc20_qr_lrot4(scratch, bSet, 7, lrot8Tbl); // b <<<= 12 + + // Set to diagonal organization and do the next 4 quarter-rounds: + // QUARTERROUND(0, 5, 10, 15) + // QUARTERROUND(1, 6, 11, 12) + // QUARTERROUND(2, 7, 8, 13) + // QUARTERROUND(3, 4, 9, 14) + __ cc20_set_qr_registers(bSet, workSt, 5, 6, 7, 4); + __ cc20_set_qr_registers(cSet, workSt, 10, 11, 8, 9); + __ cc20_set_qr_registers(dSet, workSt, 15, 12, 13, 14); + + __ cc20_qr_add4(aSet, bSet); // a += b + __ cc20_qr_xor4(dSet, aSet, dSet); // d ^= a + __ cc20_qr_lrot4(dSet, dSet, 16, lrot8Tbl); // d <<<= 16 + + __ cc20_qr_add4(cSet, dSet); // c += d + __ cc20_qr_xor4(bSet, cSet, scratch); // b ^= c (scratch) + __ cc20_qr_lrot4(scratch, bSet, 12, lrot8Tbl); // b <<<= 12 + + __ cc20_qr_add4(aSet, bSet); // a += b + __ cc20_qr_xor4(dSet, aSet, dSet); // d ^= a + __ cc20_qr_lrot4(dSet, dSet, 8, lrot8Tbl); // d <<<= 8 + + __ cc20_qr_add4(cSet, dSet); // c += d + __ cc20_qr_xor4(bSet, cSet, scratch); // b ^= c (scratch) + __ cc20_qr_lrot4(scratch, bSet, 7, lrot8Tbl); // b <<<= 12 // Decrement and iterate __ sub(loopCtr, loopCtr, 1); - __ cbnz(loopCtr, L_Q_twoRounds); + __ cbnz(loopCtr, L_twoRounds); - // Once the counter reaches zero, we fall out of the loop - // and need to add the initial state back into the working state - // represented by the a/b/c/d1Vec registers. This is destructive - // on the dState register but we no longer will need it. - __ addv(a1Vec, __ T4S, a1Vec, aState); - __ addv(b1Vec, __ T4S, b1Vec, bState); - __ addv(c1Vec, __ T4S, c1Vec, cState); - __ addv(d1Vec, __ T4S, d1Vec, dState); + __ mov(tmpAddr, state); - __ addv(a2Vec, __ T4S, a2Vec, aState); - __ addv(b2Vec, __ T4S, b2Vec, bState); - __ addv(c2Vec, __ T4S, c2Vec, cState); - __ addv(dState, __ T4S, dState, addMask); - __ addv(d2Vec, __ T4S, d2Vec, dState); + // Add the starting state back to the post-loop keystream + // state. We read/interlace the state array from memory into + // 4 registers similar to what we did in the beginning. Then + // add the counter overlay onto workSt[12] at the end. + for (i = 0; i < 16; i += 4) { + __ ld4r(v0, v1, v2, v3, __ T4S, __ post(tmpAddr, 16)); + __ addv(workSt[i], __ T4S, workSt[i], v0); + __ addv(workSt[i + 1], __ T4S, workSt[i + 1], v1); + __ addv(workSt[i + 2], __ T4S, workSt[i + 2], v2); + __ addv(workSt[i + 3], __ T4S, workSt[i + 3], v3); + } + __ addv(workSt[12], __ T4S, workSt[12], ctrAddOverlay); // Add ctr overlay - __ addv(a3Vec, __ T4S, a3Vec, aState); - __ addv(b3Vec, __ T4S, b3Vec, bState); - __ addv(c3Vec, __ T4S, c3Vec, cState); - __ addv(dState, __ T4S, dState, addMask); - __ addv(d3Vec, __ T4S, d3Vec, dState); - - __ addv(a4Vec, __ T4S, a4Vec, aState); - __ addv(b4Vec, __ T4S, b4Vec, bState); - __ addv(c4Vec, __ T4S, c4Vec, cState); - __ addv(dState, __ T4S, dState, addMask); - __ addv(d4Vec, __ T4S, d4Vec, dState); - - // Write the final state back to the result buffer - __ st1(a1Vec, b1Vec, c1Vec, d1Vec, __ T16B, __ post(keystream, 64)); - __ st1(a2Vec, b2Vec, c2Vec, d2Vec, __ T16B, __ post(keystream, 64)); - __ st1(a3Vec, b3Vec, c3Vec, d3Vec, __ T16B, __ post(keystream, 64)); - __ st1(a4Vec, b4Vec, c4Vec, d4Vec, __ T16B, __ post(keystream, 64)); + // Write working state into the keystream buffer. This is accomplished + // by taking the lane "i" from each of the four vectors and writing + // it to consecutive 4-byte offsets, then post-incrementing by 16 and + // repeating with the next 4 vectors until all 16 vectors have been used. + // Then move to the next lane and repeat the process until all lanes have + // been written. + for (i = 0; i < 4; i++) { + for (j = 0; j < 16; j += 4) { + __ st4(workSt[j], workSt[j + 1], workSt[j + 2], workSt[j + 3], __ S, i, + __ post(keystream, 16)); + } + } __ mov(r0, 256); // Return length of output keystream __ leave(); @@ -7008,6 +6961,47 @@ class StubGenerator: public StubCodeGenerator { return start; } + /** + * Arguments: + * + * Inputs: + * c_rarg0 - int crc + * c_rarg1 - byte* buf + * c_rarg2 - int length + * + * Output: + * rax - int crc result + */ + address generate_updateBytesCRC32() { + assert(UseCRC32Intrinsics, "what are we doing here?"); + + __ align(CodeEntryAlignment); + StubGenStubId stub_id = StubGenStubId::updateBytesCRC32_id; + StubCodeMark mark(this, stub_id); + + address start = __ pc(); + + const Register crc = c_rarg0; // crc + const Register buf = c_rarg1; // source java byte array address + const Register len = c_rarg2; // length + const Register table0 = c_rarg3; // crc_table address + const Register table1 = c_rarg4; + const Register table2 = c_rarg5; + const Register table3 = c_rarg6; + const Register tmp3 = c_rarg7; + + BLOCK_COMMENT("Entry:"); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + __ kernel_crc32(crc, buf, len, + table0, table1, table2, table3, rscratch1, rscratch2, tmp3); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(lr); + + return start; + } + /** * Arguments: * @@ -11403,7 +11397,7 @@ class StubGenerator: public StubCodeGenerator { #endif // COMPILER2 if (UseChaCha20Intrinsics) { - StubRoutines::_chacha20Block = generate_chacha20Block_qrpar(); + StubRoutines::_chacha20Block = generate_chacha20Block_blockpar(); } if (UseKyberIntrinsics) { From e020752ea4a6f74c321bc83597fadac51332e188 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 22 Apr 2025 16:55:11 +0000 Subject: [PATCH 301/843] 8354484: SIGSEGV when supertype of an AOT-cached class is excluded Reviewed-by: ccheung, shade --- src/hotspot/share/cds/aotArtifactFinder.cpp | 29 +++++++++++++++++++-- src/hotspot/share/cds/aotArtifactFinder.hpp | 1 + 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp index 95d242c2089..65eb06ca7f0 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.cpp +++ b/src/hotspot/share/cds/aotArtifactFinder.cpp @@ -207,11 +207,36 @@ void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) { } } +void AOTArtifactFinder::append_to_all_cached_classes(Klass* k) { + precond(!SystemDictionaryShared::should_be_excluded(k)); + _all_cached_classes->append(k); +} + void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { + if (CDSConfig::is_dumping_dynamic_archive() && ik->is_shared()) { + // This class is already included in the base archive. No need to cache + // it again in the dynamic archive. + return; + } + bool created; _seen_classes->put_if_absent(ik, &created); if (created) { - _all_cached_classes->append(ik); + append_to_all_cached_classes(ik); + + // All super types must be added. + InstanceKlass* s = ik->java_super(); + if (s != nullptr) { + add_cached_instance_class(s); + } + + Array* interfaces = ik->local_interfaces(); + int len = interfaces->length(); + for (int i = 0; i < len; i++) { + InstanceKlass* intf = interfaces->at(i); + add_cached_instance_class(intf); + } + if (CDSConfig::is_dumping_final_static_archive() && ik->is_shared_unregistered_class()) { // The following are not appliable to unregistered classes return; @@ -229,7 +254,7 @@ void AOTArtifactFinder::add_cached_type_array_class(TypeArrayKlass* tak) { bool created; _seen_classes->put_if_absent(tak, &created); if (created) { - _all_cached_classes->append(tak); + append_to_all_cached_classes(tak); scan_oops_in_array_class(tak); } } diff --git a/src/hotspot/share/cds/aotArtifactFinder.hpp b/src/hotspot/share/cds/aotArtifactFinder.hpp index d890d874af9..5d293f20af0 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.hpp +++ b/src/hotspot/share/cds/aotArtifactFinder.hpp @@ -79,6 +79,7 @@ class AOTArtifactFinder : AllStatic { static void scan_oops_in_array_class(ArrayKlass* ak); static void add_cached_type_array_class(TypeArrayKlass* tak); static void add_cached_instance_class(InstanceKlass* ik); + static void append_to_all_cached_classes(Klass* k); public: static void initialize(); static void find_artifacts(); From f98af0ad617a445362859e58af48258bfd5bed03 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Tue, 22 Apr 2025 17:31:31 +0000 Subject: [PATCH 302/843] 8354701: Open source few JToolTip tests Reviewed-by: honkar --- .../jdk/javax/swing/JToolTip/TooltipTest.java | 90 +++++++++++++++++++ test/jdk/javax/swing/JToolTip/bug4225314.java | 72 +++++++++++++++ test/jdk/javax/swing/JToolTip/bug4255441.java | 64 +++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 test/jdk/javax/swing/JToolTip/TooltipTest.java create mode 100644 test/jdk/javax/swing/JToolTip/bug4225314.java create mode 100644 test/jdk/javax/swing/JToolTip/bug4255441.java diff --git a/test/jdk/javax/swing/JToolTip/TooltipTest.java b/test/jdk/javax/swing/JToolTip/TooltipTest.java new file mode 100644 index 00000000000..c081730a8d7 --- /dev/null +++ b/test/jdk/javax/swing/JToolTip/TooltipTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4207474 4218495 4375928 + * @summary Tests various tooltip issues: HTML tooltips, long tooltip text + * and mnemonic keys displayed in tooltips + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TooltipTest + */ + +import java.awt.FlowLayout; +import java.awt.event.KeyEvent; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.UIManager; + +public class TooltipTest { + private static final String INSTRUCTIONS = """ + 1. Move the mouse over the button labeled "Red tip" and let it stay + still in order to test HTML in JToolTip. If the tooltip has some + text which is red then test passes, otherwise it fails (bug 4207474). + + 2. Move the mouse over the button labeled "Long tip". + If the last letter of the tooltip appears clipped, + then the test fails. If you can see the entire last character, + then the test passes (bug 4218495). + + 3. Verify that "M" is underlined on the button labeled "Mnemonic" + Move the mouse pointer over the button labeled "Mnemonic" and look + at tooltip when it appears. It should read "hint". + If the above is true test passes else test fails (bug 4375928). + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + PassFailJFrame.builder() + .title("TooltipTest Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(TooltipTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + + JButton b = new JButton("Red tip"); + b.setToolTipText("

Here is some " + + "red text.
"); + panel.add(b); + + b = new JButton("Long tip"); + b.setToolTipText("Is the last letter clipped?"); + panel.add(b); + + b = new JButton("Mnemonic"); + b.setMnemonic(KeyEvent.VK_M); + b.setToolTipText("hint"); + panel.add(b); + + return panel; + } +} diff --git a/test/jdk/javax/swing/JToolTip/bug4225314.java b/test/jdk/javax/swing/JToolTip/bug4225314.java new file mode 100644 index 00000000000..d36bd461272 --- /dev/null +++ b/test/jdk/javax/swing/JToolTip/bug4225314.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4225314 + * @summary Tests that tooltip is painted properly when it has thick border + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4225314 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JToolTip; +import javax.swing.border.LineBorder; + +public class bug4225314 { + private static final String INSTRUCTIONS = """ + The word "Tooltip" in both tooltips should not be clipped by the + black border and be fully visible for this test to pass. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4225314 Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4225314::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JComponent createTestUI() { + JToolTip tt1 = new JToolTip(); + tt1.setTipText("Tooltip"); + tt1.setBorder(new LineBorder(Color.BLACK, 10)); + + JToolTip tt2 = new JToolTip(); + tt2.setTipText("Tooltip"); + tt2.setBorder(new LineBorder(Color.BLACK, 10)); + + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout()); + panel.add(tt1); + panel.add(tt2); + + return panel; + } +} diff --git a/test/jdk/javax/swing/JToolTip/bug4255441.java b/test/jdk/javax/swing/JToolTip/bug4255441.java new file mode 100644 index 00000000000..4a90c975502 --- /dev/null +++ b/test/jdk/javax/swing/JToolTip/bug4255441.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4255441 + * @summary Tests that tooltip appears inside AWT Frame + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4255441 + */ + +import java.awt.FlowLayout; +import java.awt.Frame; +import javax.swing.JButton; + +public class bug4255441 { + private static final String INSTRUCTIONS = """ + Move mouse pointer inside the button. + If a tooltip with "Tooltip text" appears, the test passes. + """; + + private static Frame createTestUI() { + Frame fr = new Frame("bug4255441"); + fr.setLayout(new FlowLayout()); + + JButton bt = new JButton("Button"); + bt.setToolTipText("Tooltip text"); + fr.add(bt); + + fr.setSize(200, 200); + return fr; + } + + public static void main(String[] argv) throws Exception { + PassFailJFrame.builder() + .title("bug4255441 Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4255441::createTestUI) + .build() + .awaitAndCheck(); + } +} From 486a66469bc0c814d07e03ce0e7231b408a4d579 Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Tue, 22 Apr 2025 17:49:52 +0000 Subject: [PATCH 303/843] 8353486: Open source Swing Tests - Set 4 Reviewed-by: azvegint, dnguyen, tr --- .../javax/swing/JFileChooser/bug4464774.java | 62 +++++++++ .../javax/swing/JFileChooser/bug4522756.java | 64 +++++++++ .../javax/swing/JFileChooser/bug4759934.java | 124 ++++++++++++++++++ .../javax/swing/JFileChooser/bug4943900.java | 118 +++++++++++++++++ .../javax/swing/JOptionPane/bug4194862.java | 94 +++++++++++++ 5 files changed, 462 insertions(+) create mode 100644 test/jdk/javax/swing/JFileChooser/bug4464774.java create mode 100644 test/jdk/javax/swing/JFileChooser/bug4522756.java create mode 100644 test/jdk/javax/swing/JFileChooser/bug4759934.java create mode 100644 test/jdk/javax/swing/JFileChooser/bug4943900.java create mode 100644 test/jdk/javax/swing/JOptionPane/bug4194862.java diff --git a/test/jdk/javax/swing/JFileChooser/bug4464774.java b/test/jdk/javax/swing/JFileChooser/bug4464774.java new file mode 100644 index 00000000000..368063e46cd --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4464774.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4464774 + * @requires (os.family == "windows") + * @summary JFileChooser: selection of left-side folder buttons shown incorrectly + in Windows L&F + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4464774 + */ + +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4464774 { + private static final String INSTRUCTIONS = """ + Click any button from the buttons to the left + ("Documents", "Desktop", "My Computer" etc.) in FileChooser dialog. + When the button is toggled, it should be lowered and + should NOT have focus painted inside it (black dotted frame). + + If the above is true, press PASS else FAIL. + """; + + public static void main(String[] argv) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(65) + .rows(10) + .testUI(() -> { + JFileChooser jfc = new JFileChooser(); + jfc.setControlButtonsAreShown(false); + return jfc; + }) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4522756.java b/test/jdk/javax/swing/JFileChooser/bug4522756.java new file mode 100644 index 00000000000..87c430cfb1d --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4522756.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4522756 + * @requires (os.family == "windows") + * @summary Verifies that the Desktop icon is not missing when + JFileChooser is opened for the first time. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4522756 + */ + +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class bug4522756 { + private static final String INSTRUCTIONS = """ + Verify the following: + + 1. If Desktop icon image is present on the Desktop button + on the left panel of JFileChooser. + 2. Press Desktop button. Check that you actually + go up to the desktop. + + If the above is true, press PASS else FAIL. + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .rows(12) + .testUI(() -> { + JFileChooser jfc = new JFileChooser(); + jfc.setControlButtonsAreShown(false); + return jfc; + }) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4759934.java b/test/jdk/javax/swing/JFileChooser/bug4759934.java new file mode 100644 index 00000000000..08ccdebfb2b --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4759934.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key headful + * @bug 4759934 + * @summary windows activation problem + * @library /javax/swing/regtesthelpers + * @build Util + * @run main bug4759934 + */ + +import java.awt.Dialog; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4759934 { + private static JFrame fr; + private static Dialog dlg; + private static JFileChooser jfc; + + private static JButton frameBtn; + private static JButton dialogBtn; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(bug4759934::createTestUI); + robot.waitForIdle(); + robot.delay(1000); + + Point frameBtnLoc = Util.getCenterPoint(frameBtn); + robot.mouseMove(frameBtnLoc.x, frameBtnLoc.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(500); + + Point dlgBtnLoc = Util.getCenterPoint(dialogBtn); + robot.mouseMove(dlgBtnLoc.x , dlgBtnLoc.y); + robot.mousePress(MouseEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(MouseEvent.BUTTON1_DOWN_MASK); + robot.delay(500); + + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.delay(500); + + SwingUtilities.invokeAndWait(() -> { + if (frameBtn.hasFocus() && !dialogBtn.hasFocus()) { + throw new RuntimeException("Test failed! Focus was passed back" + + " to Frame instead of Dialog"); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (dlg != null) { + dlg.dispose(); + } + if (fr != null) { + fr.dispose(); + } + }); + } + } + + private static void createTestUI() { + fr = new JFrame("bug4759934 - JFrame"); + + frameBtn = new JButton("Show Dialog"); + frameBtn.addActionListener(e -> createDialog()); + fr.add(frameBtn); + + fr.setSize(300, 200); + fr.setLocationRelativeTo(null); + fr.setVisible(true); + } + + private static void createDialog() { + dlg = new JDialog(fr, "bug4759934 - JDialog"); + + dialogBtn = new JButton("Show FileChooser"); + dlg.add(dialogBtn); + + dialogBtn.addActionListener(e -> { + jfc = new JFileChooser(); + jfc.showOpenDialog(dlg); + }); + + dlg.setSize(300, 200); + dlg.setLocation(fr.getX() + fr.getWidth() + 10, fr.getY()); + dlg.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JFileChooser/bug4943900.java b/test/jdk/javax/swing/JFileChooser/bug4943900.java new file mode 100644 index 00000000000..0cea17e764c --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/bug4943900.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4943900 + * @summary Tests that FileFilter combo box is shown in FileChooser + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4943900 + */ + +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.filechooser.FileFilter; + +public class bug4943900 { + private static final String INSTRUCTIONS = """ + +
    +
  1. When the test runs, a JFileChooser will be displayed. +
  2. Ensure that there is a filter combo box with these two items: +
      +
    • Text Files (*.txt) + — [must be selected when the dialog opens] +
    • All Files +
    +
  3. Leave the Text files item selected and check that the + filter works: only *.txt files can appear in the file list. + You can navigate directories in the file chooser and find one + that contains some *.txt files to ensure they are shown in + the file list. On macOS when the text filter is applied verify + that the non-text files are greyed out. +
  4. Try switching the filters and ensure that the file list + is updated properly. +
  5. If the FileFilter works correctly, + press Pass else press Fail. +
+ + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + + PassFailJFrame.builder() + .title("bug4943900 Test Instructions") + .instructions(INSTRUCTIONS) + .rows(14) + .columns(50) + .testUI(bug4943900::createAndShowUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createAndShowUI() { + JFileChooser fc = new JFileChooser(); + fc.setControlButtonsAreShown(false); + TextFileFilter filter = new TextFileFilter(); + fc.setFileFilter(filter); + + JFrame frame = new JFrame("bug4943900 - JFileChooser"); + frame.add(fc); + frame.pack(); + return frame; + } + + private static final class TextFileFilter extends FileFilter { + @Override + public boolean accept(File f) { + if (f != null) { + if (f.isDirectory()) { + return true; + } + String extension = getExtension(f); + return extension != null && extension.equals("txt"); + } + return false; + } + + @Override + public String getDescription() { + return "Text Files (*.txt)"; + } + + private static String getExtension(File f) { + if (f != null) { + String filename = f.getName(); + int i = filename.lastIndexOf('.'); + if (i > 0 && i < filename.length() - 1) { + return filename.substring(i + 1).toLowerCase(); + } + } + return null; + } + } +} diff --git a/test/jdk/javax/swing/JOptionPane/bug4194862.java b/test/jdk/javax/swing/JOptionPane/bug4194862.java new file mode 100644 index 00000000000..2a2822ebf1d --- /dev/null +++ b/test/jdk/javax/swing/JOptionPane/bug4194862.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4194862 + * @summary Tests that internal frame-based dialogs are centered relative + to their parents + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4194862 + */ + +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JOptionPane; + +public class bug4194862 { + private static final String INSTRUCTIONS = """ + In the internal frame titled "Main", + click the "Show JOptionPane Dialog" button. + A dialog will appear. It should be centered with + respect to the JInternalFrame - "Main". + + If the above is true then click on JOptionPane's "YES" button + to PASS else click JOptionPane's "NO" button to FAIL the test. + """; + + public static void main(String[] args) throws Exception{ + PassFailJFrame.builder() + .title("Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4194862::createAndShowUI) + .screenCapture() + .build() + .awaitAndCheck(); + } + + private static JFrame createAndShowUI() { + JFrame frame = new JFrame("bug4194862 - JInternalFrame JOptionPane"); + JDesktopPane desktop = new JDesktopPane(); + frame.add(desktop); + JInternalFrame jInternalFrame = new JInternalFrame("Main", true); + desktop.add(jInternalFrame); + jInternalFrame.setBounds(5, 30, 390, 240); + jInternalFrame.setVisible(true); + + JButton b = new JButton("Show JOptionPane Dialog"); + b.addActionListener(e -> { + int retVal = JOptionPane.showInternalConfirmDialog( + jInternalFrame, "Am I centered?", + "bug4194862 JOptionPane", JOptionPane.YES_NO_OPTION); + switch (retVal) { + case JOptionPane.YES_OPTION -> PassFailJFrame.forcePass(); + case JOptionPane.NO_OPTION -> + PassFailJFrame.forceFail("JOptionPane isn't centered" + + " within JInternalFrame \"Main\""); + } + }); + jInternalFrame.add(b); + + for (int i = 0; i < 4; i++) { + JInternalFrame f = new JInternalFrame("JIF: "+ i); + f.setBounds(i * 50, i * 33, 120, 120); + f.setVisible(true); + desktop.add(f); + } + frame.setSize(450, 400); + return frame; + } +} From d61765f64d6361b6e71c6f783c8c5a127b1ac745 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Tue, 22 Apr 2025 17:56:04 +0000 Subject: [PATCH 304/843] 8353488: Open some JComboBox bugs 3 Reviewed-by: kizune --- .../jdk/javax/swing/JComboBox/bug4135833.java | 62 ++++++++++++ .../jdk/javax/swing/JComboBox/bug4171819.java | 89 +++++++++++++++++ .../jdk/javax/swing/JComboBox/bug4248128.java | 80 ++++++++++++++++ .../jdk/javax/swing/JComboBox/bug4436376.java | 95 +++++++++++++++++++ 4 files changed, 326 insertions(+) create mode 100644 test/jdk/javax/swing/JComboBox/bug4135833.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4171819.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4248128.java create mode 100644 test/jdk/javax/swing/JComboBox/bug4436376.java diff --git a/test/jdk/javax/swing/JComboBox/bug4135833.java b/test/jdk/javax/swing/JComboBox/bug4135833.java new file mode 100644 index 00000000000..3b2888c862d --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4135833.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; + +/* + * @test + * @bug 4135833 + * @summary Tests that JComboBox draws correctly if the first item in list is an empty string + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4135833 + */ + +public class bug4135833 { + private static final String INSTRUCTIONS = """ + Press the combo box. If the popup is readable and appears to be sized properly, + then it passes. The First item is blank intentionally. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4135833::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + JFrame frame = new JFrame("bug4135833"); + JPanel panel = new JPanel(); + JComboBox comboBox = new JComboBox(new Object[]{"", "Bob", "Hank", "Joe", "Fred"}); + panel.add(comboBox); + frame.add(panel); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4171819.java b/test/jdk/javax/swing/JComboBox/bug4171819.java new file mode 100644 index 00000000000..108512edf7e --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4171819.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.UIManager; + +/* + * @test + * @bug 4171819 + * @summary Tests that JComboBox uses a lower bevel border in windows + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4171819 + */ + +public class bug4171819 { + static boolean lafOk = true; + + private static final String INSTRUCTIONS = """ + This test is for Windows L&F only. If you see + "No Windows L&F installed" label just press "Pass". + + Look at the combo box. If the border around it looks like it's + lowered rather than raised, it passes the test. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4171819::createTestUI) + .build() + .awaitAndCheck(); + } + + public static JFrame createTestUI() { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + System.out.println("succeeded"); + } catch (Exception e) { + System.err.println("Couldn't load the Windows Look and Feel"); + lafOk = false; + } + + JFrame frame = new JFrame("bug4171819"); + JPanel panel = new JPanel(); + JComboBox comboBox; + + if (lafOk) { + comboBox = new JComboBox(new Object[]{ + "Coma Berenices", + "Triangulum", + "Camelopardis", + "Cassiopea"}); + panel.add(comboBox); + } else { + JLabel label = new JLabel("No Windows L&F installed"); + panel.add(label); + } + frame.add(panel); + frame.pack(); + return frame; + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4248128.java b/test/jdk/javax/swing/JComboBox/bug4248128.java new file mode 100644 index 00000000000..311cae4b61a --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4248128.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.BoxLayout; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4248128 7148092 + * @summary Tests that alt+down arrow pulls down JComboBox popup + * @key headful + * @run main bug4248128 + */ + +public class bug4248128 { + static JFrame frame; + static volatile JComboBox combo; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_ALT); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> { + if (!combo.isPopupVisible()) { + throw new RuntimeException("Popup did not appear."); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("4248128 Test"); + Object[] fruits = {"Banana", "Pear", "Apple"}; + combo = new JComboBox(fruits); + frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS)); + frame.add(combo); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} diff --git a/test/jdk/javax/swing/JComboBox/bug4436376.java b/test/jdk/javax/swing/JComboBox/bug4436376.java new file mode 100644 index 00000000000..064efe8c958 --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/bug4436376.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.awt.event.InputEvent; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4436376 + * @key headful + * @summary Tests that ComboBox items can't be deselected with Ctrl+click + * @run main bug4436376 + */ + +public class bug4436376 { + static JFrame frame; + static volatile Point p; + static volatile JComboBox combo; + + final static int SELECTED_INDEX = 2; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(250); + SwingUtilities.invokeAndWait(() -> createTestUI()); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> p = combo.getLocationOnScreen()); + robot.waitForIdle(); + + robot.mouseMove(p.x + 10, p.y + 10); + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> { + if (combo.getSelectedIndex() != SELECTED_INDEX) { + throw new RuntimeException("Failed: selected index has been changed"); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public static void createTestUI() { + frame = new JFrame("bug4436376"); + String[] items = new String[]{"One", "Two", "Three", "Four"}; + combo = new JComboBox(items); + combo.setSelectedIndex(SELECTED_INDEX); + + frame.setLayout(new FlowLayout()); + frame.add(combo); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + } +} From 239760ac09c78a9c989df54f6526b67448540eda Mon Sep 17 00:00:00 2001 From: Eric Caspole Date: Tue, 22 Apr 2025 19:59:41 +0000 Subject: [PATCH 305/843] 8355233: Add a DMB related benchmark Reviewed-by: kvn --- .../openjdk/bench/vm/compiler/DMBCheck.java | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 test/micro/org/openjdk/bench/vm/compiler/DMBCheck.java diff --git a/test/micro/org/openjdk/bench/vm/compiler/DMBCheck.java b/test/micro/org/openjdk/bench/vm/compiler/DMBCheck.java new file mode 100644 index 00000000000..0552e52fb02 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/DMBCheck.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.vm.compiler; + +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Group; +import org.openjdk.jmh.annotations.GroupThreads; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +@BenchmarkMode(Mode.Throughput) +@State(Scope.Benchmark) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 8, time = 4) +@Measurement(iterations = 6, time = 3) +public class DMBCheck { + + // The allocations of DoubleDMB$A and DoubleDMB$C + // will cause aarch64 dmb barrier instructions. + // The different latency of the dmb ish/ishst/ishld modes + // may make a noticeable difference in the benchmark results. + // These modes may be set by cpu defaults or XX options. + + class A { + + final String b = new String("Hi there"); + } + + class C { + + private A a; + + public A getA() { + if (a == null) { + a = new A(); + } + return a; + } + } + + static C c = null; + + @Setup + public void setup() { + c = new C(); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + void action(Blackhole b) throws Exception { + c = new C(); + + if (c.getA().b == null) { + throw new Exception("a should not be null"); + } + b.consume(c); + } + + @Benchmark + @Fork(value = 1, jvmArgs = { + "-XX:+UnlockDiagnosticVMOptions", "-XX:+AlwaysMergeDMB", "-XX:+IgnoreUnrecognizedVMOptions"}) + public void plusAlwaysMergeDMB(Blackhole b) throws Exception { + + action(b); + } + + @Benchmark + @Fork(value = 1, jvmArgs = { + "-XX:+UnlockDiagnosticVMOptions", "-XX:-AlwaysMergeDMB", "-XX:+IgnoreUnrecognizedVMOptions"}) + public void minusAlwaysMergeDMB(Blackhole b) throws Exception { + + action(b); + } + +} From 1b8f760d1b60e63c1391dcad42753a7ebb3f80ec Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Tue, 22 Apr 2025 20:17:01 +0000 Subject: [PATCH 306/843] 8354928: Clean up and open source some miscellaneous AWT tests Reviewed-by: prr, dnguyen --- .../event/InputEvent/InputEventTimeTest.java | 115 +++++++++++++ .../event/MouseWheelEvent/HWWheelScroll.java | 160 ++++++++++++++++++ .../MouseWheelEvent/WheelEventCoord.java | 95 +++++++++++ .../MouseWheelEvent/WheelScrollEnabled.java | 129 ++++++++++++++ 4 files changed, 499 insertions(+) create mode 100644 test/jdk/java/awt/event/InputEvent/InputEventTimeTest.java create mode 100644 test/jdk/java/awt/event/MouseWheelEvent/HWWheelScroll.java create mode 100644 test/jdk/java/awt/event/MouseWheelEvent/WheelEventCoord.java create mode 100644 test/jdk/java/awt/event/MouseWheelEvent/WheelScrollEnabled.java diff --git a/test/jdk/java/awt/event/InputEvent/InputEventTimeTest.java b/test/jdk/java/awt/event/InputEvent/InputEventTimeTest.java new file mode 100644 index 00000000000..38339f8e877 --- /dev/null +++ b/test/jdk/java/awt/event/InputEvent/InputEventTimeTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4176525 + * @summary InputEvent.getWhen() returns the wrong event time. + * @key headful + * @run main InputEventTimeTest + */ + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.Date; + +public class InputEventTimeTest extends Frame { + public void initUI() { + setTitle("Input Event Time Test"); + enableEvents(AWTEvent.MOUSE_EVENT_MASK); + enableEvents(AWTEvent.KEY_EVENT_MASK); + setSize(200, 200); + setLocationRelativeTo(null); + setVisible(true); + } + + public void center(Point point) { + Point loc = getLocationOnScreen(); + Dimension size = getSize(); + point.setLocation(loc.x + (size.width / 2), loc.y + (size.height / 2)); + } + + public void processEvent(AWTEvent e) { + long currentTime; + long eventTime; + long difference; + + if (!(e instanceof InputEvent)) { + return; + } + + currentTime = (new Date()).getTime(); + eventTime = ((InputEvent) e).getWhen(); + difference = currentTime - eventTime; + + if ((difference > 5000) || (difference < -5000)) { + throw new RuntimeException("The difference between current time" + + " and event creation time is " + difference + "ms"); + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + InputEventTimeTest test = new InputEventTimeTest(); + try { + EventQueue.invokeAndWait(test::initUI); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.waitForIdle(); + robot.delay(1000); + Point center = new Point(); + EventQueue.invokeAndWait(() -> test.center(center)); + robot.mouseMove(center.x, center.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON2_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON2_DOWN_MASK); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + for (int i = 0; i < 6; i++) { + robot.keyPress(KeyEvent.VK_A + i); + robot.keyRelease(KeyEvent.VK_A + i); + robot.waitForIdle(); + } + for (int i = 0; i < 150; i += 5) { + robot.mouseMove(center.x - i, center.y - i); + } + for (int i = 150; i > 0; i -= 5) { + robot.mouseMove(center.x - i, center.y - i); + } + } finally { + EventQueue.invokeAndWait(test::dispose); + } + } +} diff --git a/test/jdk/java/awt/event/MouseWheelEvent/HWWheelScroll.java b/test/jdk/java/awt/event/MouseWheelEvent/HWWheelScroll.java new file mode 100644 index 00000000000..2851ff668fe --- /dev/null +++ b/test/jdk/java/awt/event/MouseWheelEvent/HWWheelScroll.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4425654 + * @summary Test wheel scrolling of heavyweight components + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HWWheelScroll + */ + +import java.awt.Choice; +import java.awt.FileDialog; +import java.awt.Frame; +import java.awt.List; +import java.awt.TextArea; +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + +public class HWWheelScroll { + public static final int TEXT_TALL = 0; + public static final int TEXT_WIDE = 1; + public static final int TEXT_SMALL = 2; + public static final int TEXT_BIG = 3; + static String INSTRUCTIONS = """ + Test for mouse wheel scrolling of heavyweight components with built-in + scrollbars or similar functionality that is controlled by guestures + such as Apple Magic Mouse or trackpad scrolling guesture. + Several windows containing either a TextArea, List, Choice, or a + FileDialog will appear. For each window, use the mouse wheel to + scroll its content, and then minimize it or move away + and continue with the next window. + Do not close any of the opened windows except the FileDialog. + For the FileDialog, first change to a directory with enough items that a + scrollbar appears. + Some of the other windows don't have enough text to warrant scrollbars, + but should be tested anyway to make sure no crash or hang occurs. + If all scrollbars scroll correctly, press "Pass", otherwise press "Fail". + """; + + public static ArrayList initUI() { + ArrayList retValue = new ArrayList<>(); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_BIG)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_TALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_SMALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_BOTH, TEXT_WIDE)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_VERTICAL_ONLY, TEXT_TALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_VERTICAL_ONLY, TEXT_SMALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_HORIZONTAL_ONLY, TEXT_SMALL)); + retValue.add(makeTextFrame(TextArea.SCROLLBARS_HORIZONTAL_ONLY, TEXT_WIDE)); + retValue.add(makeListFrame(TEXT_TALL)); + retValue.add(makeListFrame(TEXT_WIDE)); + retValue.add(makeListFrame(TEXT_SMALL)); + Frame f = new Frame("File Dialog Owner"); + f.setSize(150, 150); + f.setLocationRelativeTo(null); + FileDialog fd = new FileDialog(f, "FileDialog"); + fd.setDirectory("."); + retValue.add(fd); + retValue.add(f); + Frame choiceFrame = new Frame("Choice"); + Choice c = new Choice(); + for (int i = 0; i < 50; i++) { + c.add(i + " choice item"); + } + choiceFrame.add(c); + choiceFrame.setSize(150, 150); + choiceFrame.setLocationRelativeTo(null); + retValue.add(choiceFrame); + return retValue; + } + + public static Frame makeTextFrame(int policy, int textShape) { + Frame f = new Frame("TextArea"); + f.add(makeTextArea(policy, textShape)); + f.setSize(150, 150); + f.setLocationRelativeTo(null); + return f; + } + + public static Frame makeListFrame(int textShape) { + Frame f = new Frame("List"); + f.add(makeList(textShape)); + f.setSize(150, 150); + f.setLocationRelativeTo(null); + return f; + } + + public static TextArea makeTextArea(int policy, int textShape) { + TextArea ta = new TextArea("", 0, 0, policy); + if (textShape == TEXT_TALL) { + for (int i = 0; i < 50 ; i++) { + ta.append(i + "\n"); + } + } else if (textShape == TEXT_WIDE) { + for (int i = 0; i < 2; i++) { + ta.append(i + "very, very, very, very, very, very, very, long line of text number\n"); + } + } else if (textShape == TEXT_SMALL) { + ta.append("text"); + } else if (textShape == TEXT_BIG) { + for (int i = 0; i < 50 ; i++) { + ta.append(i + "very, very, very, very, very, very, very, long line of text number\n"); + } + } + return ta; + } + + public static List makeList(int textShape) { + java.awt.List l = new java.awt.List(); + if (textShape == TEXT_TALL) { + for (int i = 0; i < 50 ; i++) { + l.add(" " + i + " "); + } + } else if (textShape == TEXT_WIDE) { + for (int i = 0; i < 2 ; i++) { + l.add(i + "very, very, very, very, very, very, very, long line of text number"); + } + } else if (textShape == TEXT_SMALL) { + l.add("text"); + } else if (textShape == TEXT_BIG) { + for (int i = 0; i < 50 ; i++) { + l.add(i + "very, very, very, very, very, very, very, long line of text number"); + } + } + return l; + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(HWWheelScroll::initUI) + .build() + .awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/event/MouseWheelEvent/WheelEventCoord.java b/test/jdk/java/awt/event/MouseWheelEvent/WheelEventCoord.java new file mode 100644 index 00000000000..418151d3798 --- /dev/null +++ b/test/jdk/java/awt/event/MouseWheelEvent/WheelEventCoord.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4492456 + * @summary MouseWheelEvent coordinates are wrong + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual WheelEventCoord + */ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.GridLayout; +import java.lang.reflect.InvocationTargetException; + +public class WheelEventCoord extends Frame { + static String INSTRUCTIONS = """ + This test requires mouse with scrolling wheel or device, + that has capability to simulate scrolling wheel with gestures + such as Apple mouse or a trackpad with gesture control. + If you do not have such device press "Pass". + Move mouse to the top of the button named "Button 1". + While constantly turning mouse wheel up and down slowly move + mouse cursor until it reaches bottom of the button named "Button 3". + While doing so look at the log area. + If despite the wheel direction y coordinate is steadily increases + as you move the mouse down press "Pass". + If y coordinate decreases when cursor is moving down or suddenly jumps + by more than 50 points when crossing to another button press "Fail". + """; + + public WheelEventCoord() { + super("Wheel Event Coordinates"); + setLayout(new GridLayout(3, 1)); + + add(new BigButton("Button 1")); + add(new BigButton("Button 2")); + add(new BigButton("Button 3")); + + addMouseWheelListener(e -> PassFailJFrame.log("Mouse y coordinate = " + e.getY())); + pack(); + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Wheel Event Coordinates Instructions") + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(WheelEventCoord::new) + .build() + .awaitAndCheck(); + } +} + +class BigButton extends Button { + public BigButton(String label) { + super(label); + } + + public Dimension getPreferredSize() { + return new Dimension(300, 100); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getMaximumSize() { + return getPreferredSize(); + } +} diff --git a/test/jdk/java/awt/event/MouseWheelEvent/WheelScrollEnabled.java b/test/jdk/java/awt/event/MouseWheelEvent/WheelScrollEnabled.java new file mode 100644 index 00000000000..cbdd7676e94 --- /dev/null +++ b/test/jdk/java/awt/event/MouseWheelEvent/WheelScrollEnabled.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4372477 + * @summary Test disabling of wheel scrolling + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual WheelScrollEnabled + */ + +import java.awt.BorderLayout; +import java.awt.Checkbox; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.lang.reflect.InvocationTargetException; + +public class WheelScrollEnabled extends Frame { + static String INSTRUCTIONS = """ + This test requires mouse with a scrolling wheel or + device that is able to simulate scrolling using gestures. + If you do not have such device press "Pass" to skip testing. + You should see a ScrollPane with some labels in it and two checkboxes. + For each of the four combinations of the two checkboxes, + move the cursor over the ScrollPane and rotate the mouse wheel. + When (and ONLY when) the 'WheelListener added' checkbox is checked, + scrolling the mouse wheel should produce a text message in the log area. + When (and ONLY when) the 'Wheel scrolling enabled' checkbox is checked, + the ScrollPane should scroll when mouse wheel is scrolled on top of it. + If all four checkbox combinations work properly press "Pass", + otherwise press "Fail". + """; + MouseWheelListener mwl; + Checkbox cb; + Checkbox cb2; + ScrollPane sp; + + public WheelScrollEnabled() { + setLayout(new BorderLayout()); + Panel pnl = new Panel(); + pnl.setLayout(new GridLayout(10, 10)); + for (int i = 0; i < 100; i++) { + pnl.add(new Label("Label " + i)); + } + sp = new ScrollPane(); + sp.add(pnl); + sp.setWheelScrollingEnabled(false); + mwl = new MouseWheelListener() { + int i; + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + PassFailJFrame.log("mouseWheelMoved " + i++); + } + }; + sp.addMouseWheelListener(mwl); + add(sp, BorderLayout.CENTER); + + Panel pl2 = new Panel(); + ItemListener il = new ControlListener(); + + cb = new Checkbox("WheelListener added", true); + cb.addItemListener(il); + pl2.add(cb); + + cb2 = new Checkbox("Wheel scrolling enabled", false); + cb2.addItemListener(il); + pl2.add(cb2); + + add(pl2, BorderLayout.SOUTH); + setSize(400, 200); + } + + class ControlListener implements ItemListener { + public void itemStateChanged(ItemEvent e) { + if (e.getSource() == cb) { + boolean state = cb.getState(); + if (state) { + sp.addMouseWheelListener(mwl); + } + else { + sp.removeMouseWheelListener(mwl); + } + } + if (e.getSource() == cb2) { + sp.setWheelScrollingEnabled(cb2.getState()); + } + } + } + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + PassFailJFrame.builder() + .title("Wheel Scroll Enabled Instructions") + .instructions(INSTRUCTIONS) + .logArea(10) + .testUI(WheelScrollEnabled::new) + .build() + .awaitAndCheck(); + } +} + From cc9148ddef95c6ca27ff9fee4c17fb0d4ba7f88e Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Tue, 22 Apr 2025 20:27:17 +0000 Subject: [PATCH 307/843] 8354695: Open source several swing tests batch7 Reviewed-by: kizune, achung --- .../jdk/javax/swing/JRootPane/bug4403624.java | 106 +++ .../HorizScrollers.java | 234 ++++++ .../RTLScrollers.java | 684 ++++++++++++++++++ .../javax/swing/JScrollPane/bug4166037.java | 167 +++++ .../javax/swing/JScrollPane/bug4237517.java | 69 ++ .../javax/swing/JScrollPane/bug4237560.java | 77 ++ .../javax/swing/JScrollPane/bug4244899.java | 99 +++ 7 files changed, 1436 insertions(+) create mode 100644 test/jdk/javax/swing/JRootPane/bug4403624.java create mode 100644 test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java create mode 100644 test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4166037.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4237517.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4237560.java create mode 100644 test/jdk/javax/swing/JScrollPane/bug4244899.java diff --git a/test/jdk/javax/swing/JRootPane/bug4403624.java b/test/jdk/javax/swing/JRootPane/bug4403624.java new file mode 100644 index 00000000000..1c3ba3ddd2a --- /dev/null +++ b/test/jdk/javax/swing/JRootPane/bug4403624.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4403624 + * @summary Tests JRootPane layout with invisible menubar + * @key headful + * @run main bug4403624 + */ + +import java.awt.Color; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.SwingUtilities; + +public class bug4403624 { + private static JFrame f; + private static Container c; + private static JButton b; + private static volatile Point p; + private static volatile int bWidth; + private static volatile int bHeight; + private static final int OFFSET = 2; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4403624 Test"); + JMenuBar mbar; + mbar = new JMenuBar(); + mbar.add(new JMenu("Menu")); + f.setJMenuBar(mbar); + b = new JButton("Hide Menu"); + b.addActionListener(e -> mbar.setVisible(false)); + c = f.getContentPane(); + c.setLayout(new FlowLayout()); + c.setBackground(Color.GREEN); + c.add(b); + f.pack(); + f.setLocationRelativeTo(null); + f.setAlwaysOnTop(true); + f.setVisible(true); + }); + + Robot r = new Robot(); + r.setAutoDelay(200); + r.waitForIdle(); + r.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + p = b.getLocationOnScreen(); + bWidth = b.getWidth(); + bHeight = b.getHeight(); + }); + + r.mouseMove(p.x + (bWidth / 2), p.y + (bHeight / 2)); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + SwingUtilities.invokeAndWait(() -> p = c.getLocationOnScreen()); + + Color c = r.getPixelColor(p.x + OFFSET, p.y + OFFSET); + + if (c.getGreen() < 240 && c.getBlue() > 10 && c.getRed() > 10) { + System.out.println("EXPECTED: " + Color.GREEN); + System.out.println("ACTUAL: " + c); + throw new RuntimeException("Failure to hide menu bar."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java new file mode 100644 index 00000000000..b584fd66da3 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5078454 + * @summary Test horizontal wheel scroll behavior of (including RTL) + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual HorizScrollers + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; + +public class HorizScrollers { + private static final String INSTRUCTIONS = """ + This is a semi-automatic test with three phases. + For each phase, you will need to change the mouse setting, as + directed by a dialog. Once the correct setting is confirmed, + the next test phase will run automatically. + DO NOT TOUCH ANYTHING DURING TESTING! + + The test will automatically FAIL during testing if something + fails. Otherwise, the test will automatically PASS after the + third testing phase. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("HorizScrollers Instructions") + .instructions(INSTRUCTIONS) + .columns(45) + .testTimeOut(10) + .splitUIRight(ConfigPanel::new) + .logArea(6) + .build() + .awaitAndCheck(); + } + + private static final int[] SCROLLAMTS = {1, 30, 3}; + private static final String[] CONFIG_MSGS = { + "Set the scrolling speed to the slowest value (1 line).", + "Set the scrolling speed to the fastest value (30 lines).", + "Set the scrolling speed to two ticks above the slowest value (3 lines)." + }; + + private static int current = 0; + private static final String MW_TEXT = "Rotate the mouse wheel here"; + private static final String CONFIG_INSTRUCTION_TEMPLATE = """ + Configure Mouse Wheel for Phase %d + + Open the Mouse Control Panel and go to the 'Wheel' tab. + If 'Wheel' tab is not available just press Pass. + + %s + + Test the setting on the area below. + Once the mouse is setup correctly, the area will turn green. + When you're ready for the next part of the test to run, press GO! + """; + + static class ConfigPanel extends JPanel + implements ActionListener, MouseWheelListener { + JTextArea msg; + JButton goBtn; + JLabel mwArea; + int scrollAmount; + + private final Color defaultBg; + + ConfigPanel() { + this.scrollAmount = SCROLLAMTS[current]; + Container content = this; + content.setLayout(new BorderLayout()); + msg = new JTextArea(); + msg.setMargin(new Insets(5, 5, 5, 5)); + msg.setEditable(false); + msg.setLineWrap(true); + msg.setWrapStyleWord(true); + content.add(msg, BorderLayout.NORTH); + + mwArea = new JLabel(MW_TEXT, SwingConstants.CENTER); + mwArea.setPreferredSize(new Dimension(200, 250)); + mwArea.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + mwArea.setOpaque(true); + mwArea.addMouseWheelListener(this); + content.add(mwArea, BorderLayout.CENTER); + + defaultBg = mwArea.getBackground(); + setPhase(current); + + goBtn = new JButton("GO!"); + goBtn.setEnabled(false); + goBtn.addActionListener(this); + JPanel flowPanel = new JPanel(); + flowPanel.setLayout(new FlowLayout()); + flowPanel.add(goBtn); + content.add(flowPanel, BorderLayout.SOUTH); + + setPreferredSize(new Dimension(600, 400)); + } + + public void setPhase(int phase) { + if (phase < 3) { + setVisible(true); + PassFailJFrame.log("Phase %d scroll speed %d" + .formatted(phase + 1, SCROLLAMTS[phase])); + PassFailJFrame.log(CONFIG_MSGS[phase]); + + scrollAmount = SCROLLAMTS[phase]; + msg.setText(CONFIG_INSTRUCTION_TEMPLATE + .formatted(phase + 1, CONFIG_MSGS[phase])); + mwArea.setBackground(defaultBg); + mwArea.setText(MW_TEXT); + } else { + // all cases passed + showFinalReminderIfNeeded(false); + } + } + + private void showFinalReminderIfNeeded(boolean isFailure) { + if (scrollAmount != 3) { + JOptionPane.showMessageDialog( + ConfigPanel.this.getTopLevelAncestor(), + ("Test %s. please make sure you have restored " + + "the original speed value blah blah") + .formatted(isFailure + ? "failed" + : "passed"), + isFailure + ? "Failure" + : "Success", + isFailure + ? JOptionPane.WARNING_MESSAGE + : JOptionPane.INFORMATION_MESSAGE + ); + } + + if (isFailure) { + PassFailJFrame.forceFail(); + } else { + PassFailJFrame.forcePass(); + } + } + + public void actionPerformed(ActionEvent e) { + if (e.getSource() == goBtn) { + goBtn.setEnabled(false); + + new Thread(() -> { // new thread to avoid running robot on EDT + boolean passed; + try { + passed = RTLScrollers.runTest(SCROLLAMTS[current]); + } catch (Exception ex) { + PassFailJFrame.log("Failure: " + ex); + SwingUtilities.invokeLater(() -> + showFinalReminderIfNeeded(true)); + return; + } + + PassFailJFrame.log("Phase %d passed: %b\n" + .formatted(current + 1, passed)); + if (passed) { + SwingUtilities.invokeLater(() -> { + goBtn.setEnabled(true); + setPhase(++current); + }); + } else { + SwingUtilities.invokeLater(() -> + showFinalReminderIfNeeded(true)); + } + }).start(); + } + } + + public void mouseWheelMoved(MouseWheelEvent e) { + int eventScrollAmt = e.getScrollAmount(); + if (eventScrollAmt == scrollAmount) { + mwArea.setBackground(Color.GREEN); + mwArea.setText("Mouse wheel configured - press Go"); + goBtn.setEnabled(true); + goBtn.requestFocusInWindow(); + PassFailJFrame.log("Proceed to the test with go button"); + return; + } + if (eventScrollAmt < scrollAmount) { + mwArea.setText("Increase the scroll speed. (Want:" + + scrollAmount + " Got:" + eventScrollAmt + ")"); + } else { + mwArea.setText("Decrease the scroll speed. (Want:" + + scrollAmount + " Got:" + eventScrollAmt + ")"); + } + } + } +} \ No newline at end of file diff --git a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java new file mode 100644 index 00000000000..24e8df6fad8 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// A few Swing components which use the mouse wheel to scroll + +import java.awt.AWTException; +import java.awt.Color; +import java.awt.ComponentOrientation; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.ListModel; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +public class RTLScrollers extends JDialog + implements MouseWheelListener, ActionListener { + private static final int ROWS = 5; + private static final int COLUMNS = 150; + private static final int WINWIDTH = 1000; + + static RTLScrollers rtl; + static volatile RTLScrollers f; + static volatile boolean retVal; + static volatile JScrollPane jsp; + static volatile JScrollBar hsb; + static volatile JScrollBar sb; + static volatile Point loc; + static volatile Dimension size; + TestList list; + JScrollPane listScroller; + JTextArea text; + JScrollPane textScroller; + TestTable table; + JScrollPane tableScroller; + JCheckBoxMenuItem rightToLeft; + ImageIcon photoIcon; + int scrollAmount; + + private static Robot robot; + private static BufferedImage logo = genIcon(166, 39, Color.PINK); + private static BufferedImage photo = genIcon(59, 80, Color.MAGENTA); + private static BufferedImage photo2 = genIcon(80, 53, Color.ORANGE); + + private static BufferedImage genIcon(int width, int height, Color color) { + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics g = image.getGraphics(); + g.setColor(color); + g.fillRect(0, 0, width, height); + + return image; + } + + public RTLScrollers() { + this(0); + } + + public RTLScrollers(int scrollAmount) { + super(new JFrame(), "RTLScrollers", false); + + this.scrollAmount = scrollAmount; + Container content = getContentPane(); + content.setLayout(new GridBagLayout()); + + DefaultListModel listModel = new DefaultListModel<>(); + + photoIcon = new ImageIcon(photo); + for (int i = 0; i < COLUMNS / 4 ; i++) { + for (int j = 0; j < ROWS; j++) { + listModel.addElement(new ImageIcon(logo)); + } + for (int j = 0; j < ROWS; j++) { + listModel.addElement(photoIcon); + } + for (int j = 0; j < ROWS; j++) { + listModel.addElement(new ImageIcon(photo2)); + } + for (int j = 0; j < ROWS; j++) { + listModel.addElement("Text Item " + ((1 + i) * 3)); + } + } + + list = new TestList(listModel); + list.setVisibleRowCount(ROWS); + list.setLayoutOrientation(JList.VERTICAL_WRAP); + listScroller = new JScrollPane(list); + listScroller.addMouseWheelListener(this); + + text = new JTextArea(); + for (int j = 0; j < ROWS ; j++) { + for (int i = 0; i < COLUMNS ; i++) { + text.append(i + " some text, some more text, a really long line of text "); + } + text.append("\n"); + } + + textScroller = new JScrollPane(text); + textScroller.addMouseWheelListener(this); + + DefaultTableModel model = new DefaultTableModel(ROWS, COLUMNS); + table = new TestTable(model); + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + for (int i = 0; i < COLUMNS; i++) { + for (int j = 0; j < ROWS; j++) { + table.setValueAt(j + ", " + i, j, i); + } + + TableColumn column = table.getColumnModel().getColumn(i); + + if (i % 4 == 0) { + column.setMinWidth(0); + column.setPreferredWidth(0); + column.setMaxWidth(0); + } + else if ((i + 1) % 4 == 0) { + column.setMinWidth(95); + column.setPreferredWidth(95); + column.setMaxWidth(95); + } + else if ((i + 2) % 4 == 0) { + column.setMinWidth(26); + column.setPreferredWidth(26); + column.setMaxWidth(26); + } + else { + column.setMinWidth(50); + column.setPreferredWidth(50); + column.setMaxWidth(50); + } + } + tableScroller = new JScrollPane(table); + tableScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + tableScroller.addMouseWheelListener(this); + + GridBagConstraints tableGBC = new GridBagConstraints(0, + 0, + 1, + 1, + 1.0, + 0.3, + GridBagConstraints.CENTER, + GridBagConstraints.BOTH, + new Insets(0,0,0,0), + 0, + 0); + content.add(tableScroller, tableGBC); + GridBagConstraints textGBC = new GridBagConstraints(0, + 1, + 1, + 1, + 1.0, + 0.3, + GridBagConstraints.CENTER, + GridBagConstraints.BOTH, + new Insets(0,0,0,0), + 0, + 0); + content.add(textScroller, textGBC); + + GridBagConstraints listGBC = new GridBagConstraints(0, + 2, + 1, + 5, + 1.0, + 1.2, + GridBagConstraints.CENTER, + GridBagConstraints.BOTH, + new Insets(0,0,0,0), + 0, + 0); + + content.add(listScroller, listGBC); + + rightToLeft = new JCheckBoxMenuItem("Right-To-Left", false); + rightToLeft.addActionListener(this); + JMenu menu = new JMenu("Component Orientation"); + menu.add(rightToLeft); + + JMenuItem close = new JMenuItem("Close"); + close.addActionListener(e -> RTLScrollers.this.setVisible(false)); + menu.add(close); + + JMenuBar mb = new JMenuBar(); + mb.add(menu); + setJMenuBar(mb); + setBounds(0, 0, WINWIDTH, 760); + setLocationRelativeTo(null); + } + + public void actionPerformed(ActionEvent e) { + if (rightToLeft.getState()) { + applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + } + else { + applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + } + } + public void mouseWheelMoved(MouseWheelEvent e) { + System.out.println("Rotation: " + e.getWheelRotation()); + } + + public static boolean runTest(int scrollAmount) + throws InterruptedException, InvocationTargetException { + System.out.println("RTLS.runTest()"); + if (robot == null) { + try { + robot = new Robot(); + robot.setAutoDelay(150); + robot.setAutoWaitForIdle(true); + } + catch (AWTException e) { + e.printStackTrace(); + return false; + } + } + + SwingUtilities.invokeAndWait(() -> { + rtl = new RTLScrollers(scrollAmount); + rtl.setVisible(true); + }); + robot.delay(100); + + SwingUtilities.invokeAndWait(() -> { + try { + retVal = rtl.runTests(scrollAmount); + } catch (Exception e) { + e.printStackTrace(); + } finally { + rtl.setVisible(false); + rtl.dispose(); + } + }); + + robot.delay(100); + System.out.println("RTLS.runTest(): " + retVal); + return retVal; + } + + private boolean runTests(int scrollAmount) + throws InterruptedException, InvocationTargetException { + if (robot == null) { + try { + robot = new Robot(); + robot.setAutoDelay(150); + robot.setAutoWaitForIdle(true); + } + catch (AWTException e) { + e.printStackTrace(); + return false; + } + } + + // + // run robot tests + // + robot.delay(500); + + System.out.println("Testing Table"); + testComp(table, scrollAmount); + + System.out.println("Testing List"); + testComp(list, scrollAmount); + + SwingUtilities.invokeAndWait(() -> { + applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + }); + robot.delay(100); + + System.out.println("Testing RTL Table"); + testComp(table, scrollAmount); + + System.out.println("Testing RTL List"); + testComp(list, scrollAmount); + + return true; + } + + public boolean testComp(TestTools comp, int scrollAmount) + throws InterruptedException, InvocationTargetException { + // Make sure we start from the beginning + SwingUtilities.invokeAndWait(() -> { + jsp = (JScrollPane)((JComponent)comp).getParent().getParent(); + hsb = jsp.getHorizontalScrollBar(); + hsb.setValue(hsb.getMinimum()); + + loc = jsp.getLocationOnScreen(); + size = jsp.getSize(); + }); + int midx = loc.x + size.width / 2; + int midy = loc.y + size.height / 2; + int maxIdx = 0; + robot.mouseMove(midx, midy); + + // Don't bother for max scroll w/ RTL JList, because the block increment is broken + if (scrollAmount != 30 || !(comp instanceof TestList) + || getComponentOrientation().isLeftToRight()) { + scrollToMiddle(jsp, robot); + + // check that we're lined up + comp.checkTopCellIsLinedUp(); + + int startVal = hsb.getValue(); + int leadingCell = comp.getLeadingCell().y; + System.out.println("leadingCell is " + leadingCell); + + // become unaligned + int width = comp.getLeadingCellWidth(); + int midVal = startVal + width / 2; + System.out.println("becoming unaligned: startVal is " + + startVal + ", midVal is " + midVal); + SwingUtilities.invokeAndWait(() -> hsb.setValue(midVal)); + + // + // Check partial inc up + // + robot.mouseWheel(-1); + + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -scrollAmount + 1); + } + comp.checkTopCellIsLinedUp(); + + // + // Check partial inc down + // + SwingUtilities.invokeAndWait(() -> hsb.setValue(midVal)); + robot.delay(100); + robot.mouseWheel(1); + + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, scrollAmount); + } + comp.checkTopCellIsLinedUp(); + + // + // Check full inc down (3 times) + // + SwingUtilities.invokeAndWait(() -> hsb.setValue(startVal)); + leadingCell = comp.getLeadingCell().y; + + // Once... + robot.mouseWheel(1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, scrollAmount); + } + comp.checkTopCellIsLinedUp(); + + // Twice... + robot.mouseWheel(1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, (2 * scrollAmount)); + } + + comp.checkTopCellIsLinedUp(); + + // Thrice... + robot.mouseWheel(1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, (3 * scrollAmount)); + + } + comp.checkTopCellIsLinedUp(); + + // + // Check full inc up (3 times) + // + leadingCell = comp.getLeadingCell().y; + + // Once... + robot.mouseWheel(-1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -scrollAmount); + } + comp.checkTopCellIsLinedUp(); + + // Twice... + robot.mouseWheel(-1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -(2 * scrollAmount)); + } + comp.checkTopCellIsLinedUp(); + + // Thrice... + robot.mouseWheel(-1); + if (scrollAmount == 30) { // hack for max scroll amount + comp.checkTopCellIsMax(maxIdx++); + } + else { + comp.checkTopCellIs(leadingCell, -(3 * scrollAmount)); + } + comp.checkTopCellIsLinedUp(); + } + + // + // Test acceleration for max scrolling + // (this part should still work for RTL JList) + if (scrollAmount == 30) { + SwingUtilities.invokeAndWait(() -> { + hsb.setValue(hsb.getMinimum()); + }); + robot.delay(100); + robot.mouseWheel(2); + robot.mouseWheel(2); + robot.mouseWheel(2); + if (hsb.getValue() < hsb.getMaximum() - hsb.getVisibleAmount()) { + throw new RuntimeException("Wheel acceleration for max " + + "scrolling doesn't work: hsb value (" + hsb.getValue() + + " < hsb max (" + hsb.getMaximum() + + ") - hsb vis (" + hsb.getVisibleAmount() + ")"); + } + robot.delay(100); + robot.mouseWheel(-2); + robot.mouseWheel(-2); + robot.mouseWheel(-2); + if (hsb.getValue() > hsb.getMinimum()) { + throw new RuntimeException("Wheel acceleration for max " + + "scrolling doesn't work: hsb value (" + + hsb.getValue() + " > hsb min (" + hsb.getMinimum() + ")"); + } + } + + return true; + } + + class TestTable extends JTable implements TestTools { + final int[] MAXVALS = {23, 67, 67, 89, 111, 89, 66, 45}; //Lookup table + public TestTable(TableModel model) { + super(model); + } + + public void checkTopCellIsLinedUp() { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + Point leading = getLeadingCell(); + Rectangle visRect = getVisibleRect(); + Rectangle cellRect = getCellRect(leading.x, leading.y, true); + + if (isLeftToRight) { + if (cellRect.x != visRect.x) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + else { + if (cellRect.x + cellRect.width != visRect.x + visRect.width) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + } + + public void checkTopCellIs(int col) { + Point cell = getLeadingCell(); + if (cell.y != col) { + throw new RuntimeException("leading cell (" + cell.y + + ") is not " + col); + } + } + + /* + * Account for 0-width cells + * + * shift is a non-0 number of visible cells to shift. The shift is + * augmented for zero-width cells, and the new sum is passed into + * checkTopCellIs(). + */ + public void checkTopCellIs(int col, int shift) { + if (shift == 0) { + checkTopCellIs(col); + return; + } + + int row = getLeadingCell().x; + int newShift = 0; + int foundCells = 0; + int direction = shift > 0 ? 1 : -1; + int index = col; + Rectangle cellRect; + + while (foundCells < Math.abs(shift)) { + index += direction; + cellRect = getCellRect(row, index, true); + if (cellRect.width > 0) { + foundCells++; + } + newShift++; + } + + checkTopCellIs(col + (direction*newShift)); + } + + public void checkTopCellIsMax(int idx) { + checkTopCellIs(MAXVALS[idx]); + } + + public int getLeadingCellWidth() { + Point leading = getLeadingCell(); + Rectangle cellRect = getCellRect(leading.x, leading.y, true); + return cellRect.width; + } + + public Point getLeadingCell() { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + Rectangle visRect = getVisibleRect(); + int row = rowAtPoint(visRect.getLocation()); + int column; + if (isLeftToRight) { + column = columnAtPoint(visRect.getLocation()); + } + else { + column = columnAtPoint(new Point(visRect.x + visRect.width - 1, visRect.y)); + } + return new Point(row, column); + } + } + + class TestList extends JList implements TestTools { + final int[] MAXVALS = {5, 16, 15, 20, 25, 20, 15, 10 }; + public TestList(ListModel model) { + super(model); + } + + // Note - implemented in terms of columns + public Point getLeadingCell() { + System.out.println("TL.gLC(): first vis index is " + + getFirstVisibleIndex()); + return new Point(getFirstVisibleIndex() / ROWS, + getFirstVisibleIndex() / ROWS); + } + public void checkTopCellIsLinedUp() { + boolean isLeftToRight = getComponentOrientation().isLeftToRight(); + int visIdx = getFirstVisibleIndex(); + Rectangle cellRect = getCellBounds(visIdx, visIdx); + Rectangle visRect = getVisibleRect(); + if (isLeftToRight) { + if (cellRect.x != visRect.x) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + else { + if (cellRect.x + cellRect.width != visRect.x + visRect.width) { + throw new RuntimeException("leading cell is not aligned!"); + } + } + } + public void checkTopCellIs(int col) { + int firstVis = getLeadingCell().y; + if (firstVis != col) { + throw new RuntimeException("leading cell (" + + firstVis + ") is not " + col); + } + } + public void checkTopCellIs(int idx, int shift) { + checkTopCellIs(idx + shift); + + } + public void checkTopCellIsMax(int idx) { + checkTopCellIs(MAXVALS[idx]); + } + public int getLeadingCellWidth() { + int visIdx = getFirstVisibleIndex(); + Rectangle cellRect = getCellBounds(visIdx, visIdx); + System.out.println("TL.gLCW(): leading cell width is " + cellRect.width); + return cellRect.width; + } + } + + private interface TestTools { + /** + * Throws a runtime exception if the top cell isn't lined up + */ + void checkTopCellIsLinedUp(); + void checkTopCellIs(int col); + void checkTopCellIs(int col, int shift); + int getLeadingCellWidth(); + Point getLeadingCell(); + + void checkTopCellIsMax(int idx); + } + + public void scrollToMiddle(JScrollPane jsp, Robot robot) + throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(() -> { + sb = jsp.getHorizontalScrollBar(); + loc = sb.getLocationOnScreen(); + size = sb.getSize(); + }); + robot.setAutoDelay(250); + + robot.mouseMove(loc.x + size.width / 2, + loc.y + size.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + SwingUtilities.invokeAndWait(() -> { + if (jsp == listScroller) { + int idx = list.getFirstVisibleIndex(); + list.ensureIndexIsVisible(idx); + } + }); + } + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> f = new RTLScrollers()); + } finally { + SwingUtilities.invokeAndWait(() -> { + f.setVisible(true); + f.dispose(); + }); + } + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4166037.java b/test/jdk/javax/swing/JScrollPane/bug4166037.java new file mode 100644 index 00000000000..e2ce75867a7 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4166037.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4166037 + * @summary Tests if changes to JScrollPane propagate to ScrollPaneLayout + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4166037 + */ + +import java.awt.Color; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneLayout; + +public class bug4166037 { + static final String INSTRUCTIONS = """ + Press button "Never". Scroll bars should disappear. + Press button "Always". Scroll bars should appear. + Press button "Colhead". Label ColumnHeader should + get replaced with yellow rectangles. + Press button "Corner". You should see 4 green + rectangles in the corners of the scroll pane. + Press button "Rowhead". Label RowHeader should get + replaced with yellow rectangles. + Press button "Viewport". Viewport (the rest of the + area except scrollbars) should get replaced with yellow + rectangles. + If the behavior is as described, the test PASSES. + Otherwise, this test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4166037 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4166037::createUI) + .logArea() + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("JScrollPane in JScrollLayout Test"); + JScrollPane scroll = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + JPanel p = new JPanel(); + scroll.setSize(200, 200); + f.add(scroll); + f.setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS)); + JButton bn = new JButton("Never"); + bn.addActionListener(e -> { + PassFailJFrame.log("pane before: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout before: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); + scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + PassFailJFrame.log("pane after: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout after: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + }); + JButton ba = new JButton("Always"); + ba.addActionListener(e -> { + PassFailJFrame.log("pane before: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout before: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + PassFailJFrame.log("pane after: " + + scroll.getVerticalScrollBarPolicy() + + scroll.getHorizontalScrollBarPolicy()); + PassFailJFrame.log("layout after: " + + ((ScrollPaneLayout) scroll.getLayout()).getVerticalScrollBarPolicy() + + ((ScrollPaneLayout) scroll.getLayout()).getHorizontalScrollBarPolicy()); + }); + JLabel ch = new JLabel("ColumnHeader"); + scroll.setColumnHeaderView(ch); + JButton b1 = new JButton("Colhead"); + b1.addActionListener(e -> { + JPanel filler = new JPanel(); + filler.setSize(150, 150); + filler.setBackground(Color.yellow); + scroll.getColumnHeader().add(filler); + }); + JButton b2 = new JButton("Corners"); + b2.addActionListener(e -> { + JPanel filler1 = new JPanel(); + filler1.setSize(150, 150); + filler1.setBackground(Color.green); + scroll.setCorner(JScrollPane.LOWER_RIGHT_CORNER, filler1); + JPanel filler2 = new JPanel(); + filler2.setSize(150, 150); + filler2.setBackground(Color.green); + scroll.setCorner(JScrollPane.LOWER_LEFT_CORNER, filler2); + JPanel filler3 = new JPanel(); + filler3.setSize(150, 150); + filler3.setBackground(Color.green); + scroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, filler3); + JPanel filler4 = new JPanel(); + filler4.setSize(150, 150); + filler4.setBackground(Color.green); + scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, filler4); + }); + JLabel rh = new JLabel("RowHeader"); + scroll.setRowHeaderView(rh); + JButton b3 = new JButton("Rowhead"); + b3.addActionListener(e -> { + JPanel filler = new JPanel(); + filler.setSize(150, 150); + filler.setBackground(Color.yellow); + scroll.getRowHeader().add(filler); + }); + JButton b4 = new JButton("Viewport"); + b4.addActionListener(e -> { + JPanel filler = new JPanel(); + filler.setSize(150, 150); + filler.setBackground(Color.yellow); + scroll.getViewport().add(filler); + }); + + p.add(bn); + p.add(ba); + p.add(b1); + p.add(b2); + p.add(b3); + p.add(b4); + f.add(p); + f.setSize(300, 300); + return f; + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4237517.java b/test/jdk/javax/swing/JScrollPane/bug4237517.java new file mode 100644 index 00000000000..4e1d1356199 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4237517.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4237517 + * @summary Tests that scrolling with blit draws the right thing + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4237517 + */ + +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; + +public class bug4237517 { + static final String INSTRUCTIONS = """ + Select the first item in the list and hit PageDown + key two times. If the list is redrawn correctly, + i.e. if the digits go in order, then the test PASSES. + Otherwise, the test FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4237517 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4237517::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame f = new JFrame("Scrolling Window Blit Test"); + String[] data = new String[100]; + + for (int counter = 0; counter < data.length; counter++) { + data[counter] = Integer.toString(counter); + } + JList list = new JList(data); + JScrollPane sp = new JScrollPane(list); + sp.getViewport().putClientProperty("EnableWindowBlit", Boolean.TRUE); + f.add(sp); + f.setSize(200, 200); + return f; + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4237560.java b/test/jdk/javax/swing/JScrollPane/bug4237560.java new file mode 100644 index 00000000000..4f8f27683e5 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4237560.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4237560 + * @summary Tests that JScrollPane do not distort TAB order in an HTML page + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4237560 + */ + +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JScrollPane; + +public class bug4237560 { + static final String INSTRUCTIONS = """ + A JEditorPane contains 10 input fields and is inserted into + JScrollPane. Click text field #8 so that it is selected. Press + TAB three times (even if text field #9 and #10 are not visible in + the ScrollPane). If this gives focus to the first text field (#1) + the test PASSES, else it FAILS. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4237560 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4237560::createUI) + .build() + .awaitAndCheck(); + } + + private static final String TEXT = "
\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
"; + + private static JFrame createUI() { + JFrame frame = new JFrame("JScrollPane HTML TAB Test"); + JEditorPane viewer = new JEditorPane("text/html", TEXT); + viewer.setEditable(false); + frame.add(new JScrollPane(viewer)); + frame.setSize(300, 300); + return frame; + } +} diff --git a/test/jdk/javax/swing/JScrollPane/bug4244899.java b/test/jdk/javax/swing/JScrollPane/bug4244899.java new file mode 100644 index 00000000000..4cb5367f4f5 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/bug4244899.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4244899 + * @summary Tests whether scrolling with blit has artifacts + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4244899 + */ + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +public class bug4244899 { + static final String INSTRUCTIONS = """ + Widen the first column of the table, so that + you get a horizontal scrollbar. Click in the + scrollbar (not on the thumb, but in the track). + If you notice some artifacts/flashing at + the bottom of the frame, the test FAILS. + Otherwise, the test PASSES. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("bug4244899 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4244899::createUI) + .build() + .awaitAndCheck(); + } + + static class TestModel extends AbstractTableModel { + private final int rows = 20; + private final int cols = 5; + + private Integer[][] data; + + public TestModel() { + data = new Integer[rows][]; + int realCount = 0; + for (int counter = 0; counter < rows; counter++) { + data[counter] = new Integer[cols]; + for (int y = 0; y < cols; y++) { + data[counter][y] = Integer.valueOf(realCount); + realCount = (realCount + 1) % 23; + } + } + } + + public int getRowCount() { + return data.length; + } + + public int getColumnCount() { + return data[0].length; + } + + public Object getValueAt(int row, int column) { + return data[row][column]; + } + } + + static JFrame createUI() { + JFrame f = new JFrame("Scrolling Blit Artifact Test"); + JTable table = new JTable(new TestModel()); + JScrollPane sp = new JScrollPane(table); + sp.getViewport().putClientProperty("EnableWindowBlit", Boolean.TRUE); + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + f.add(sp); + f.setSize(400, 400); + return f; + } +} From b7e8952ad6def4ebae8c8c3c04cf6793f472b029 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 22 Apr 2025 23:21:26 +0000 Subject: [PATCH 308/843] 8355071: Fix nsk/jdi test to not require lookup of main thread in order to set the breakpoint used for communication Reviewed-by: lmesnik, amenkov --- .../BooleanType/_itself_/booleantype001.java | 11 +---- .../addInstanceFilter/instancefilter002.java | 12 +----- .../addInstanceFilter/instancefilter003.java | 12 +----- .../addThreadFilter/threadfilter002.java | 12 +----- .../addThreadFilter/threadfilter003.java | 12 +----- .../location/location001.java | 13 +----- .../jdi/ByteType/_itself_/bytetype001.java | 11 +---- .../jdi/CharType/_itself_/chartype001.java | 11 +---- .../definedClasses/definedclasses001.java | 11 +---- .../visibleClasses/visibleclasses001.java | 11 +---- .../addClassExclusionFilter/filter003.java | 15 ++----- .../addClassFilter_rt/filter_rt002.java | 12 +----- .../addClassFilter_s/filter_s002.java | 13 +----- .../DoubleType/_itself_/doubletype001.java | 11 +---- .../nsk/jdi/Event/request/request001.java | 13 +----- .../EventIterator/nextEvent/nextevent001.java | 13 +----- .../nsk/jdi/EventQueue/remove/remove004.java | 15 +------ .../jdi/EventQueue/remove_l/remove_l004.java | 15 +------ .../addCountFilter/addcountfilter001.java | 12 +----- .../jdi/EventRequest/disable/disable002.java | 12 +----- .../jdi/EventRequest/enable/enable001.java | 12 +----- .../jdi/EventRequest/enable/enable002.java | 12 +----- .../getProperty/getproperty001.java | 12 +----- .../EventRequest/isEnabled/isenabled001.java | 12 +----- .../putProperty/putproperty001.java | 12 +----- .../setEnabled/setenabled001.java | 12 +----- .../setEnabled/setenabled002.java | 12 +----- .../setEnabled/setenabled003.java | 12 +----- .../setSuspendPolicy/setsuspendpolicy001.java | 12 +----- .../suspendPolicy/suspendpolicy001.java | 12 +----- .../accwtchpreq002.java | 12 +----- .../breakpointRequests/breakpreq002.java | 12 +----- .../classPrepareRequests/clsprepreq002.java | 12 +----- .../classUnloadRequests/clsunlreq002.java | 12 +----- .../craccwtchpreq003.java | 12 +----- .../crbreakpreq003.java | 12 +----- .../createClassPrepareRequest/cpreg001.java | 12 +----- .../createClassUnloadRequest/cureg001.java | 12 +----- .../createExceptionRequest/crexreq009.java | 12 +----- .../createExceptionRequest/crexreq010.java | 12 +----- .../createMethodEntryRequest/menreg001.java | 12 +----- .../createMethodExitRequest/mexreg001.java | 12 +----- .../crmodwtchpreq003.java | 12 +----- .../createStepRequest/crstepreq002.java | 12 +----- .../createStepRequest/crstepreq003.java | 10 +---- .../createStepRequest/crstepreq004.java | 6 +-- .../createThreadDeathRequest/tdreg001.java | 12 +----- .../createThreadStartRequest/tsreg001.java | 12 +----- .../createVMDeathRequest/vmdreg001.java | 12 +----- .../deleteAllBreakpoints/delallbreakp002.java | 12 +----- .../deleteEventRequest/delevtreq002.java | 12 +----- .../deleteEventRequests/delevtreqs002.java | 12 +----- .../exceptionRequests/excreq002.java | 12 +----- .../methodEntryRequests/methentreq002.java | 12 +----- .../methodExitRequests/methexitreq002.java | 12 +----- .../modwtchpreq002.java | 12 +----- .../stepRequests/stepreq002.java | 12 +----- .../threadDeathRequests/thrdeathreq002.java | 12 +----- .../threadStartRequests/thrstartreq002.java | 12 +----- .../vmDeathRequests/vmdeathreq001.java | 12 +----- .../eventIterator/eventiterator001.java | 13 +----- .../eventIterator/eventiterator002.java | 14 ++----- .../eventIterator/eventiterator003.java | 11 +---- .../eventIterator/eventiterator004.java | 13 +----- .../nsk/jdi/EventSet/resume/resume002.java | 13 ++---- .../nsk/jdi/EventSet/resume/resume003.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume004.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume005.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume006.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume007.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume010.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume011.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume012.java | 12 ++---- .../nsk/jdi/EventSet/resume/resume013.java | 12 ++---- .../suspendPolicy/suspendpolicy001.java | 12 ++---- .../suspendPolicy/suspendpolicy002.java | 12 ++---- .../suspendPolicy/suspendpolicy003.java | 12 ++---- .../suspendPolicy/suspendpolicy004.java | 12 ++---- .../suspendPolicy/suspendpolicy005.java | 12 ++---- .../suspendPolicy/suspendpolicy006.java | 12 ++---- .../suspendPolicy/suspendpolicy007.java | 12 ++---- .../suspendPolicy/suspendpolicy008.java | 12 ++---- .../suspendPolicy/suspendpolicy009.java | 12 ++---- .../suspendPolicy/suspendpolicy010.java | 12 ++---- .../suspendPolicy/suspendpolicy011.java | 12 ++---- .../suspendPolicy/suspendpolicy012.java | 12 ++---- .../suspendPolicy/suspendpolicy013.java | 12 ++---- .../suspendPolicy/suspendpolicy014.java | 12 ++---- .../suspendPolicy/suspendpolicy015.java | 12 ++---- .../suspendPolicy/suspendpolicy016.java | 12 ++---- .../suspendPolicy/suspendpolicy017.java | 12 ++---- .../addClassExclusionFilter/filter002.java | 12 +----- .../addClassFilter_rt/filter_rt002.java | 12 +----- .../addClassFilter_s/filter_s002.java | 12 +----- .../addInstanceFilter/instancefilter002.java | 12 +----- .../addInstanceFilter/instancefilter003.java | 12 +----- .../addThreadFilter/threadfilter002.java | 12 +----- .../addThreadFilter/threadfilter003.java | 12 +----- .../exception/exception001.java | 12 +----- .../notifyCaught/notifycaught001.java | 12 +----- .../notifyUncaught/notifyuncaught001.java | 12 +----- .../jdi/FloatType/_itself_/floattype001.java | 11 +---- .../IntegerType/_itself_/integertype001.java | 11 +---- .../jdi/LocatableEvent/thread/thread001.java | 11 +---- .../jdi/LongType/_itself_/longtype001.java | 11 +---- .../jdi/Method/isObsolete/isobsolete001.java | 17 +++----- .../jdi/Method/isObsolete/isobsolete002.java | 17 +++----- .../addClassExclusionFilter/filter002.java | 12 +----- .../addClassFilter_rt/filter_rt002.java | 12 +----- .../addClassFilter_s/filter_s002.java | 12 +----- .../addInstanceFilter/instancefilter002.java | 12 +----- .../addInstanceFilter/instancefilter003.java | 12 +----- .../addThreadFilter/threadfilter002.java | 12 +----- .../addThreadFilter/threadfilter003.java | 12 +----- .../addClassExclusionFilter/filter002.java | 12 +----- .../addClassFilter_rt/filter_rt002.java | 12 +----- .../addClassFilter_s/filter_s002.java | 12 +----- .../addInstanceFilter/instancefilter002.java | 12 +----- .../addInstanceFilter/instancefilter003.java | 12 +----- .../addThreadFilter/threadfilter002.java | 12 +----- .../addThreadFilter/threadfilter003.java | 12 +----- .../_itself_/mwevent001.java | 12 +----- .../disablecollection002.java | 11 +---- .../classPath/classpath001.java | 15 +------ .../_itself_/primitivetype001.java | 11 +---- .../classLoader/classloader001.java | 15 +------ .../ReferenceType/getValue/getvalue001.java | 15 +------ .../ReferenceType/getValue/getvalue002.java | 15 +------ .../ReferenceType/getValue/getvalue003.java | 15 +------ .../ReferenceType/getValues/getvalues001.java | 15 +------ .../jdi/ReferenceType/isFinal/isfinal001.java | 15 +------ .../ReferenceType/isStatic/isstatic001.java | 11 +---- .../ReferenceType/isStatic/isstatic002.java | 11 +---- .../nestedTypes/nestedtypes001.java | 15 +------ .../nestedTypes/nestedtypes002.java | 15 +------ .../jdi/ShortType/_itself_/shorttype001.java | 11 +---- .../addClassExclusionFilter/filter002.java | 16 ++----- .../addClassFilter_rt/filter_rt002.java | 12 +----- .../addClassFilter_s/filter_s002.java | 12 +----- .../addInstanceFilter/instancefilter002.java | 12 +----- .../addInstanceFilter/instancefilter003.java | 12 +----- .../nsk/jdi/StepRequest/depth/depth001.java | 12 +----- .../nsk/jdi/StepRequest/depth/depth002.java | 12 +----- .../nsk/jdi/StepRequest/depth/depth003.java | 12 +----- .../nsk/jdi/StepRequest/size/size001.java | 12 +----- .../nsk/jdi/StepRequest/size/size002.java | 12 +----- .../nsk/jdi/StepRequest/thread/thread001.java | 12 +----- .../addThreadFilter/addthreadfilter001.java | 13 +----- .../addThreadFilter/addthreadfilter002.java | 14 ++----- .../addThreadFilter/addthreadfilter003.java | 11 +---- .../addThreadFilter/addthreadfilter005.java | 12 +----- .../popFrames/popframes001.java | 15 +------ .../popFrames/popframes002.java | 14 +------ .../popFrames/popframes003.java | 19 ++------- .../popFrames/popframes004.java | 12 +----- .../popFrames/popframes005.java | 12 +----- .../addThreadFilter/addthreadfilter001.java | 13 +----- .../addThreadFilter/addthreadfilter003.java | 11 +---- .../addThreadFilter/addthreadfilter005.java | 12 +----- .../jdi/VMDeathEvent/_itself_/vmdeath002.java | 11 +---- .../jdi/VMDeathEvent/_itself_/vmdeath003.java | 11 +---- .../allClasses/allclasses001.java | 15 +------ .../canAddMethod/canaddmethod001.java | 15 +------ .../canPopFrames/canpopframes001.java | 15 +------ .../canredefineclasses001.java | 15 +------ .../canreqvmdev001.java | 15 +------ .../curc001.java | 15 +------ .../canusefilters001.java | 15 +------ .../canwatchaccess001.java | 15 +------ .../canwatchmod001.java | 15 +------ .../redefineClasses/redefineclasses001.java | 25 ++++------- .../jdi/VoidType/_itself_/voidtype001.java | 11 +---- .../addClassExclusionFilter/filter003.java | 12 +----- .../addClassExclusionFilter/filter004.java | 12 +----- .../addClassFilter_rt/filter_rt003.java | 12 +----- .../addClassFilter_rt/filter_rt004.java | 12 +----- .../addClassFilter_s/filter_s003.java | 12 +----- .../addClassFilter_s/filter_s004.java | 12 +----- .../addInstanceFilter/instancefilter003.java | 12 +----- .../addInstanceFilter/instancefilter004.java | 12 +----- .../addInstanceFilter/instancefilter005.java | 12 +----- .../addInstanceFilter/instancefilter006.java | 12 +----- .../addThreadFilter/addthreadfilter003.java | 12 +----- .../addThreadFilter/addthreadfilter004.java | 12 +----- .../addThreadFilter/addthreadfilter005.java | 12 +----- .../addThreadFilter/addthreadfilter006.java | 12 +----- .../jdi/WatchpointRequest/field/field001.java | 13 +----- .../jdi/WatchpointRequest/field/field002.java | 12 +----- .../vmTestbase/nsk/share/jdi/JDIBase.java | 42 ++++++++++++++++++- 189 files changed, 462 insertions(+), 1923 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java index 92bb93ad15c..49c0b778c76 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,14 +244,7 @@ public class booleantype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java index e37ee7eacbe..31dd6718177 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,15 +257,7 @@ public class instancefilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java index 612792a417b..5562d2c4239 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,15 +245,7 @@ public class instancefilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java index 6d39e3d31c1..b76ccc799f2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,15 +252,7 @@ public class threadfilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java index 421ffc26185..ff18b6b6cf5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,15 +252,7 @@ public class threadfilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java index f2d2de73210..325159b6eb5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,16 +250,7 @@ public class location001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java index 4c56c75ad13..36666e3b08e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,7 @@ public class bytetype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java index 66579c598b7..3b0d71619ae 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,7 @@ public class chartype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java index 59fc1a0ab11..c7b9cb92858 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,14 +241,7 @@ public class definedclasses001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java index 63b6fec010c..1d561c27b95 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,14 +255,7 @@ public class visibleclasses001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java index cabaf723c14..c0bfe91a750 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,18 +244,9 @@ public class filter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; + setupBreakpointForCommunication(debuggeeClass); - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); - - //------------------------------------------------------ testing section + //------------------------------------------------------ testing section log1(" TESTING BEGINS"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java index dfaaa176977..9be0d89a4b9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,15 +248,7 @@ public class filter_rt002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java index c175dff4e2f..1cc0dff5c99 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,16 +250,7 @@ public class filter_s002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java index c7aa128fa94..99ddbbdcbcc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,7 @@ public class doubletype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java index c6d7b7292e7..970aedb047d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -308,16 +308,7 @@ public class request001 extends JDIBase { log2("......setting up ClassPrepareEvent"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java index 11b6e4824fc..a6018450771 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -306,16 +306,7 @@ public class nextevent001 extends JDIBase { log2("......setting up ClassPrepareEvent"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java index a5d74ff3d95..f6cf40dad38 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,18 +243,7 @@ public class remove004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java index 056030aab3d..9a84dd3f0fe 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,18 +238,7 @@ public class remove_l004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java index 41411b88ac9..f4e41409cae 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,15 +248,7 @@ public class addcountfilter001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java index 2bf6c911e6d..b46bf2ee1a2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,15 +244,7 @@ public class disable002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java index 109ab148806..615cf46c746 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,15 +244,7 @@ public class enable001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java index f4f9a14ac1d..767f069438f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class enable002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java index 886993a4bb0..b4b9f0edcbc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class getproperty001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java index 3ef5500e4ab..d91db9a5a6a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,15 +245,7 @@ public class isenabled001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java index fcedeca850b..479c40904e7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class putproperty001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java index 1d7c80dfa34..57ed8454eda 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,15 +243,7 @@ public class setenabled001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java index c7bcfaa47b7..25b665dbed9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -247,15 +247,7 @@ public class setenabled002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java index 8e129027b51..7ebe5b99a1f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class setenabled003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java index e1b315519fd..04995ea0b13 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,15 +248,7 @@ public class setsuspendpolicy001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java index 7f927de1577..b11a291b2f5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,15 +244,7 @@ public class suspendpolicy001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java index f27f6a12e31..c7b1af9d79b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,15 +245,7 @@ public class accwtchpreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java index 4046560e444..69979345382 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,15 +240,7 @@ public class breakpreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java index c9719ba3a54..b2905b6527e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class clsprepreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java index b6bc52f154e..c185b8b398e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class clsunlreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java index 2be4f8afc9d..9326ce5c7d9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,15 +244,7 @@ public class craccwtchpreq003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java index 610a691b269..b4af90a642c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class crbreakpreq003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java index dd0848af06c..62761b58d33 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,15 +240,7 @@ public class cpreg001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java index bba4427d531..4cedae783cf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -239,15 +239,7 @@ public class cureg001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java index 4ba4bba13a3..fa92b0e5b96 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,15 +242,7 @@ public class crexreq009 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java index 6d466265ddf..28a787d957f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,15 +243,7 @@ public class crexreq010 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java index e744ec1e8f8..7bfeb11932a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -239,15 +239,7 @@ public class menreg001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java index 9d107ee60b0..94b97da9c0e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,15 +238,7 @@ public class mexreg001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java index 24198633580..6059dead131 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,15 +243,7 @@ public class crmodwtchpreq003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java index da62eaea146..a5dd9023dfd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,15 +243,7 @@ public class crstepreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java index 129d9470730..d712fb34c42 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -157,14 +157,6 @@ public class crstepreq003 { //--------------------------------------------------------- mutable common methods private void execTest() { - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); -/* - BreakpointRequest bpRequest = setBreakpoint( mainThread, - debuggeeClass, - "methodForCommunication", - 2, - "breakpointForCommunication"); -*/ BreakpointRequest bpRequest = setBreakpoint( null, debuggeeClass, "breakInThread", diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java index 24305ec29f2..1ab0ce68af8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -158,9 +158,7 @@ public class crstepreq004 { //--------------------------------------------------------- mutable common methods private void execTest() { - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = setBreakpoint( mainThread, + BreakpointRequest bpRequest = setBreakpoint( null, debuggeeClass, "methodForCommunication", lineForBreakInThread, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java index 5c650112f56..e2045f9a94d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -239,15 +239,7 @@ public class tdreg001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java index 8b594d43285..ed81b00561e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,15 +238,7 @@ public class tsreg001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java index dcc5c1b680c..29f1cacf7e7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class vmdreg001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java index 072277425cc..9ed87be5e11 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,15 +240,7 @@ public class delallbreakp002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java index 9cfafaea23e..5b5481af063 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class delevtreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java index 8a53a91e8e1..03e5e38a3ec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,15 +244,7 @@ public class delevtreqs002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java index 7c59958fb89..78219909d03 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,15 +242,7 @@ public class excreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java index 2b37b6e47fa..95a9b36d826 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class methentreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java index e63a1cd4349..f975441a9ba 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,15 +240,7 @@ public class methexitreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java index fe60b2c3963..8a9d5fcbd34 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -247,15 +247,7 @@ public class modwtchpreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java index b4354995389..e1f2677c429 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class stepreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java index ab46a848c8e..9e1b9d8edec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class thrdeathreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java index f7607b22e08..d192c61470d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class thrstartreq002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java index 7f839dcc192..3f740b2f30e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,15 +241,7 @@ public class vmdeathreq001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java index f16ab02ddfe..e56fb00108d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -266,16 +266,7 @@ public class eventiterator001 extends JDIBase { cpRequest.disable(); debuggeeClass = event.referenceType(); - - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); - + setupBreakpointForCommunication(debuggeeClass); } else if (property.equals("TestClassPrepareRequest")) { nn2++; if (nn2 > 1) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java index e0a32aa0aa2..0d374f39e37 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,16 +255,7 @@ public class eventiterator002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section @@ -286,6 +277,7 @@ public class eventiterator002 extends JDIBase { vm.resume(); breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java index 323dea95fe7..35a9eedfd4d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,14 +251,7 @@ public class eventiterator003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java index 084db7b6676..20686736deb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -276,16 +276,7 @@ public class eventiterator004 extends JDIBase { log2("......setting up ClassPrepareEvent"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java index 09bcb91cbdd..b391036fa26 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,14 +260,7 @@ public class resume002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -287,10 +280,10 @@ public class resume002 extends JDIBase { ReferenceType testClassReference = null; - for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java index 3ea05a0c7d9..0e13529f5e1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,14 +260,7 @@ public class resume003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -291,6 +284,7 @@ public class resume003 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java index 413309e92ad..398e6f074a0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,14 +253,7 @@ public class resume004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -285,6 +278,7 @@ public class resume004 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java index 13e0344dd3f..7074828dc8d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,14 +253,7 @@ public class resume005 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -285,6 +278,7 @@ public class resume005 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java index ef87bba8a0d..492afad89ca 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,14 +253,7 @@ public class resume006 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -282,6 +275,7 @@ public class resume006 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java index 235fe36c35c..8052c193954 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,14 +253,7 @@ public class resume007 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -282,6 +275,7 @@ public class resume007 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java index d49e0c516a3..443b7e94286 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,14 +253,7 @@ public class resume010 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -281,6 +274,7 @@ public class resume010 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java index fb9c1e6fde4..0eb923321bd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,14 +254,7 @@ public class resume011 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -280,6 +273,7 @@ public class resume011 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java index 3d153675ee8..32f30882efb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,14 +255,7 @@ public class resume012 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -281,6 +274,7 @@ public class resume012 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java index d1fc3cb68bb..6019903d6b8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,14 +255,7 @@ public class resume013 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -280,6 +273,7 @@ public class resume013 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java index dd51b0d0390..d145bf46136 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,14 +257,8 @@ public class suspendpolicy001 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java index 01be6ad55c4..93f0a5ca627 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,14 +258,7 @@ public class suspendpolicy002 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -300,6 +293,7 @@ public class suspendpolicy002 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java index 522d6019f25..5c0052e84f9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -265,14 +265,7 @@ public class suspendpolicy003 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -308,6 +301,7 @@ public class suspendpolicy003 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java index cddb7ace5b0..d6b6a76be19 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,14 +259,7 @@ public class suspendpolicy004 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -303,6 +296,7 @@ public class suspendpolicy004 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java index 9d0c7604aba..cfdb6513482 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,14 +259,7 @@ public class suspendpolicy005 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -303,6 +296,7 @@ public class suspendpolicy005 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java index 068dd94eead..660f4bbbc36 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,14 +258,7 @@ public class suspendpolicy006 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -301,6 +294,7 @@ public class suspendpolicy006 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java index 4601a0039fa..71abca720e1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,14 +258,7 @@ public class suspendpolicy007 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -300,6 +293,7 @@ public class suspendpolicy007 extends JDIBase { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java index d507d8c6a38..f0838067241 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,14 +258,7 @@ public class suspendpolicy008 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -295,6 +288,7 @@ public class suspendpolicy008 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java index ca284271be8..21bffce5cf3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,14 +258,7 @@ public class suspendpolicy009 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -295,6 +288,7 @@ public class suspendpolicy009 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(debuggeeName); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java index ec015576277..7bd3b660b93 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,14 +257,7 @@ public class suspendpolicy010 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -294,6 +287,7 @@ public class suspendpolicy010 extends JDIBase { for (int i = 0; ; i++) { breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java index 03d7677c0fb..47025717ed7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -266,14 +266,7 @@ public class suspendpolicy011 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -300,6 +293,7 @@ public class suspendpolicy011 extends JDIBase { int policy = 0; breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java index bb5488d9eb6..420b2fe6c87 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -265,14 +265,7 @@ public class suspendpolicy012 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -299,6 +292,7 @@ public class suspendpolicy012 extends JDIBase { int policy = 0; breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java index d78655d1b2a..db3a15f3571 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -266,14 +266,7 @@ public class suspendpolicy013 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -300,6 +293,7 @@ public class suspendpolicy013 extends JDIBase { int policy = 0; breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java index 511dc1ddcc1..d1258b93b0d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -267,14 +267,7 @@ public class suspendpolicy014 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -301,6 +294,7 @@ public class suspendpolicy014 extends JDIBase { int policy = 0; breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java index a3961c1d005..a14f2485129 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -267,14 +267,7 @@ public class suspendpolicy015 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -301,6 +294,7 @@ public class suspendpolicy015 extends JDIBase { int policy = 0; breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java index 0b6257f34ef..3c270b547fb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -265,14 +265,7 @@ public class suspendpolicy016 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -299,6 +292,7 @@ public class suspendpolicy016 extends JDIBase { int policy = 0; breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java index c7589574ee5..171db5a9bb6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -267,14 +267,7 @@ public class suspendpolicy017 extends JDIBase { log2("......setting up ClassPrepareEvent for breakpointForCommunication"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); @@ -301,6 +294,7 @@ public class suspendpolicy017 extends JDIBase { int policy = 0; breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java index d0dac294c8b..9402145c3a0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,15 +249,7 @@ public class filter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java index c3a39e40d0b..ea0e2d36891 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_rt002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java index 8fa62d0edfc..c5cad69c37d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_s002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java index 6f62f5b08d5..c39f6c8c15d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,15 +257,7 @@ public class instancefilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java index f1e9f6607ff..80f8c4024e2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,15 +245,7 @@ public class instancefilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java index d641750204c..bb20c736a06 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,15 +252,7 @@ public class threadfilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java index 467a66f52fc..0d6f85304c8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,15 +252,7 @@ public class threadfilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java index 4c0d1824812..ef0bf984182 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,15 +244,7 @@ public class exception001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); vm.resume(); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java index ad747876586..fd3410f5d4c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,15 +242,7 @@ public class notifycaught001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java index 883e020caa6..557f60138ba 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,15 +242,7 @@ public class notifyuncaught001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java index 156d4b471ba..5a051ad546f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,7 @@ public class floattype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java index 206882b2768..e40dbb1b784 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,7 @@ public class integertype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java index 543123066cf..f2031008b2f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,14 +253,7 @@ public class thread001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java index 05d5baf3a66..a483e04e5d9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,7 @@ public class longtype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001.java index 02ce3f5e020..6ccbbca659c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -261,16 +261,7 @@ public class isobsolete001 extends JDIBase { return; } - - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByName("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section @@ -288,6 +279,7 @@ public class isobsolete001 extends JDIBase { vm.resume(); breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); @@ -315,7 +307,8 @@ public class isobsolete001 extends JDIBase { log2(" : isObsolete() == false for m2 method before redefineClasses() invocation "); // Create breakpoint request to have isobsolete002b.m2 on the top of the stack. - bpRequest = debuggee.makeBreakpoint(redefClass, methodName, brkpLineNumber); + BreakpointRequest bpRequest = + debuggee.makeBreakpoint(redefClass, methodName, brkpLineNumber); bpRequest.addThreadFilter(mainThread); bpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); bpRequest.putProperty("number", "one"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java index 1693a63843e..35f59f55524 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -259,16 +259,7 @@ public class isobsolete002 extends JDIBase { return; } - - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - ThreadReference mainThread = debuggee.threadByName("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section @@ -284,6 +275,7 @@ public class isobsolete002 extends JDIBase { vm.resume(); breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); @@ -315,7 +307,8 @@ public class isobsolete002 extends JDIBase { log2(" : isObsolete() == false for m2 method before redefineClasses() invocation"); // Create breakpoint request to have isobsolete002b.m2 on the top of the stack. - bpRequest = debuggee.makeBreakpoint(redefClass, methodName, brkpLineNumber); + BreakpointRequest bpRequest = + debuggee.makeBreakpoint(redefClass, methodName, brkpLineNumber); bpRequest.addThreadFilter(mainThread); bpRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); bpRequest.putProperty("number", "one"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java index 5fef3066c44..6e293a98670 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,15 +249,7 @@ public class filter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java index 1d83e104b72..b34e5c577db 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_rt002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java index 7cb4c40ee47..215639d825f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,15 +249,7 @@ public class filter_s002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java index 3f013618ac9..02cdff05b4e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,15 +257,7 @@ public class instancefilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java index 67009ca963d..a6386045f20 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,15 +248,7 @@ public class instancefilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java index b889d75510b..a5a2b16318e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,15 +252,7 @@ public class threadfilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java index 161190a7abd..da83ab4ece4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,15 +252,7 @@ public class threadfilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java index 75f7ad3a523..3fd039e10d1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,15 +249,7 @@ public class filter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java index 374ebace2ff..4dedd0debb0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,15 +249,7 @@ public class filter_rt002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java index 3d243865d1a..917bc96c467 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,15 +249,7 @@ public class filter_s002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java index 25ccf74fe0d..a00e92c32e9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,15 +257,7 @@ public class instancefilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java index 33d8d261291..c5414ae5ae1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class instancefilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java index b87bfba5fa6..8d2dab19a45 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,15 +251,7 @@ public class threadfilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java index b09d7f46f9e..0067f7dde19 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,15 +251,7 @@ public class threadfilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java index 42a1e08eb3b..ef10699b5fe 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,15 +252,7 @@ public class mwevent001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java index 89dcfde4d99..b7ea4154fec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -261,14 +261,7 @@ public class disablecollection002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java index 97908175e7b..f67e21a7cdd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,18 +244,7 @@ public class classpath001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java index a3c32fb0d27..bb3d23352a1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,14 +237,7 @@ public class primitivetype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java index 644e60f4844..1040f7eba69 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -230,18 +230,7 @@ public class classloader001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java index bcd64b0b460..ad2be88a6db 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,18 +231,7 @@ public class getvalue001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java index 5d7439b2f8c..8c9aae8802b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -230,18 +230,7 @@ public class getvalue002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java index b81bfd78729..46411cb9d74 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -230,18 +230,7 @@ public class getvalue003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java index b14d687b411..4e7fb04fe0d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -234,18 +234,7 @@ public class getvalues001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java index 885e1ec17a4..88d0d5d8138 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -218,18 +218,7 @@ public class isfinal001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java index e6e901f31e5..d72a6480dbf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,14 +246,7 @@ public class isstatic001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java index d07705fe4c6..b3cf2483d80 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,14 +246,7 @@ public class isstatic002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java index 69d2a8ed24b..7369b663876 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -224,18 +224,7 @@ public class nestedtypes001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java index 344e1fd199a..dce3f638f28 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,18 +225,7 @@ public class nestedtypes002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch (Exception e) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java index fea3e5c78b4..54e297f27e8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,7 @@ public class shorttype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java index e53f12004cf..d64fa09323c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,15 +248,7 @@ public class filter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section @@ -271,6 +263,7 @@ public class filter002 extends JDIBase { vm.resume(); breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); @@ -287,8 +280,7 @@ public class filter002 extends JDIBase { switch (i) { case 0: - ThreadReference thread1 = debuggee.threadByNameOrThrow("main"); - eventRequest1 = setting23StepRequest(thread1, testedClassName1, + eventRequest1 = setting23StepRequest(mainThread, testedClassName1, EventRequest.SUSPEND_NONE, property1); eventRequest1.enable(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java index e12e48e9ebf..23be3eab4c9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_rt002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java index db080ef80ed..d4ff86268da 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_s002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java index e75a998a07c..19ddd279425 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,15 +257,7 @@ public class instancefilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java index f4fa3e1bf68..1f8236db782 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class instancefilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java index 99d24970e6d..de63a0af86b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class depth001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java index 09b0fa297b4..5cd109f6fa3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class depth002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java index ef3668a66e8..03b8f415b56 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class depth003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java index 33b2c02e8eb..db59bf6e498 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class size001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java index 5a0df354569..09b0c53ea8c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,15 +246,7 @@ public class size002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java index 8bb9711d37b..a8d3769c6c2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,15 +248,7 @@ public class thread001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java index 542a5280d4b..020c04c05d5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,16 +243,7 @@ public class addthreadfilter001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java index 4d572e1d12c..961a38a6393 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,16 +240,7 @@ public class addthreadfilter002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section @@ -259,6 +250,7 @@ public class addthreadfilter002 extends JDIBase { vm.resume(); breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java index 70d9e87fee4..3a5770ff03c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,14 +254,7 @@ public class addthreadfilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java index 30fac8e0aaa..d07758242ec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,15 +254,7 @@ public class addthreadfilter005 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java index 69c30d0aa24..3091f510977 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,18 +260,7 @@ public class popframes001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java index 2e5b28c2dfc..c47358e96f8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,7 +111,6 @@ public class popframes002 extends JDIBase { //====================================================== test program - BreakpointRequest bpRequest; BreakpointRequest breakpointRequest2; BreakpointRequest breakpointRequest3; @@ -259,16 +258,7 @@ public class popframes002 extends JDIBase { return; } - - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - log2("......setting BreakpointRequest (bpRequest) in main thread"); - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - log2("bpRequest.enable();"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java index 27866885bdb..84ee5996a77 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,7 +110,6 @@ public class popframes003 extends JDIBase { //====================================================== test program - BreakpointRequest bpRequest; MethodEntryRequest meRequest; BreakpointRequest bpRequest2; @@ -260,18 +259,7 @@ public class popframes003 extends JDIBase { return; } - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference threadMainRef = debuggee.threadByNameOrThrow("main"); - try { - bpRequest = settingBreakpoint(threadMainRef, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section @@ -284,9 +272,10 @@ public class popframes003 extends JDIBase { vm.resume(); breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() log2("......setting MethodEntryRequest (meRequest) in ForCommunication.methodForCommunication"); - meRequest = settingMethodEntryRequest(threadMainRef, + meRequest = settingMethodEntryRequest(mainThread, debuggeeName + "$ForCommunication", "zero"); log2("meRequest.enable();"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java index 5e06aec1810..eb46fac37da 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,15 +258,7 @@ public class popframes004 extends JDIBase { return; } - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - log2("......setting BreakpointRequest (bpRequest) in main thread"); - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - log2("bpRequest.enable();"); - bpRequest.enable(); + bpRequest = setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java index 7618a200e28..ec499eba24d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -262,15 +262,7 @@ public class popframes005 extends JDIBase { return; } - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - log2("......setting BreakpointRequest (bpRequest) in main thread"); - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - log2("bpRequest.enable();"); - bpRequest.enable(); + bpRequest = setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java index ace63e511aa..b9a15b2c377 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,16 +243,7 @@ public class addthreadfilter001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java index 21cf8a9d164..cacda11b6c4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,14 +254,7 @@ public class addthreadfilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java index 8dad0781d16..255984d7a01 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,15 +248,7 @@ public class addthreadfilter005 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java index 1fa254e7d4a..12804532315 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,14 +237,7 @@ public class vmdeath002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java index 8070d8143c1..26b4693d696 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,14 +242,7 @@ public class vmdeath003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java index 44477e156f9..e5981bf0b34 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,18 +236,7 @@ public class allclasses001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java index f0eea0731c0..d31f547f80d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,18 +225,7 @@ public class canaddmethod001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java index 03f38b66f1f..31e29c10240 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,18 +225,7 @@ public class canpopframes001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java index 88e54ac79a4..b1023026c47 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,18 +225,7 @@ public class canredefineclasses001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java index 8d057c809cb..aa43d39b559 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,18 +225,7 @@ public class canreqvmdev001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java index 62d44d8c7bb..b95f5a19a31 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,18 +225,7 @@ public class curc001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java index c03cef0d05c..ad337dd54f5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,18 +225,7 @@ public class canusefilters001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java index 466c2c6ed78..6b0d64d9781 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,18 +236,7 @@ public class canwatchaccess001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java index b64d346994d..07410545e9f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,18 +237,7 @@ public class canwatchmod001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - try { - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - } catch ( Exception e ) { - throw e; - } - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java index 5db62c170de..aab5c173f30 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -264,15 +264,7 @@ public class redefineclasses001 extends JDIBase { return; } - - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section @@ -293,6 +285,7 @@ public class redefineclasses001 extends JDIBase { vm.resume(); breakpointForCommunication(); + ThreadReference mainThread = bpEvent.thread(); // bpEvent saved by breakpointForCommunication() int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); @@ -310,9 +303,9 @@ public class redefineclasses001 extends JDIBase { case 0: List classes = vm.classesByName(bpClassName); bpClass = (ReferenceType) classes.get(0); - bpRequest2 = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - bpClass, - bpMethodName, bpLineName, "one"); + bpRequest2 = settingBreakpoint(mainThread, + bpClass, + bpMethodName, bpLineName, "one"); bpRequest2.enable(); vm.resume(); @@ -335,9 +328,9 @@ public class redefineclasses001 extends JDIBase { case 1: - bpRequest3 = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - bpClass, - bpMethodName, bpLineName, "one"); + bpRequest3 = settingBreakpoint(mainThread, + bpClass, + bpMethodName, bpLineName, "one"); bpRequest3.enable(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java index f3e0c7f583d..90da9975df4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,14 +237,7 @@ public class voidtype001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - BreakpointRequest bpRequest; - - bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java index 7b77beedc1a..d7a182cba79 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java index 6be78f1d596..0b8d7135cfb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java index 1fd6ae0ffde..0d2176b0910 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_rt003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java index 1e37d5cac41..0bd09aca339 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_rt004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java index 92234071cc6..d2ea9213899 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_s003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java index 21030c2bf40..3790d2e7dcc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,15 +250,7 @@ public class filter_s004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java index 1d71e9990d3..5b3184ded80 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,15 +258,7 @@ public class instancefilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java index 12a0fdac2c8..dd02ed1c67f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,15 +258,7 @@ public class instancefilter004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java index 005367911af..9e690424420 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -247,15 +247,7 @@ public class instancefilter005 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java index e479bb104eb..21756dfd59c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -247,15 +247,7 @@ public class instancefilter006 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java index 344d0e36428..75f4e45345d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -261,15 +261,7 @@ public class addthreadfilter003 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java index c875dcaa034..b4c7b60971b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -261,15 +261,7 @@ public class addthreadfilter004 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java index e5bc8a555ed..9e371abf8ee 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -261,15 +261,7 @@ public class addthreadfilter005 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java index 3ee70ff8202..8f24855f9af 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -262,15 +262,7 @@ public class addthreadfilter006 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java index 36af014db0b..0b6d1b67a42 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,16 +248,7 @@ public class field001 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); - + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section log1(" TESTING BEGINS"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java index 3fbbeb5915b..314b0b32cc7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,15 +249,7 @@ public class field002 extends JDIBase { log2(" received: ClassPrepareEvent for debuggeeClass"); - String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; - - ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); - - BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); - bpRequest.enable(); + setupBreakpointForCommunication(debuggeeClass); //------------------------------------------------------ testing section diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIBase.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIBase.java index bc722844afd..ac99b121651 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIBase.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,12 +89,33 @@ public class JDIBase { protected Location breakpLocation = null; protected BreakpointEvent bpEvent; + protected final BreakpointRequest settingBreakpoint( + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { + return settingBreakpoint_private(null, testedClass, methodName, bpLine, property); + } + protected final BreakpointRequest settingBreakpoint(ThreadReference thread, ReferenceType testedClass, String methodName, String bpLine, String property) throws JDITestRuntimeException { + if (thread == null) { + log3("ERROR: TEST_ERROR_IN_settingBreakpoint(): thread is null"); + } + return settingBreakpoint_private(thread, testedClass, methodName, bpLine, property); + } + + private final BreakpointRequest settingBreakpoint_private(ThreadReference thread, + ReferenceType testedClass, + String methodName, + String bpLine, + String property) + throws JDITestRuntimeException { log2("......setting up a breakpoint:"); log2(" thread: " + thread + "; class: " + testedClass + @@ -119,11 +140,14 @@ public class JDIBase { try { breakpRequest = eventRManager.createBreakpointRequest(lineLocation); breakpRequest.putProperty("number", property); - breakpRequest.addThreadFilter(thread); + if (thread != null) { + breakpRequest.addThreadFilter(thread); + } breakpRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); } catch (Exception e1) { log3("ERROR: inner Exception within settingBreakpoint() : " + e1); breakpRequest = null; + e1.printStackTrace(logHandler.getOutStream()); } } } catch (Exception e2) { @@ -188,6 +212,19 @@ public class JDIBase { eventIterator = eventSet.eventIterator(); } + // Sets up the standard breakpoint for communication. The breakpoint is set on + // methodForCommunication() using the line number stored in the "lineForComm" + // local variable. The breakpoint is enabled. + protected BreakpointRequest setupBreakpointForCommunication(ReferenceType debuggeeClass) { + String bPointMethod = "methodForCommunication"; + String lineForComm = "lineForComm"; + + BreakpointRequest bpRequest = + settingBreakpoint(debuggeeClass, bPointMethod, lineForComm, "zero"); + bpRequest.enable(); + return bpRequest; + } + protected void breakpointForCommunication() throws JDITestRuntimeException { log2("breakpointForCommunication"); @@ -219,6 +256,7 @@ public class JDIBase { Event event = eventIterator.nextEvent(); if (event instanceof BreakpointEvent) { + bpEvent = (BreakpointEvent) event; return; } if (EventFilters.filtered(event, debuggeeName)) { From 53924882326d3756a4ec52f37a59c8a81059a069 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Wed, 23 Apr 2025 00:13:09 +0000 Subject: [PATCH 309/843] 8355332: Fix failing semi-manual test EDT issue Reviewed-by: azvegint --- .../HorizScrollers.java | 7 +++--- .../RTLScrollers.java | 24 ++++++++----------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java index b584fd66da3..61124ea1e97 100644 --- a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java +++ b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java @@ -161,8 +161,9 @@ public class HorizScrollers { if (scrollAmount != 3) { JOptionPane.showMessageDialog( ConfigPanel.this.getTopLevelAncestor(), - ("Test %s. please make sure you have restored " + - "the original speed value blah blah") + ("Test %s. Please make sure you have restored " + + "the original scrolling speed in the " + + "Mouse settings.") .formatted(isFailure ? "failed" : "passed"), @@ -231,4 +232,4 @@ public class HorizScrollers { } } } -} \ No newline at end of file +} diff --git a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java index 24e8df6fad8..da395282bf5 100644 --- a/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java +++ b/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/RTLScrollers.java @@ -265,22 +265,21 @@ public class RTLScrollers extends JDialog } } + robot.delay(1000); SwingUtilities.invokeAndWait(() -> { rtl = new RTLScrollers(scrollAmount); rtl.setVisible(true); }); robot.delay(100); - SwingUtilities.invokeAndWait(() -> { - try { - retVal = rtl.runTests(scrollAmount); - } catch (Exception e) { - e.printStackTrace(); - } finally { + try { + retVal = rtl.runTests(scrollAmount); + } finally { + SwingUtilities.invokeAndWait(() -> { rtl.setVisible(false); rtl.dispose(); - } - }); + }); + } robot.delay(100); System.out.println("RTLS.runTest(): " + retVal); @@ -312,9 +311,8 @@ public class RTLScrollers extends JDialog System.out.println("Testing List"); testComp(list, scrollAmount); - SwingUtilities.invokeAndWait(() -> { - applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); - }); + SwingUtilities.invokeAndWait(() -> + applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT)); robot.delay(100); System.out.println("Testing RTL Table"); @@ -467,9 +465,7 @@ public class RTLScrollers extends JDialog // Test acceleration for max scrolling // (this part should still work for RTL JList) if (scrollAmount == 30) { - SwingUtilities.invokeAndWait(() -> { - hsb.setValue(hsb.getMinimum()); - }); + SwingUtilities.invokeAndWait(() -> hsb.setValue(hsb.getMinimum())); robot.delay(100); robot.mouseWheel(2); robot.mouseWheel(2); From 4c373703d9ed63dfc85df7cdcc04ecad5b02ade0 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Wed, 23 Apr 2025 02:04:46 +0000 Subject: [PATCH 310/843] 8354668: Missing REX2 prefix accounting in ZGC barriers leads to incorrect encoding Reviewed-by: aboldtch, sviswanathan --- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp | 14 +++++++------- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp | 2 +- src/hotspot/cpu/x86/gc/z/z_x86_64.ad | 4 ++-- src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index 9cdf0b229c0..0891d303563 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -391,8 +391,8 @@ void ZBarrierSetAssembler::store_barrier_fast(MacroAssembler* masm, if (rnew_zaddress != noreg) { // noreg means null; no need to color __ movptr(rnew_zpointer, rnew_zaddress); - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shlq(rnew_zpointer, barrier_Relocation::unpatched); + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); __ orq_imm32(rnew_zpointer, barrier_Relocation::unpatched); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodAfterOr); } @@ -969,13 +969,13 @@ void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, #define __ ce->masm()-> static void z_uncolor(LIR_Assembler* ce, LIR_Opr ref) { - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shrq(ref->as_register(), barrier_Relocation::unpatched); + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); } static void z_color(LIR_Assembler* ce, LIR_Opr ref) { - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shlq(ref->as_register(), barrier_Relocation::unpatched); + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); __ orq_imm32(ref->as_register(), barrier_Relocation::unpatched); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodAfterOr); } @@ -1278,8 +1278,8 @@ void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, static int patch_barrier_relocation_offset(int format) { switch (format) { - case ZBarrierRelocationFormatLoadGoodBeforeShl: - return 3; + case ZBarrierRelocationFormatLoadGoodAfterShX: + return -1; case ZBarrierRelocationFormatStoreGoodAfterCmp: return -2; @@ -1300,7 +1300,7 @@ static int patch_barrier_relocation_offset(int format) { static uint16_t patch_barrier_relocation_value(int format) { switch (format) { - case ZBarrierRelocationFormatLoadGoodBeforeShl: + case ZBarrierRelocationFormatLoadGoodAfterShX: return (uint16_t)ZPointerLoadShift; case ZBarrierRelocationFormatMarkBadAfterTest: @@ -1327,7 +1327,7 @@ void ZBarrierSetAssembler::patch_barrier_relocation(address addr, int format) { const int offset = patch_barrier_relocation_offset(format); const uint16_t value = patch_barrier_relocation_value(format); uint8_t* const patch_addr = (uint8_t*)addr + offset; - if (format == ZBarrierRelocationFormatLoadGoodBeforeShl) { + if (format == ZBarrierRelocationFormatLoadGoodAfterShX) { *patch_addr = (uint8_t)value; } else { *(uint16_t*)patch_addr = value; diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp index 8bb653ec5fb..6976452bd63 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp @@ -49,7 +49,7 @@ class ZLoadBarrierStubC2; class ZStoreBarrierStubC2; #endif // COMPILER2 -const int ZBarrierRelocationFormatLoadGoodBeforeShl = 0; +const int ZBarrierRelocationFormatLoadGoodAfterShX = 0; const int ZBarrierRelocationFormatLoadBadAfterTest = 1; const int ZBarrierRelocationFormatMarkBadAfterTest = 2; const int ZBarrierRelocationFormatStoreGoodAfterCmp = 3; diff --git a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad index 045aa5d5381..e2484a71e7d 100644 --- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad @@ -35,15 +35,15 @@ source %{ #include "gc/z/zBarrierSetAssembler.hpp" static void z_color(MacroAssembler* masm, const MachNode* node, Register ref) { - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shlq(ref, barrier_Relocation::unpatched); + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); __ orq_imm32(ref, barrier_Relocation::unpatched); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodAfterOr); } static void z_uncolor(MacroAssembler* masm, const MachNode* node, Register ref) { - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shrq(ref, barrier_Relocation::unpatched); + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); } static void z_keep_alive_load_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register ref) { diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index 9e6a4789dc2..7e239a68983 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -221,7 +221,7 @@ bool CodeInstaller::pd_relocate(address pc, jint mark) { return true; #if INCLUDE_ZGC case Z_BARRIER_RELOCATION_FORMAT_LOAD_GOOD_BEFORE_SHL: - _instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); + _instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); return true; case Z_BARRIER_RELOCATION_FORMAT_LOAD_BAD_AFTER_TEST: _instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatLoadBadAfterTest); From a8c6ff161c2c4f1dcf0f8588c9d007994c84e703 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Wed, 23 Apr 2025 02:10:25 +0000 Subject: [PATCH 311/843] 8355239: RISC-V: Do not support subword scatter store Reviewed-by: mli, fjiang --- src/hotspot/cpu/riscv/riscv_v.ad | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 7c1ca4f8960..6fea439954c 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -89,6 +89,8 @@ source %{ return UseZvbb; case Op_LoadVectorGather: case Op_LoadVectorGatherMasked: + case Op_StoreVectorScatter: + case Op_StoreVectorScatterMasked: if (is_subword_type(bt)) { return false; } From bc518a6cbb9fadc47b00239b4d721c1c62dc5dad Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 23 Apr 2025 02:32:36 +0000 Subject: [PATCH 312/843] 8355240: Remove unused Import in StringUTF16 Reviewed-by: rgiulietti --- src/java.base/share/classes/java/lang/StringUTF16.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StringUTF16.java b/src/java.base/share/classes/java/lang/StringUTF16.java index 99226ac1012..a07c022040f 100644 --- a/src/java.base/share/classes/java/lang/StringUTF16.java +++ b/src/java.base/share/classes/java/lang/StringUTF16.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; import static java.lang.String.UTF16; -import static java.lang.String.LATIN1; final class StringUTF16 { From 8c89fb95351ea0bc5ffdd920c18f9e820231f233 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 23 Apr 2025 03:40:26 +0000 Subject: [PATCH 313/843] 8355179: Reinstate javax/swing/JScrollBar/4865918/bug4865918.java headful and macos run Reviewed-by: abhiscxk, serb --- .../swing/JScrollBar/4865918/bug4865918.java | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/test/jdk/javax/swing/JScrollBar/4865918/bug4865918.java b/test/jdk/javax/swing/JScrollBar/4865918/bug4865918.java index 96b1034c943..d68f1bff597 100644 --- a/test/jdk/javax/swing/JScrollBar/4865918/bug4865918.java +++ b/test/jdk/javax/swing/JScrollBar/4865918/bug4865918.java @@ -24,14 +24,16 @@ /* * @test * @bug 4865918 - * @requires (os.family != "mac") + * @key headful * @summary REGRESSION:JCK1.4a-runtime api/javax_swing/interactive/JScrollBarTests.html#JScrollBar * @run main bug4865918 */ import java.awt.Dimension; +import java.awt.Robot; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import javax.swing.JFrame; import javax.swing.JScrollBar; import javax.swing.SwingUtilities; import java.util.concurrent.CountDownLatch; @@ -41,24 +43,33 @@ import java.util.Date; public class bug4865918 { + private static JFrame frame; private static TestScrollBar sbar; private static final CountDownLatch mousePressLatch = new CountDownLatch(1); public static void main(String[] argv) throws Exception { - String osName = System.getProperty("os.name"); - if (osName.toLowerCase().contains("os x")) { - System.out.println("This test is not for MacOS, considered passed."); - return; - } - SwingUtilities.invokeAndWait(() -> setupTest()); + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> createAndShowGUI()); - SwingUtilities.invokeAndWait(() -> sbar.pressMouse()); - if (!mousePressLatch.await(2, TimeUnit.SECONDS)) { - throw new RuntimeException("Timed out waiting for mouse press"); - } + robot.waitForIdle(); + robot.delay(1000); - if (getValue() != 9) { - throw new RuntimeException("The scrollbar block increment is incorrect"); + SwingUtilities.invokeAndWait(() -> sbar.pressMouse()); + if (!mousePressLatch.await(2, TimeUnit.SECONDS)) { + throw new RuntimeException("Timed out waiting for mouse press"); + } + + if (getValue() != 9) { + throw new RuntimeException("The scrollbar block increment " + + getValue() + " is incorrect"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); } } @@ -73,8 +84,8 @@ public class bug4865918 { return result[0]; } - private static void setupTest() { - + private static void createAndShowGUI() { + frame = new JFrame("bug4865918"); sbar = new TestScrollBar(JScrollBar.HORIZONTAL, -1, 10, -100, 100); sbar.setPreferredSize(new Dimension(200, 20)); sbar.setBlockIncrement(10); @@ -83,7 +94,11 @@ public class bug4865918 { mousePressLatch.countDown(); } }); - + frame.getContentPane().add(sbar); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); } static class TestScrollBar extends JScrollBar { From 9a2b425b13cc468d8627c1548d1d39015ce17af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Wed, 23 Apr 2025 05:17:41 +0000 Subject: [PATCH 314/843] 8354920: SA core file support on Linux only prints error messages when debug logging is enabled Reviewed-by: cjplummer, kevinw --- .../linux/native/libsaproc/libproc_impl.c | 4 +- .../linux/native/libsaproc/ps_core.c | 89 ++++++++++++------- .../linux/native/libsaproc/ps_proc.c | 34 +++++-- .../macosx/native/libsaproc/libproc_impl.c | 4 +- .../macosx/native/libsaproc/ps_core.c | 43 +++++---- .../share/native/libsaproc/ps_core_common.c | 2 + 6 files changed, 114 insertions(+), 62 deletions(-) diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c index 977347048a3..74563aa0d6c 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -349,7 +349,7 @@ const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* p thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id) { thread_info* newthr; if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) { - print_debug("can't allocate memory for thread_info\n"); + print_error("can't allocate memory for thread_info\n"); return NULL; } diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c index b1b69c81e2e..808ef42e069 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include #include #include +#include #include "libproc_impl.h" #include "ps_core_common.h" #include "proc_service.h" @@ -67,7 +68,7 @@ static bool sort_map_array(struct ps_prochandle* ph) { // allocate map_array map_info** array; if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) { - print_debug("can't allocate memory for map array\n"); + print_error("can't allocate memory for map array\n"); return false; } @@ -189,8 +190,10 @@ static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size prstatus_t* prstat = (prstatus_t*) buf; thread_info* newthr; print_debug("got integer regset for lwp %d\n", prstat->pr_pid); - if((newthr = add_thread_info(ph, prstat->pr_pid)) == NULL) + if((newthr = add_thread_info(ph, prstat->pr_pid)) == NULL) { + print_error("failed to add thread info\n"); return false; + } // copy regs memcpy(&newthr->regs, prstat->pr_reg, sizeof(struct user_regs_struct)); @@ -256,20 +259,20 @@ static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) { // we are interested in just prstatus entries. we will ignore the rest. // Advance the seek pointer to the start of the PT_NOTE data if (lseek(ph->core->core_fd, note_phdr->p_offset, SEEK_SET) == (off_t)-1) { - print_debug("failed to lseek to PT_NOTE data\n"); + print_error("failed to lseek to PT_NOTE data\n"); return false; } // Now process the PT_NOTE structures. Each one is preceded by // an Elf{32/64}_Nhdr structure describing its type and size. if ( (buf = (char*) malloc(size)) == NULL) { - print_debug("can't allocate memory for reading core notes\n"); + print_error("can't allocate memory for reading core notes\n"); goto err; } // read notes into buffer if (read(ph->core->core_fd, buf, size) != size) { - print_debug("failed to read notes, core file must have been truncated\n"); + print_error("failed to read notes, core file must have been truncated\n"); goto err; } @@ -282,6 +285,7 @@ static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) { if (notep->n_type == NT_PRSTATUS) { if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) { + print_error("failed to handle NT_PRSTATUS note\n"); return false; } } else if (notep->n_type == NT_AUXV) { @@ -314,8 +318,10 @@ static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) { ELF_PHDR* phbuf = NULL; ELF_PHDR* core_php = NULL; - if ((phbuf = read_program_header_table(ph->core->core_fd, core_ehdr)) == NULL) + if ((phbuf = read_program_header_table(ph->core->core_fd, core_ehdr)) == NULL) { + print_error("failed to read program header table\n"); return false; + } /* * Now iterate through the program headers in the core file. @@ -344,6 +350,7 @@ static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) { switch (core_php->p_type) { case PT_NOTE: if (core_handle_note(ph, core_php) != true) { + print_error("failed to read note segment\n"); goto err; } break; @@ -351,7 +358,10 @@ static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) { case PT_LOAD: { if (core_php->p_filesz != 0) { if (add_map_info(ph, ph->core->core_fd, core_php->p_offset, - core_php->p_vaddr, core_php->p_filesz, core_php->p_flags) == NULL) goto err; + core_php->p_vaddr, core_php->p_filesz, core_php->p_flags) == NULL) { + print_error("failed to add map info\n"); + goto err; + } } break; } @@ -376,6 +386,7 @@ static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* li int page_size = sysconf(_SC_PAGE_SIZE); if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) { + print_error("failed to read program header table\n"); return false; } @@ -391,6 +402,7 @@ static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* li if (existing_map == NULL){ if (add_map_info(ph, lib_fd, lib_php->p_offset, target_vaddr, lib_php->p_memsz, lib_php->p_flags) == NULL) { + print_error("failed to add map info\n"); goto err; } } else if (lib_php->p_flags != existing_map->flags) { @@ -412,7 +424,7 @@ static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* li (existing_map->fd != lib_fd) && (ROUNDUP(existing_map->memsz, page_size) != ROUNDUP(lib_php->p_memsz, page_size))) { - print_debug("address conflict @ 0x%lx (existing map size = %ld, size = %ld, flags = %d)\n", + print_error("address conflict @ 0x%lx (existing map size = %ld, size = %ld, flags = %d)\n", target_vaddr, existing_map->memsz, lib_php->p_memsz, lib_php->p_flags); goto err; } @@ -442,12 +454,12 @@ static bool read_interp_segments(struct ps_prochandle* ph) { ELF_EHDR interp_ehdr; if (read_elf_header(ph->core->interp_fd, &interp_ehdr) != true) { - print_debug("interpreter is not a valid ELF file\n"); + print_error("interpreter is not a valid ELF file\n"); return false; } if (read_lib_segments(ph, ph->core->interp_fd, &interp_ehdr, ph->core->ld_base_addr) != true) { - print_debug("can't read segments of interpreter\n"); + print_error("can't read segments of interpreter\n"); return false; } @@ -463,6 +475,7 @@ static uintptr_t read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehd uintptr_t result = 0L; if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) { + print_error("failed to read program header table\n"); return 0L; } @@ -473,7 +486,10 @@ static uintptr_t read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehd case PT_LOAD: { // add only non-writable segments of non-zero filesz if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) { - if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz, exec_php->p_flags) == NULL) goto err; + if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz, exec_php->p_flags) == NULL) { + print_error("failed to add map info\n"); + goto err; + } } break; } @@ -484,18 +500,19 @@ static uintptr_t read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehd // BUF_SIZE is PATH_MAX + NAME_MAX + 1. if (exec_php->p_filesz > BUF_SIZE) { + print_error("Invalid ELF interpreter info\n"); goto err; } if (pread(ph->core->exec_fd, interp_name, exec_php->p_filesz, exec_php->p_offset) != exec_php->p_filesz) { - print_debug("Unable to read in the ELF interpreter\n"); + print_error("Unable to read in the ELF interpreter\n"); goto err; } interp_name[exec_php->p_filesz] = '\0'; print_debug("ELF interpreter %s\n", interp_name); // read interpreter segments as well if ((ph->core->interp_fd = pathmap_open(interp_name)) < 0) { - print_debug("can't open runtime loader\n"); + print_error("can't open runtime loader\n"); goto err; } break; @@ -555,7 +572,7 @@ static uintptr_t calc_prelinked_load_address(struct ps_prochandle* ph, int lib_f phbuf = read_program_header_table(lib_fd, elf_ehdr); if (phbuf == NULL) { - print_debug("can't read program header of shared object\n"); + print_error("can't read program header of shared object\n"); return INVALID_LOAD_ADDRESS; } @@ -571,7 +588,7 @@ static uintptr_t calc_prelinked_load_address(struct ps_prochandle* ph, int lib_f if (ps_pdread(ph, (psaddr_t)link_map_addr + LINK_MAP_LD_OFFSET, &lib_ld, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read address of dynamic section in shared object\n"); + print_error("can't read address of dynamic section in shared object\n"); return INVALID_LOAD_ADDRESS; } @@ -607,7 +624,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { dyn.d_tag = DT_NULL; while (dyn.d_tag != DT_DEBUG) { if (ps_pdread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) { - print_debug("can't read debug info from _DYNAMIC\n"); + print_error("can't read debug info from _DYNAMIC\n"); return false; } addr += sizeof(ELF_DYN); @@ -618,14 +635,14 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { // at debug_base we have struct r_debug. This has first link map in r_map field if (ps_pdread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET, &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read first link map address\n"); + print_error("can't read first link map address\n"); return false; } // read ld_base address from struct r_debug if (ps_pdread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read ld base address\n"); + print_error("can't read ld base address\n"); return false; } ph->core->ld_base_addr = ld_base_addr; @@ -634,11 +651,13 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { // now read segments from interp (i.e ld.so or ld-linux.so or ld-elf.so) if (read_interp_segments(ph) != true) { + print_error("failed to read interp segments\n"); return false; } // after adding interpreter (ld.so) mappings sort again if (sort_map_array(ph) != true) { + print_error("failed to sort segment map array\n"); return false; } @@ -654,14 +673,14 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { if (ps_pdread(ph, (psaddr_t) link_map_addr + LINK_MAP_ADDR_OFFSET, &lib_base_diff, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read shared object base address diff\n"); + print_error("can't read shared object base address diff\n"); return false; } // read address of the name if (ps_pdread(ph, (psaddr_t) link_map_addr + LINK_MAP_NAME_OFFSET, &lib_name_addr, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read address of shared object name\n"); + print_error("can't read address of shared object name\n"); return false; } @@ -687,6 +706,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { lib_base_diff = calc_prelinked_load_address(ph, lib_fd, &elf_ehdr, link_map_addr); if (lib_base_diff == INVALID_LOAD_ADDRESS) { close(lib_fd); + print_error("failed to calculate load address\n"); return false; } } @@ -696,15 +716,17 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { lib_name, lib_base, lib_base_diff); // while adding library mappings we need to use "base difference". if (! read_lib_segments(ph, lib_fd, &elf_ehdr, lib_base_diff)) { - print_debug("can't read shared object's segments\n"); + print_error("can't read shared object's segments\n"); close(lib_fd); return false; } add_lib_info_fd(ph, lib_name, lib_fd, lib_base); // Map info is added for the library (lib_name) so // we need to re-sort it before calling the p_pdread. - if (sort_map_array(ph) != true) + if (sort_map_array(ph) != true) { + print_error("failed to sort segment map array\n"); return false; + } } else { print_debug("can't read ELF header for shared object %s\n", lib_name); close(lib_fd); @@ -716,7 +738,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { // read next link_map address if (ps_pdread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET, &link_map_addr, sizeof(uintptr_t)) != PS_OK) { - print_debug("can't read next link in link_map\n"); + print_error("can't read next link in link_map\n"); return false; } } @@ -732,13 +754,13 @@ Pgrab_core(const char* exec_file, const char* core_file) { struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); if (ph == NULL) { - print_debug("can't allocate ps_prochandle\n"); + print_error("can't allocate ps_prochandle\n"); return NULL; } if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { free(ph); - print_debug("can't allocate ps_prochandle\n"); + print_error("can't allocate ps_prochandle\n"); return NULL; } @@ -750,39 +772,42 @@ Pgrab_core(const char* exec_file, const char* core_file) { // open the core file if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) { - print_debug("can't open core file\n"); + print_error("can't open core file: %s\n", strerror(errno)); goto err; } // read core file ELF header if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) { - print_debug("core file is not a valid ELF ET_CORE file\n"); + print_error("core file is not a valid ELF ET_CORE file\n"); goto err; } if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) { - print_debug("can't open executable file\n"); + print_error("can't open executable file: %s\n", strerror(errno)); goto err; } if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || ((exec_ehdr.e_type != ET_EXEC) && (exec_ehdr.e_type != ET_DYN))) { - print_debug("executable file is not a valid ELF file\n"); + print_error("executable file is not a valid ELF file\n"); goto err; } // process core file segments if (read_core_segments(ph, &core_ehdr) != true) { + print_error("failed to read core segments\n"); goto err; } // process exec file segments uintptr_t exec_base_addr = read_exec_segments(ph, &exec_ehdr); if (exec_base_addr == 0L) { + print_error("failed to read exec segments\n"); goto err; } print_debug("exec_base_addr = 0x%lx\n", exec_base_addr); if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, exec_base_addr) == NULL) { + print_error("failed to add lib info\n"); goto err; } @@ -790,19 +815,23 @@ Pgrab_core(const char* exec_file, const char* core_file) { // here because read_shared_lib_info needs to read from debuggee // address space if (sort_map_array(ph) != true) { + print_error("failed to sort segment map array\n"); goto err; } if (read_shared_lib_info(ph) != true) { + print_error("failed to read libraries\n"); goto err; } // sort again because we have added more mappings from shared objects if (sort_map_array(ph) != true) { + print_error("failed to sort segment map array\n"); goto err; } if (init_classsharing_workaround(ph) != true) { + print_error("failed to workaround class sharing\n"); goto err; } diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c index de81e962d8a..fdaa30c3f5d 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -349,7 +349,7 @@ static bool read_lib_info(struct ps_prochandle* ph) { snprintf(fname, sizeof(fname), "/proc/%d/maps", ph->pid); fp = fopen(fname, "r"); if (fp == NULL) { - print_debug("can't open /proc/%d/maps file\n", ph->pid); + print_error("can't open /proc/%d/maps file\n", ph->pid); return false; } @@ -447,13 +447,14 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) { if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) { snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle"); - print_debug("%s\n", err_buf); + print_error("%s\n", err_buf); return NULL; } if ((attach_status = ptrace_attach(pid, err_buf, err_buf_len)) != ATTACH_SUCCESS) { if (attach_status == ATTACH_THREAD_DEAD) { - print_error("The process with pid %d does not exist.\n", pid); + snprintf(err_buf, err_buf_len, "The process with pid %d does not exist.", pid); + print_error("%s\n", err_buf); } free(ph); return NULL; @@ -461,7 +462,12 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) { // initialize ps_prochandle ph->pid = pid; - add_thread_info(ph, ph->pid); + if (add_thread_info(ph, ph->pid) == NULL) { + snprintf(err_buf, err_buf_len, "failed to add thread info"); + print_error("%s\n", err_buf); + free(ph); + return NULL; + } // initialize vtable ph->ops = &process_ops; @@ -469,7 +475,10 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) { // read library info and symbol tables, must do this before attaching threads, // as the symbols in the pthread library will be used to figure out // the list of threads within the same process. - read_lib_info(ph); + if (read_lib_info(ph) == false) { + snprintf(err_buf, err_buf_len, "failed to read lib info"); + goto err; + } /* * Read thread info. @@ -491,7 +500,10 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) { continue; } if (!process_doesnt_exist(lwp_id)) { - add_thread_info(ph, lwp_id); + if (add_thread_info(ph, lwp_id) == NULL) { + snprintf(err_buf, err_buf_len, "failed to add thread info"); + goto err; + } } } closedir(dirp); @@ -510,11 +522,15 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) { delete_thread_info(ph, current_thr); } else { - Prelease(ph); - return NULL; + snprintf(err_buf, err_buf_len, "Failed to attach to the thread with lwp_id %d.", current_thr->lwp_id); + goto err; } // ATTACH_THREAD_DEAD } // !ATTACH_SUCCESS } } return ph; +err: + print_error("%s\n", err_buf); + Prelease(ph); + return NULL; } diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c b/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c index ff48c402f8d..8bcd09d40ce 100644 --- a/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c +++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -323,7 +323,7 @@ const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* p sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { sa_thread_info* newthr; if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) { - print_debug("can't allocate memory for thread_info\n"); + print_error("can't allocate memory for thread_info\n"); return NULL; } diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c index e07b3a8fd97..149997dc4bb 100644 --- a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c +++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -74,7 +74,7 @@ static bool sort_map_array(struct ps_prochandle* ph) { // allocate map_array map_info** array; if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) { - print_debug("can't allocate memory for map array\n"); + print_error("can't allocate memory for map array\n"); return false; } @@ -280,6 +280,7 @@ static bool read_core_segments(struct ps_prochandle* ph) { lseek(fd, offset, SEEK_SET); if(read(fd, (void *)&fhead, sizeof(mach_header_64)) != sizeof(mach_header_64)) { + print_error("Failed to read program header table\n"); goto err; } print_debug("total commands: %d\n", fhead.ncmds); @@ -287,6 +288,7 @@ static bool read_core_segments(struct ps_prochandle* ph) { for (i = 0; i < fhead.ncmds; i++) { lseek(fd, offset, SEEK_SET); if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) { + print_error("Failed to read command\n"); goto err; } offset += lcmd.cmdsize; // next command position @@ -294,14 +296,14 @@ static bool read_core_segments(struct ps_prochandle* ph) { if (lcmd.cmd == LC_SEGMENT_64) { lseek(fd, -sizeof(load_command), SEEK_CUR); if (read(fd, (void *)&segcmd, sizeof(segment_command_64)) != sizeof(segment_command_64)) { - print_debug("failed to read LC_SEGMENT_64 i = %d!\n", i); + print_error("failed to read LC_SEGMENT_64 i = %d!\n", i); goto err; } // The base of the library is offset by a random amount which ends up as a load command with a // filesize of 0. This must be ignored otherwise the base address of the library is wrong. if (segcmd.filesize != 0) { if (add_map_info(ph, fd, segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize, segcmd.flags) == NULL) { - print_debug("Failed to add map_info at i = %d\n", i); + print_error("Failed to add map_info at i = %d\n", i); goto err; } } @@ -318,7 +320,7 @@ static bool read_core_segments(struct ps_prochandle* ph) { uint32_t size = sizeof(load_command); while (size < lcmd.cmdsize) { if (read(fd, (void *)&fc, sizeof(thread_fc)) != sizeof(thread_fc)) { - printf("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(thread_fc); @@ -326,14 +328,14 @@ static bool read_core_segments(struct ps_prochandle* ph) { if (fc.flavor == x86_THREAD_STATE) { x86_thread_state_t thrstate; if (read(fd, (void *)&thrstate, sizeof(x86_thread_state_t)) != sizeof(x86_thread_state_t)) { - printf("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(x86_thread_state_t); // create thread info list, update lwp_id later sa_thread_info* newthr = add_thread_info(ph, (pthread_t) -1, (lwpid_t) num_threads++); if (newthr == NULL) { - printf("create thread_info failed\n"); + print_error("create thread_info failed\n"); goto err; } @@ -370,14 +372,14 @@ static bool read_core_segments(struct ps_prochandle* ph) { } else if (fc.flavor == x86_FLOAT_STATE) { x86_float_state_t flstate; if (read(fd, (void *)&flstate, sizeof(x86_float_state_t)) != sizeof(x86_float_state_t)) { - print_debug("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(x86_float_state_t); } else if (fc.flavor == x86_EXCEPTION_STATE) { x86_exception_state_t excpstate; if (read(fd, (void *)&excpstate, sizeof(x86_exception_state_t)) != sizeof(x86_exception_state_t)) { - printf("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(x86_exception_state_t); @@ -387,14 +389,14 @@ static bool read_core_segments(struct ps_prochandle* ph) { if (fc.flavor == ARM_THREAD_STATE64) { arm_thread_state64_t thrstate; if (read(fd, (void *)&thrstate, sizeof(arm_thread_state64_t)) != sizeof(arm_thread_state64_t)) { - printf("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(arm_thread_state64_t); // create thread info list, update lwp_id later sa_thread_info* newthr = add_thread_info(ph, (pthread_t) -1, (lwpid_t) num_threads++); if (newthr == NULL) { - printf("create thread_info failed\n"); + print_error("create thread_info failed\n"); goto err; } @@ -443,21 +445,21 @@ static bool read_core_segments(struct ps_prochandle* ph) { } else if (fc.flavor == ARM_NEON_STATE64) { arm_neon_state64_t flstate; if (read(fd, (void *)&flstate, sizeof(arm_neon_state64_t)) != sizeof(arm_neon_state64_t)) { - printf("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(arm_neon_state64_t); } else if (fc.flavor == ARM_EXCEPTION_STATE64) { arm_exception_state64_t excpstate; if (read(fd, (void *)&excpstate, sizeof(arm_exception_state64_t)) != sizeof(arm_exception_state64_t)) { - printf("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(arm_exception_state64_t); } else if (fc.flavor == ARM_DEBUG_STATE64) { arm_debug_state64_t dbgstate; if (read(fd, (void *)&dbgstate, sizeof(arm_debug_state64_t)) != sizeof(arm_debug_state64_t)) { - printf("Reading flavor, count failed.\n"); + print_error("Reading flavor, count failed.\n"); goto err; } size += sizeof(arm_debug_state64_t); @@ -631,6 +633,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { lseek(fd, -sizeof(uint32_t), SEEK_CUR); // This is the beginning of the mach-o file in the segment. if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) { + print_error("Failed to file header\n"); goto err; } fpos = ltell(fd); @@ -641,6 +644,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { // LC_ID_DYLIB is the file itself for a .dylib lseek(fd, fpos, SEEK_SET); if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) { + print_error("Failed to read command\n"); return false; // error } fpos += lcmd.cmdsize; // next command position @@ -652,6 +656,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) { if (lcmd.cmd == LC_ID_DYLIB) { lseek(fd, -sizeof(load_command), SEEK_CUR); if (read(fd, (void *)&dylibcmd, sizeof(dylib_command)) != sizeof(dylib_command)) { + print_error("Failed to read command\n"); return false; } /**** name stored at dylib_command.dylib.name.offset, is a C string */ @@ -710,13 +715,13 @@ struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) { struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); if (ph == NULL) { - print_debug("can't allocate ps_prochandle\n"); + print_error("can't allocate ps_prochandle\n"); return NULL; } if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { free(ph); - print_debug("can't allocate ps_prochandle\n"); + print_error("can't allocate ps_prochandle\n"); return NULL; } @@ -738,12 +743,12 @@ struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) { // read core file header if (read_macho64_header(ph->core->core_fd, &core_header) != true || core_header.filetype != MH_CORE) { - print_debug("core file is not a valid Mach-O file\n"); + print_error("core file is not a valid Mach-O file\n"); goto err; } if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) { - print_error("can't open executable file\n"); + print_error("can't open executable file: %s\n", strerror(errno)); goto err; } @@ -779,7 +784,7 @@ struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) { } if (init_classsharing_workaround(ph) != true) { - print_error("failed to workaround classshareing\n"); + print_error("failed to workaround class sharing\n"); goto err; } diff --git a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c index 3c244aab0f3..40757a346fe 100644 --- a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c +++ b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c @@ -141,6 +141,7 @@ map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset, uintptr_t vaddr, size_t memsz, uint32_t flags) { map_info* map; if ((map = allocate_init_map(fd, offset, vaddr, memsz, flags)) == NULL) { + print_error("failed to allocate map\n"); return NULL; } @@ -158,6 +159,7 @@ static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset map_info* map; if ((map = allocate_init_map(ph->core->classes_jsa_fd, offset, vaddr, memsz, MAP_R_FLAG)) == NULL) { + print_debug("failed to allocate class share map\n"); return NULL; } From 27faf45422082009f23463984b8a6e43c15e9e71 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Wed, 23 Apr 2025 06:22:30 +0000 Subject: [PATCH 315/843] 8354826: Make ResolverConfigurationImpl.lock field final Reviewed-by: dfuchs, jpai --- .../unix/classes/sun/net/dns/ResolverConfigurationImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java index a466331de93..2f633ad711d 100644 --- a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java +++ b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ public final class ResolverConfigurationImpl extends ResolverConfiguration { // Lock helds whilst loading configuration or checking - private static Object lock = new Object(); + private static final Object lock = new Object(); // Time of last refresh. private static long lastRefresh = -1; From 263983d0fb9ca567b03d2be4c82cf9fe3d0e6f61 Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Wed, 23 Apr 2025 08:04:57 +0000 Subject: [PATCH 316/843] 8298733: Reconsider monitors_on_stack assert Reviewed-by: pchilanomate, coleenp --- .../share/runtime/continuationFreezeThaw.cpp | 59 +++++++++++++------ src/hotspot/share/runtime/stackWatermark.hpp | 3 +- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index 12a75c6c62e..d20cfde09ca 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -565,10 +565,50 @@ void FreezeBase::copy_to_chunk(intptr_t* from, intptr_t* to, int size) { #endif } +static void assert_frames_in_continuation_are_safe(JavaThread* thread) { +#ifdef ASSERT + StackWatermark* watermark = StackWatermarkSet::get(thread, StackWatermarkKind::gc); + if (watermark == nullptr) { + return; + } + ContinuationEntry* ce = thread->last_continuation(); + RegisterMap map(thread, + RegisterMap::UpdateMap::include, + RegisterMap::ProcessFrames::skip, + RegisterMap::WalkContinuation::skip); + map.set_include_argument_oops(false); + for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { + watermark->assert_is_frame_safe(f); + } +#endif // ASSERT +} + +#ifdef ASSERT +static bool monitors_on_stack(JavaThread* thread) { + assert_frames_in_continuation_are_safe(thread); + ContinuationEntry* ce = thread->last_continuation(); + RegisterMap map(thread, + RegisterMap::UpdateMap::include, + RegisterMap::ProcessFrames::skip, + RegisterMap::WalkContinuation::skip); + map.set_include_argument_oops(false); + for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { + if ((f.is_interpreted_frame() && ContinuationHelper::InterpretedFrame::is_owning_locks(f)) || + (f.is_compiled_frame() && ContinuationHelper::CompiledFrame::is_owning_locks(map.thread(), &map, f)) || + (f.is_native_frame() && ContinuationHelper::NativeFrame::is_owning_locks(map.thread(), f))) { + return true; + } + } + return false; +} +#endif // ASSERT + // Called _after_ the last possible safepoint during the freeze operation (chunk allocation) void FreezeBase::unwind_frames() { ContinuationEntry* entry = _cont.entry(); entry->flush_stack_processing(_thread); + assert_frames_in_continuation_are_safe(_thread); + assert(LockingMode != LM_LEGACY || !monitors_on_stack(_thread), "unexpected monitors on stack"); set_anchor_to_entry(_thread, entry); } @@ -1621,23 +1661,6 @@ static void jvmti_mount_end(JavaThread* current, ContinuationWrapper& cont, fram #endif // INCLUDE_JVMTI #ifdef ASSERT -static bool monitors_on_stack(JavaThread* thread) { - ContinuationEntry* ce = thread->last_continuation(); - RegisterMap map(thread, - RegisterMap::UpdateMap::include, - RegisterMap::ProcessFrames::include, - RegisterMap::WalkContinuation::skip); - map.set_include_argument_oops(false); - for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { - if ((f.is_interpreted_frame() && ContinuationHelper::InterpretedFrame::is_owning_locks(f)) || - (f.is_compiled_frame() && ContinuationHelper::CompiledFrame::is_owning_locks(map.thread(), &map, f)) || - (f.is_native_frame() && ContinuationHelper::NativeFrame::is_owning_locks(map.thread(), f))) { - return true; - } - } - return false; -} - // There are no interpreted frames if we're not called from the interpreter and we haven't ancountered an i2c // adapter or called Deoptimization::unpack_frames. As for native frames, upcalls from JNI also go through the // interpreter (see JavaCalls::call_helper), while the UpcallLinker explicitly sets cont_fastpath. @@ -1714,8 +1737,6 @@ static inline freeze_result freeze_internal(JavaThread* current, intptr_t* const assert(entry->is_virtual_thread() == (entry->scope(current) == java_lang_VirtualThread::vthread_scope()), ""); - assert(LockingMode != LM_LEGACY || (monitors_on_stack(current) == ((current->held_monitor_count() - current->jni_monitor_count()) > 0)), - "Held monitor count and locks on stack invariant: " INT64_FORMAT " JNI: " INT64_FORMAT, (int64_t)current->held_monitor_count(), (int64_t)current->jni_monitor_count()); assert(LockingMode == LM_LEGACY || (current->held_monitor_count() == 0 && current->jni_monitor_count() == 0), "Held monitor count should only be used for LM_LEGACY: " INT64_FORMAT " JNI: " INT64_FORMAT, (int64_t)current->held_monitor_count(), (int64_t)current->jni_monitor_count()); diff --git a/src/hotspot/share/runtime/stackWatermark.hpp b/src/hotspot/share/runtime/stackWatermark.hpp index 8d51f694a1d..4f1c65c903c 100644 --- a/src/hotspot/share/runtime/stackWatermark.hpp +++ b/src/hotspot/share/runtime/stackWatermark.hpp @@ -102,7 +102,6 @@ protected: void yield_processing(); static bool has_barrier(const frame& f); void ensure_safe(const frame& f); - void assert_is_frame_safe(const frame& f) NOT_DEBUG_RETURN; bool is_frame_safe(const frame& f); // API for consumers of the stack watermark barrier. @@ -151,6 +150,8 @@ public: void on_safepoint(); void start_processing(); void finish_processing(void* context); + + void assert_is_frame_safe(const frame& f) NOT_DEBUG_RETURN; }; #endif // SHARE_RUNTIME_STACKWATERMARK_HPP From c2e90bcc8026fb2047b42deae6cdad738d6d01b8 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Wed, 23 Apr 2025 08:21:07 +0000 Subject: [PATCH 317/843] 8355363: [BACKOUT] 8354668: Missing REX2 prefix accounting in ZGC barriers leads to incorrect encoding Reviewed-by: chagedorn --- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp | 14 +++++++------- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp | 2 +- src/hotspot/cpu/x86/gc/z/z_x86_64.ad | 4 ++-- src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index 0891d303563..9cdf0b229c0 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -391,8 +391,8 @@ void ZBarrierSetAssembler::store_barrier_fast(MacroAssembler* masm, if (rnew_zaddress != noreg) { // noreg means null; no need to color __ movptr(rnew_zpointer, rnew_zaddress); + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shlq(rnew_zpointer, barrier_Relocation::unpatched); - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); __ orq_imm32(rnew_zpointer, barrier_Relocation::unpatched); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodAfterOr); } @@ -969,13 +969,13 @@ void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, #define __ ce->masm()-> static void z_uncolor(LIR_Assembler* ce, LIR_Opr ref) { + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shrq(ref->as_register(), barrier_Relocation::unpatched); - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); } static void z_color(LIR_Assembler* ce, LIR_Opr ref) { + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shlq(ref->as_register(), barrier_Relocation::unpatched); - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); __ orq_imm32(ref->as_register(), barrier_Relocation::unpatched); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodAfterOr); } @@ -1278,8 +1278,8 @@ void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, static int patch_barrier_relocation_offset(int format) { switch (format) { - case ZBarrierRelocationFormatLoadGoodAfterShX: - return -1; + case ZBarrierRelocationFormatLoadGoodBeforeShl: + return 3; case ZBarrierRelocationFormatStoreGoodAfterCmp: return -2; @@ -1300,7 +1300,7 @@ static int patch_barrier_relocation_offset(int format) { static uint16_t patch_barrier_relocation_value(int format) { switch (format) { - case ZBarrierRelocationFormatLoadGoodAfterShX: + case ZBarrierRelocationFormatLoadGoodBeforeShl: return (uint16_t)ZPointerLoadShift; case ZBarrierRelocationFormatMarkBadAfterTest: @@ -1327,7 +1327,7 @@ void ZBarrierSetAssembler::patch_barrier_relocation(address addr, int format) { const int offset = patch_barrier_relocation_offset(format); const uint16_t value = patch_barrier_relocation_value(format); uint8_t* const patch_addr = (uint8_t*)addr + offset; - if (format == ZBarrierRelocationFormatLoadGoodAfterShX) { + if (format == ZBarrierRelocationFormatLoadGoodBeforeShl) { *patch_addr = (uint8_t)value; } else { *(uint16_t*)patch_addr = value; diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp index 6976452bd63..8bb653ec5fb 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp @@ -49,7 +49,7 @@ class ZLoadBarrierStubC2; class ZStoreBarrierStubC2; #endif // COMPILER2 -const int ZBarrierRelocationFormatLoadGoodAfterShX = 0; +const int ZBarrierRelocationFormatLoadGoodBeforeShl = 0; const int ZBarrierRelocationFormatLoadBadAfterTest = 1; const int ZBarrierRelocationFormatMarkBadAfterTest = 2; const int ZBarrierRelocationFormatStoreGoodAfterCmp = 3; diff --git a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad index e2484a71e7d..045aa5d5381 100644 --- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad @@ -35,15 +35,15 @@ source %{ #include "gc/z/zBarrierSetAssembler.hpp" static void z_color(MacroAssembler* masm, const MachNode* node, Register ref) { + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shlq(ref, barrier_Relocation::unpatched); - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); __ orq_imm32(ref, barrier_Relocation::unpatched); __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodAfterOr); } static void z_uncolor(MacroAssembler* masm, const MachNode* node, Register ref) { + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); __ shrq(ref, barrier_Relocation::unpatched); - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); } static void z_keep_alive_load_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register ref) { diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index 7e239a68983..9e6a4789dc2 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -221,7 +221,7 @@ bool CodeInstaller::pd_relocate(address pc, jint mark) { return true; #if INCLUDE_ZGC case Z_BARRIER_RELOCATION_FORMAT_LOAD_GOOD_BEFORE_SHL: - _instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodAfterShX); + _instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl); return true; case Z_BARRIER_RELOCATION_FORMAT_LOAD_BAD_AFTER_TEST: _instructions->relocate(pc, barrier_Relocation::spec(), ZBarrierRelocationFormatLoadBadAfterTest); From e76f20301c3dcd65610e982fc98b7a08ebf0c8f1 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Wed, 23 Apr 2025 10:13:26 +0000 Subject: [PATCH 318/843] 8354309: Sort GC includes Reviewed-by: eosterlund, iwalulya, kbarrett --- .../c1/shenandoahBarrierSetC1_aarch64.cpp | 2 +- .../shenandoahBarrierSetAssembler_aarch64.cpp | 6 ++--- .../cpu/aarch64/gc/z/zAddress_aarch64.cpp | 2 +- .../arm/gc/g1/g1BarrierSetAssembler_arm.cpp | 1 - .../arm/gc/shared/barrierSetNMethod_arm.cpp | 2 +- .../ppc/gc/shared/barrierSetNMethod_ppc.cpp | 2 +- .../c1/shenandoahBarrierSetC1_ppc.cpp | 2 +- .../shenandoahBarrierSetAssembler_ppc.cpp | 6 ++--- src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp | 2 +- .../gc/shared/barrierSetNMethod_riscv.cpp | 2 +- .../c1/shenandoahBarrierSetC1_riscv.cpp | 2 +- .../shenandoahBarrierSetAssembler_riscv.cpp | 6 ++--- src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp | 2 +- .../s390/gc/g1/g1BarrierSetAssembler_s390.cpp | 4 +-- .../c1/shenandoahBarrierSetC1_x86.cpp | 2 +- .../shenandoahBarrierSetAssembler_x86.cpp | 4 +-- .../os/windows/gc/z/zSyscall_windows.hpp | 1 - .../gc/epsilon/epsilonMonitoringSupport.cpp | 2 +- src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp | 2 +- src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp | 2 +- src/hotspot/share/gc/g1/g1AllocRegion.cpp | 2 +- src/hotspot/share/gc/g1/g1Allocator.cpp | 2 +- .../gc/g1/g1AnalyticsSequences.inline.hpp | 1 + src/hotspot/share/gc/g1/g1BarrierSet.hpp | 2 +- .../share/gc/g1/g1BlockOffsetTable.inline.hpp | 3 ++- src/hotspot/share/gc/g1/g1CardSet.inline.hpp | 1 + .../gc/g1/g1CardSetContainers.inline.hpp | 1 + .../share/gc/g1/g1CardSetMemory.inline.hpp | 1 + src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 6 ++--- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 2 +- .../share/gc/g1/g1CollectionSet.inline.hpp | 1 + src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 2 +- src/hotspot/share/gc/g1/g1ConcurrentMark.hpp | 2 +- ...ConcurrentMarkObjArrayProcessor.inline.hpp | 2 +- .../gc/g1/g1ConcurrentRebuildAndScrub.cpp | 3 +-- .../share/gc/g1/g1ConcurrentRefine.cpp | 1 + src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp | 2 +- src/hotspot/share/gc/g1/g1EdenRegions.hpp | 2 +- .../gc/g1/g1EvacFailureRegions.inline.hpp | 3 ++- src/hotspot/share/gc/g1/g1EvacStats.cpp | 2 +- src/hotspot/share/gc/g1/g1EvacStats.hpp | 2 +- src/hotspot/share/gc/g1/g1FullCollector.cpp | 2 +- src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 4 +-- .../share/gc/g1/g1HeapRegionManager.cpp | 2 +- src/hotspot/share/gc/g1/g1InitLogger.cpp | 2 +- .../share/gc/g1/g1MonitoringSupport.cpp | 2 +- .../share/gc/g1/g1MonitoringSupport.hpp | 2 +- .../share/gc/g1/g1MonotonicArena.inline.hpp | 1 + .../gc/g1/g1MonotonicArenaFreeMemoryTask.cpp | 2 +- src/hotspot/share/gc/g1/g1NMethodClosure.cpp | 2 +- .../share/gc/g1/g1OopClosures.inline.hpp | 2 +- .../share/gc/g1/g1ParScanThreadState.hpp | 2 +- src/hotspot/share/gc/g1/g1Policy.cpp | 7 +++--- src/hotspot/share/gc/g1/g1Policy.hpp | 2 +- src/hotspot/share/gc/g1/g1RemSet.cpp | 4 +-- src/hotspot/share/gc/g1/g1ServiceThread.cpp | 2 +- src/hotspot/share/gc/g1/g1SurvivorRegions.cpp | 2 +- src/hotspot/share/gc/g1/g1Trace.cpp | 2 +- src/hotspot/share/gc/g1/g1VMOperations.cpp | 2 +- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 6 ++--- .../share/gc/g1/g1YoungGCPreEvacuateTasks.cpp | 2 +- .../share/gc/parallel/parallelInitLogger.cpp | 2 +- .../gc/parallel/psAdaptiveSizePolicy.cpp | 2 +- src/hotspot/share/gc/parallel/psCardTable.cpp | 2 +- .../share/gc/parallel/psCompactionManager.cpp | 2 +- .../share/gc/parallel/psCompactionManager.hpp | 2 +- src/hotspot/share/gc/parallel/psScavenge.cpp | 6 ++--- src/hotspot/share/gc/parallel/psScavenge.hpp | 2 +- .../share/gc/parallel/psVMOperations.cpp | 2 +- .../share/gc/serial/serialArguments.cpp | 4 +-- src/hotspot/share/gc/serial/serialFullGC.cpp | 4 +-- .../gc/serial/tenuredGeneration.inline.hpp | 1 + src/hotspot/share/gc/shared/ageTable.cpp | 2 +- .../gc/shared/barrierSetConfig.inline.hpp | 2 +- .../share/gc/shared/barrierSetNMethod.cpp | 2 +- src/hotspot/share/gc/shared/bufferNode.cpp | 2 +- .../share/gc/shared/c1/barrierSetC1.hpp | 2 +- .../share/gc/shared/c2/barrierSetC2.cpp | 2 +- .../gc/shared/c2/cardTableBarrierSetC2.cpp | 2 +- .../share/gc/shared/c2/modRefBarrierSetC2.cpp | 2 +- src/hotspot/share/gc/shared/cardTable.cpp | 2 +- src/hotspot/share/gc/shared/collectedHeap.cpp | 6 ++--- src/hotspot/share/gc/shared/gcHeapSummary.hpp | 2 +- src/hotspot/share/gc/shared/gcInitLogger.cpp | 2 +- src/hotspot/share/gc/shared/gcLocker.cpp | 4 +-- src/hotspot/share/gc/shared/gcLogPrecious.hpp | 2 +- .../share/gc/shared/gcOverheadChecker.hpp | 4 +-- .../share/gc/shared/gcPolicyCounters.cpp | 2 +- src/hotspot/share/gc/shared/gcTimer.cpp | 2 +- src/hotspot/share/gc/shared/gcTraceTime.cpp | 2 +- .../share/gc/shared/gcVMOperations.cpp | 2 +- .../share/gc/shared/locationPrinter.cpp | 2 +- src/hotspot/share/gc/shared/memAllocator.cpp | 2 +- .../share/gc/shared/parallelCleaning.cpp | 3 +-- .../share/gc/shared/partialArrayState.cpp | 1 + .../shared/partialArrayTaskStepper.inline.hpp | 3 ++- .../shared/referenceProcessorPhaseTimes.cpp | 2 +- src/hotspot/share/gc/shared/satbMarkQueue.cpp | 2 +- .../gc/shared/stringdedup/stringDedup.cpp | 2 +- .../shared/stringdedup/stringDedupTable.cpp | 4 +-- .../shared/stringdedup/stringDedupTable.hpp | 2 +- .../share/gc/shared/taskTerminator.cpp | 2 +- src/hotspot/share/gc/shared/taskqueue.cpp | 2 +- .../shared/threadLocalAllocBuffer.inline.hpp | 2 +- src/hotspot/share/gc/shared/weakProcessor.cpp | 2 +- .../shenandoah/c1/shenandoahBarrierSetC1.cpp | 2 +- .../shenandoah/c2/shenandoahBarrierSetC2.cpp | 6 ++--- .../gc/shenandoah/c2/shenandoahSupport.cpp | 2 +- .../shenandoahAdaptiveHeuristics.cpp | 2 +- .../shenandoahAdaptiveHeuristics.hpp | 2 +- .../shenandoahCompactHeuristics.cpp | 2 +- .../shenandoahGenerationalHeuristics.cpp | 3 +-- .../heuristics/shenandoahGlobalHeuristics.cpp | 3 +-- .../heuristics/shenandoahHeuristics.cpp | 2 +- .../heuristics/shenandoahYoungHeuristics.cpp | 1 - .../mode/shenandoahGenerationalMode.cpp | 2 +- .../shenandoah/mode/shenandoahPassiveMode.cpp | 2 +- .../gc/shenandoah/shenandoahBarrierSet.cpp | 2 +- .../shenandoahBarrierSet.inline.hpp | 2 +- .../shenandoah/shenandoahClosures.inline.hpp | 4 +-- .../gc/shenandoah/shenandoahCodeRoots.hpp | 2 +- .../gc/shenandoah/shenandoahConcurrentGC.cpp | 6 ++--- .../shenandoah/shenandoahConcurrentMark.cpp | 4 +-- .../gc/shenandoah/shenandoahControlThread.cpp | 6 ++--- .../gc/shenandoah/shenandoahControlThread.hpp | 4 +-- .../gc/shenandoah/shenandoahController.cpp | 3 +-- .../gc/shenandoah/shenandoahController.hpp | 2 +- .../gc/shenandoah/shenandoahDegeneratedGC.cpp | 4 +-- .../gc/shenandoah/shenandoahEvacTracker.cpp | 4 +-- .../share/gc/shenandoah/shenandoahFreeSet.cpp | 2 +- .../share/gc/shenandoah/shenandoahFreeSet.hpp | 2 +- .../share/gc/shenandoah/shenandoahFullGC.cpp | 13 +++++----- .../share/gc/shenandoah/shenandoahGC.hpp | 2 +- .../gc/shenandoah/shenandoahGeneration.cpp | 5 ++-- .../gc/shenandoah/shenandoahGeneration.hpp | 2 +- .../shenandoah/shenandoahGenerationSizer.cpp | 2 +- .../shenandoahGenerationalControlThread.cpp | 8 +++--- .../shenandoahGenerationalEvacuationTask.cpp | 2 +- .../shenandoahGenerationalFullGC.cpp | 4 +-- .../shenandoah/shenandoahGenerationalHeap.cpp | 2 +- .../shenandoah/shenandoahGlobalGeneration.cpp | 2 +- .../shenandoah/shenandoahGlobalGeneration.hpp | 2 +- .../share/gc/shenandoah/shenandoahHeap.cpp | 25 ++++++++----------- .../share/gc/shenandoah/shenandoahHeap.hpp | 8 +++--- .../gc/shenandoah/shenandoahHeap.inline.hpp | 14 +++++------ .../gc/shenandoah/shenandoahHeapRegion.cpp | 6 ++--- .../shenandoahHeapRegion.inline.hpp | 3 ++- .../shenandoahHeapRegionCounters.cpp | 2 +- .../shenandoahHeapRegionCounters.hpp | 2 +- .../gc/shenandoah/shenandoahHeapRegionSet.cpp | 2 +- .../gc/shenandoah/shenandoahHeapRegionSet.hpp | 2 +- .../gc/shenandoah/shenandoahInitLogger.cpp | 4 +-- .../share/gc/shenandoah/shenandoahLock.cpp | 3 +-- .../share/gc/shenandoah/shenandoahMark.hpp | 2 +- .../gc/shenandoah/shenandoahMarkBitMap.cpp | 2 +- .../shenandoah/shenandoahMarkingContext.cpp | 1 - .../shenandoahMarkingContext.inline.hpp | 1 + .../gc/shenandoah/shenandoahMemoryPool.cpp | 2 +- .../share/gc/shenandoah/shenandoahMetrics.cpp | 4 +-- .../gc/shenandoah/shenandoahMmuTracker.cpp | 2 +- .../shenandoahMonitoringSupport.cpp | 2 +- .../share/gc/shenandoah/shenandoahOldGC.cpp | 2 +- .../gc/shenandoah/shenandoahOldGeneration.cpp | 2 +- .../gc/shenandoah/shenandoahPhaseTimings.cpp | 8 +++--- .../gc/shenandoah/shenandoahPhaseTimings.hpp | 4 +-- .../shenandoahReferenceProcessor.cpp | 4 +-- .../gc/shenandoah/shenandoahRootProcessor.cpp | 2 +- .../shenandoahRootProcessor.inline.hpp | 2 +- .../gc/shenandoah/shenandoahRootVerifier.cpp | 6 ++--- .../share/gc/shenandoah/shenandoahRuntime.cpp | 2 +- .../shenandoahScanRemembered.inline.hpp | 11 ++++---- .../gc/shenandoah/shenandoahSimpleBitMap.hpp | 4 +-- .../shenandoahStringDedup.inline.hpp | 3 ++- .../gc/shenandoah/shenandoahTaskqueue.hpp | 2 +- .../shenandoah/shenandoahThreadLocalData.hpp | 8 +++--- .../share/gc/shenandoah/shenandoahUnload.cpp | 4 +-- .../share/gc/shenandoah/shenandoahUtils.cpp | 2 +- .../share/gc/shenandoah/shenandoahUtils.hpp | 2 +- .../gc/shenandoah/shenandoahVerifier.cpp | 2 +- .../gc/shenandoah/shenandoahWorkGroup.cpp | 3 +-- .../shenandoah/shenandoahYoungGeneration.cpp | 2 +- .../shenandoah/shenandoahYoungGeneration.hpp | 2 +- .../gc/shenandoah/vmStructs_shenandoah.hpp | 2 +- src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp | 2 +- src/hotspot/share/gc/z/zHeapIterator.hpp | 2 +- src/hotspot/share/gc/z/zMarkContext.hpp | 2 +- src/hotspot/share/gc/z/zMarkingSMR.hpp | 2 +- src/hotspot/share/gc/z/zNMT.cpp | 2 +- src/hotspot/share/gc/z/zNMT.hpp | 2 +- src/hotspot/share/gc/z/zNMethod.cpp | 2 +- src/hotspot/share/gc/z/zNMethodTable.cpp | 2 +- src/hotspot/share/gc/z/zObjArrayAllocator.cpp | 2 +- src/hotspot/share/gc/z/zRuntimeWorkers.cpp | 2 +- src/hotspot/share/gc/z/zStat.cpp | 2 +- .../share/gc/z/zUncoloredRoot.inline.hpp | 2 +- src/hotspot/share/gc/z/zVerify.cpp | 2 +- .../gc/z/zVirtualMemoryManager.inline.hpp | 2 +- 197 files changed, 283 insertions(+), 286 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp index e33ef47cf3c..e4db8a9ab1f 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp @@ -27,9 +27,9 @@ #include "c1/c1_MacroAssembler.hpp" #include "compiler/compilerDefinitions.inline.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" -#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #define __ masm->masm()-> diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index ac22b43faaf..a2b3f44c68b 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -23,6 +23,8 @@ * */ +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" @@ -30,10 +32,8 @@ #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" -#include "interpreter/interpreter.hpp" #include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" #include "runtime/javaThread.hpp" #include "runtime/sharedRuntime.hpp" #ifdef COMPILER1 diff --git a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp index 20e37528c04..7008615ed43 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp @@ -21,8 +21,8 @@ * questions. */ -#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "gc/z/zAddress.hpp" #include "gc/z/zBarrierSetAssembler.hpp" #include "gc/z/zGlobals.hpp" diff --git a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp index 466dcc8fe66..049477cda76 100644 --- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp @@ -26,7 +26,6 @@ #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BarrierSetAssembler.hpp" #include "gc/g1/g1BarrierSetRuntime.hpp" -#include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1HeapRegion.hpp" #include "gc/g1/g1ThreadLocalData.hpp" diff --git a/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp b/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp index 224a499ff54..c6cc0ce406e 100644 --- a/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp +++ b/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp @@ -29,8 +29,8 @@ #include "memory/resourceArea.hpp" #include "runtime/frame.inline.hpp" #include "runtime/javaThread.hpp" -#include "runtime/sharedRuntime.hpp" #include "runtime/registerMap.hpp" +#include "runtime/sharedRuntime.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp index 19084ed27c7..1b44a169e67 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp @@ -23,8 +23,8 @@ */ #include "code/codeBlob.hpp" -#include "code/nmethod.hpp" #include "code/nativeInst.hpp" +#include "code/nmethod.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/barrierSetNMethod.hpp" diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/c1/shenandoahBarrierSetC1_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/c1/shenandoahBarrierSetC1_ppc.cpp index 48422bc6621..5b24259103f 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/c1/shenandoahBarrierSetC1_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/c1/shenandoahBarrierSetC1_ppc.cpp @@ -26,9 +26,9 @@ #include "asm/macroAssembler.inline.hpp" #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" +#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" -#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #define __ masm->masm()-> diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index 842201e1584..ec5b98bd4c5 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp @@ -24,8 +24,10 @@ */ #include "asm/macroAssembler.inline.hpp" -#include "gc/shared/gcArguments.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcArguments.hpp" +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" @@ -34,8 +36,6 @@ #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "interpreter/interpreter.hpp" #include "macroAssembler_ppc.hpp" #include "runtime/javaThread.hpp" diff --git a/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp b/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp index 2e3eed8ec60..f3a7a948f70 100644 --- a/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp @@ -21,8 +21,8 @@ * questions. */ -#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "gc/z/zAddress.inline.hpp" #include "gc/z/zGlobals.hpp" #include "runtime/globals.hpp" diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp index 39da77181c6..f24e4f789bc 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp @@ -31,8 +31,8 @@ #include "memory/resourceArea.hpp" #include "runtime/frame.inline.hpp" #include "runtime/javaThread.hpp" -#include "runtime/sharedRuntime.hpp" #include "runtime/registerMap.hpp" +#include "runtime/sharedRuntime.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" #if INCLUDE_JVMCI diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp index 2a96bd32cf8..11c4e5dc81b 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp @@ -26,9 +26,9 @@ #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" -#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #define __ masm->masm()-> diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp index 3021351cca8..4c1056e75a5 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp @@ -23,6 +23,8 @@ * */ +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" @@ -30,10 +32,8 @@ #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" -#include "interpreter/interpreter.hpp" #include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" #include "runtime/javaThread.hpp" #include "runtime/sharedRuntime.hpp" #ifdef COMPILER1 diff --git a/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp index 1f2f0146f04..5f783e6fb8b 100644 --- a/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp @@ -22,8 +22,8 @@ * questions. */ -#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "gc/z/zAddress.hpp" #include "gc/z/zBarrierSetAssembler.hpp" #include "gc/z/zGlobals.hpp" diff --git a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp index 2054c3db36c..dea3317270e 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp @@ -24,16 +24,16 @@ */ #include "asm/macroAssembler.inline.hpp" -#include "registerSaver_s390.hpp" -#include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BarrierSetAssembler.hpp" #include "gc/g1/g1BarrierSetRuntime.hpp" +#include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1HeapRegion.hpp" #include "gc/g1/g1SATBMarkQueueSet.hpp" #include "gc/g1/g1ThreadLocalData.hpp" #include "interpreter/interp_masm.hpp" +#include "registerSaver_s390.hpp" #include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp index 298e5640b27..66fb4cbb8c7 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp @@ -26,9 +26,9 @@ #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" -#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #define __ masm->masm()-> diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index 45e4c46161f..deb8111adad 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -23,6 +23,8 @@ * */ +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" @@ -30,8 +32,6 @@ #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "interpreter/interpreter.hpp" #include "runtime/javaThread.hpp" #include "runtime/sharedRuntime.hpp" diff --git a/src/hotspot/os/windows/gc/z/zSyscall_windows.hpp b/src/hotspot/os/windows/gc/z/zSyscall_windows.hpp index d6174de7d88..3d20fa5a924 100644 --- a/src/hotspot/os/windows/gc/z/zSyscall_windows.hpp +++ b/src/hotspot/os/windows/gc/z/zSyscall_windows.hpp @@ -27,7 +27,6 @@ #include "utilities/globalDefinitions.hpp" #include -#include class ZSyscall { private: diff --git a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp index 540ede9dd83..a2ae6f8a14a 100644 --- a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp @@ -22,8 +22,8 @@ * */ -#include "gc/epsilon/epsilonMonitoringSupport.hpp" #include "gc/epsilon/epsilonHeap.hpp" +#include "gc/epsilon/epsilonMonitoringSupport.hpp" #include "gc/shared/generationCounters.hpp" #include "memory/allocation.hpp" #include "memory/metaspaceCounters.hpp" diff --git a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp index a0eb218dd6c..c4791311e9b 100644 --- a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp +++ b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp @@ -22,8 +22,8 @@ * */ -#include "c1/c1_LIRGenerator.hpp" #include "c1/c1_CodeStubs.hpp" +#include "c1/c1_LIRGenerator.hpp" #include "gc/g1/c1/g1BarrierSetC1.hpp" #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BarrierSetAssembler.hpp" diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index 57e481668f8..bca2255479b 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -29,8 +29,8 @@ #include "gc/g1/g1BarrierSetAssembler.hpp" #include "gc/g1/g1BarrierSetRuntime.hpp" #include "gc/g1/g1CardTable.hpp" -#include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/g1HeapRegion.hpp" +#include "gc/g1/g1ThreadLocalData.hpp" #include "opto/arraycopynode.hpp" #include "opto/block.hpp" #include "opto/compile.hpp" diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.cpp b/src/hotspot/share/gc/g1/g1AllocRegion.cpp index 29907cbc051..7e748cf7e9f 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.cpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.cpp @@ -23,8 +23,8 @@ */ #include "gc/g1/g1AllocRegion.inline.hpp" -#include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1EvacStats.inline.hpp" #include "gc/shared/tlab_globals.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index 49a4958f718..c44234fa11c 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -24,9 +24,9 @@ #include "gc/g1/g1Allocator.inline.hpp" #include "gc/g1/g1AllocRegion.inline.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1EvacInfo.hpp" #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" diff --git a/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp b/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp index cd59cac80b4..9fae49320bc 100644 --- a/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp +++ b/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_G1_G1ANALYTICSSEQUENCES_INLINE_HPP #include "gc/g1/g1AnalyticsSequences.hpp" + #include "gc/g1/g1Predictions.hpp" bool G1PhaseDependentSeq::enough_samples_to_use_mixed_seq() const { diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.hpp index 3212aec2780..8c2605b9746 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp @@ -27,9 +27,9 @@ #include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1SATBMarkQueueSet.hpp" +#include "gc/shared/bufferNode.hpp" #include "gc/shared/cardTable.hpp" #include "gc/shared/cardTableBarrierSet.hpp" -#include "gc/shared/bufferNode.hpp" class G1CardTable; diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index 7e6b0e56d93..e35ae08dfad 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -26,11 +26,12 @@ #define SHARE_GC_G1_G1BLOCKOFFSETTABLE_INLINE_HPP #include "gc/g1/g1BlockOffsetTable.hpp" + #include "gc/g1/g1HeapRegion.hpp" #include "gc/shared/cardTable.hpp" #include "gc/shared/memset_with_concurrent_readers.hpp" -#include "runtime/atomic.hpp" #include "oops/oop.inline.hpp" +#include "runtime/atomic.hpp" inline HeapWord* G1BlockOffsetTable::block_start_reaching_into_card(const void* addr) const { assert(_reserved.contains(addr), "invalid address"); diff --git a/src/hotspot/share/gc/g1/g1CardSet.inline.hpp b/src/hotspot/share/gc/g1/g1CardSet.inline.hpp index 7d753f00bfb..4909e922c6b 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSet.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_G1_G1CARDSET_INLINE_HPP #include "gc/g1/g1CardSet.hpp" + #include "gc/g1/g1CardSetContainers.inline.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp index 61707dcf012..0efc44dea12 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_G1_G1CARDSETCONTAINERS_INLINE_HPP #include "gc/g1/g1CardSetContainers.hpp" + #include "gc/g1/g1GCPhaseTimes.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/checkedCast.hpp" diff --git a/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp index 8c0fab3fd11..7bb618e79b4 100644 --- a/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_G1_G1CARDSETMEMORY_INLINE_HPP #include "gc/g1/g1CardSetMemory.hpp" + #include "gc/g1/g1CardSetContainers.inline.hpp" #include "gc/g1/g1MonotonicArena.inline.hpp" #include "utilities/globalCounter.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 31f0cc12aa5..8b36bf124f2 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -35,16 +35,16 @@ #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectionSetCandidates.hpp" #include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineThread.hpp" -#include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1DirtyCardQueue.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1FullCollector.hpp" #include "gc/g1/g1GCCounters.hpp" #include "gc/g1/g1GCParPhaseTimesTracker.hpp" -#include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1GCPauseType.hpp" +#include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" @@ -91,8 +91,8 @@ #include "gc/shared/taskqueue.inline.hpp" #include "gc/shared/taskTerminator.hpp" #include "gc/shared/tlab_globals.hpp" -#include "gc/shared/workerPolicy.hpp" #include "gc/shared/weakProcessor.inline.hpp" +#include "gc/shared/workerPolicy.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/heapInspection.hpp" diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 8d449ceedc6..0f583e8dcbf 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -27,8 +27,8 @@ #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BiasedArray.hpp" -#include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1CardSet.hpp" +#include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.hpp" diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.inline.hpp b/src/hotspot/share/gc/g1/g1CollectionSet.inline.hpp index f295eff3edd..717f6860eb6 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_G1_G1COLLECTIONSET_INLINE_HPP #include "gc/g1/g1CollectionSet.hpp" + #include "gc/g1/g1HeapRegionRemSet.hpp" template diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 0b8e66f9043..ef62587d868 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -52,8 +52,8 @@ #include "gc/shared/referencePolicy.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/suspendibleThreadSet.hpp" -#include "gc/shared/taskTerminator.hpp" #include "gc/shared/taskqueue.inline.hpp" +#include "gc/shared/taskTerminator.hpp" #include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/workerPolicy.hpp" #include "jvm.h" diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index d54f9bc96f1..2fb9732b88e 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -31,8 +31,8 @@ #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1RegionMarkStatsCache.hpp" #include "gc/shared/gcCause.hpp" -#include "gc/shared/taskTerminator.hpp" #include "gc/shared/taskqueue.hpp" +#include "gc/shared/taskTerminator.hpp" #include "gc/shared/verifyOption.hpp" #include "gc/shared/workerThread.hpp" #include "gc/shared/workerUtils.hpp" diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp index d51c5c74082..bc2fd565aab 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp @@ -27,9 +27,9 @@ #include "gc/g1/g1ConcurrentMarkObjArrayProcessor.hpp" +#include "gc/shared/gc_globals.hpp" #include "oops/oop.inline.hpp" #include "oops/oopsHierarchy.hpp" -#include "gc/shared/gc_globals.hpp" inline bool G1CMObjArrayProcessor::should_be_sliced(oop obj) { return obj->is_objArray() && ((objArrayOop)obj)->size() >= 2 * ObjArrayMarkingStride; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp index 993df8b47ce..0633e18411d 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp @@ -23,10 +23,9 @@ */ -#include "gc/g1/g1ConcurrentRebuildAndScrub.hpp" - #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp" +#include "gc/g1/g1ConcurrentRebuildAndScrub.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionManager.inline.hpp" #include "gc/shared/gc_globals.hpp" diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index ce4738d784e..dc88f09f980 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -38,6 +38,7 @@ #include "runtime/mutexLocker.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" + #include G1ConcurrentRefineThread* G1ConcurrentRefineThreadControl::create_refinement_thread(uint worker_id, bool initializing) { diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp index ce2f88c9b48..6beb536df87 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp @@ -25,9 +25,9 @@ #ifndef SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP #define SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP -#include "gc/g1/g1FreeIdSet.hpp" #include "gc/g1/g1CardTable.hpp" #include "gc/g1/g1ConcurrentRefineStats.hpp" +#include "gc/g1/g1FreeIdSet.hpp" #include "gc/shared/bufferNode.hpp" #include "gc/shared/bufferNodeList.hpp" #include "gc/shared/ptrQueue.hpp" diff --git a/src/hotspot/share/gc/g1/g1EdenRegions.hpp b/src/hotspot/share/gc/g1/g1EdenRegions.hpp index 81d02381c9b..a6e005ff2dc 100644 --- a/src/hotspot/share/gc/g1/g1EdenRegions.hpp +++ b/src/hotspot/share/gc/g1/g1EdenRegions.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_GC_G1_G1EDENREGIONS_HPP #define SHARE_GC_G1_G1EDENREGIONS_HPP -#include "gc/g1/g1RegionsOnNodes.hpp" #include "gc/g1/g1HeapRegion.hpp" +#include "gc/g1/g1RegionsOnNodes.hpp" #include "runtime/globals.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp b/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp index 0d4f5091d9e..6d5084a1447 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp +++ b/src/hotspot/share/gc/g1/g1EvacFailureRegions.inline.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_GC_G1_G1EVACFAILUREREGIONS_INLINE_HPP #define SHARE_GC_G1_G1EVACFAILUREREGIONS_INLINE_HPP -#include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1EvacFailureRegions.hpp" + +#include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/gc/g1/g1EvacStats.cpp b/src/hotspot/share/gc/g1/g1EvacStats.cpp index b0e5f7b6864..049175a4ecc 100644 --- a/src/hotspot/share/gc/g1/g1EvacStats.cpp +++ b/src/hotspot/share/gc/g1/g1EvacStats.cpp @@ -23,8 +23,8 @@ */ #include "gc/g1/g1EvacStats.hpp" -#include "gc/shared/gcId.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcId.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "runtime/globals.hpp" diff --git a/src/hotspot/share/gc/g1/g1EvacStats.hpp b/src/hotspot/share/gc/g1/g1EvacStats.hpp index 8b7360f55e3..4227cbab936 100644 --- a/src/hotspot/share/gc/g1/g1EvacStats.hpp +++ b/src/hotspot/share/gc/g1/g1EvacStats.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_GC_G1_G1EVACSTATS_HPP #define SHARE_GC_G1_G1EVACSTATS_HPP -#include "gc/shared/plab.hpp" #include "gc/shared/gcUtil.hpp" +#include "gc/shared/plab.hpp" // Records various memory allocation statistics gathered during evacuation. All sizes // are in HeapWords. diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index e9d6d23149f..a1e1d152fd8 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -35,9 +35,9 @@ #include "gc/g1/g1OopClosures.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RegionMarkStatsCache.inline.hpp" +#include "gc/shared/classUnloadingContext.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/preservedMarks.inline.hpp" -#include "gc/shared/classUnloadingContext.hpp" #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/verifyOption.hpp" #include "gc/shared/weakProcessor.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index ebe77b2551d..5b0d5ca8eb9 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -31,11 +31,11 @@ #include "gc/shared/oopStorageSet.hpp" #include "gc/shared/tlab_globals.hpp" #include "gc/shared/workerDataArray.inline.hpp" -#include "memory/resourceArea.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" -#include "runtime/timer.hpp" +#include "memory/resourceArea.hpp" #include "runtime/os.hpp" +#include "runtime/timer.hpp" #include "utilities/enumIterator.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp index 016b2046265..0098839c1a4 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp @@ -24,8 +24,8 @@ #include "gc/g1/g1Arguments.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1CommittedRegionMap.inline.hpp" +#include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1HeapRegion.hpp" #include "gc/g1/g1HeapRegionManager.inline.hpp" #include "gc/g1/g1HeapRegionPrinter.hpp" diff --git a/src/hotspot/share/gc/g1/g1InitLogger.cpp b/src/hotspot/share/gc/g1/g1InitLogger.cpp index 1e09eed9043..1838b55e4d3 100644 --- a/src/hotspot/share/gc/g1/g1InitLogger.cpp +++ b/src/hotspot/share/gc/g1/g1InitLogger.cpp @@ -23,8 +23,8 @@ */ #include "gc/g1/g1InitLogger.hpp" -#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "runtime/globals.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp index 03bd1840206..6d1ffdb7c00 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp @@ -23,9 +23,9 @@ */ #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1MemoryPool.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1Policy.hpp" -#include "gc/g1/g1MemoryPool.hpp" #include "gc/shared/hSpaceCounters.hpp" #include "memory/metaspaceCounters.hpp" #include "runtime/mutexLocker.hpp" diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp index f22581ad9b1..62c502d497c 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp @@ -27,9 +27,9 @@ #include "gc/shared/collectorCounters.hpp" #include "gc/shared/generationCounters.hpp" +#include "runtime/mutex.hpp" #include "services/memoryManager.hpp" #include "services/memoryService.hpp" -#include "runtime/mutex.hpp" class CollectorCounters; class G1CollectedHeap; diff --git a/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp b/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp index f01248424a0..4ded4bcccae 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArena.inline.hpp @@ -27,6 +27,7 @@ #define SHARE_GC_G1_G1MONOTONICARENA_INLINE_HPP #include "gc/g1/g1MonotonicArena.hpp" + #include "runtime/atomic.hpp" #include "utilities/globalCounter.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp index cc857a53969..40c199dee49 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp @@ -28,8 +28,8 @@ #include "gc/g1/g1HeapRegionRemSet.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" #include "gc/g1/g1MonotonicArenaFreePool.hpp" -#include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/share/gc/g1/g1NMethodClosure.cpp b/src/hotspot/share/gc/g1/g1NMethodClosure.cpp index 8dc817f1452..d74aa5eae1d 100644 --- a/src/hotspot/share/gc/g1/g1NMethodClosure.cpp +++ b/src/hotspot/share/gc/g1/g1NMethodClosure.cpp @@ -23,11 +23,11 @@ */ #include "code/nmethod.hpp" -#include "gc/g1/g1NMethodClosure.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1HeapRegion.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" +#include "gc/g1/g1NMethodClosure.hpp" #include "gc/shared/barrierSetNMethod.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp index 5ab1f58bce1..8d84f144f02 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp @@ -38,8 +38,8 @@ #include "memory/iterator.inline.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" -#include "oops/oopsHierarchy.hpp" #include "oops/oop.inline.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/prefetch.inline.hpp" #include "utilities/align.hpp" diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 94ca0878df8..4d569622238 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -26,8 +26,8 @@ #define SHARE_GC_G1_G1PARSCANTHREADSTATE_HPP #include "gc/g1/g1CollectedHeap.hpp" -#include "gc/g1/g1RedirtyCardsQueue.hpp" #include "gc/g1/g1OopClosures.hpp" +#include "gc/g1/g1RedirtyCardsQueue.hpp" #include "gc/g1/g1YoungGCAllocationFailureInjector.hpp" #include "gc/shared/ageTable.hpp" #include "gc/shared/copyFailedInfo.hpp" diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index deb67656a41..6488bf44e41 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -28,20 +28,21 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectionSetCandidates.inline.hpp" +#include "gc/g1/g1CollectionSetChooser.hpp" #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" #include "gc/g1/g1ConcurrentRefineStats.hpp" -#include "gc/g1/g1CollectionSetChooser.hpp" +#include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "gc/g1/g1IHOPControl.hpp" -#include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1SurvivorRegions.hpp" #include "gc/g1/g1YoungGenSizer.hpp" #include "gc/shared/concurrentGCBreakpoints.hpp" #include "gc/shared/gcPolicyCounters.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "logging/log.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" @@ -49,8 +50,6 @@ #include "utilities/growableArray.hpp" #include "utilities/pair.hpp" -#include "gc/shared/gcTraceTime.inline.hpp" - G1Policy::G1Policy(STWGCTimer* gc_timer) : _predictor((100 - G1ConfidencePercent) / 100.0), _analytics(new G1Analytics(&_predictor)), diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index fb24b5ab72b..37d66ee6535 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -31,8 +31,8 @@ #include "gc/g1/g1HeapRegionAttr.hpp" #include "gc/g1/g1MMUTracker.hpp" #include "gc/g1/g1OldGenAllocationTracker.hpp" -#include "gc/g1/g1RemSetTrackingPolicy.hpp" #include "gc/g1/g1Predictions.hpp" +#include "gc/g1/g1RemSetTrackingPolicy.hpp" #include "gc/g1/g1YoungGenSizer.hpp" #include "gc/shared/gcCause.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index a25fce2d006..c4f84b02d01 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -40,12 +40,12 @@ #include "gc/g1/g1HeapRegionRemSet.inline.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1Policy.hpp" -#include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1RemSet.hpp" +#include "gc/g1/g1RootClosures.hpp" #include "gc/shared/bufferNode.hpp" #include "gc/shared/bufferNodeList.hpp" -#include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "jfr/jfrEvents.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" diff --git a/src/hotspot/share/gc/g1/g1ServiceThread.cpp b/src/hotspot/share/gc/g1/g1ServiceThread.cpp index 5f664cfba3a..22675ec2a64 100644 --- a/src/hotspot/share/gc/g1/g1ServiceThread.cpp +++ b/src/hotspot/share/gc/g1/g1ServiceThread.cpp @@ -26,8 +26,8 @@ #include "logging/log.hpp" #include "runtime/cpuTimeCounters.hpp" #include "runtime/mutexLocker.hpp" -#include "runtime/timer.hpp" #include "runtime/os.hpp" +#include "runtime/timer.hpp" G1SentinelTask::G1SentinelTask() : G1ServiceTask("Sentinel Task") { set_time(max_jlong); diff --git a/src/hotspot/share/gc/g1/g1SurvivorRegions.cpp b/src/hotspot/share/gc/g1/g1SurvivorRegions.cpp index dd3323f4079..edd4f35d5ed 100644 --- a/src/hotspot/share/gc/g1/g1SurvivorRegions.cpp +++ b/src/hotspot/share/gc/g1/g1SurvivorRegions.cpp @@ -24,8 +24,8 @@ #include "gc/g1/g1HeapRegion.hpp" #include "gc/g1/g1SurvivorRegions.hpp" -#include "utilities/growableArray.hpp" #include "utilities/debug.hpp" +#include "utilities/growableArray.hpp" G1SurvivorRegions::G1SurvivorRegions() : _regions(new (mtGC) GrowableArray(8, mtGC)), diff --git a/src/hotspot/share/gc/g1/g1Trace.cpp b/src/hotspot/share/gc/g1/g1Trace.cpp index 3cc8a8a28e1..6c9a87e4d98 100644 --- a/src/hotspot/share/gc/g1/g1Trace.cpp +++ b/src/hotspot/share/gc/g1/g1Trace.cpp @@ -23,9 +23,9 @@ */ #include "gc/g1/g1EvacInfo.hpp" +#include "gc/g1/g1GCPauseType.hpp" #include "gc/g1/g1HeapRegionTraceType.hpp" #include "gc/g1/g1Trace.hpp" -#include "gc/g1/g1GCPauseType.hpp" #include "gc/shared/gcHeapSummary.hpp" #include "jfr/jfrEvents.hpp" #if INCLUDE_JFR diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index 9552bd6d418..260817f7a57 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -25,8 +25,8 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1Policy.hpp" -#include "gc/g1/g1VMOperations.hpp" #include "gc/g1/g1Trace.hpp" +#include "gc/g1/g1VMOperations.hpp" #include "gc/shared/concurrentGCBreakpoints.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/gcId.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index 44803564de1..69586b4ebf2 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -32,9 +32,9 @@ #include "gc/g1/g1CollectionSetCandidates.inline.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.hpp" -#include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1EvacFailureRegions.inline.hpp" #include "gc/g1/g1EvacInfo.hpp" +#include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapRegionPrinter.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" @@ -49,9 +49,9 @@ #include "gc/g1/g1YoungGCPostEvacuateTasks.hpp" #include "gc/g1/g1YoungGCPreEvacuateTasks.hpp" #include "gc/shared/concurrentGCBreakpoints.hpp" -#include "gc/shared/gcTraceTime.inline.hpp" -#include "gc/shared/gcTimer.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcTimer.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/workerPolicy.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp index 63e77979812..839b70d93af 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp @@ -25,9 +25,9 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentRefineStats.hpp" #include "gc/g1/g1DirtyCardQueue.hpp" -#include "gc/g1/g1YoungGCPreEvacuateTasks.hpp" #include "gc/g1/g1RegionPinCache.inline.hpp" #include "gc/g1/g1ThreadLocalData.hpp" +#include "gc/g1/g1YoungGCPreEvacuateTasks.hpp" #include "gc/shared/barrierSet.inline.hpp" #include "gc/shared/threadLocalAllocBuffer.inline.hpp" #include "memory/allocation.inline.hpp" diff --git a/src/hotspot/share/gc/parallel/parallelInitLogger.cpp b/src/hotspot/share/gc/parallel/parallelInitLogger.cpp index b28f0385c51..1d9c9f840ba 100644 --- a/src/hotspot/share/gc/parallel/parallelInitLogger.cpp +++ b/src/hotspot/share/gc/parallel/parallelInitLogger.cpp @@ -23,8 +23,8 @@ */ #include "gc/parallel/parallelInitLogger.hpp" -#include "gc/shared/genArguments.hpp" #include "gc/shared/gcLogPrecious.hpp" +#include "gc/shared/genArguments.hpp" void ParallelInitLogger::print_heap() { log_info_p(gc, init)("Alignments:" diff --git a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp index 3bb0c0bf119..b4f860e053f 100644 --- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp +++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp @@ -27,8 +27,8 @@ #include "gc/parallel/psGCAdaptivePolicyCounters.hpp" #include "gc/parallel/psScavenge.hpp" #include "gc/shared/gcCause.hpp" -#include "gc/shared/gcUtil.hpp" #include "gc/shared/gcPolicyCounters.hpp" +#include "gc/shared/gcUtil.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" #include "utilities/align.hpp" diff --git a/src/hotspot/share/gc/parallel/psCardTable.cpp b/src/hotspot/share/gc/parallel/psCardTable.cpp index f8841b9a164..22a38d816f6 100644 --- a/src/hotspot/share/gc/parallel/psCardTable.cpp +++ b/src/hotspot/share/gc/parallel/psCardTable.cpp @@ -32,8 +32,8 @@ #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/prefetch.inline.hpp" -#include "utilities/spinYield.hpp" #include "utilities/align.hpp" +#include "utilities/spinYield.hpp" // Checks an individual oop for missing precise marks. Mark // may be either dirty or newgen. diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp index f00e18c3297..ba936277821 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp @@ -23,8 +23,8 @@ */ #include "gc/parallel/objectStartArray.hpp" -#include "gc/parallel/parMarkBitMap.inline.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" +#include "gc/parallel/parMarkBitMap.inline.hpp" #include "gc/parallel/psCompactionManager.inline.hpp" #include "gc/parallel/psOldGen.hpp" #include "gc/parallel/psParallelCompact.inline.hpp" diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp index 739d2cb1cc7..b013238a9f8 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp @@ -28,8 +28,8 @@ #include "classfile/classLoaderData.hpp" #include "gc/parallel/psParallelCompact.hpp" #include "gc/shared/partialArraySplitter.hpp" -#include "gc/shared/partialArrayTaskStats.hpp" #include "gc/shared/partialArrayState.hpp" +#include "gc/shared/partialArrayTaskStats.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/taskqueue.hpp" diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index be31da5b05d..661bc3da3e1 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -44,8 +44,8 @@ #include "gc/shared/gcVMOperations.hpp" #include "gc/shared/isGCActiveMark.hpp" #include "gc/shared/oopStorage.inline.hpp" -#include "gc/shared/oopStorageSetParState.inline.hpp" #include "gc/shared/oopStorageParState.inline.hpp" +#include "gc/shared/oopStorageSetParState.inline.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" @@ -57,18 +57,18 @@ #include "gc/shared/workerPolicy.hpp" #include "gc/shared/workerThread.hpp" #include "gc/shared/workerUtils.hpp" +#include "logging/log.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" -#include "logging/log.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/threadCritical.hpp" #include "runtime/threads.hpp" -#include "runtime/vmThread.hpp" #include "runtime/vmOperations.hpp" +#include "runtime/vmThread.hpp" #include "services/memoryService.hpp" #include "utilities/stack.inline.hpp" diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index 55abdfd3cf3..8da555a8bb4 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -28,8 +28,8 @@ #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 "gc/shared/referenceProcessor.hpp" #include "memory/allStatic.hpp" #include "oops/oop.hpp" #include "utilities/stack.hpp" diff --git a/src/hotspot/share/gc/parallel/psVMOperations.cpp b/src/hotspot/share/gc/parallel/psVMOperations.cpp index 4873853a3dd..dc96d9506e2 100644 --- a/src/hotspot/share/gc/parallel/psVMOperations.cpp +++ b/src/hotspot/share/gc/parallel/psVMOperations.cpp @@ -22,8 +22,8 @@ * */ -#include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/parallelScavengeHeap.inline.hpp" +#include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/psScavenge.hpp" #include "gc/parallel/psVMOperations.hpp" #include "gc/shared/gcLocker.hpp" diff --git a/src/hotspot/share/gc/serial/serialArguments.cpp b/src/hotspot/share/gc/serial/serialArguments.cpp index 9b55e0cd9f6..aed1c2353b4 100644 --- a/src/hotspot/share/gc/serial/serialArguments.cpp +++ b/src/hotspot/share/gc/serial/serialArguments.cpp @@ -22,10 +22,10 @@ * */ -#include "gc/shared/fullGCForwarding.hpp" -#include "gc/shared/gcArguments.hpp" #include "gc/serial/serialArguments.hpp" #include "gc/serial/serialHeap.hpp" +#include "gc/shared/fullGCForwarding.hpp" +#include "gc/shared/gcArguments.hpp" void SerialArguments::initialize() { GCArguments::initialize(); diff --git a/src/hotspot/share/gc/serial/serialFullGC.cpp b/src/hotspot/share/gc/serial/serialFullGC.cpp index 9d0dc1932fc..15468704547 100644 --- a/src/hotspot/share/gc/serial/serialFullGC.cpp +++ b/src/hotspot/share/gc/serial/serialFullGC.cpp @@ -22,8 +22,8 @@ * */ -#include "classfile/classLoaderDataGraph.hpp" #include "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderDataGraph.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" @@ -43,11 +43,11 @@ #include "gc/shared/collectedHeap.inline.hpp" #include "gc/shared/continuationGCSupport.inline.hpp" #include "gc/shared/fullGCForwarding.inline.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/gcHeapSummary.hpp" #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTraceTime.inline.hpp" -#include "gc/shared/gc_globals.hpp" #include "gc/shared/modRefBarrierSet.hpp" #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/referencePolicy.hpp" diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp index c6a6a0ae716..d88b2566299 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_SERIAL_TENUREDGENERATION_INLINE_HPP #include "gc/serial/tenuredGeneration.hpp" + #include "gc/shared/space.hpp" inline size_t TenuredGeneration::capacity() const { diff --git a/src/hotspot/share/gc/shared/ageTable.cpp b/src/hotspot/share/gc/shared/ageTable.cpp index f5b62466556..2ed6ea967db 100644 --- a/src/hotspot/share/gc/shared/ageTable.cpp +++ b/src/hotspot/share/gc/shared/ageTable.cpp @@ -28,11 +28,11 @@ #include "gc/shared/gc_globals.hpp" #include "jvm.h" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/perfData.hpp" #include "utilities/copy.hpp" -#include "logging/logStream.hpp" /* Copyright (c) 1992, 2025, Oracle and/or its affiliates, and Stanford University. See the LICENSE file for license information. */ diff --git a/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp b/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp index 38c568889d1..f637c227ee1 100644 --- a/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp +++ b/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp @@ -27,8 +27,8 @@ #include "gc/shared/barrierSetConfig.hpp" -#include "gc/shared/modRefBarrierSet.inline.hpp" #include "gc/shared/cardTableBarrierSet.inline.hpp" +#include "gc/shared/modRefBarrierSet.inline.hpp" #if INCLUDE_EPSILONGC #include "gc/epsilon/epsilonBarrierSet.hpp" diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp index c5d8a7e5401..41eb0a24b62 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp @@ -35,8 +35,8 @@ #include "oops/method.inline.hpp" #include "runtime/frame.inline.hpp" #include "runtime/javaThread.hpp" -#include "runtime/threadWXSetters.inline.hpp" #include "runtime/threads.hpp" +#include "runtime/threadWXSetters.inline.hpp" #include "utilities/debug.hpp" #if INCLUDE_JVMCI #include "jvmci/jvmciRuntime.hpp" diff --git a/src/hotspot/share/gc/shared/bufferNode.cpp b/src/hotspot/share/gc/shared/bufferNode.cpp index e27b1279c79..b064f9c7efe 100644 --- a/src/hotspot/share/gc/shared/bufferNode.cpp +++ b/src/hotspot/share/gc/shared/bufferNode.cpp @@ -23,8 +23,8 @@ */ #include "gc/shared/bufferNode.hpp" -#include "utilities/debug.hpp" #include "memory/allocation.inline.hpp" +#include "utilities/debug.hpp" #include diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp index 3d0621cdc7a..e618a81b26b 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp @@ -26,9 +26,9 @@ #define SHARE_GC_SHARED_C1_BARRIERSETC1_HPP #include "c1/c1_Decorators.hpp" -#include "c1/c1_LIRGenerator.hpp" #include "c1/c1_Instruction.hpp" #include "c1/c1_LIR.hpp" +#include "c1/c1_LIRGenerator.hpp" #include "memory/allocation.hpp" class LIRGenerator; diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index 92154e7a46e..f0ed9687f11 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -24,8 +24,8 @@ #include "code/vmreg.inline.hpp" #include "gc/shared/barrierSet.hpp" -#include "gc/shared/tlab_globals.hpp" #include "gc/shared/c2/barrierSetC2.hpp" +#include "gc/shared/tlab_globals.hpp" #include "opto/arraycopynode.hpp" #include "opto/block.hpp" #include "opto/convertnode.hpp" diff --git a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp index 7df210d9fb6..536cd6da1ef 100644 --- a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp @@ -23,9 +23,9 @@ */ #include "ci/ciUtilities.hpp" +#include "gc/shared/c2/cardTableBarrierSetC2.hpp" #include "gc/shared/cardTable.hpp" #include "gc/shared/cardTableBarrierSet.hpp" -#include "gc/shared/c2/cardTableBarrierSetC2.hpp" #include "gc/shared/gc_globals.hpp" #include "opto/arraycopynode.hpp" #include "opto/graphKit.hpp" diff --git a/src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp index cf5d3fc7e16..ddc9caedd71 100644 --- a/src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp @@ -22,10 +22,10 @@ * */ +#include "gc/shared/c2/modRefBarrierSetC2.hpp" #include "opto/arraycopynode.hpp" #include "opto/graphKit.hpp" #include "opto/idealKit.hpp" -#include "gc/shared/c2/modRefBarrierSetC2.hpp" Node* ModRefBarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const { DecoratorSet decorators = access.decorators(); diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 3236d73933c..e5dbbcc0746 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -24,8 +24,8 @@ #include "gc/shared/cardTable.hpp" #include "gc/shared/collectedHeap.hpp" -#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/space.hpp" #include "logging/log.hpp" #include "memory/memoryReserver.hpp" diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 9c55a894ee7..ec9872bf402 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -29,15 +29,15 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectedHeap.inline.hpp" -#include "gc/shared/gcLocker.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/gcHeapSummary.hpp" -#include "gc/shared/stringdedup/stringDedup.hpp" +#include "gc/shared/gcLocker.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/gcVMOperations.hpp" #include "gc/shared/gcWhen.hpp" -#include "gc/shared/gc_globals.hpp" #include "gc/shared/memAllocator.hpp" +#include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/tlab_globals.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" diff --git a/src/hotspot/share/gc/shared/gcHeapSummary.hpp b/src/hotspot/share/gc/shared/gcHeapSummary.hpp index fb048d06a41..ae08f60d3a6 100644 --- a/src/hotspot/share/gc/shared/gcHeapSummary.hpp +++ b/src/hotspot/share/gc/shared/gcHeapSummary.hpp @@ -26,8 +26,8 @@ #define SHARE_GC_SHARED_GCHEAPSUMMARY_HPP #include "memory/allocation.hpp" -#include "memory/metaspaceStats.hpp" #include "memory/metaspaceChunkFreeListSummary.hpp" +#include "memory/metaspaceStats.hpp" class VirtualSpaceSummary : public StackObj { HeapWord* _start; diff --git a/src/hotspot/share/gc/shared/gcInitLogger.cpp b/src/hotspot/share/gc/shared/gcInitLogger.cpp index f2d9fffdc11..91bebf726c1 100644 --- a/src/hotspot/share/gc/shared/gcInitLogger.cpp +++ b/src/hotspot/share/gc/shared/gcInitLogger.cpp @@ -22,9 +22,9 @@ * */ +#include "gc/shared/gc_globals.hpp" #include "gc/shared/gcInitLogger.hpp" #include "gc/shared/gcLogPrecious.hpp" -#include "gc/shared/gc_globals.hpp" #include "logging/log.hpp" #include "oops/compressedOops.hpp" #include "runtime/globals.hpp" diff --git a/src/hotspot/share/gc/shared/gcLocker.cpp b/src/hotspot/share/gc/shared/gcLocker.cpp index caf752f70c8..fbc953512bb 100644 --- a/src/hotspot/share/gc/shared/gcLocker.cpp +++ b/src/hotspot/share/gc/shared/gcLocker.cpp @@ -25,15 +25,15 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcLocker.hpp" #include "gc/shared/gcTrace.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" -#include "logging/log.hpp" #include "runtime/atomic.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaThread.inline.hpp" #include "runtime/safepoint.hpp" -#include "utilities/spinYield.hpp" #include "runtime/threadSMR.hpp" +#include "utilities/spinYield.hpp" #include "utilities/ticks.hpp" // GCLockerTimingDebugLogger tracks specific timing information for GC lock waits. diff --git a/src/hotspot/share/gc/shared/gcLogPrecious.hpp b/src/hotspot/share/gc/shared/gcLogPrecious.hpp index ec8b1c670f3..8aa70252b3d 100644 --- a/src/hotspot/share/gc/shared/gcLogPrecious.hpp +++ b/src/hotspot/share/gc/shared/gcLogPrecious.hpp @@ -24,10 +24,10 @@ #ifndef SHARE_GC_SHARED_GCLOGPRECIOUS_HPP #define SHARE_GC_SHARED_GCLOGPRECIOUS_HPP -#include "utilities/globalDefinitions.hpp" #include "logging/logHandle.hpp" #include "memory/allStatic.hpp" #include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" class Mutex; class stringStream; diff --git a/src/hotspot/share/gc/shared/gcOverheadChecker.hpp b/src/hotspot/share/gc/shared/gcOverheadChecker.hpp index d4a9b5cd70d..e29ae2ab911 100644 --- a/src/hotspot/share/gc/shared/gcOverheadChecker.hpp +++ b/src/hotspot/share/gc/shared/gcOverheadChecker.hpp @@ -26,9 +26,9 @@ #ifndef SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP #define SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP -#include "memory/allocation.hpp" -#include "gc/shared/gcCause.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcCause.hpp" +#include "memory/allocation.hpp" #include "runtime/globals.hpp" class SoftRefPolicy; diff --git a/src/hotspot/share/gc/shared/gcPolicyCounters.cpp b/src/hotspot/share/gc/shared/gcPolicyCounters.cpp index d24ad745aa1..343ad6ca41e 100644 --- a/src/hotspot/share/gc/shared/gcPolicyCounters.cpp +++ b/src/hotspot/share/gc/shared/gcPolicyCounters.cpp @@ -22,8 +22,8 @@ * */ -#include "gc/shared/gcPolicyCounters.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcPolicyCounters.hpp" #include "memory/resourceArea.hpp" GCPolicyCounters::GCPolicyCounters(const char* name, int collectors, diff --git a/src/hotspot/share/gc/shared/gcTimer.cpp b/src/hotspot/share/gc/shared/gcTimer.cpp index 85859750151..a5bc7bfb02f 100644 --- a/src/hotspot/share/gc/shared/gcTimer.cpp +++ b/src/hotspot/share/gc/shared/gcTimer.cpp @@ -22,8 +22,8 @@ * */ -#include "gc/shared/gcTimer.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcTimer.hpp" #include "utilities/growableArray.hpp" // the "time" parameter for most functions diff --git a/src/hotspot/share/gc/shared/gcTraceTime.cpp b/src/hotspot/share/gc/shared/gcTraceTime.cpp index def8a3f3f5c..5839027b585 100644 --- a/src/hotspot/share/gc/shared/gcTraceTime.cpp +++ b/src/hotspot/share/gc/shared/gcTraceTime.cpp @@ -23,8 +23,8 @@ */ #include "gc/shared/collectedHeap.hpp" -#include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/gcTrace.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/share/gc/shared/gcVMOperations.cpp b/src/hotspot/share/gc/shared/gcVMOperations.cpp index 8e5768ce6a9..1632dca61d5 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.cpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.cpp @@ -25,10 +25,10 @@ #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" #include "gc/shared/allocTracer.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/gcId.hpp" #include "gc/shared/gcLocker.hpp" #include "gc/shared/gcVMOperations.hpp" -#include "gc/shared/gc_globals.hpp" #include "gc/shared/softRefPolicy.hpp" #include "interpreter/oopMapCache.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/gc/shared/locationPrinter.cpp b/src/hotspot/share/gc/shared/locationPrinter.cpp index b5efb540d45..85fdcd37524 100644 --- a/src/hotspot/share/gc/shared/locationPrinter.cpp +++ b/src/hotspot/share/gc/shared/locationPrinter.cpp @@ -25,9 +25,9 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/locationPrinter.hpp" #include "memory/universe.hpp" -#include "runtime/os.hpp" #include "oops/klass.hpp" #include "oops/oop.inline.hpp" +#include "runtime/os.hpp" bool LocationPrinter::is_valid_obj(void* obj) { if (!is_object_aligned(obj)) { diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp index 64ca4635718..74ef1f66184 100644 --- a/src/hotspot/share/gc/shared/memAllocator.cpp +++ b/src/hotspot/share/gc/shared/memAllocator.cpp @@ -35,8 +35,8 @@ #include "prims/jvmtiExport.hpp" #include "runtime/continuationJavaClasses.inline.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/sharedRuntime.hpp" #include "runtime/javaThread.hpp" +#include "runtime/sharedRuntime.hpp" #include "services/lowMemoryDetector.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" diff --git a/src/hotspot/share/gc/shared/parallelCleaning.cpp b/src/hotspot/share/gc/shared/parallelCleaning.cpp index 1b1eaf4d79a..8cb09939f22 100644 --- a/src/hotspot/share/gc/shared/parallelCleaning.cpp +++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp @@ -22,13 +22,12 @@ * */ -#include "classfile/symbolTable.hpp" #include "classfile/stringTable.hpp" +#include "classfile/symbolTable.hpp" #include "code/codeCache.hpp" #include "gc/shared/parallelCleaning.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" -#include "logging/log.hpp" #include "runtime/atomic.hpp" CodeCacheUnloadingTask::CodeCacheUnloadingTask(uint num_workers, bool unloading_occurred) : diff --git a/src/hotspot/share/gc/shared/partialArrayState.cpp b/src/hotspot/share/gc/shared/partialArrayState.cpp index f79e012a36d..8db39281a05 100644 --- a/src/hotspot/share/gc/shared/partialArrayState.cpp +++ b/src/hotspot/share/gc/shared/partialArrayState.cpp @@ -32,6 +32,7 @@ #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" + #include PartialArrayState::PartialArrayState(oop src, oop dst, diff --git a/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp b/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp index 1d43578b5fe..9d127697e58 100644 --- a/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp +++ b/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP #define SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP -#include "gc/shared/partialArrayState.hpp" #include "gc/shared/partialArrayTaskStepper.hpp" + +#include "gc/shared/partialArrayState.hpp" #include "runtime/atomic.hpp" #include "utilities/checkedCast.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp index 83eaccd9813..fd2bd8f3edc 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp @@ -23,8 +23,8 @@ */ #include "gc/shared/gcTimer.hpp" -#include "gc/shared/referenceProcessorPhaseTimes.hpp" #include "gc/shared/referenceProcessor.inline.hpp" +#include "gc/shared/referenceProcessorPhaseTimes.hpp" #include "gc/shared/workerDataArray.inline.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" diff --git a/src/hotspot/share/gc/shared/satbMarkQueue.cpp b/src/hotspot/share/gc/shared/satbMarkQueue.cpp index 6e33d27897c..915eaa116fb 100644 --- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp +++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp @@ -22,8 +22,8 @@ * */ -#include "gc/shared/satbMarkQueue.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/satbMarkQueue.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp index 9ad8decec7e..b3f96da1cce 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp @@ -25,9 +25,9 @@ #include "classfile/javaClasses.inline.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/oopStorage.hpp" #include "gc/shared/oopStorageSet.hpp" -#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/stringdedup/stringDedupConfig.hpp" #include "gc/shared/stringdedup/stringDedupProcessor.hpp" diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp index 5c6628cba5c..83c6fea8c5b 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp @@ -33,10 +33,10 @@ #include "gc/shared/stringdedup/stringDedupConfig.hpp" #include "gc/shared/stringdedup/stringDedupStat.hpp" #include "gc/shared/stringdedup/stringDedupTable.hpp" -#include "memory/allocation.hpp" -#include "memory/resourceArea.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" +#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" #include "oops/access.hpp" #include "oops/oopsHierarchy.hpp" #include "oops/typeArrayOop.inline.hpp" diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp index 19df8184a05..a163319e84c 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp @@ -25,9 +25,9 @@ #ifndef SHARE_GC_SHARED_STRINGDEDUP_STRINGDEDUPTABLE_HPP #define SHARE_GC_SHARED_STRINGDEDUP_STRINGDEDUPTABLE_HPP -#include "memory/allStatic.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/stringdedup/stringDedupStat.hpp" +#include "memory/allStatic.hpp" #include "oops/typeArrayOop.hpp" #include "oops/weakHandle.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shared/taskTerminator.cpp b/src/hotspot/share/gc/shared/taskTerminator.cpp index 1353c3f8c8a..cc84665087b 100644 --- a/src/hotspot/share/gc/shared/taskTerminator.cpp +++ b/src/hotspot/share/gc/shared/taskTerminator.cpp @@ -24,8 +24,8 @@ */ #include "gc/shared/gc_globals.hpp" -#include "gc/shared/taskTerminator.hpp" #include "gc/shared/taskqueue.hpp" +#include "gc/shared/taskTerminator.hpp" #include "logging/log.hpp" #include "runtime/globals.hpp" #include "runtime/javaThread.hpp" diff --git a/src/hotspot/share/gc/shared/taskqueue.cpp b/src/hotspot/share/gc/shared/taskqueue.cpp index a244ba45415..162eadc3cf0 100644 --- a/src/hotspot/share/gc/shared/taskqueue.cpp +++ b/src/hotspot/share/gc/shared/taskqueue.cpp @@ -23,8 +23,8 @@ */ #include "gc/shared/taskqueue.hpp" -#include "oops/oop.inline.hpp" #include "logging/log.hpp" +#include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/javaThread.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp index 32a830a2bb1..22d19b77806 100644 --- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp +++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp @@ -29,8 +29,8 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" -#include "memory/universe.hpp" #include "logging/log.hpp" +#include "memory/universe.hpp" #include "runtime/javaThread.hpp" #include "runtime/osThread.hpp" #include "utilities/copy.hpp" diff --git a/src/hotspot/share/gc/shared/weakProcessor.cpp b/src/hotspot/share/gc/shared/weakProcessor.cpp index d7de8b5d8a8..bc7e9ad6375 100644 --- a/src/hotspot/share/gc/shared/weakProcessor.cpp +++ b/src/hotspot/share/gc/shared/weakProcessor.cpp @@ -27,8 +27,8 @@ #include "gc/shared/oopStorage.inline.hpp" #include "gc/shared/oopStorageParState.inline.hpp" #include "gc/shared/oopStorageSet.hpp" -#include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/oopStorageSetParState.inline.hpp" +#include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/weakProcessorTimes.hpp" #include "memory/allocation.inline.hpp" #include "memory/iterator.hpp" diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp index 9a12e0ed1a1..9f58016a6f1 100644 --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp @@ -26,6 +26,7 @@ #include "c1/c1_IR.hpp" #include "gc/shared/satbMarkQueue.hpp" +#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" @@ -33,7 +34,6 @@ #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" #ifdef ASSERT #define __ gen->lir(__FILE__, __LINE__)-> diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 8df4413cc2f..d71e84d33b0 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -25,15 +25,15 @@ #include "classfile/javaClasses.hpp" #include "gc/shared/barrierSet.hpp" +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#include "gc/shenandoah/c2/shenandoahSupport.hpp" +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" -#include "gc/shenandoah/c2/shenandoahSupport.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "opto/arraycopynode.hpp" #include "opto/escape.hpp" #include "opto/graphKit.hpp" diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 4652dbce0e3..56d88d44d27 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -25,8 +25,8 @@ #include "classfile/javaClasses.hpp" -#include "gc/shenandoah/c2/shenandoahSupport.hpp" #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#include "gc/shenandoah/c2/shenandoahSupport.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahForwarding.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index 5280e9b2ac4..eb87a9dc4c1 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -26,9 +26,9 @@ #include "gc/shared/gcCause.hpp" +#include "gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp" #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp" -#include "gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp index a47024f3a4b..68e540960c7 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp @@ -26,10 +26,10 @@ #ifndef SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHADAPTIVEHEURISTICS_HPP #define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHADAPTIVEHEURISTICS_HPP -#include "memory/allocation.hpp" #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" +#include "memory/allocation.hpp" #include "utilities/numberSeq.hpp" class ShenandoahAllocationRate : public CHeapObj { diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp index 9d211314474..403405b984d 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp @@ -24,8 +24,8 @@ */ -#include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/heuristics/shenandoahCompactHeuristics.hpp" +#include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index afc9abc496e..08fd4599346 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -26,13 +26,12 @@ #include "gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" +#include "gc/shenandoah/shenandoahEvacInfo.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" -#include "gc/shenandoah/shenandoahEvacInfo.hpp" #include "gc/shenandoah/shenandoahTrace.hpp" - #include "logging/log.hpp" ShenandoahGenerationalHeuristics::ShenandoahGenerationalHeuristics(ShenandoahGeneration* generation) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp index 919f6c88afa..b8d85de0487 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp @@ -25,10 +25,9 @@ #include "gc/shenandoah/heuristics/shenandoahGlobalHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" -#include "gc/shenandoah/shenandoahGlobalGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahGlobalGeneration.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" - #include "utilities/quickSort.hpp" ShenandoahGlobalHeuristics::ShenandoahGlobalHeuristics(ShenandoahGlobalGeneration* generation) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp index 4c7ed07b2a0..b151a75e6e7 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp @@ -25,10 +25,10 @@ */ #include "gc/shared/gcCause.hpp" +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "logging/log.hpp" #include "logging/logTag.hpp" #include "runtime/globals_extension.hpp" diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp index 9f8c6225d23..ba09eeb8794 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp @@ -30,7 +30,6 @@ #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" - #include "utilities/quickSort.hpp" ShenandoahYoungHeuristics::ShenandoahYoungHeuristics(ShenandoahYoungGeneration* generation) diff --git a/src/hotspot/share/gc/shenandoah/mode/shenandoahGenerationalMode.cpp b/src/hotspot/share/gc/shenandoah/mode/shenandoahGenerationalMode.cpp index 6c885834155..fa784d5bb90 100644 --- a/src/hotspot/share/gc/shenandoah/mode/shenandoahGenerationalMode.cpp +++ b/src/hotspot/share/gc/shenandoah/mode/shenandoahGenerationalMode.cpp @@ -22,8 +22,8 @@ * */ -#include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" #include "gc/shenandoah/mode/shenandoahGenerationalMode.hpp" #include "logging/log.hpp" #include "logging/logTag.hpp" diff --git a/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp b/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp index 893321db1dc..296a1979b01 100644 --- a/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp +++ b/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp @@ -23,8 +23,8 @@ */ #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" -#include "gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp" #include "gc/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp" +#include "gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp" #include "gc/shenandoah/mode/shenandoahPassiveMode.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index 446e1914407..5d19a6a34e3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -24,8 +24,8 @@ */ #include "gc/shared/barrierSetNMethod.hpp" -#include "gc/shenandoah/shenandoahBarrierSetClone.inline.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" +#include "gc/shenandoah/shenandoahBarrierSetClone.inline.hpp" #include "gc/shenandoah/shenandoahBarrierSetNMethod.hpp" #include "gc/shenandoah/shenandoahBarrierSetStackChunk.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp index 20937b9d08e..b176446452a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -30,6 +30,7 @@ #include "gc/shared/accessBarrierSupport.inline.hpp" #include "gc/shared/cardTable.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" @@ -40,7 +41,6 @@ #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "memory/iterator.inline.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp index c08c9501201..725e4e6e3e9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp @@ -31,10 +31,10 @@ #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahEvacOOMHandler.inline.hpp" -#include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" -#include "gc/shenandoah/shenandoahNMethod.inline.hpp" #include "gc/shenandoah/shenandoahMark.inline.hpp" +#include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" +#include "gc/shenandoah/shenandoahNMethod.inline.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp" #include "memory/iterator.inline.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp index 34db132ab83..d29c446f210 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp @@ -26,9 +26,9 @@ #define SHARE_GC_SHENANDOAH_SHENANDOAHCODEROOTS_HPP #include "code/codeCache.hpp" -#include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "gc/shenandoah/shenandoahLock.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" +#include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "memory/allStatic.hpp" #include "memory/iterator.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 7b9aafad149..5b5fe2c1af6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -35,11 +35,10 @@ #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" -#include "gc/shenandoah/shenandoahOldGeneration.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "gc/shenandoah/shenandoahLock.hpp" #include "gc/shenandoah/shenandoahMark.inline.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" +#include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" @@ -47,8 +46,9 @@ #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" #include "gc/shenandoah/shenandoahVMOperations.hpp" -#include "gc/shenandoah/shenandoahWorkGroup.hpp" #include "gc/shenandoah/shenandoahWorkerPolicy.hpp" +#include "gc/shenandoah/shenandoahWorkGroup.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "memory/allocation.hpp" #include "prims/jvmtiTagMap.hpp" #include "runtime/vmThread.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index 4a0f43226d7..facba2236be 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -33,13 +33,13 @@ #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahMark.inline.hpp" +#include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" -#include "gc/shenandoah/shenandoahPhaseTimings.hpp" +#include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" -#include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "memory/iterator.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/continuation.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index 0b20b4ddf9f..6975bd9f350 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -23,6 +23,8 @@ * */ +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahConcurrentGC.hpp" #include "gc/shenandoah/shenandoahControlThread.hpp" @@ -34,11 +36,9 @@ #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahPacer.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "logging/log.hpp" -#include "memory/metaspaceUtils.hpp" #include "memory/metaspaceStats.hpp" +#include "memory/metaspaceUtils.hpp" ShenandoahControlThread::ShenandoahControlThread() : ShenandoahController(), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp index be99ef1d865..9d95b5df7ed 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp @@ -25,10 +25,10 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCONTROLTHREAD_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHCONTROLTHREAD_HPP -#include "gc/shared/gcCause.hpp" #include "gc/shared/concurrentGCThread.hpp" -#include "gc/shenandoah/shenandoahGC.hpp" +#include "gc/shared/gcCause.hpp" #include "gc/shenandoah/shenandoahController.hpp" +#include "gc/shenandoah/shenandoahGC.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahController.cpp b/src/hotspot/share/gc/shenandoah/shenandoahController.cpp index c430981bfe6..52182b092c9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahController.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahController.cpp @@ -24,9 +24,8 @@ */ #include "gc/shared/gc_globals.hpp" +#include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahController.hpp" - -#include "shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp index 83cde94f509..d24f52cb3f1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCONTROLLER_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHCONTROLLER_HPP -#include "gc/shared/gcCause.hpp" #include "gc/shared/concurrentGCThread.hpp" +#include "gc/shared/gcCause.hpp" #include "gc/shenandoah/shenandoahAllocRequest.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index 8cc4e2de8ea..7aaf7bd9f48 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -39,9 +39,9 @@ #include "gc/shenandoah/shenandoahSTWMark.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" -#include "gc/shenandoah/shenandoahWorkerPolicy.hpp" #include "gc/shenandoah/shenandoahVMOperations.hpp" +#include "gc/shenandoah/shenandoahWorkerPolicy.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "runtime/vmThread.hpp" #include "utilities/events.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp index 3ddc8bf636e..d393c17f64a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp @@ -24,11 +24,11 @@ */ #include "gc/shenandoah/shenandoahAgeCensus.hpp" -#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahEvacTracker.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "runtime/threadSMR.inline.hpp" #include "runtime/thread.hpp" +#include "runtime/threadSMR.inline.hpp" ShenandoahEvacuationStats::ShenandoahEvacuationStats() : _evacuations_completed(0), _bytes_completed(0), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index e87c771dec4..9787611d4fb 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -31,9 +31,9 @@ #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "gc/shenandoah/shenandoahSimpleBitMap.hpp" #include "gc/shenandoah/shenandoahSimpleBitMap.inline.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" #include "runtime/orderAccess.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp index 80954af6d1a..902e6547afd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp @@ -26,8 +26,8 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHFREESET_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHFREESET_HPP -#include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" +#include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahSimpleBitMap.hpp" // Each ShenandoahHeapRegion is associated with a ShenandoahFreeSetPartitionId. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index 9436f09cbe0..f017b3de962 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -34,23 +34,22 @@ #include "gc/shared/workerThread.hpp" #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" -#include "gc/shenandoah/shenandoahCollectorPolicy.hpp" -#include "gc/shenandoah/shenandoahConcurrentGC.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" +#include "gc/shenandoah/shenandoahConcurrentGC.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahFullGC.hpp" #include "gc/shenandoah/shenandoahGenerationalFullGC.hpp" #include "gc/shenandoah/shenandoahGlobalGeneration.hpp" -#include "gc/shenandoah/shenandoahPhaseTimings.hpp" -#include "gc/shenandoah/shenandoahMark.inline.hpp" -#include "gc/shenandoah/shenandoahMonitoringSupport.hpp" -#include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" -#include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" +#include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" +#include "gc/shenandoah/shenandoahHeapRegionSet.hpp" +#include "gc/shenandoah/shenandoahMark.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahMetrics.hpp" +#include "gc/shenandoah/shenandoahMonitoringSupport.hpp" +#include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" #include "gc/shenandoah/shenandoahSTWMark.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp index f10d5eef969..f08bdce0a20 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHGC_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHGC_HPP -#include "memory/allocation.hpp" #include "gc/shared/gcCause.hpp" +#include "memory/allocation.hpp" /* * Base class of three Shenandoah GC modes diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index ad91119ddad..9a511de939c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -23,8 +23,9 @@ * */ -#include "gc/shenandoah/shenandoahCollectorPolicy.hpp" +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectionSetPreselector.hpp" +#include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" @@ -37,8 +38,6 @@ #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" - #include "utilities/quickSort.hpp" template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 31c86985c6f..242acbdea8c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -25,12 +25,12 @@ #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHGENERATION_HPP #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHGENERATION_HPP -#include "memory/allocation.hpp" #include "gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp" #include "gc/shenandoah/shenandoahAffiliation.hpp" #include "gc/shenandoah/shenandoahGenerationType.hpp" #include "gc/shenandoah/shenandoahLock.hpp" #include "gc/shenandoah/shenandoahMarkingContext.hpp" +#include "memory/allocation.hpp" class ShenandoahCollectionSet; class ShenandoahHeap; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationSizer.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationSizer.cpp index c6827878cd1..17f3d2f199f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationSizer.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationSizer.cpp @@ -23,13 +23,13 @@ * */ +#include "gc/shared/gc_globals.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationSizer.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -#include "gc/shared/gc_globals.hpp" #include "logging/log.hpp" #include "runtime/globals_extension.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 4d291ba50f7..2f2f13ca87b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -27,22 +27,22 @@ #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahConcurrentGC.hpp" -#include "gc/shenandoah/shenandoahGenerationalControlThread.hpp" #include "gc/shenandoah/shenandoahDegeneratedGC.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahFullGC.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" +#include "gc/shenandoah/shenandoahGenerationalControlThread.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" -#include "gc/shenandoah/shenandoahOldGC.hpp" -#include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" +#include "gc/shenandoah/shenandoahOldGC.hpp" +#include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahPacer.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "logging/log.hpp" -#include "memory/metaspaceUtils.hpp" #include "memory/metaspaceStats.hpp" +#include "memory/metaspaceUtils.hpp" #include "runtime/atomic.hpp" #include "utilities/events.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp index 6a845afa4fd..ba9ef5979a8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp @@ -31,8 +31,8 @@ #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahPacer.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" class ShenandoahConcurrentEvacuator : public ObjectClosure { private: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index 3387ed9d7a8..142c2d47989 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -25,14 +25,14 @@ #include "gc/shared/fullGCForwarding.inline.hpp" #include "gc/shared/preservedMarks.inline.hpp" +#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalFullGC.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" -#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #ifdef ASSERT void assert_regions_used_not_more_than_capacity(ShenandoahGeneration* generation) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 09b985e3b8d..1f84feb20e8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -40,9 +40,9 @@ #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahRegulatorThread.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" +#include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahWorkerPolicy.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -#include "gc/shenandoah/shenandoahUtils.hpp" #include "logging/log.hpp" #include "utilities/events.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp index 230fff16252..a16a71b8175 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp @@ -22,8 +22,8 @@ * */ -#include "gc/shenandoah/shenandoahAgeCensus.hpp" #include "gc/shenandoah/heuristics/shenandoahGlobalHeuristics.hpp" +#include "gc/shenandoah/shenandoahAgeCensus.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGlobalGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp index d51a77fdf8f..5857170d4cc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp @@ -26,8 +26,8 @@ #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHGLOBALGENERATION_HPP #include "gc/shenandoah/shenandoahGeneration.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" // A "generation" that represents the whole heap. class ShenandoahGlobalGeneration : public ShenandoahGeneration { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 045f485090d..82c6cdb8971 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -27,7 +27,6 @@ #include "cds/archiveHeapWriter.hpp" #include "classfile/systemDictionary.hpp" - #include "gc/shared/classUnloadingContext.hpp" #include "gc/shared/fullGCForwarding.hpp" #include "gc/shared/gcArguments.hpp" @@ -37,24 +36,26 @@ #include "gc/shared/memAllocator.hpp" #include "gc/shared/plab.hpp" #include "gc/shared/tlab_globals.hpp" - #include "gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp" #include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" +#include "gc/shenandoah/mode/shenandoahGenerationalMode.hpp" +#include "gc/shenandoah/mode/shenandoahPassiveMode.hpp" +#include "gc/shenandoah/mode/shenandoahSATBMode.hpp" #include "gc/shenandoah/shenandoahAllocRequest.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" +#include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahCodeRoots.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahConcurrentMark.hpp" #include "gc/shenandoah/shenandoahControlThread.hpp" -#include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahGlobalGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" -#include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" +#include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahInitLogger.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" @@ -73,18 +74,9 @@ #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" #include "gc/shenandoah/shenandoahVMOperations.hpp" -#include "gc/shenandoah/shenandoahWorkGroup.hpp" #include "gc/shenandoah/shenandoahWorkerPolicy.hpp" +#include "gc/shenandoah/shenandoahWorkGroup.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -#include "gc/shenandoah/mode/shenandoahGenerationalMode.hpp" -#include "gc/shenandoah/mode/shenandoahPassiveMode.hpp" -#include "gc/shenandoah/mode/shenandoahSATBMode.hpp" - -#if INCLUDE_JFR -#include "gc/shenandoah/shenandoahJfrSupport.hpp" -#endif - -#include "memory/allocation.hpp" #include "memory/allocation.hpp" #include "memory/classLoaderMetaspace.hpp" #include "memory/memoryReserver.hpp" @@ -103,9 +95,12 @@ #include "runtime/stackWatermarkSet.hpp" #include "runtime/threads.hpp" #include "runtime/vmThread.hpp" -#include "utilities/globalDefinitions.hpp" #include "utilities/events.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/powerOfTwo.hpp" +#if INCLUDE_JFR +#include "gc/shenandoah/shenandoahJfrSupport.hpp" +#endif class ShenandoahPretouchHeapTask : public WorkerTask { private: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 46f8a134051..4f24b9e1abd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -27,19 +27,19 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHHEAP_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHHEAP_HPP +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/markBitMap.hpp" #include "gc/shared/softRefPolicy.hpp" -#include "gc/shared/collectedHeap.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahAllocRequest.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahController.hpp" -#include "gc/shenandoah/shenandoahLock.hpp" #include "gc/shenandoah/shenandoahEvacOOMHandler.hpp" #include "gc/shenandoah/shenandoahEvacTracker.hpp" -#include "gc/shenandoah/shenandoahGenerationType.hpp" #include "gc/shenandoah/shenandoahGenerationSizer.hpp" +#include "gc/shenandoah/shenandoahGenerationType.hpp" +#include "gc/shenandoah/shenandoahLock.hpp" #include "gc/shenandoah/shenandoahMmuTracker.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "gc/shenandoah/shenandoahUnload.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index f4ef186743c..cf9d808f7ce 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -30,28 +30,28 @@ #include "gc/shenandoah/shenandoahHeap.hpp" #include "classfile/javaClasses.inline.hpp" -#include "gc/shared/markBitMap.inline.hpp" -#include "gc/shared/threadLocalAllocBuffer.inline.hpp" #include "gc/shared/continuationGCSupport.inline.hpp" +#include "gc/shared/markBitMap.inline.hpp" #include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/shared/threadLocalAllocBuffer.inline.hpp" #include "gc/shared/tlab_globals.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" #include "gc/shenandoah/shenandoahForwarding.inline.hpp" -#include "gc/shenandoah/shenandoahWorkGroup.hpp" -#include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp" -#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" +#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" +#include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" +#include "gc/shenandoah/shenandoahWorkGroup.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/javaThread.hpp" -#include "runtime/prefetch.inline.hpp" #include "runtime/objectMonitor.inline.hpp" +#include "runtime/prefetch.inline.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index a25e2dfd88f..d00a99ee728 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -29,14 +29,14 @@ #include "gc/shared/tlab_globals.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" -#include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp" +#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" -#include "gc/shenandoah/shenandoahGeneration.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "jfr/jfrEvents.hpp" #include "memory/allocation.hpp" #include "memory/iterator.inline.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp index 7f29a8628aa..0df482c1e2d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp @@ -27,8 +27,9 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_INLINE_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_INLINE_HPP -#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" + +#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahPacer.inline.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp index 360c7d2d649..918e6bf1be6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp @@ -28,8 +28,8 @@ #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" -#include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahHeapRegionCounters.hpp" +#include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp index c139980af41..508b40e49a8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp @@ -26,8 +26,8 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGIONCOUNTERS_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGIONCOUNTERS_HPP -#include "memory/allocation.hpp" #include "logging/logFileStreamOutput.hpp" +#include "memory/allocation.hpp" /** * This provides the following in JVMStat: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.cpp index 46d54c70fe1..368738fe5ea 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.cpp @@ -23,9 +23,9 @@ * */ -#include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "runtime/atomic.hpp" #include "utilities/copy.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp index d933fda60b1..f81bf77d26e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp @@ -25,10 +25,10 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGIONSET_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGIONSET_HPP -#include "memory/allocation.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" +#include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" class ShenandoahHeapRegionSet; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp index b4ea327965b..b5e5e6fd698 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp @@ -24,11 +24,11 @@ * */ +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahInitLogger.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "logging/log.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp b/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp index 47a144a638f..fcfe0d1d5d6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahLock.cpp @@ -23,12 +23,11 @@ */ -#include "runtime/os.hpp" - #include "gc/shenandoah/shenandoahLock.hpp" #include "runtime/atomic.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaThread.hpp" +#include "runtime/os.hpp" #include "runtime/os.inline.hpp" void ShenandoahLock::contended_lock(bool allow_block_for_safepoint) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp index ae8d52a3d0e..4aef14f2c9a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp @@ -29,9 +29,9 @@ #include "gc/shared/ageTable.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/taskTerminator.hpp" +#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationType.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" -#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahTaskqueue.hpp" enum StringDedupMode { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp index 9986afc6f20..34e6af41b42 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp @@ -24,8 +24,8 @@ * */ -#include "gc/shenandoah/shenandoahMarkBitMap.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahMarkBitMap.inline.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 399db525cf9..0babeaffd3e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -27,7 +27,6 @@ #include "gc/shared/markBitMap.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.hpp" - #include "shenandoahGlobalGeneration.hpp" ShenandoahMarkingContext::ShenandoahMarkingContext(MemRegion heap_region, MemRegion bitmap_region, size_t num_regions) : diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp index d9bddd5fbb6..e3ba774283c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp @@ -28,6 +28,7 @@ #define SHARE_GC_SHENANDOAH_SHENANDOAHMARKINGCONTEXT_INLINE_HPP #include "gc/shenandoah/shenandoahMarkingContext.hpp" + #include "gc/shenandoah/shenandoahMarkBitMap.inline.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp index e9aa69b5555..ebfe5267160 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp @@ -25,8 +25,8 @@ */ #include "gc/shenandoah/shenandoahMemoryPool.hpp" -#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" ShenandoahMemoryPool::ShenandoahMemoryPool(ShenandoahHeap* heap, const char* name) : diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp index 32386e6aec0..edd4f875be4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp @@ -23,10 +23,10 @@ * */ -#include "gc/shenandoah/shenandoahMetrics.hpp" +#include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" -#include "gc/shenandoah/shenandoahFreeSet.hpp" +#include "gc/shenandoah/shenandoahMetrics.hpp" ShenandoahMetricsSnapshot::ShenandoahMetricsSnapshot() { _heap = ShenandoahHeap::heap(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp index 663864b1294..5867478d734 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp @@ -24,8 +24,8 @@ */ #include "gc/shenandoah/shenandoahAsserts.hpp" -#include "gc/shenandoah/shenandoahMmuTracker.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahMmuTracker.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp index 31265addda8..6b72cbdd62b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp @@ -25,9 +25,9 @@ #include "gc/shared/collectorCounters.hpp" #include "gc/shared/generationCounters.hpp" #include "gc/shared/hSpaceCounters.hpp" -#include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegionCounters.hpp" +#include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "memory/metaspaceCounters.hpp" #include "services/memoryService.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp index 7c28378bf24..1724fc2849f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp @@ -25,11 +25,11 @@ #include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" +#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahOldGC.hpp" -#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "prims/jvmtiTagMap.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index b0c42c7b40f..35d963f1801 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -26,6 +26,7 @@ #include "gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" +#include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" @@ -35,7 +36,6 @@ #include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" -#include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp index e16275b480a..62a25881b5a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp @@ -25,11 +25,11 @@ #include "gc/shared/workerDataArray.inline.hpp" -#include "gc/shenandoah/shenandoahCollectorPolicy.hpp" -#include "gc/shenandoah/shenandoahPhaseTimings.hpp" -#include "gc/shenandoah/shenandoahHeap.inline.hpp" -#include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/shenandoahCollectorPolicy.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahPhaseTimings.hpp" +#include "gc/shenandoah/shenandoahUtils.hpp" #include "runtime/orderAccess.hpp" #include "utilities/ostream.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index 9100ad2b220..0a456151318 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -26,9 +26,9 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHPHASETIMINGS_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHPHASETIMINGS_HPP -#include "jfr/jfrEvents.hpp" -#include "gc/shenandoah/shenandoahNumberSeq.hpp" #include "gc/shared/workerDataArray.hpp" +#include "gc/shenandoah/shenandoahNumberSeq.hpp" +#include "jfr/jfrEvents.hpp" #include "memory/allocation.hpp" class ShenandoahCollectorPolicy; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index 0e10e8c819f..2bbce179af8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -26,14 +26,14 @@ #include "classfile/javaClasses.hpp" #include "gc/shared/workerThread.hpp" -#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" +#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" -#include "runtime/atomic.hpp" #include "logging/log.hpp" +#include "runtime/atomic.hpp" static ReferenceType reference_type(oop reference) { return InstanceKlass::cast(reference->klass())->reference_type(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index b3b5109f6b3..8693046297d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -26,9 +26,9 @@ #include "classfile/classLoaderData.hpp" #include "code/nmethod.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" -#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" +#include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" #include "gc/shenandoah/shenandoahStackWatermark.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp index f1544c1762e..fa3fa90b2f5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp @@ -29,11 +29,11 @@ #include "classfile/classLoaderDataGraph.hpp" #include "gc/shared/oopStorageSetParState.inline.hpp" +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "memory/resourceArea.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp index 4c7ae68fdbe..11ff92cd9cc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp @@ -28,16 +28,16 @@ #include "classfile/classLoaderDataGraph.hpp" #include "code/codeCache.hpp" +#include "gc/shared/oopStorage.inline.hpp" +#include "gc/shared/oopStorageSet.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" -#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahRootVerifier.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" -#include "gc/shared/oopStorage.inline.hpp" -#include "gc/shared/oopStorageSet.hpp" #include "runtime/javaThread.hpp" #include "runtime/jniHandles.hpp" #include "runtime/threads.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp index 2984debd9f8..d2a5f71bca6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp @@ -26,8 +26,8 @@ #include "gc/shenandoah/shenandoahBarrierSetClone.inline.hpp" #include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -#include "runtime/interfaceSupport.inline.hpp" #include "oops/oop.inline.hpp" +#include "runtime/interfaceSupport.inline.hpp" #include "utilities/copy.hpp" JRT_LEAF(void, ShenandoahRuntime::arraycopy_barrier_oop(oop* src, oop* dst, size_t length)) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp index b0fc55631e0..68bec5c2071 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp @@ -26,18 +26,19 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHSCANREMEMBEREDINLINE_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHSCANREMEMBEREDINLINE_HPP -#include "memory/iterator.hpp" -#include "oops/oop.hpp" -#include "oops/objArrayOop.hpp" +#include "gc/shenandoah/shenandoahScanRemembered.hpp" + #include "gc/shared/collectorCounters.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahCardStats.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" -#include "gc/shenandoah/shenandoahScanRemembered.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "logging/log.hpp" +#include "memory/iterator.hpp" +#include "oops/objArrayOop.hpp" +#include "oops/oop.hpp" // Process all objects starting within count clusters beginning with first_cluster and for which the start address is // less than end_of_range. For any non-array object whose header lies on a dirty card, scan the entire object, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSimpleBitMap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahSimpleBitMap.hpp index 55d21b06e4b..3a4cb8cf742 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahSimpleBitMap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahSimpleBitMap.hpp @@ -25,10 +25,10 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHSIMPLEBITMAP_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHSIMPLEBITMAP_HPP -#include - #include "gc/shenandoah/shenandoahAsserts.hpp" +#include + // TODO: Merge the enhanced capabilities of ShenandoahSimpleBitMap into src/hotspot/share/utilities/bitMap.hpp // and deprecate ShenandoahSimpleBitMap. The key enhanced capabilities to be integrated include: // diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp index 042143254bc..1559dd81849 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStringDedup.inline.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHSTRINGDEDUP_INLINE_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHSTRINGDEDUP_INLINE_HPP +#include "gc/shenandoah/shenandoahStringDedup.hpp" + #include "classfile/javaClasses.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" -#include "gc/shenandoah/shenandoahStringDedup.hpp" #include "oops/markWord.hpp" bool ShenandoahStringDedup::is_string_candidate(oop obj) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp index 10887ad8c19..342b599caf5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp @@ -26,8 +26,8 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHTASKQUEUE_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHTASKQUEUE_HPP -#include "gc/shared/taskTerminator.hpp" #include "gc/shared/taskqueue.hpp" +#include "gc/shared/taskTerminator.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" #include "nmt/memTag.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp index 933cc501562..c1cebdf1dde 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp @@ -26,16 +26,16 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHTHREADLOCALDATA_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHTHREADLOCALDATA_HPP -#include "gc/shared/plab.hpp" -#include "gc/shared/gcThreadLocalData.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcThreadLocalData.hpp" +#include "gc/shared/plab.hpp" +#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahCardTable.hpp" #include "gc/shenandoah/shenandoahCodeRoots.hpp" -#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahEvacTracker.hpp" +#include "gc/shenandoah/shenandoahGenerationalHeap.hpp" #include "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp" -#include "gc/shenandoah/mode/shenandoahMode.hpp" #include "runtime/javaThread.hpp" #include "utilities/debug.hpp" #include "utilities/sizes.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp index 6bd50154b4f..83151313f75 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp @@ -29,11 +29,11 @@ #include "code/codeBehaviours.hpp" #include "code/codeCache.hpp" #include "code/dependencyContext.hpp" -#include "gc/shared/gcBehaviours.hpp" #include "gc/shared/classUnloadingContext.hpp" +#include "gc/shared/gcBehaviours.hpp" #include "gc/shared/suspendibleThreadSet.hpp" -#include "gc/shenandoah/shenandoahNMethod.inline.hpp" #include "gc/shenandoah/shenandoahLock.hpp" +#include "gc/shenandoah/shenandoahNMethod.inline.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahRootProcessor.hpp" #include "gc/shenandoah/shenandoahUnload.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp index ecca550d553..176baa133c8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp @@ -24,7 +24,6 @@ */ -#include "jfr/jfrEvents.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcWhen.hpp" @@ -36,6 +35,7 @@ #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" +#include "jfr/jfrEvents.hpp" #include "utilities/debug.hpp" ShenandoahPhaseTimings::Phase ShenandoahTimingsTracker::_current_phase = ShenandoahPhaseTimings::_invalid_phase; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp index fd30279d318..8a508c4afd8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp @@ -37,8 +37,8 @@ #include "jfr/jfrEvents.hpp" #include "memory/allocation.hpp" #include "runtime/safepoint.hpp" -#include "runtime/vmThread.hpp" #include "runtime/vmOperations.hpp" +#include "runtime/vmThread.hpp" #include "services/memoryService.hpp" class GCTimer; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 37951c311ed..cdf78485207 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -27,11 +27,11 @@ #include "gc/shared/tlab_globals.hpp" #include "gc/shenandoah/shenandoahAsserts.hpp" #include "gc/shenandoah/shenandoahForwarding.inline.hpp" -#include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" +#include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahRootProcessor.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp index d6c47339f28..f2431a5ad0a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp @@ -25,10 +25,9 @@ #include "gc/shenandoah/shenandoahHeap.inline.hpp" +#include "gc/shenandoah/shenandoahTaskqueue.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "gc/shenandoah/shenandoahWorkGroup.hpp" -#include "gc/shenandoah/shenandoahTaskqueue.hpp" - #include "logging/log.hpp" #include "runtime/threads.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp index 8663515d019..daf5d456af5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp @@ -22,13 +22,13 @@ * */ +#include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" #include "gc/shenandoah/shenandoahAgeCensus.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegionClosures.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -#include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" ShenandoahYoungGeneration::ShenandoahYoungGeneration(uint max_queues, size_t max_capacity, size_t soft_max_capacity) : ShenandoahGeneration(YOUNG, max_queues, max_capacity, soft_max_capacity), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp index 1237e28c06e..a8ebab507b6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHYOUNGGENERATION_HPP #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHYOUNGGENERATION_HPP -#include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp" +#include "gc/shenandoah/shenandoahGeneration.hpp" class ShenandoahYoungGeneration : public ShenandoahGeneration { private: diff --git a/src/hotspot/share/gc/shenandoah/vmStructs_shenandoah.hpp b/src/hotspot/share/gc/shenandoah/vmStructs_shenandoah.hpp index 851fa394722..a245f91fa71 100644 --- a/src/hotspot/share/gc/shenandoah/vmStructs_shenandoah.hpp +++ b/src/hotspot/share/gc/shenandoah/vmStructs_shenandoah.hpp @@ -24,9 +24,9 @@ #ifndef SHARE_GC_SHENANDOAH_VMSTRUCTS_SHENANDOAH_HPP #define SHARE_GC_SHENANDOAH_VMSTRUCTS_SHENANDOAH_HPP -#include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.hpp" +#include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" diff --git a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp index f3643c0a325..7bd24955910 100644 --- a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp +++ b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp @@ -21,12 +21,12 @@ * questions. */ +#include "c1/c1_CodeStubs.hpp" #include "c1/c1_FrameMap.hpp" #include "c1/c1_LIR.hpp" #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_LIRGenerator.hpp" #include "c1/c1_MacroAssembler.hpp" -#include "c1/c1_CodeStubs.hpp" #include "gc/z/c1/zBarrierSetC1.hpp" #include "gc/z/zBarrierSet.hpp" #include "gc/z/zBarrierSetAssembler.hpp" diff --git a/src/hotspot/share/gc/z/zHeapIterator.hpp b/src/hotspot/share/gc/z/zHeapIterator.hpp index fb58e3abe5f..2b570e98f1c 100644 --- a/src/hotspot/share/gc/z/zHeapIterator.hpp +++ b/src/hotspot/share/gc/z/zHeapIterator.hpp @@ -25,8 +25,8 @@ #define SHARE_GC_Z_ZHEAPITERATOR_HPP #include "gc/shared/collectedHeap.hpp" -#include "gc/shared/taskTerminator.hpp" #include "gc/shared/taskqueue.hpp" +#include "gc/shared/taskTerminator.hpp" #include "gc/z/zGranuleMap.hpp" #include "gc/z/zLock.hpp" #include "gc/z/zRootsIterator.hpp" diff --git a/src/hotspot/share/gc/z/zMarkContext.hpp b/src/hotspot/share/gc/z/zMarkContext.hpp index 009252e524d..788e17cae8f 100644 --- a/src/hotspot/share/gc/z/zMarkContext.hpp +++ b/src/hotspot/share/gc/z/zMarkContext.hpp @@ -24,8 +24,8 @@ #ifndef SHARE_GC_Z_ZMARKCONTEXT_HPP #define SHARE_GC_Z_ZMARKCONTEXT_HPP -#include "gc/z/zMarkCache.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" +#include "gc/z/zMarkCache.hpp" #include "memory/allocation.hpp" class ZMarkStripe; diff --git a/src/hotspot/share/gc/z/zMarkingSMR.hpp b/src/hotspot/share/gc/z/zMarkingSMR.hpp index a6c5afe76c9..26670d95959 100644 --- a/src/hotspot/share/gc/z/zMarkingSMR.hpp +++ b/src/hotspot/share/gc/z/zMarkingSMR.hpp @@ -26,8 +26,8 @@ #include "gc/z/zArray.hpp" #include "gc/z/zValue.hpp" -#include "utilities/globalDefinitions.hpp" #include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" class ZMarkStackListNode; diff --git a/src/hotspot/share/gc/z/zNMT.cpp b/src/hotspot/share/gc/z/zNMT.cpp index 76e164308dd..1019bcfdd96 100644 --- a/src/hotspot/share/gc/z/zNMT.cpp +++ b/src/hotspot/share/gc/z/zNMT.cpp @@ -24,9 +24,9 @@ #include "gc/z/zAddress.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zNMT.hpp" +#include "nmt/memoryFileTracker.hpp" #include "nmt/memTag.hpp" #include "nmt/memTracker.hpp" -#include "nmt/memoryFileTracker.hpp" #include "utilities/nativeCallStack.hpp" MemoryFileTracker::MemoryFile* ZNMT::_device = nullptr; diff --git a/src/hotspot/share/gc/z/zNMT.hpp b/src/hotspot/share/gc/z/zNMT.hpp index b5b1aa07870..5fea74ee8ae 100644 --- a/src/hotspot/share/gc/z/zNMT.hpp +++ b/src/hotspot/share/gc/z/zNMT.hpp @@ -27,8 +27,8 @@ #include "gc/z/zAddress.hpp" #include "gc/z/zGlobals.hpp" #include "memory/allStatic.hpp" -#include "nmt/memTracker.hpp" #include "nmt/memoryFileTracker.hpp" +#include "nmt/memTracker.hpp" #include "utilities/globalDefinitions.hpp" class ZNMT : public AllStatic { diff --git a/src/hotspot/share/gc/z/zNMethod.cpp b/src/hotspot/share/gc/z/zNMethod.cpp index 4ae440ea231..bf592c20fa2 100644 --- a/src/hotspot/share/gc/z/zNMethod.cpp +++ b/src/hotspot/share/gc/z/zNMethod.cpp @@ -22,8 +22,8 @@ */ #include "code/codeCache.hpp" -#include "code/relocInfo.hpp" #include "code/nmethod.hpp" +#include "code/relocInfo.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetNMethod.hpp" #include "gc/shared/classUnloadingContext.hpp" diff --git a/src/hotspot/share/gc/z/zNMethodTable.cpp b/src/hotspot/share/gc/z/zNMethodTable.cpp index 0aec0d5a9c7..bbc8f56b654 100644 --- a/src/hotspot/share/gc/z/zNMethodTable.cpp +++ b/src/hotspot/share/gc/z/zNMethodTable.cpp @@ -21,8 +21,8 @@ * questions. */ -#include "code/relocInfo.hpp" #include "code/nmethod.hpp" +#include "code/relocInfo.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetNMethod.hpp" #include "gc/z/zHash.inline.hpp" diff --git a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp index a4484ba1023..ddb0ca49278 100644 --- a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp +++ b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp @@ -21,8 +21,8 @@ * questions. */ -#include "gc/z/zThreadLocalData.hpp" #include "gc/z/zObjArrayAllocator.hpp" +#include "gc/z/zThreadLocalData.hpp" #include "gc/z/zUtils.inline.hpp" #include "oops/arrayKlass.hpp" #include "runtime/interfaceSupport.inline.hpp" diff --git a/src/hotspot/share/gc/z/zRuntimeWorkers.cpp b/src/hotspot/share/gc/z/zRuntimeWorkers.cpp index f19e5cd5469..c8c4cde9ba0 100644 --- a/src/hotspot/share/gc/z/zRuntimeWorkers.cpp +++ b/src/hotspot/share/gc/z/zRuntimeWorkers.cpp @@ -21,8 +21,8 @@ * questions. */ -#include "gc/shared/gcLogPrecious.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/gcLogPrecious.hpp" #include "gc/z/zRuntimeWorkers.hpp" #include "runtime/java.hpp" diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp index 558ccdf105a..a6b2bd0930d 100644 --- a/src/hotspot/share/gc/z/zStat.cpp +++ b/src/hotspot/share/gc/z/zStat.cpp @@ -24,9 +24,9 @@ #include "gc/shared/gc_globals.hpp" #include "gc/z/zAbort.inline.hpp" #include "gc/z/zCollectedHeap.hpp" +#include "gc/z/zCPU.inline.hpp" #include "gc/z/zDirector.hpp" #include "gc/z/zDriver.hpp" -#include "gc/z/zCPU.inline.hpp" #include "gc/z/zGeneration.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zNMethodTable.hpp" diff --git a/src/hotspot/share/gc/z/zUncoloredRoot.inline.hpp b/src/hotspot/share/gc/z/zUncoloredRoot.inline.hpp index f0b3dfcb42c..0d9fccde87c 100644 --- a/src/hotspot/share/gc/z/zUncoloredRoot.inline.hpp +++ b/src/hotspot/share/gc/z/zUncoloredRoot.inline.hpp @@ -27,9 +27,9 @@ #include "gc/z/zUncoloredRoot.hpp" #include "gc/z/zAddress.inline.hpp" +#include "gc/z/zBarrier.hpp" #include "gc/z/zBarrier.inline.hpp" #include "gc/z/zHeap.inline.hpp" -#include "gc/z/zBarrier.hpp" #include "oops/oop.hpp" template diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index 117d27997ee..68290c2c009 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -32,8 +32,8 @@ #include "gc/z/zResurrection.hpp" #include "gc/z/zRootsIterator.hpp" #include "gc/z/zStackWatermark.hpp" -#include "gc/z/zStoreBarrierBuffer.inline.hpp" #include "gc/z/zStat.hpp" +#include "gc/z/zStoreBarrierBuffer.inline.hpp" #include "gc/z/zVerify.hpp" #include "memory/allocation.hpp" #include "memory/iterator.inline.hpp" diff --git a/src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp b/src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp index 78f966d0f84..27159b4eff8 100644 --- a/src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp +++ b/src/hotspot/share/gc/z/zVirtualMemoryManager.inline.hpp @@ -26,8 +26,8 @@ #include "gc/z/zVirtualMemoryManager.hpp" -#include "utilities/globalDefinitions.hpp" #include "gc/z/zRangeRegistry.inline.hpp" +#include "utilities/globalDefinitions.hpp" inline bool ZVirtualMemoryManager::is_multi_partition_enabled() const { From 82c249446f2bd6f3b0e612c5ef3e6bfcab388c3b Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 23 Apr 2025 10:40:45 +0000 Subject: [PATCH 319/843] 8354228: Parallel: Set correct minimum of InitialSurvivorRatio Reviewed-by: tschatzl, gli --- .../share/gc/parallel/parallelArguments.cpp | 23 ++++++++++--------- src/hotspot/share/gc/shared/gc_globals.hpp | 2 +- .../TestMinAndInitialSurvivorRatioFlags.java | 2 -- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/gc/parallel/parallelArguments.cpp b/src/hotspot/share/gc/parallel/parallelArguments.cpp index 6309f52c82e..2cddbafd871 100644 --- a/src/hotspot/share/gc/parallel/parallelArguments.cpp +++ b/src/hotspot/share/gc/parallel/parallelArguments.cpp @@ -66,6 +66,18 @@ void ParallelArguments::initialize() { } } + if (InitialSurvivorRatio < MinSurvivorRatio) { + if (FLAG_IS_CMDLINE(InitialSurvivorRatio)) { + if (FLAG_IS_CMDLINE(MinSurvivorRatio)) { + jio_fprintf(defaultStream::error_stream(), + "Inconsistent MinSurvivorRatio vs InitialSurvivorRatio: %d vs %d\n", MinSurvivorRatio, InitialSurvivorRatio); + } + FLAG_SET_DEFAULT(MinSurvivorRatio, InitialSurvivorRatio); + } else { + FLAG_SET_DEFAULT(InitialSurvivorRatio, MinSurvivorRatio); + } + } + // If InitialSurvivorRatio or MinSurvivorRatio were not specified, but the // SurvivorRatio has been set, reset their default values to SurvivorRatio + // 2. By doing this we make SurvivorRatio also work for Parallel Scavenger. @@ -101,17 +113,6 @@ void ParallelArguments::initialize_alignments() { void ParallelArguments::initialize_heap_flags_and_sizes_one_pass() { // Do basic sizing work GenArguments::initialize_heap_flags_and_sizes(); - - // The survivor ratio's are calculated "raw", unlike the - // default gc, which adds 2 to the ratio value. We need to - // make sure the values are valid before using them. - if (MinSurvivorRatio < 3) { - FLAG_SET_ERGO(MinSurvivorRatio, 3); - } - - if (InitialSurvivorRatio < 3) { - FLAG_SET_ERGO(InitialSurvivorRatio, 3); - } } void ParallelArguments::initialize_heap_flags_and_sizes() { diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index ba29daf2fe1..56b8bc4e4ff 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -412,7 +412,7 @@ \ product(uintx, InitialSurvivorRatio, 8, \ "Initial ratio of young generation/survivor space size") \ - range(0, max_uintx) \ + range(3, max_uintx) \ \ product(bool, UseGCOverheadLimit, true, \ "Use policy to limit of proportion of time spent in GC " \ diff --git a/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java b/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java index 0e91f7f20ab..5f585575e7a 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java @@ -65,8 +65,6 @@ public class TestMinAndInitialSurvivorRatioFlags { testSurvivorRatio(-1, 15, 3, options, true); testSurvivorRatio(-1, 15, 3, options, false); testSurvivorRatio(-1, 10, 10, options, true); - testSurvivorRatio(-1, 3, 15, options, true); - testSurvivorRatio(-1, 3, 15, options, false); } /** From ef0cd1823d7d57e42e66255a0e80bfa495a7102d Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Wed, 23 Apr 2025 11:48:48 +0000 Subject: [PATCH 320/843] 8354949: JFR: Split up the EventInstrumentation class Reviewed-by: mgronlun, liach --- .../jdk/jfr/internal/ClassInspector.java | 361 ++++++++ .../jfr/internal/EventInstrumentation.java | 803 ++++++------------ .../classes/jdk/jfr/internal/JVMUpcalls.java | 16 +- .../jdk/jfr/internal/util/Bytecode.java | 9 +- .../jdk/jfr/internal/util/ImplicitFields.java | 5 +- 5 files changed, 643 insertions(+), 551 deletions(-) create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java new file mode 100644 index 00000000000..e7e0eac54ff --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.jfr.internal; + +import static jdk.jfr.internal.util.Bytecode.classDesc; + +import java.lang.classfile.Annotation; +import java.lang.classfile.AnnotationElement; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.Attribute; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.FieldModel; +import java.lang.classfile.MethodModel; +import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.constant.ConstantDescs; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import jdk.jfr.Enabled; +import jdk.jfr.Name; +import jdk.jfr.Registered; +import jdk.jfr.SettingControl; +import jdk.jfr.SettingDefinition; +import jdk.jfr.internal.util.Bytecode; +import jdk.jfr.internal.util.ImplicitFields; +import jdk.jfr.internal.util.Bytecode.FieldDesc; +import jdk.jfr.internal.util.Bytecode.MethodDesc; +import jdk.jfr.internal.util.Bytecode.SettingDesc; +import jdk.jfr.internal.util.Utils; + +final class ClassInspector { + private static final ClassDesc TYPE_SETTING_DEFINITION = Bytecode.classDesc(SettingDefinition.class); + private static final ClassDesc ANNOTATION_REGISTERED = classDesc(Registered.class); + private static final ClassDesc ANNOTATION_NAME = classDesc(Name.class); + private static final ClassDesc ANNOTATION_ENABLED = classDesc(Enabled.class); + private static final ClassDesc ANNOTATION_REMOVE_FIELDS = classDesc(RemoveFields.class); + + private final ClassModel classModel; + private final Class superClass; + private final boolean isJDK; + private final ImplicitFields implicitFields; + private final List settingsDescs = new ArrayList<>(); + private final List fieldDescs = new ArrayList<>(); + private final String className; + + ClassInspector(Class superClass, byte[] bytes, boolean isJDK) { + this.superClass = superClass; + this.classModel = ClassFile.of().parse(bytes); + this.isJDK = isJDK; + this.className = classModel.thisClass().asInternalName().replace("/", "."); + this.implicitFields = determineImplicitFields(); + } + + String getClassName() { + return className; + } + + MethodDesc findStaticCommitMethod() { + if (!isJDK) { + return null; + } + StringBuilder sb = new StringBuilder(); + sb.append("("); + for (FieldDesc field : fieldDescs) { + sb.append(field.type().descriptorString()); + } + sb.append(")V"); + MethodDesc m = MethodDesc.of("commit", sb.toString()); + for (MethodModel method : classModel.methods()) { + if (m.matches(method)) { + return m; + } + } + return null; + } + + String getEventName() { + String name = annotationValue(ANNOTATION_NAME, String.class); + return name == null ? getClassName() : name; + } + + boolean isRegistered() { + Boolean result = annotationValue(ANNOTATION_REGISTERED, Boolean.class); + if (result != null) { + return result.booleanValue(); + } + if (superClass != null) { + Registered r = superClass.getAnnotation(Registered.class); + if (r != null) { + return r.value(); + } + } + return true; + } + + boolean isEnabled() { + Boolean result = annotationValue(ANNOTATION_ENABLED, Boolean.class); + if (result != null) { + return result.booleanValue(); + } + if (superClass != null) { + Enabled e = superClass.getAnnotation(Enabled.class); + if (e != null) { + return e.value(); + } + } + return true; + } + + boolean hasStaticMethod(MethodDesc method) { + for (MethodModel m : classModel.methods()) { + if (Modifier.isStatic(m.flags().flagsMask())) { + return method.matches(m); + } + } + return false; + } + + static boolean isValidField(int access, ClassDesc classDesc) { + String className = classDesc.packageName(); + if (!className.isEmpty()) { + className = className + "."; + } + className += classDesc.displayName(); + return isValidField(access, className); + } + + static boolean isValidField(int access, String className) { + if (Modifier.isTransient(access) || Modifier.isStatic(access)) { + return false; + } + return Type.isValidJavaFieldType(className); + } + + List getSettings() { + return settingsDescs; + } + + List getFields() { + return fieldDescs; + } + + boolean hasDuration() { + return implicitFields.hasDuration(); + } + + boolean hasStackTrace() { + return implicitFields.hasStackTrace(); + } + + boolean hasEventThread() { + return implicitFields.hasEventThread(); + } + + ClassDesc getClassDesc() { + return classModel.thisClass().asSymbol(); + } + + ClassModel getClassModel() { + return classModel; + } + + boolean isJDK() { + return isJDK; + } + + private ImplicitFields determineImplicitFields() { + if (isJDK) { + Class eventClass = MirrorEvents.find(isJDK, getClassName()); + if (eventClass != null) { + return new ImplicitFields(eventClass); + } + } + ImplicitFields ifs = new ImplicitFields(superClass); + String[] value = annotationValue(ANNOTATION_REMOVE_FIELDS, String[].class); + if (value != null) { + ifs.removeFields(value); + } + return ifs; + } + + private List getAnnotationValues(ClassDesc classDesc) { + List list = new ArrayList<>(); + for (Attribute attribute: classModel.attributes()) { + if (attribute instanceof RuntimeVisibleAnnotationsAttribute rvaa) { + for (Annotation a : rvaa.annotations()) { + if (a.classSymbol().equals(classDesc) && a.elements().size() == 1) { + AnnotationElement ae = a.elements().getFirst(); + if (ae.name().equalsString("value")) { + list.add(ae.value()); + } + } + } + } + } + return list; + } + + @SuppressWarnings("unchecked") + // Only supports String, String[] and Boolean values + private T annotationValue(ClassDesc classDesc, Class type) { + for (AnnotationValue a : getAnnotationValues(classDesc)) { + if (a instanceof AnnotationValue.OfBoolean ofb && type.equals(Boolean.class)) { + Boolean b = ofb.booleanValue(); + return (T) b; + } + if (a instanceof AnnotationValue.OfString ofs && type.equals(String.class)) { + String s = ofs.stringValue(); + return (T) s; + } + if (a instanceof AnnotationValue.OfArray ofa && type.equals(String[].class)) { + List list = ofa.values(); + String[] array = new String[list.size()]; + int index = 0; + for (AnnotationValue av : list) { + var avs = (AnnotationValue.OfString) av; + array[index++] = avs.stringValue(); + } + return (T) array; + } + } + return null; + } + + void buildSettings() { + Set foundMethods = new HashSet<>(); + buildClassSettings(foundMethods); + buildSuperClassSettings(foundMethods); + } + + private void buildClassSettings(Set foundMethods) { + for (MethodModel m : classModel.methods()) { + for (Attribute attribute : m.attributes()) { + if (attribute instanceof RuntimeVisibleAnnotationsAttribute rvaa) { + for (Annotation a : rvaa.annotations()) { + // We can't really validate the method at this + // stage. We would need to check that the parameter + // is an instance of SettingControl. + if (a.classSymbol().equals(TYPE_SETTING_DEFINITION)) { + String name = m.methodName().stringValue(); + // Use @Name if it exists + for (Annotation nameCandidate : rvaa.annotations()) { + if (nameCandidate.className().equalsString(ANNOTATION_NAME.descriptorString())) { + if (nameCandidate.elements().size() == 1) { + AnnotationElement ae = nameCandidate.elements().getFirst(); + if (ae.name().equalsString("value")) { + if (ae.value() instanceof AnnotationValue.OfString s) { + name = Utils.validJavaIdentifier(s.stringValue(), name); + } + } + } + } + } + // Add setting if method returns boolean and has one parameter + MethodTypeDesc mtd = m.methodTypeSymbol(); + if (ConstantDescs.CD_boolean.equals(mtd.returnType())) { + if (mtd.parameterList().size() == 1) { + ClassDesc type = mtd.parameterList().getFirst(); + if (type.isClassOrInterface()) { + String methodName = m.methodName().stringValue(); + foundMethods.add(methodName); + settingsDescs.add(new SettingDesc(type, methodName)); + } + } + } + } + } + } + } + } + } + + private void buildSuperClassSettings(Set foundMethods) { + for (Class c = superClass; jdk.internal.event.Event.class != c; c = c.getSuperclass()) { + for (java.lang.reflect.Method method : c.getDeclaredMethods()) { + if (!foundMethods.contains(method.getName())) { + buildSettingsMethod(foundMethods, method); + } + } + } + } + + private void buildSettingsMethod(Set foundMethods, java.lang.reflect.Method method) { + // Skip private methods in base classes + if (!Modifier.isPrivate(method.getModifiers())) { + if (method.getReturnType().equals(Boolean.TYPE)) { + if (method.getParameterCount() == 1) { + Class type = method.getParameters()[0].getType(); + if (SettingControl.class.isAssignableFrom(type)) { + ClassDesc paramType = Bytecode.classDesc(type); + foundMethods.add(method.getName()); + settingsDescs.add(new SettingDesc(paramType, method.getName())); + } + } + } + } + } + + void buildFields() { + Set foundFields = new HashSet<>(); + // These two fields are added by native as 'transient' so they will be + // ignored by the loop below. + // The benefit of adding them manually is that we can + // control in which order they occur and we can add @Name, @Description + // in Java, instead of in native. It also means code for adding implicit + // fields for native can be reused by Java. + fieldDescs.add(ImplicitFields.FIELD_START_TIME); + if (implicitFields.hasDuration()) { + fieldDescs.add(ImplicitFields.FIELD_DURATION); + } + for (FieldModel field : classModel.fields()) { + if (!foundFields.contains(field.fieldName().stringValue()) && isValidField(field.flags().flagsMask(), field.fieldTypeSymbol())) { + fieldDescs.add(FieldDesc.of(field.fieldTypeSymbol(), field.fieldName().stringValue())); + foundFields.add(field.fieldName().stringValue()); + } + } + for (Class c = superClass; jdk.internal.event.Event.class != c; c = c.getSuperclass()) { + for (Field field : c.getDeclaredFields()) { + // Skip private fields in base classes + if (!Modifier.isPrivate(field.getModifiers())) { + if (isValidField(field.getModifiers(), field.getType().getName())) { + String fieldName = field.getName(); + if (!foundFields.contains(fieldName)) { + fieldDescs.add(FieldDesc.of(field.getType(), fieldName)); + foundFields.add(fieldName); + } + } + } + } + } + } +} 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 7567aea664c..96e6f36e5c8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -25,71 +25,49 @@ package jdk.jfr.internal; -import java.lang.constant.ClassDesc; -import java.lang.constant.MethodTypeDesc; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; +import static jdk.jfr.internal.util.Bytecode.classDesc; +import static jdk.jfr.internal.util.Bytecode.getfield; +import static jdk.jfr.internal.util.Bytecode.invokestatic; +import static jdk.jfr.internal.util.Bytecode.invokevirtual; +import static jdk.jfr.internal.util.Bytecode.putfield; -import java.lang.classfile.Annotation; -import java.lang.classfile.AnnotationElement; -import java.lang.classfile.AnnotationValue; +import java.lang.classfile.ClassBuilder; import java.lang.classfile.ClassElement; -import java.lang.classfile.ClassModel; import java.lang.classfile.ClassFile; import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeBuilder.BlockCodeBuilder; import java.lang.classfile.FieldModel; import java.lang.classfile.Label; import java.lang.classfile.MethodModel; +import java.lang.classfile.MethodTransform; import java.lang.classfile.TypeKind; -import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.util.List; +import java.util.function.Consumer; + +import jdk.jfr.Event; +import jdk.jfr.SettingControl; import jdk.jfr.internal.event.EventConfiguration; import jdk.jfr.internal.event.EventWriter; -import jdk.jfr.Enabled; -import jdk.jfr.Event; -import jdk.jfr.Name; -import jdk.jfr.Registered; -import jdk.jfr.SettingControl; -import jdk.jfr.SettingDefinition; -import jdk.jfr.internal.util.Utils; import jdk.jfr.internal.util.Bytecode; -import jdk.jfr.internal.util.ImplicitFields; import jdk.jfr.internal.util.Bytecode.FieldDesc; import jdk.jfr.internal.util.Bytecode.MethodDesc; -import static jdk.jfr.internal.util.Bytecode.invokevirtual; -import static jdk.jfr.internal.util.Bytecode.invokestatic; -import static jdk.jfr.internal.util.Bytecode.getfield; -import static jdk.jfr.internal.util.Bytecode.putfield; -import static jdk.jfr.internal.util.Bytecode.classDesc; +import jdk.jfr.internal.util.Bytecode.SettingDesc; +import jdk.jfr.internal.util.ImplicitFields; /** * Class responsible for adding instrumentation to a subclass of {@link Event}. * */ final class EventInstrumentation { + private static final FieldDesc FIELD_EVENT_CONFIGURATION = FieldDesc.of(Object.class, "eventConfiguration"); - private record SettingDesc(ClassDesc paramType, String methodName) { - } - - private static final FieldDesc FIELD_DURATION = FieldDesc.of(long.class, ImplicitFields.DURATION); - private static final FieldDesc FIELD_EVENT_CONFIGURATION = FieldDesc.of(Object.class, "eventConfiguration");; - private static final FieldDesc FIELD_START_TIME = FieldDesc.of(long.class, ImplicitFields.START_TIME); - private static final ClassDesc ANNOTATION_ENABLED = classDesc(Enabled.class); - private static final ClassDesc ANNOTATION_NAME = classDesc(Name.class); - private static final ClassDesc ANNOTATION_REGISTERED = classDesc(Registered.class); - private static final ClassDesc ANNOTATION_REMOVE_FIELDS = classDesc(RemoveFields.class); private static final ClassDesc TYPE_EVENT_CONFIGURATION = classDesc(EventConfiguration.class); - private static final ClassDesc TYPE_ISE = Bytecode.classDesc(IllegalStateException.class); + private static final ClassDesc TYPE_ISE = classDesc(IllegalStateException.class); private static final ClassDesc TYPE_EVENT_WRITER = classDesc(EventWriter.class); - private static final ClassDesc TYPE_OBJECT = Bytecode.classDesc(Object.class); - private static final ClassDesc TYPE_SETTING_DEFINITION = Bytecode.classDesc(SettingDefinition.class); + private static final ClassDesc TYPE_OBJECT = classDesc(Object.class); + private static final MethodDesc METHOD_BEGIN = MethodDesc.of("begin", "()V"); private static final MethodDesc METHOD_COMMIT = MethodDesc.of("commit", "()V"); private static final MethodDesc METHOD_DURATION = MethodDesc.of("duration", "(J)J"); @@ -104,301 +82,234 @@ final class EventInstrumentation { private static final MethodDesc METHOD_SHOULD_COMMIT_LONG = MethodDesc.of("shouldCommit", "(J)Z"); private static final MethodDesc METHOD_TIME_STAMP = MethodDesc.of("timestamp", "()J"); - private final ClassModel classModel; - private final List settingDescs; - private final List fieldDescs;; - private final String eventName; - private final String className; - private final Class superClass; - private final boolean untypedEventConfiguration; - private final MethodDesc staticCommitMethod; + private final ClassInspector inspector; private final long eventTypeId; + private final ClassDesc eventClassDesc; + private final MethodDesc staticCommitMethod; + private final boolean untypedEventConfiguration; private final boolean guardEventConfiguration; - private final boolean isJDK; - private final Map> methodUpdates = new LinkedHashMap<>(); - private final ImplicitFields implicitFields; - EventInstrumentation(Class superClass, byte[] bytes, long id, boolean isJDK, boolean guardEventConfiguration) { + /** + * Creates an EventInstrumentation object. + * + * @param inspector class inspector + * @param id the event type ID to use + * @param guardEventConfiguration guard against event configuration being null. + * Needed when instrumentation is added before + * registration (bytesForEagerInstrumentation) + */ + EventInstrumentation(ClassInspector inspector, long id, boolean guardEventConfiguration) { + inspector.buildFields(); + if (!inspector.isJDK()) { + // Only user-defined events have custom settings. + inspector.buildSettings(); + } + this.inspector = inspector; this.eventTypeId = id; - this.superClass = superClass; - this.isJDK = isJDK; - this.classModel = createClassModel(bytes); - this.className = classModel.thisClass().asInternalName().replace("/", "."); - String name = annotationValue(classModel, ANNOTATION_NAME, String.class); - this.eventName = name == null ? className : name; - this.implicitFields = determineImplicitFields(); - this.settingDescs = buildSettingDescs(superClass, classModel); - this.fieldDescs = buildFieldDescs(superClass, classModel); - this.staticCommitMethod = isJDK ? findStaticCommitMethod(classModel, fieldDescs) : null; - this.untypedEventConfiguration = hasUntypedConfiguration(); - // Corner case when we are forced to generate bytecode - // (bytesForEagerInstrumentation) - // We can't reference EventConfiguration::isEnabled() before event class has - // been registered, - // so we add a guard against a null reference. this.guardEventConfiguration = guardEventConfiguration; + this.eventClassDesc = inspector.getClassDesc(); + this.staticCommitMethod = inspector.findStaticCommitMethod(); + this.untypedEventConfiguration = hasUntypedConfiguration(); } - private ImplicitFields determineImplicitFields() { - if (isJDK) { - Class eventClass = MirrorEvents.find(isJDK, className); - if (eventClass != null) { - return new ImplicitFields(eventClass); + byte[] buildInstrumented() { + return ClassFile.of().transformClass(inspector.getClassModel(), this::transform); + } + + private void transform(ClassBuilder clb, ClassElement cle) { + if (cle instanceof MethodModel method && instrumentable(method) instanceof Consumer modification) { + clb.transformMethod(method, MethodTransform.transformingCode((codeBuilder, _) -> modification.accept(codeBuilder))); + } else { + clb.with(cle); + } + } + + private Consumer instrumentable(MethodModel method) { + if (isMethod(method, METHOD_IS_ENABLED)) { + return this::methodIsEnabled; + } + if (isMethod(method, METHOD_BEGIN)) { + return this::methodBegin; + } + if (isMethod(method, METHOD_END)) { + return this::methodEnd; + } + if (isMethod(method, METHOD_EVENT_SHOULD_COMMIT)) { + return this::methodShouldCommit; + } + if (staticCommitMethod == null && isMethod(method, METHOD_COMMIT)) { + return this::methodCommit; + } + if (inspector.isJDK() && isStatic(method)) { + if (isMethod(method, METHOD_ENABLED)) { + return this::methodEnabledStatic; } - } - ImplicitFields ifs = new ImplicitFields(superClass); - String[] value = annotationValue(classModel, ANNOTATION_REMOVE_FIELDS, String[].class); - if (value != null) { - ifs.removeFields(value); - } - return ifs; - } - - static MethodDesc findStaticCommitMethod(ClassModel classModel, List fields) { - StringBuilder sb = new StringBuilder(); - sb.append("("); - for (FieldDesc field : fields) { - sb.append(field.type().descriptorString()); - } - sb.append(")V"); - MethodDesc m = MethodDesc.of("commit", sb.toString()); - for (MethodModel method : classModel.methods()) { - String d = method.methodTypeSymbol().descriptorString(); - if (method.methodName().equalsString("commit") && m.descriptor().descriptorString().equals(d)) { - return m; + if (isMethod(method, METHOD_SHOULD_COMMIT_LONG)) { + return this::methodShouldCommitStatic; + } + if (isMethod(method, METHOD_TIME_STAMP)) { + return this::methodTimestamp; + } + if (staticCommitMethod != null && isMethod(method, staticCommitMethod)) { + return this::methodCommit; } } return null; } - private boolean hasUntypedConfiguration() { - for (FieldModel f : classModel.fields()) { - if (f.fieldName().equalsString(FIELD_EVENT_CONFIGURATION.name())) { - return f.fieldType().equalsString(TYPE_OBJECT.descriptorString()); - } - } - throw new InternalError("Class missing configuration field"); - } - - public String getClassName() { - return classModel.thisClass().asInternalName().replace("/", "."); - } - - private ClassModel createClassModel(byte[] bytes) { - return ClassFile.of().parse(bytes); - } - - boolean isRegistered() { - Boolean result = annotationValue(classModel, ANNOTATION_REGISTERED, Boolean.class); - if (result != null) { - return result.booleanValue(); - } - if (superClass != null) { - Registered r = superClass.getAnnotation(Registered.class); - if (r != null) { - return r.value(); - } - } - return true; - } - - boolean isEnabled() { - Boolean result = annotationValue(classModel, ANNOTATION_ENABLED, Boolean.class); - if (result != null) { - return result.booleanValue(); - } - if (superClass != null) { - Enabled e = superClass.getAnnotation(Enabled.class); - if (e != null) { - return e.value(); - } - } - return true; - } - - @SuppressWarnings("unchecked") - // Only supports String, String[] and Boolean values - private static T annotationValue(ClassModel classModel, ClassDesc classDesc, Class type) { - String typeDescriptor = classDesc.descriptorString(); - for (ClassElement ce : classModel) { - if (ce instanceof RuntimeVisibleAnnotationsAttribute rvaa) { - for (Annotation a : rvaa.annotations()) { - if (a.className().equalsString(typeDescriptor)) { - if (a.elements().size() == 1) { - AnnotationElement ae = a.elements().getFirst(); - if (ae.name().equalsString("value")) { - if (ae.value() instanceof AnnotationValue.OfBoolean ofb && type.equals(Boolean.class)) { - Boolean b = ofb.booleanValue(); - return (T)b; - } - if (ae.value() instanceof AnnotationValue.OfString ofs && type.equals(String.class)) { - String s = ofs.stringValue(); - return (T)s; - } - if (ae.value() instanceof AnnotationValue.OfArray ofa && type.equals(String[].class)) { - List list = ofa.values(); - String[] array = new String[list.size()]; - int index = 0; - for (AnnotationValue av : list) { - var avs = (AnnotationValue.OfString)av; - array[index++] = avs.stringValue(); - } - return (T)array; - } - } - } - } - } - } - } - return null; - } - - private static List buildSettingDescs(Class superClass, ClassModel classModel) { - Set methodSet = new HashSet<>(); - List settingDescs = new ArrayList<>(); - for (MethodModel m : classModel.methods()) { - for (var me : m) { - if (me instanceof RuntimeVisibleAnnotationsAttribute rvaa) { - for (Annotation a : rvaa.annotations()) { - // We can't really validate the method at this - // stage. We would need to check that the parameter - // is an instance of SettingControl. - if (a.className().equalsString(TYPE_SETTING_DEFINITION.descriptorString())) { - String name = m.methodName().stringValue(); - // Use @Name if it exists - for (Annotation nameCandidate : rvaa.annotations()) { - if (nameCandidate.className().equalsString(ANNOTATION_NAME.descriptorString())) { - if (nameCandidate.elements().size() == 1) { - AnnotationElement ae = nameCandidate.elements().getFirst(); - if (ae.name().equalsString("value")) { - if (ae.value() instanceof AnnotationValue.OfString s) { - name = Utils.validJavaIdentifier(s.stringValue(), name); - } - } - } - } - } - // Add setting if method returns boolean and has one parameter - MethodTypeDesc mtd = m.methodTypeSymbol(); - if ("Z".equals(mtd.returnType().descriptorString())) { - if (mtd.parameterList().size() == 1) { - ClassDesc type = mtd.parameterList().getFirst(); - if (type.isClassOrInterface()) { - String methodName = m.methodName().stringValue(); - methodSet.add(methodName); - settingDescs.add(new SettingDesc(type, methodName)); - } - } - } - } - } - } - } - } - for (Class c = superClass; jdk.internal.event.Event.class != c; c = c.getSuperclass()) { - for (java.lang.reflect.Method method : c.getDeclaredMethods()) { - if (!methodSet.contains(method.getName())) { - // skip private method in base classes - if (!Modifier.isPrivate(method.getModifiers())) { - if (method.getReturnType().equals(Boolean.TYPE)) { - if (method.getParameterCount() == 1) { - Class type = method.getParameters()[0].getType(); - if (SettingControl.class.isAssignableFrom(type)) { - ClassDesc paramType = Bytecode.classDesc(type); - methodSet.add(method.getName()); - settingDescs.add(new SettingDesc(paramType, method.getName())); - } - } - } - } - } - } - } - return settingDescs; - } - - private List buildFieldDescs(Class superClass, ClassModel classModel) { - Set fieldSet = new HashSet<>(); - List fieldDescs = new ArrayList<>(classModel.fields().size()); - // These two fields are added by native as 'transient' so they will be - // ignored by the loop below. - // The benefit of adding them manually is that we can - // control in which order they occur and we can add @Name, @Description - // in Java, instead of in native. It also means code for adding implicit - // fields for native can be reused by Java. - fieldDescs.add(FIELD_START_TIME); - if (implicitFields.hasDuration()) { - fieldDescs.add(FIELD_DURATION); - } - for (FieldModel field : classModel.fields()) { - if (!fieldSet.contains(field.fieldName().stringValue()) && isValidField(field.flags().flagsMask(), field.fieldTypeSymbol())) { - FieldDesc fi = FieldDesc.of(field.fieldTypeSymbol(), field.fieldName().stringValue()); - fieldDescs.add(fi); - fieldSet.add(field.fieldName().stringValue()); - } - } - for (Class c = superClass; jdk.internal.event.Event.class != c; c = c.getSuperclass()) { - for (Field field : c.getDeclaredFields()) { - // skip private field in base classes - if (!Modifier.isPrivate(field.getModifiers())) { - if (isValidField(field.getModifiers(), field.getType().getName())) { - String fieldName = field.getName(); - if (!fieldSet.contains(fieldName)) { - fieldDescs.add(FieldDesc.of(field.getType(), fieldName)); - fieldSet.add(fieldName); - } - } - } - } - } - return fieldDescs; - } - - public static boolean isValidField(int access, ClassDesc classDesc) { - String className = classDesc.packageName(); - if (!className.isEmpty()) { - className = className + "."; - } - className += classDesc.displayName(); - return isValidField(access, className); - } - - public static boolean isValidField(int access, String className) { - if (Modifier.isTransient(access) || Modifier.isStatic(access)) { - return false; - } - return Type.isValidJavaFieldType(className); - } - - public byte[] buildInstrumented() { - makeInstrumented(); - return toByteArray(); - } - - byte[] toByteArray() { - return ClassFile.of().build(classModel.thisClass().asSymbol(), classBuilder -> { - for (ClassElement ce : classModel) { - boolean updated = false; - if (ce instanceof MethodModel method) { - Consumer methodUpdate = findMethodUpdate(method); - if (methodUpdate != null) { - classBuilder.withMethod(method.methodName().stringValue(), method.methodTypeSymbol(), method.flags().flagsMask(), methodBuilder -> { - methodBuilder.withCode(methodUpdate); - }); - updated = true; - } - } - if (!updated) { - classBuilder.with(ce); - } + private void methodIsEnabled(CodeBuilder codeBuilder) { + Label nullLabel = codeBuilder.newLabel(); + if (guardEventConfiguration) { + getEventConfiguration(codeBuilder); + codeBuilder.ifnull(nullLabel); + } + getEventConfiguration(codeBuilder); + invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_IS_ENABLED); + codeBuilder.ireturn(); + if (guardEventConfiguration) { + codeBuilder.labelBinding(nullLabel); + codeBuilder.iconst_0(); + codeBuilder.ireturn(); + } + } + + private void methodBegin(CodeBuilder codeBuilder) { + if (!inspector.hasDuration()) { + throwMissingDuration(codeBuilder, "begin"); + } else { + codeBuilder.aload(0); + invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_TIME_STAMP); + putfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_START_TIME); + codeBuilder.return_(); + } + } + + private void methodEnd(CodeBuilder codeBuilder) { + if (!inspector.hasDuration()) { + throwMissingDuration(codeBuilder, "end"); + } else { + codeBuilder.aload(0); + codeBuilder.aload(0); + getfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_START_TIME); + invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_DURATION); + putfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION); + codeBuilder.return_(); + } + } + + private void methodShouldCommit(CodeBuilder codeBuilder) { + Label fail = codeBuilder.newLabel(); + if (guardEventConfiguration) { + getEventConfiguration(codeBuilder); + codeBuilder.ifnull(fail); + } + // if (!eventConfiguration.shouldCommit(duration) goto fail; + getEventConfiguration(codeBuilder); + codeBuilder.aload(0); + getfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION); + invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT); + codeBuilder.ifeq(fail); + List settingDescs = inspector.getSettings(); + for (int index = 0; index < settingDescs.size(); index++) { + SettingDesc sd = settingDescs.get(index); + // if (!settingsMethod(eventConfiguration.settingX)) goto fail; + codeBuilder.aload(0); + getEventConfiguration(codeBuilder); + codeBuilder.loadConstant(index); + invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_GET_SETTING); + MethodTypeDesc mdesc = MethodTypeDesc.ofDescriptor("(" + sd.paramType().descriptorString() + ")Z"); + codeBuilder.checkcast(sd.paramType()); + codeBuilder.invokevirtual(eventClassDesc, sd.methodName(), mdesc); + codeBuilder.ifeq(fail); + } + // return true + codeBuilder.iconst_1(); + codeBuilder.ireturn(); + // return false + codeBuilder.labelBinding(fail); + codeBuilder.iconst_0(); + codeBuilder.ireturn(); + } + + private void methodCommit(CodeBuilder codeBuilder) { + Label excluded = codeBuilder.newLabel(); + Label end = codeBuilder.newLabel(); + codeBuilder.trying(blockCodeBuilder -> { + if (staticCommitMethod != null) { + updateStaticCommit(blockCodeBuilder, excluded); + } else { + updateInstanceCommit(blockCodeBuilder, end, excluded); } + // stack: [integer] + // notified -> restart event write attempt + blockCodeBuilder.ifeq(blockCodeBuilder.startLabel()); + // stack: [] + blockCodeBuilder.goto_(end); + }, catchBuilder -> { + catchBuilder.catchingAll(catchAllHandler -> { + getEventWriter(catchAllHandler); + // stack: [ex] [EW] + catchAllHandler.dup(); + // stack: [ex] [EW] [EW] + Label rethrow = catchAllHandler.newLabel(); + catchAllHandler.ifnull(rethrow); + // stack: [ex] [EW] + catchAllHandler.dup(); + // stack: [ex] [EW] [EW] + invokevirtual(catchAllHandler, TYPE_EVENT_WRITER, METHOD_RESET); + catchAllHandler.labelBinding(rethrow); + // stack:[ex] [EW] + catchAllHandler.pop(); + // stack:[ex] + catchAllHandler.athrow(); + }); }); + codeBuilder.labelBinding(excluded); + // stack: [EW] + codeBuilder.pop(); + codeBuilder.labelBinding(end); + // stack: [] + codeBuilder.return_(); } - public byte[] buildUninstrumented() { - makeUninstrumented(); - return toByteArray(); + private void methodEnabledStatic(CodeBuilder codeBuilder) { + Label nullLabel = codeBuilder.newLabel(); + if (guardEventConfiguration) { + getEventConfiguration(codeBuilder); + codeBuilder.ifnull(nullLabel); + } + getEventConfiguration(codeBuilder); + invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_IS_ENABLED); + codeBuilder.ireturn(); + if (guardEventConfiguration) { + codeBuilder.labelBinding(nullLabel); + codeBuilder.iconst_0(); + codeBuilder.ireturn(); + } + } + + private void methodTimestamp(CodeBuilder codeBuilder) { + invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_TIME_STAMP); + codeBuilder.lreturn(); + } + + private void methodShouldCommitStatic(CodeBuilder codeBuilder) { + Label fail = codeBuilder.newLabel(); + if (guardEventConfiguration) { + // if (eventConfiguration == null) goto fail; + getEventConfiguration(codeBuilder); + codeBuilder.ifnull(fail); + } + // return eventConfiguration.shouldCommit(duration); + getEventConfiguration(codeBuilder); + codeBuilder.lload(0); + codeBuilder.invokevirtual(TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT.name(), METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT.descriptor()); + codeBuilder.ireturn(); + // fail: + codeBuilder.labelBinding(fail); + // return false + codeBuilder.iconst_0(); + codeBuilder.ireturn(); } private void throwMissingDuration(CodeBuilder codeBuilder, String method) { @@ -406,144 +317,7 @@ final class EventInstrumentation { Bytecode.throwException(codeBuilder, TYPE_ISE, message); } - private void makeInstrumented() { - // MyEvent#isEnabled() - updateEnabledMethod(METHOD_IS_ENABLED); - - // MyEvent#begin() - updateMethod(METHOD_BEGIN, codeBuilder -> { - if (!implicitFields.hasDuration()) { - throwMissingDuration(codeBuilder, "begin"); - } else { - codeBuilder.aload(0); - invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_TIME_STAMP); - putfield(codeBuilder, getEventClassDesc(), FIELD_START_TIME); - codeBuilder.return_(); - } - }); - - // MyEvent#end() - updateMethod(METHOD_END, codeBuilder -> { - if (!implicitFields.hasDuration()) { - throwMissingDuration(codeBuilder, "end"); - } else { - codeBuilder.aload(0); - codeBuilder.aload(0); - getfield(codeBuilder, getEventClassDesc(), FIELD_START_TIME); - invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_DURATION); - putfield(codeBuilder, getEventClassDesc(), FIELD_DURATION); - codeBuilder.return_(); - } - }); - - // MyEvent#commit() or static MyEvent#commit(...) - MethodDesc m = staticCommitMethod == null ? METHOD_COMMIT : staticCommitMethod; - updateMethod(m, codeBuilder -> { - Label excluded = codeBuilder.newLabel(); - Label end = codeBuilder.newLabel(); - codeBuilder.trying(blockCodeBuilder -> { - if (staticCommitMethod != null) { - updateStaticCommit(blockCodeBuilder, excluded); - } else { - updateInstanceCommit(blockCodeBuilder, end, excluded); - } - // stack: [integer] - // notified -> restart event write attempt - blockCodeBuilder.ifeq(blockCodeBuilder.startLabel()); - // stack: [] - blockCodeBuilder.goto_(end); - }, catchBuilder -> { - catchBuilder.catchingAll(catchAllHandler -> { - getEventWriter(catchAllHandler); - // stack: [ex] [EW] - catchAllHandler.dup(); - // stack: [ex] [EW] [EW] - Label rethrow = catchAllHandler.newLabel(); - catchAllHandler.ifnull(rethrow); - // stack: [ex] [EW] - catchAllHandler.dup(); - // stack: [ex] [EW] [EW] - invokevirtual(catchAllHandler, TYPE_EVENT_WRITER, METHOD_RESET); - catchAllHandler.labelBinding(rethrow); - // stack:[ex] [EW] - catchAllHandler.pop(); - // stack:[ex] - catchAllHandler.athrow(); - }); - }); - codeBuilder.labelBinding(excluded); - // stack: [EW] - codeBuilder.pop(); - codeBuilder.labelBinding(end); - // stack: [] - codeBuilder.return_(); - }); - - // MyEvent#shouldCommit() - updateMethod(METHOD_EVENT_SHOULD_COMMIT, codeBuilder -> { - Label fail = codeBuilder.newLabel(); - if (guardEventConfiguration) { - getEventConfiguration(codeBuilder); - codeBuilder.ifnull(fail); - } - // if (!eventConfiguration.shouldCommit(duration) goto fail; - getEventConfiguration(codeBuilder); - codeBuilder.aload(0); - getfield(codeBuilder, getEventClassDesc(), FIELD_DURATION); - invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT); - codeBuilder.ifeq(fail); - for (int index = 0; index < settingDescs.size(); index++) { - SettingDesc sd = settingDescs.get(index); - // if (!settingsMethod(eventConfiguration.settingX)) goto fail; - codeBuilder.aload(0); - getEventConfiguration(codeBuilder); - codeBuilder.loadConstant(index); - invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_GET_SETTING); - MethodTypeDesc mdesc = MethodTypeDesc.ofDescriptor("(" + sd.paramType().descriptorString() + ")Z"); - codeBuilder.checkcast(sd.paramType()); - codeBuilder.invokevirtual(getEventClassDesc(), sd.methodName(), mdesc); - codeBuilder.ifeq(fail); - } - // return true - codeBuilder.iconst_1(); - codeBuilder.ireturn(); - // return false - codeBuilder.labelBinding(fail); - codeBuilder.iconst_0(); - codeBuilder.ireturn(); - }); - - if (isJDK) { - if (hasStaticMethod(METHOD_ENABLED)) { - updateEnabledMethod(METHOD_ENABLED); - } - - updateIfStaticMethodExists(METHOD_SHOULD_COMMIT_LONG, codeBuilder -> { - Label fail = codeBuilder.newLabel(); - if (guardEventConfiguration) { - // if (eventConfiguration == null) goto fail; - getEventConfiguration(codeBuilder); - codeBuilder.ifnull(fail); - } - // return eventConfiguration.shouldCommit(duration); - getEventConfiguration(codeBuilder); - codeBuilder.lload(0); - codeBuilder.invokevirtual(TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT.name(), METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT.descriptor()); - codeBuilder.ireturn(); - // fail: - codeBuilder.labelBinding(fail); - // return false - codeBuilder.iconst_0(); - codeBuilder.ireturn(); - }); - updateIfStaticMethodExists(METHOD_TIME_STAMP, codeBuilder -> { - invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_TIME_STAMP); - codeBuilder.lreturn(); - }); - } - } - - void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) { + private void updateStaticCommit(BlockCodeBuilder blockCodeBuilder, Label excluded) { // indexes the argument type array, the argument type array does not include // 'this' int argIndex = 0; @@ -576,7 +350,7 @@ final class EventInstrumentation { invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.method()); fieldIndex++; // stack: [EW] - if (implicitFields.hasDuration()) { + if (inspector.hasDuration()) { // write duration blockCodeBuilder.dup(); // stack: [EW], [EW] @@ -588,14 +362,14 @@ final class EventInstrumentation { fieldIndex++; } // stack: [EW] - if (implicitFields.hasEventThread()) { + if (inspector.hasEventThread()) { // write eventThread blockCodeBuilder.dup(); // stack: [EW], [EW] invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_EVENT_THREAD.method()); } // stack: [EW] - if (implicitFields.hasStackTrace()) { + if (inspector.hasStackTrace()) { // write stackTrace blockCodeBuilder.dup(); // stack: [EW], [EW] @@ -603,6 +377,7 @@ final class EventInstrumentation { } // stack: [EW] // write custom fields + List fieldDescs = inspector.getFields(); while (fieldIndex < fieldDescs.size()) { blockCodeBuilder.dup(); // stack: [EW], [EW] @@ -622,19 +397,19 @@ final class EventInstrumentation { // stack: [int] } - void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end, Label excluded) { + private void updateInstanceCommit(BlockCodeBuilder blockCodeBuilder, Label end, Label excluded) { // if (!isEnable()) { // return; // } blockCodeBuilder.aload(0); - invokevirtual(blockCodeBuilder, getEventClassDesc(), METHOD_IS_ENABLED); + invokevirtual(blockCodeBuilder, eventClassDesc, METHOD_IS_ENABLED); Label l0 = blockCodeBuilder.newLabel(); blockCodeBuilder.ifne(l0); blockCodeBuilder.return_(); blockCodeBuilder.labelBinding(l0); // long startTime = this.startTime blockCodeBuilder.aload(0); - getfield(blockCodeBuilder, getEventClassDesc(), FIELD_START_TIME); + getfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_START_TIME); blockCodeBuilder.lstore(1); // if (startTime == 0) { // startTime = EventWriter.timestamp(); @@ -654,7 +429,7 @@ final class EventInstrumentation { // } blockCodeBuilder.labelBinding(durationEvent); blockCodeBuilder.aload(0); - getfield(blockCodeBuilder, getEventClassDesc(), FIELD_DURATION); + getfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION); blockCodeBuilder.lconst_0(); blockCodeBuilder.lcmp(); blockCodeBuilder.ifne(commit); @@ -662,11 +437,11 @@ final class EventInstrumentation { invokestatic(blockCodeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_TIME_STAMP); blockCodeBuilder.lload(1); blockCodeBuilder.lsub(); - putfield(blockCodeBuilder, getEventClassDesc(), FIELD_DURATION); + putfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION); blockCodeBuilder.labelBinding(commit); // if (shouldCommit()) { blockCodeBuilder.aload(0); - invokevirtual(blockCodeBuilder, getEventClassDesc(), METHOD_EVENT_SHOULD_COMMIT); + invokevirtual(blockCodeBuilder, eventClassDesc, METHOD_EVENT_SHOULD_COMMIT); blockCodeBuilder.ifeq(end); getEventWriter(blockCodeBuilder); // stack: [EW] @@ -687,39 +462,40 @@ final class EventInstrumentation { invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.method()); fieldIndex++; // stack: [EW] - if (implicitFields.hasDuration()) { + if (inspector.hasDuration()) { // write duration blockCodeBuilder.dup(); // stack: [EW] [EW] blockCodeBuilder.aload(0); // stack: [EW] [EW] [this] - getfield(blockCodeBuilder, getEventClassDesc(), FIELD_DURATION); + getfield(blockCodeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION); // stack: [EW] [EW] [long] invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.method()); fieldIndex++; } // stack: [EW] - if (implicitFields.hasEventThread()) { + if (inspector.hasEventThread()) { // write eventThread blockCodeBuilder.dup(); // stack: [EW] [EW] invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_EVENT_THREAD.method()); } // stack: [EW] - if (implicitFields.hasStackTrace()) { + if (inspector.hasStackTrace()) { // write stack trace blockCodeBuilder.dup(); // stack: [EW] [EW] invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, EventWriterMethod.PUT_STACK_TRACE.method()); } // stack: [EW] + List fieldDescs = inspector.getFields(); while (fieldIndex < fieldDescs.size()) { FieldDesc field = fieldDescs.get(fieldIndex); blockCodeBuilder.dup(); // stack: [EW] [EW] blockCodeBuilder.aload(0); // stack: [EW] [EW] [this] - getfield(blockCodeBuilder, getEventClassDesc(), field); + getfield(blockCodeBuilder, eventClassDesc, field); // stack: [EW] [EW] EventWriterMethod eventMethod = EventWriterMethod.lookupMethod(field); invokevirtual(blockCodeBuilder, TYPE_EVENT_WRITER, eventMethod.method()); @@ -731,90 +507,33 @@ final class EventInstrumentation { // stack:[int] } - private void updateEnabledMethod(MethodDesc method) { - updateMethod(method, codeBuilder -> { - Label nullLabel = codeBuilder.newLabel(); - if (guardEventConfiguration) { - getEventConfiguration(codeBuilder); - codeBuilder.ifnull(nullLabel); - } - getEventConfiguration(codeBuilder); - invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_IS_ENABLED); - codeBuilder.ireturn(); - if (guardEventConfiguration) { - codeBuilder.labelBinding(nullLabel); - codeBuilder.iconst_0(); - codeBuilder.ireturn(); - } - }); + private static boolean isStatic(MethodModel method) { + return (method.flags().flagsMask() & ClassFile.ACC_STATIC) != 0; } - private void updateIfStaticMethodExists(MethodDesc method, Consumer code) { - if (hasStaticMethod(method)) { - updateMethod(method, code); - } + private static boolean isMethod(MethodModel m, MethodDesc desc) { + return desc.matches(m); } - private boolean hasStaticMethod(MethodDesc method) { - for (MethodModel m : classModel.methods()) { - if (m.methodName().equalsString(method.name()) && m.methodTypeSymbol().equals(method.descriptor())) { - return Modifier.isStatic(m.flags().flagsMask()); - } - } - return false; - } - - private void getEventWriter(CodeBuilder codeBuilder) { + private static void getEventWriter(CodeBuilder codeBuilder) { invokestatic(codeBuilder, TYPE_EVENT_WRITER, METHOD_GET_EVENT_WRITER); } private void getEventConfiguration(CodeBuilder codeBuilder) { if (untypedEventConfiguration) { - codeBuilder.getstatic(getEventClassDesc(), FIELD_EVENT_CONFIGURATION.name(), TYPE_OBJECT); + codeBuilder.getstatic(eventClassDesc, FIELD_EVENT_CONFIGURATION.name(), TYPE_OBJECT); codeBuilder.checkcast(TYPE_EVENT_CONFIGURATION); } else { - codeBuilder.getstatic(getEventClassDesc(), FIELD_EVENT_CONFIGURATION.name(), TYPE_EVENT_CONFIGURATION); + codeBuilder.getstatic(eventClassDesc, FIELD_EVENT_CONFIGURATION.name(), TYPE_EVENT_CONFIGURATION); } } - private void makeUninstrumented() { - updateExistingWithReturnFalse(METHOD_EVENT_SHOULD_COMMIT); - updateExistingWithReturnFalse(METHOD_IS_ENABLED); - updateExistingWithEmptyVoidMethod(METHOD_COMMIT); - if (staticCommitMethod != null) { - updateExistingWithEmptyVoidMethod(staticCommitMethod); + private boolean hasUntypedConfiguration() { + for (FieldModel f : inspector.getClassModel().fields()) { + if (f.fieldName().equalsString(FIELD_EVENT_CONFIGURATION.name())) { + return f.fieldType().equalsString(TYPE_OBJECT.descriptorString()); + } } - updateExistingWithEmptyVoidMethod(METHOD_BEGIN); - updateExistingWithEmptyVoidMethod(METHOD_END); - } - - private final void updateExistingWithEmptyVoidMethod(MethodDesc voidMethod) { - updateMethod(voidMethod, codeBuilder -> { - codeBuilder.return_(); - }); - } - - private final void updateExistingWithReturnFalse(MethodDesc voidMethod) { - updateMethod(voidMethod, codeBuilder -> { - codeBuilder.iconst_0(); - codeBuilder.ireturn(); - }); - } - - private Consumer findMethodUpdate(MethodModel mm) { - MethodDesc m = MethodDesc.of(mm.methodName().stringValue(), mm.methodType().stringValue()); - return methodUpdates.get(m); - } - - private void updateMethod(MethodDesc method, Consumer codeBuilder) { - methodUpdates.put(method, codeBuilder); - } - - private ClassDesc getEventClassDesc() { - return classModel.thisClass().asSymbol(); - } - - public String getEventName() { - return eventName; + throw new InternalError("Class missing configuration field"); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java index 36dc2259be9..18b76cc3ff9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java @@ -72,7 +72,8 @@ final class JVMUpcalls { } boolean jdkClass = Utils.isJDKClass(clazz); Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Adding instrumentation to event class " + clazz.getName() + " using retransform"); - EventInstrumentation ei = new EventInstrumentation(clazz.getSuperclass(), oldBytes, traceId, jdkClass, false); + ClassInspector c = new ClassInspector(clazz.getSuperclass(), oldBytes, jdkClass); + EventInstrumentation ei = new EventInstrumentation(c, traceId, false); byte[] bytes = ei.buildInstrumented(); Bytecode.log(clazz.getName(), bytes); return bytes; @@ -105,9 +106,9 @@ final class JVMUpcalls { } String eventName = ""; try { - EventInstrumentation ei = new EventInstrumentation(superClass, oldBytes, traceId, bootClassLoader, true); - eventName = ei.getEventName(); - if (!JVMSupport.shouldInstrument(bootClassLoader, ei.getEventName())) { + ClassInspector c = new ClassInspector(superClass, oldBytes, bootClassLoader); + eventName = c.getEventName(); + if (!JVMSupport.shouldInstrument(bootClassLoader, c.getEventName())) { Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Skipping instrumentation for " + eventName + " since container support is missing"); return oldBytes; } @@ -118,14 +119,15 @@ final class JVMUpcalls { // No need to generate bytecode if: // 1) Event class is disabled, and there is not an external configuration that overrides. // 2) Event class has @Registered(false) - if (!mr.isEnabled(ei.getEventName()) && !ei.isEnabled() || !ei.isRegistered()) { + if (!mr.isEnabled(c.getEventName()) && !c.isEnabled() || !c.isRegistered()) { Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Skipping instrumentation for event type " + eventName + " since event was disabled on class load"); return oldBytes; } } - Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Adding " + (forceInstrumentation ? "forced " : "") + "instrumentation for event type " + eventName + " during initial class load"); + EventInstrumentation ei = new EventInstrumentation(c, traceId, true); byte[] bytes = ei.buildInstrumented(); - Bytecode.log(ei.getClassName() + "(" + traceId + ")", bytes); + Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Adding " + (forceInstrumentation ? "forced " : "") + "instrumentation for event type " + eventName + " during initial class load"); + Bytecode.log(c.getClassName() + "(" + traceId + ")", bytes); return bytes; } catch (Throwable t) { Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Unexpected error when adding instrumentation for event type " + eventName + ". " + t.getMessage()); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Bytecode.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Bytecode.java index 1241993e762..3cea5e80643 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Bytecode.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Bytecode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jdk.jfr.internal.Logger; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; import java.lang.classfile.CodeBuilder; +import java.lang.classfile.MethodModel; import java.lang.classfile.ClassModel; import java.lang.classfile.ClassFile; import jdk.internal.classfile.components.ClassPrinter; @@ -74,6 +75,12 @@ public final class Bytecode { MethodTypeDesc mtd = MethodTypeDesc.of(returnDesc, parameterDesc); return new MethodDesc(methodName, mtd); } + + public boolean matches(MethodModel m) { + return this.descriptor().equals(m.methodTypeSymbol()) && m.methodName().equalsString(this.name()); + } + } + public record SettingDesc(ClassDesc paramType, String methodName) { } public static ClassDesc classDesc(ValueDescriptor v) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/ImplicitFields.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/ImplicitFields.java index c97efe0bdb9..4c82569a83f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/ImplicitFields.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/ImplicitFields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.List; import jdk.jfr.internal.RemoveFields; +import jdk.jfr.internal.util.Bytecode.FieldDesc; /** * Class that describes fields that was not directly named * in the event definition. @@ -37,6 +38,8 @@ public final class ImplicitFields { public static final String DURATION = "duration"; public static final String EVENT_THREAD = "eventThread"; public static final String STACK_TRACE = "stackTrace"; + public static final FieldDesc FIELD_DURATION = FieldDesc.of(long.class, DURATION); + public static final FieldDesc FIELD_START_TIME = FieldDesc.of(long.class, START_TIME); private final List fields = new ArrayList<>(4); From 44c5aca54d1e0aaf0616f77845c5b3b1e2fccf5a Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Wed, 23 Apr 2025 11:53:09 +0000 Subject: [PATCH 321/843] 8341491: Reserve and commit memory operations should be protected by NMT lock Reviewed-by: stuefe, stefank --- src/hotspot/share/runtime/os.cpp | 10 ++++ test/hotspot/gtest/runtime/test_os.cpp | 68 ++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index e4bab3410c1..943f81d752c 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -2251,6 +2251,11 @@ void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); } +// The scope of NmtVirtualMemoryLocker covers both pd_uncommit_memory and record_virtual_memory_uncommit because +// these operations must happen atomically to avoid races causing NMT to fall out os sync with the OS reality. +// We do not have the same lock protection for pd_commit_memory and record_virtual_memory_commit. +// We assume that there is some external synchronization that prevents a region from being uncommitted +// before it is finished being committed. bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { assert_nonempty_range(addr, bytes); bool res; @@ -2273,6 +2278,11 @@ bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { return res; } +// The scope of NmtVirtualMemoryLocker covers both pd_release_memory and record_virtual_memory_release because +// these operations must happen atomically to avoid races causing NMT to fall out os sync with the OS reality. +// We do not have the same lock protection for pd_reserve_memory and record_virtual_memory_reserve. +// We assume that there is some external synchronization that prevents a region from being released +// before it is finished being reserved. bool os::release_memory(char* addr, size_t bytes) { assert_nonempty_range(addr, bytes); bool res; diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp index ee6d1427d0b..04d71a55a49 100644 --- a/test/hotspot/gtest/runtime/test_os.cpp +++ b/test/hotspot/gtest/runtime/test_os.cpp @@ -28,6 +28,7 @@ #include "runtime/os.inline.hpp" #include "runtime/thread.hpp" #include "runtime/threads.hpp" +#include "testutils.hpp" #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -1113,3 +1114,70 @@ TEST_VM(os, free_without_uncommit) { os::release_memory(base, size); } #endif + +TEST_VM(os, commit_memory_or_exit) { + const size_t page_sz = os::vm_page_size(); + const size_t size = 16 * page_sz; + const char* letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + char* base = os::reserve_memory(size, false, mtTest); + ASSERT_NOT_NULL(base); + os::commit_memory_or_exit(base, size, false, "Commit failed."); + strcpy(base, letters); + ASSERT_TRUE(os::uncommit_memory(base, size, false)); + os::commit_memory_or_exit(base, size, page_sz, false, "Commit with alignment hint failed."); + strcpy(base, letters); + ASSERT_TRUE(os::uncommit_memory(base, size, false)); + EXPECT_TRUE(os::release_memory(base, size)); +} + +#if !defined(_AIX) + +TEST_VM(os, map_memory_to_file) { + const char* letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const size_t size = strlen(letters) +1; + + int fd = os::open("map_memory_to_file.txt", O_RDWR | O_CREAT, 0666); + EXPECT_TRUE(fd > 0); + EXPECT_TRUE(os::write(fd, letters, size)); + + char* result = os::map_memory_to_file(size, fd, mtTest); + ASSERT_NOT_NULL(result); + EXPECT_EQ(strcmp(letters, result), 0); + EXPECT_TRUE(os::unmap_memory(result, size)); + ::close(fd); +} + +TEST_VM(os, map_unmap_memory) { + const char* letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char* path = "map_unmap_memory.txt"; + const size_t size = strlen(letters) + 1; + int fd = os::open(path, O_RDWR | O_CREAT, 0666); + EXPECT_TRUE(fd > 0); + EXPECT_TRUE(os::write(fd, letters, size)); + ::close(fd); + + fd = os::open(path, O_RDONLY, 0666); + char* result = os::map_memory(fd, path, 0, nullptr, size, true, false, mtTest); + ASSERT_NOT_NULL(result); + EXPECT_EQ(strcmp(letters, result), 0); + EXPECT_TRUE(os::unmap_memory(result, size)); + ::close(fd); +} + +TEST_VM(os, map_memory_to_file_aligned) { + const char* letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const size_t size = strlen(letters) + 1; + + int fd = os::open("map_memory_to_file.txt", O_RDWR | O_CREAT, 0666); + EXPECT_TRUE(fd > 0); + EXPECT_TRUE(os::write(fd, letters, size)); + + char* result = os::map_memory_to_file_aligned(os::vm_allocation_granularity(), os::vm_allocation_granularity(), fd, mtTest); + ASSERT_NOT_NULL(result); + EXPECT_EQ(strcmp(letters, result), 0); + EXPECT_TRUE(os::unmap_memory(result, os::vm_allocation_granularity())); + ::close(fd); +} + +#endif // !defined(_AIX) From c873837da6e373613866f5f5c0017f0fccb97b57 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 23 Apr 2025 13:01:42 +0000 Subject: [PATCH 322/843] 8355300: Add final to BitSieve Reviewed-by: liach, pminborg --- src/java.base/share/classes/java/math/BitSieve.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/math/BitSieve.java b/src/java.base/share/classes/java/math/BitSieve.java index 8d0d370f9be..4403d79a22f 100644 --- a/src/java.base/share/classes/java/math/BitSieve.java +++ b/src/java.base/share/classes/java/math/BitSieve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,22 +44,22 @@ package java.math; * @author Michael McCloskey * @since 1.3 */ -class BitSieve { +final class BitSieve { /** * Stores the bits in this bitSieve. */ - private long bits[]; + private final long[] bits; /** * Length is how many bits this sieve holds. */ - private int length; + private final int length; /** * A small sieve used to filter out multiples of small primes in a search * sieve. */ - private static BitSieve smallSieve = new BitSieve(); + private static final BitSieve smallSieve = new BitSieve(); /** * Construct a "small sieve" with a base of 0. This constructor is From a372937d8480404e69eff43682c91506997fd8ee Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Wed, 23 Apr 2025 13:22:57 +0000 Subject: [PATCH 323/843] 8350983: JShell LocalExecutionControl only needs stopCheck() on backward branches Reviewed-by: jlahoda, liach, asotona --- .../execution/LocalExecutionControl.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/LocalExecutionControl.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/LocalExecutionControl.java index 1f4dae2df38..5f547b25178 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/LocalExecutionControl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/LocalExecutionControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,16 @@ import java.lang.constant.ConstantDescs; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import java.lang.classfile.ClassFile; import java.lang.classfile.ClassTransform; +import java.lang.classfile.CodeTransform; +import java.lang.classfile.Label; import java.lang.classfile.instruction.BranchInstruction; +import java.lang.classfile.instruction.LabelTarget; /** * An implementation of {@link jdk.jshell.spi.ExecutionControl} which executes @@ -90,11 +95,19 @@ public class LocalExecutionControl extends DirectExecutionControl { private static byte[] instrument(byte[] classFile) { var cc = ClassFile.of(); return cc.transformClass(cc.parse(classFile), - ClassTransform.transformingMethodBodies((cob, coe) -> { - if (coe instanceof BranchInstruction) - cob.invokestatic(CD_Cancel, "stopCheck", ConstantDescs.MTD_void); - cob.with(coe); - })); + ClassTransform.transformingMethodBodies( + CodeTransform.ofStateful(() -> { + Set