From 535922059c961db1129fbed8ef39f69b79bb0132 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 25 Jul 2024 11:07:37 +0000 Subject: [PATCH 1/5] 8335428: Enhanced Building of Processes Reviewed-by: rhalade, djelinski --- .../classes/java/lang/ProcessImpl.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java index 967693dcbc3..3efcfe4d146 100644 --- a/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -204,13 +204,14 @@ private static String[] getTokensFromCommand(String command) { private static final int VERIFICATION_LEGACY = 3; // See Command shell overview for documentation of special characters. // https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490954(v=technet.10) - private static final char ESCAPE_VERIFICATION[][] = { + private static final String ESCAPE_VERIFICATION[] = { // We guarantee the only command file execution for implicit [cmd.exe] run. // http://technet.microsoft.com/en-us/library/bb490954.aspx - {' ', '\t', '\"', '<', '>', '&', '|', '^'}, - {' ', '\t', '\"', '<', '>'}, - {' ', '\t', '\"', '<', '>'}, - {' ', '\t'} + // All space characters require quoting are checked in needsEscaping(). + "\t\"<>&|^", + "\t\"<>", + "\t\"<>", + "\t" }; private static String createCommandLine(int verificationType, @@ -325,9 +326,13 @@ private static boolean needsEscaping(int verificationType, String arg) { } if (!argIsQuoted) { - char testEscape[] = ESCAPE_VERIFICATION[verificationType]; - for (int i = 0; i < testEscape.length; ++i) { - if (arg.indexOf(testEscape[i]) >= 0) { + for (int i = 0; i < arg.length(); i++) { + char ch = arg.charAt(i); + if (Character.isLetterOrDigit(ch)) + continue; // skip over common characters + // All space chars require quotes and other mode specific characters + if (Character.isSpaceChar(ch) || + ESCAPE_VERIFICATION[verificationType].indexOf(ch) >= 0) { return true; } } From aaf3415de8ab6f3342308e4c7efa838376181525 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Wed, 7 Aug 2024 04:03:55 +0000 Subject: [PATCH 2/5] 8336564: Enhance mask blit functionality redux Reviewed-by: rhalade, mschoene, psadhukhan, prr --- src/java.desktop/share/native/libawt/java2d/SurfaceData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h index 8975f8d4a9d..f7124961392 100644 --- a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h +++ b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h @@ -60,7 +60,7 @@ typedef struct { #define UNSAFE_TO_SUB(a, b) \ (((b >= 0) && (a < 0) && (a < (INT_MIN + b))) || \ - ((b < 0) && (a >= 0) && (-b > (INT_MAX - a)))) \ + ((b < 0) && (a >= 0) && (a > (INT_MAX + b)))) \ /* * The SurfaceDataRasInfo structure is used to pass in and return various From a9fae67913d49c0fd4925abd6ac9285d274d9c9b Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Wed, 18 Sep 2024 14:11:13 +0000 Subject: [PATCH 3/5] 8339180: Enhanced Building of Processes: Follow-on Issue Reviewed-by: naoto, djelinski --- src/java.base/windows/classes/java/lang/ProcessImpl.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java index 3efcfe4d146..7f7c1e75013 100644 --- a/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -208,10 +208,10 @@ private static String[] getTokensFromCommand(String command) { // We guarantee the only command file execution for implicit [cmd.exe] run. // http://technet.microsoft.com/en-us/library/bb490954.aspx // All space characters require quoting are checked in needsEscaping(). - "\t\"<>&|^", - "\t\"<>", - "\t\"<>", - "\t" + "\"<>&|^", + "\"<>", + "\"<>", + "" }; private static String createCommandLine(int verificationType, @@ -332,6 +332,7 @@ private static boolean needsEscaping(int verificationType, String arg) { continue; // skip over common characters // All space chars require quotes and other mode specific characters if (Character.isSpaceChar(ch) || + Character.isWhitespace(ch) || ESCAPE_VERIFICATION[verificationType].indexOf(ch) >= 0) { return true; } From 93ea8e708d5fc3dfe01de8d5b6d1061fef91b5d4 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Tue, 15 Oct 2024 15:28:47 +0000 Subject: [PATCH 4/5] 8330045: Enhance array handling Co-authored-by: Christian Hagedorn Co-authored-by: Emanuel Peter Co-authored-by: Francisco Ferrari Bihurriet Co-authored-by: Martin Balao Reviewed-by: rhalade, ahgross, thartmann, epeter, adinn, roland --- src/hotspot/share/opto/subnode.cpp | 101 +++++++++++++----- .../compiler/c2/gvn/TestBoolNodeGVN.java | 57 ++++++---- 2 files changed, 112 insertions(+), 46 deletions(-) diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 445eb168214..f1eca4682bd 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1623,27 +1623,17 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { return new BoolNode( ncmp, _test.negate() ); } - // Change ((x & (m - 1)) u< m) into (m > 0) - // This is the off-by-one variant of ((x & m) u<= m) - if (cop == Op_CmpU && - _test._test == BoolTest::lt && - cmp1_op == Op_AndI) { - Node* l = cmp1->in(1); - Node* r = cmp1->in(2); - for (int repeat = 0; repeat < 2; repeat++) { - bool match = r->Opcode() == Op_AddI && r->in(2)->find_int_con(0) == -1 && - r->in(1) == cmp2; - if (match) { - // arraylength known to be non-negative, so a (arraylength != 0) is sufficient, - // but to be compatible with the array range check pattern, use (arraylength u> 0) - Node* ncmp = cmp2->Opcode() == Op_LoadRange - ? phase->transform(new CmpUNode(cmp2, phase->intcon(0))) - : phase->transform(new CmpINode(cmp2, phase->intcon(0))); - return new BoolNode(ncmp, BoolTest::gt); - } else { - // commute and try again - l = cmp1->in(2); - r = cmp1->in(1); + // Transform: "((x & (m - 1)) u 0)" + // This is case [CMPU_MASK] which is further described at the method comment of BoolNode::Value_cmpu_and_mask(). + if (cop == Op_CmpU && _test._test == BoolTest::lt && cmp1_op == Op_AndI) { + Node* m = cmp2; // RHS: m + for (int add_idx = 1; add_idx <= 2; add_idx++) { // LHS: "(m + (-1)) & x" or "x & (m + (-1))"? + Node* maybe_m_minus_1 = cmp1->in(add_idx); + if (maybe_m_minus_1->Opcode() == Op_AddI && + maybe_m_minus_1->in(2)->find_int_con(0) == -1 && + maybe_m_minus_1->in(1) == m) { + Node* m_cmpu_0 = phase->transform(new CmpUNode(m, phase->intcon(0))); + return new BoolNode(m_cmpu_0, BoolTest::gt); } } } @@ -1809,9 +1799,57 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { // } } -//------------------------------Value------------------------------------------ -// Change ((x & m) u<= m) or ((m & x) u<= m) to always true -// Same with ((x & m) u< m+1) and ((m & x) u< m+1) +// We use the following Lemmas/insights for the following two transformations (1) and (2): +// x & y <=u y, for any x and y (Lemma 1, masking always results in a smaller unsigned number) +// y u 0) +// This is the off-by-one variant of the above. +// +// We now prove that this replacement is correct. This is the same as proving +// "m >u 0" if and only if "x & (m - 1) u 0 <=> x & (m - 1) m >u 0": +// We prove this by contradiction: +// Assume m <=u 0 which is equivalent to m == 0: +// and thus +// x & (m - 1) u 0 => x & (m - 1) u 0, no underflow of "m - 1" +// +// +// Note that the signed version of "m > 0": +// m > 0 <=> x & (m - 1) 0 +// is false which is a contradiction. +// +// (1a) and (1b) is covered by this method since we can directly return a true value as type while (2) is covered +// in BoolNode::Ideal since we create a new non-constant node (see [CMPU_MASK]). const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { Node* cmp = in(1); if (cmp != nullptr && cmp->Opcode() == Op_CmpU) { @@ -1819,14 +1857,21 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { Node* cmp2 = cmp->in(2); if (cmp1->Opcode() == Op_AndI) { - Node* bound = nullptr; + Node* m = nullptr; if (_test._test == BoolTest::le) { - bound = cmp2; + // (1a) "((x & m) <=u m)", cmp2 = m + m = cmp2; } else if (_test._test == BoolTest::lt && cmp2->Opcode() == Op_AddI && cmp2->in(2)->find_int_con(0) == 1) { - bound = cmp2->in(1); + // (1b) "(x & m) in(1); + const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int(); + if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) { + // Exclude any case where m == -1 is possible. + m = rhs_m; + } } - if (cmp1->in(2) == bound || cmp1->in(1) == bound) { + if (cmp1->in(2) == m || cmp1->in(1) == m) { return TypeInt::ONE; } } diff --git a/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java b/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java index 3f2fe7ecf05..384dc6f8f11 100644 --- a/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java +++ b/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java @@ -56,27 +56,47 @@ public static boolean testShouldReplaceCpmUCase1(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(failOn = IRNode.CMP_U, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldReplaceCpmUCase2(int x, int m) { return !(Integer.compareUnsigned((m & x), m) > 0); } @Test - @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @Arguments(values = {Argument.DEFAULT, Argument.RANDOM_EACH}) @IR(failOn = IRNode.CMP_U, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldReplaceCpmUCase3(int x, int m) { + m = Math.max(0, m); return Integer.compareUnsigned((x & m), m + 1) < 0; } @Test - @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @Arguments(values = {Argument.DEFAULT, Argument.RANDOM_EACH}) @IR(failOn = IRNode.CMP_U, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldReplaceCpmUCase4(int x, int m) { + m = Math.max(0, m); + return Integer.compareUnsigned((m & x), m + 1) < 0; + } + + @Test + @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @IR(counts = {IRNode.CMP_U, "1"}, // m could be -1 and thus optimization cannot be applied + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + public static boolean testShouldNotReplaceCpmUCase1(int x, int m) { + return Integer.compareUnsigned((x & m), m + 1) < 0; + } + + @Test + @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @IR(counts = {IRNode.CMP_U, "1"}, // m could be -1 and thus optimization cannot be applied + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + public static boolean testShouldNotReplaceCpmUCase2(int x, int m) { return Integer.compareUnsigned((m & x), m + 1) < 0; } @@ -92,8 +112,8 @@ public static boolean testShouldHaveCpmUCase1(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(counts = {IRNode.CMP_U, "1"}, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldHaveCpmUCase2(int x, int m) { return !(Integer.compareUnsigned((m & x), m - 1) > 0); } @@ -101,8 +121,8 @@ public static boolean testShouldHaveCpmUCase2(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(counts = {IRNode.CMP_U, "1"}, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldHaveCpmUCase3(int x, int m) { return Integer.compareUnsigned((x & m), m + 2) < 0; } @@ -110,22 +130,23 @@ public static boolean testShouldHaveCpmUCase3(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(counts = {IRNode.CMP_U, "1"}, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldHaveCpmUCase4(int x, int m) { return Integer.compareUnsigned((m & x), m + 2) < 0; } private static void testCorrectness() { int[] values = { - 0, 1, 5, 8, 16, 42, 100, new Random().nextInt(0, Integer.MAX_VALUE), Integer.MAX_VALUE + -100, -42, -16, -8, -5, -1, 0, 1, 5, 8, 16, 42, 100, + new Random().nextInt(), Integer.MAX_VALUE, Integer.MIN_VALUE }; for (int x : values) { for (int m : values) { - if (!testShouldReplaceCpmUCase1(x, m) | - !testShouldReplaceCpmUCase2(x, m) | - !testShouldReplaceCpmUCase3(x, m) | + if (!testShouldReplaceCpmUCase1(x, m) || + !testShouldReplaceCpmUCase2(x, m) || + !testShouldReplaceCpmUCase3(x, m) || !testShouldReplaceCpmUCase4(x, m)) { throw new RuntimeException("Bad result for x = " + x + " and m = " + m + ", expected always true"); } From 99e21c6aaf853ebd3e640946f1dd5d292ccee408 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 22 Jan 2025 18:47:06 +0000 Subject: [PATCH 5/5] 8348013: [doc] fix typo in java.md caused by JDK-8347763 Reviewed-by: iklam Backport-of: e1cf3517ae0dcfa98e22d669f9f624dfbbd6ab73 --- src/java.base/share/man/java.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index 822c728d330..9d1d6e266a3 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -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 @@ -4011,12 +4011,12 @@ The values for these options (if specified), should be identical when creating a CDS archive. Otherwise, if there is a mismatch of any of these options, the CDS archive may be partially or completely disabled, leading to lower performance. -- If the -XX:+AOTClassLoading options *was* used during CDS archive creation, the CDS archive +- If the -XX:+AOTClassLinking options *was* used during CDS archive creation, the CDS archive cannot be used, and the following error message is printed: `CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used` -- If the -XX:+AOTClassLoading options *was not* used during CDS archive creation, the CDS archive +- If the -XX:+AOTClassLinking options *was not* used during CDS archive creation, the CDS archive can be used, but the "archived module graph" feature will be disabled. This can lead to increased start-up time.