diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 2ccc755be3c..b8a9afc123f 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -6259,14 +6259,10 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value) // Intrinsic for // -// - sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len) -// Encodes char[] to byte[] in ISO-8859-1 -// -// - java.lang.StringCoding#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len) -// Encodes byte[] (containing UTF-16) to byte[] in ISO-8859-1 -// -// - java.lang.StringCoding#encodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len) -// Encodes char[] to byte[] in ASCII +// - sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray +// return the number of characters copied. +// - java/lang/StringUTF16.compress +// return index of non-latin1 character if copy fails, otherwise 'len'. // // This version always returns the number of characters copied, and does not // clobber the 'len' register. A successful copy will complete with the post- diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index dcf20752a21..824ea872935 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -2813,14 +2813,10 @@ void C2_MacroAssembler::char_array_compress_v(Register src, Register dst, Regist // Intrinsic for // -// - sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len) -// Encodes char[] to byte[] in ISO-8859-1 -// -// - java.lang.StringCoding#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len) -// Encodes byte[] (containing UTF-16) to byte[] in ISO-8859-1 -// -// - java.lang.StringCoding#encodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len) -// Encodes char[] to byte[] in ASCII +// - sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray +// return the number of characters copied. +// - java/lang/StringUTF16.compress +// return index of non-latin1 character if copy fails, otherwise 'len'. // // This version always returns the number of characters copied. A successful // copy will complete with the post-condition: 'res' == 'len', while an diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 3f18d8c6262..be7deb884ce 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -6251,46 +6251,32 @@ void MacroAssembler::evpbroadcast(BasicType type, XMMRegister dst, Register src, } } -// Encode given char[]/byte[] to byte[] in ISO_8859_1 or ASCII -// -// @IntrinsicCandidate -// int sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0( -// char[] sa, int sp, byte[] da, int dp, int len) { -// int i = 0; -// for (; i < len; i++) { -// char c = sa[sp++]; -// if (c > '\u00FF') -// break; -// da[dp++] = (byte) c; -// } -// return i; -// } -// -// @IntrinsicCandidate -// int java.lang.StringCoding.encodeISOArray0( -// byte[] sa, int sp, byte[] da, int dp, int len) { -// int i = 0; -// for (; i < len; i++) { -// char c = StringUTF16.getChar(sa, sp++); -// if (c > '\u00FF') -// break; -// da[dp++] = (byte) c; -// } -// return i; -// } -// -// @IntrinsicCandidate -// int java.lang.StringCoding.encodeAsciiArray0( -// char[] sa, int sp, byte[] da, int dp, int len) { -// int i = 0; -// for (; i < len; i++) { -// char c = sa[sp++]; -// if (c >= '\u0080') -// break; -// da[dp++] = (byte) c; -// } -// return i; -// } +// encode char[] to byte[] in ISO_8859_1 or ASCII + //@IntrinsicCandidate + //private static int implEncodeISOArray(byte[] sa, int sp, + //byte[] da, int dp, int len) { + // int i = 0; + // for (; i < len; i++) { + // char c = StringUTF16.getChar(sa, sp++); + // if (c > '\u00FF') + // break; + // da[dp++] = (byte)c; + // } + // return i; + //} + // + //@IntrinsicCandidate + //private static int implEncodeAsciiArray(char[] sa, int sp, + // byte[] da, int dp, int len) { + // int i = 0; + // for (; i < len; i++) { + // char c = sa[sp++]; + // if (c >= '\u0080') + // break; + // da[dp++] = (byte)c; + // } + // return i; + //} void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, XMMRegister tmp1Reg, XMMRegister tmp2Reg, XMMRegister tmp3Reg, XMMRegister tmp4Reg, diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 6f9c2326a45..07fa294e8e1 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -415,18 +415,18 @@ class methodHandle; \ do_class(java_lang_StringCoding, "java/lang/StringCoding") \ do_intrinsic(_countPositives, java_lang_StringCoding, countPositives_name, countPositives_signature, F_S) \ - do_name( countPositives_name, "countPositives0") \ + do_name( countPositives_name, "countPositives") \ do_signature(countPositives_signature, "([BII)I") \ \ do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ - do_name( encodeISOArray_name, "encodeISOArray0") \ + do_name( encodeISOArray_name, "implEncodeISOArray") \ do_signature(encodeISOArray_signature, "([CI[BII)I") \ \ do_intrinsic(_encodeByteISOArray, java_lang_StringCoding, encodeISOArray_name, indexOfI_signature, F_S) \ \ do_intrinsic(_encodeAsciiArray, java_lang_StringCoding, encodeAsciiArray_name, encodeISOArray_signature, F_S) \ - do_name( encodeAsciiArray_name, "encodeAsciiArray0") \ + do_name( encodeAsciiArray_name, "implEncodeAsciiArray") \ \ do_class(java_math_BigInteger, "java/math/BigInteger") \ do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \ diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 7fa3ca638c2..f470049bf7e 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -675,9 +675,6 @@ product(bool, PrintIntrinsics, false, DIAGNOSTIC, \ "prints attempted and successful inlining of intrinsics") \ \ - develop(bool, VerifyIntrinsicChecks, false, \ - "Verify in intrinsic that Java level checks work as expected") \ - \ develop(bool, StressReflectiveCode, false, \ "Use inexact types at allocations, etc., to test reflection") \ \ diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index a057f66a989..2c2a7c020b8 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -940,11 +940,7 @@ inline Node* LibraryCallKit::generate_limit_guard(Node* offset, } // Emit range checks for the given String.value byte array -void LibraryCallKit::generate_string_range_check(Node* array, - Node* offset, - Node* count, - bool char_count, - bool halt_on_oob) { +void LibraryCallKit::generate_string_range_check(Node* array, Node* offset, Node* count, bool char_count) { if (stopped()) { return; // already stopped } @@ -962,17 +958,10 @@ void LibraryCallKit::generate_string_range_check(Node* array, generate_limit_guard(offset, count, load_array_length(array), bailout); if (bailout->req() > 1) { - if (halt_on_oob) { - bailout = _gvn.transform(bailout)->as_Region(); - Node* frame = _gvn.transform(new ParmNode(C->start(), TypeFunc::FramePtr)); - Node* halt = _gvn.transform(new HaltNode(bailout, frame, "unexpected guard failure in intrinsic")); - C->root()->add_req(halt); - } else { - PreserveJVMState pjvms(this); - set_control(_gvn.transform(bailout)); - uncommon_trap(Deoptimization::Reason_intrinsic, - Deoptimization::Action_maybe_recompile); - } + PreserveJVMState pjvms(this); + set_control(_gvn.transform(bailout)); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_maybe_recompile); } } @@ -1130,7 +1119,6 @@ bool LibraryCallKit::inline_array_equals(StrIntrinsicNode::ArgEnc ae) { //------------------------------inline_countPositives------------------------------ -// int java.lang.StringCoding#countPositives0(byte[] ba, int off, int len) bool LibraryCallKit::inline_countPositives() { if (too_many_traps(Deoptimization::Reason_intrinsic)) { return false; @@ -1142,14 +1130,13 @@ bool LibraryCallKit::inline_countPositives() { Node* offset = argument(1); Node* len = argument(2); - if (VerifyIntrinsicChecks) { - ba = must_be_not_null(ba, true); - generate_string_range_check(ba, offset, len, false, true); - if (stopped()) { - return true; - } - } + ba = must_be_not_null(ba, true); + // Range checks + generate_string_range_check(ba, offset, len, false); + if (stopped()) { + return true; + } Node* ba_start = array_element_address(ba, offset, T_BYTE); Node* result = new CountPositivesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len); set_result(_gvn.transform(result)); @@ -6184,9 +6171,6 @@ CallStaticJavaNode* LibraryCallKit::get_uncommon_trap_from_success_proj(Node* no } //-------------inline_encodeISOArray----------------------------------- -// int sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len) -// int java.lang.StringCoding#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len) -// int java.lang.StringCoding#encodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len) // encode char[] to byte[] in ISO_8859_1 or ASCII bool LibraryCallKit::inline_encodeISOArray(bool ascii) { assert(callee()->signature()->size() == 5, "encodeISOArray has 5 parameters"); @@ -6197,14 +6181,8 @@ bool LibraryCallKit::inline_encodeISOArray(bool ascii) { Node *dst_offset = argument(3); Node *length = argument(4); - // Cast source & target arrays to not-null - if (VerifyIntrinsicChecks) { - src = must_be_not_null(src, true); - dst = must_be_not_null(dst, true); - if (stopped()) { - return true; - } - } + src = must_be_not_null(src, true); + dst = must_be_not_null(dst, true); const TypeAryPtr* src_type = src->Value(&_gvn)->isa_aryptr(); const TypeAryPtr* dst_type = dst->Value(&_gvn)->isa_aryptr(); @@ -6221,15 +6199,6 @@ bool LibraryCallKit::inline_encodeISOArray(bool ascii) { return false; } - // Check source & target bounds - if (VerifyIntrinsicChecks) { - generate_string_range_check(src, src_offset, length, src_elem == T_BYTE, true); - generate_string_range_check(dst, dst_offset, length, false, true); - if (stopped()) { - return true; - } - } - Node* src_start = array_element_address(src, src_offset, T_CHAR); Node* dst_start = array_element_address(dst, dst_offset, dst_elem); // 'src_start' points to src array + scaled offset diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index bfe29814dec..00ba4c795f1 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -163,8 +163,7 @@ class LibraryCallKit : public GraphKit { Node* array_length, RegionNode* region); void generate_string_range_check(Node* array, Node* offset, - Node* length, bool char_count, - bool halt_on_oob = false); + Node* length, bool char_count); Node* current_thread_helper(Node* &tls_output, ByteSize handle_offset, bool is_immutable); Node* generate_current_thread(Node* &tls_output); diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index d7aef113e15..d3eda052740 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1111,7 +1111,7 @@ public final class String int sp = 0; int sl = len; while (sp < sl) { - int ret = StringCoding.encodeISOArray(val, sp, dst, dp, len); + int ret = StringCoding.implEncodeISOArray(val, sp, dst, dp, len); sp = sp + ret; dp = dp + ret; if (ret != len) { diff --git a/src/java.base/share/classes/java/lang/StringCoding.java b/src/java.base/share/classes/java/lang/StringCoding.java index 545f216b755..c02af28c37d 100644 --- a/src/java.base/share/classes/java/lang/StringCoding.java +++ b/src/java.base/share/classes/java/lang/StringCoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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. * @@ -26,11 +26,8 @@ package java.lang; -import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.IntrinsicCandidate; -import java.util.function.BiFunction; - /** * Utility class for string encoding and decoding. */ @@ -41,7 +38,7 @@ class StringCoding { /** * Count the number of leading non-zero ascii chars in the range. */ - static int countNonZeroAscii(String s) { + public static int countNonZeroAscii(String s) { byte[] value = s.value(); if (s.isLatin1()) { return countNonZeroAsciiLatin1(value, 0, value.length); @@ -53,7 +50,7 @@ class StringCoding { /** * Count the number of non-zero ascii chars in the range. */ - private static int countNonZeroAsciiLatin1(byte[] ba, int off, int len) { + public static int countNonZeroAsciiLatin1(byte[] ba, int off, int len) { int limit = off + len; for (int i = off; i < limit; i++) { if (ba[i] <= 0) { @@ -66,7 +63,7 @@ class StringCoding { /** * Count the number of leading non-zero ascii chars in the range. */ - private static int countNonZeroAsciiUTF16(byte[] ba, int off, int strlen) { + public static int countNonZeroAsciiUTF16(byte[] ba, int off, int strlen) { int limit = off + strlen; for (int i = off; i < limit; i++) { char c = StringUTF16.charAt(ba, i); @@ -77,7 +74,7 @@ class StringCoding { return strlen; } - static boolean hasNegatives(byte[] ba, int off, int len) { + public static boolean hasNegatives(byte[] ba, int off, int len) { return countPositives(ba, off, len) != len; } @@ -88,24 +85,9 @@ class StringCoding { * bytes in the range. If there are negative bytes, the implementation must return * a value that is less than or equal to the index of the first negative byte * in the range. - * - * @param ba a byte array - * @param off the index of the first byte to start reading from - * @param len the total number of bytes to read - * @throws NullPointerException if {@code ba} is null - * @throws ArrayIndexOutOfBoundsException if the provided sub-range is - * {@linkplain Preconditions#checkFromIndexSize(int, int, int, BiFunction) out of bounds} */ - static int countPositives(byte[] ba, int off, int len) { - Preconditions.checkFromIndexSize( - off, len, - ba.length, // Implicit null check on `ba` - Preconditions.AIOOBE_FORMATTER); - return countPositives0(ba, off, len); - } - @IntrinsicCandidate - private static int countPositives0(byte[] ba, int off, int len) { + public static int countPositives(byte[] ba, int off, int len) { int limit = off + len; for (int i = off; i < limit; i++) { if (ba[i] < 0) { @@ -115,37 +97,9 @@ class StringCoding { return len; } - /** - * Encodes as many ISO-8859-1 codepoints as possible from the source byte - * array containing characters encoded in UTF-16, into the destination byte - * array, assuming that the encoding is ISO-8859-1 compatible. - * - * @param sa the source byte array containing characters encoded in UTF-16 - * @param sp the index of the character (not byte!) from the source array to start reading from - * @param da the target byte array - * @param dp the index of the target array to start writing to - * @param len the maximum number of characters (not bytes!) to be encoded - * @return the total number of characters (not bytes!) successfully encoded - * @throws NullPointerException if any of the provided arrays is null - */ - static int encodeISOArray(byte[] sa, int sp, - byte[] da, int dp, int len) { - // This method should tolerate invalid arguments, matching the lenient behavior of the VM intrinsic. - // Hence, using operator expressions instead of `Preconditions`, which throw on failure. - int sl; - if ((sp | dp | len) < 0 || - // Halving the length of `sa` to obtain the number of characters: - sp >= (sl = sa.length >>> 1) || // Implicit null check on `sa` - dp >= da.length) { // Implicit null check on `da` - return 0; - } - int minLen = Math.min(len, Math.min(sl - sp, da.length - dp)); - return encodeISOArray0(sa, sp, da, dp, minLen); - } - @IntrinsicCandidate - private static int encodeISOArray0(byte[] sa, int sp, - byte[] da, int dp, int len) { + public static int implEncodeISOArray(byte[] sa, int sp, + byte[] da, int dp, int len) { int i = 0; for (; i < len; i++) { char c = StringUTF16.getChar(sa, sp++); @@ -156,35 +110,10 @@ class StringCoding { return i; } - /** - * Encodes as many ASCII codepoints as possible from the source - * character array into the destination byte array, assuming that - * the encoding is ASCII compatible. - * - * @param sa the source character array - * @param sp the index of the source array to start reading from - * @param da the target byte array - * @param dp the index of the target array to start writing to - * @param len the maximum number of characters to be encoded - * @return the total number of characters successfully encoded - * @throws NullPointerException if any of the provided arrays is null - */ - static int encodeAsciiArray(char[] sa, int sp, - byte[] da, int dp, int len) { - // This method should tolerate invalid arguments, matching the lenient behavior of the VM intrinsic. - // Hence, using operator expressions instead of `Preconditions`, which throw on failure. - if ((sp | dp | len) < 0 || - sp >= sa.length || // Implicit null check on `sa` - dp >= da.length) { // Implicit null check on `da` - return 0; - } - int minLen = Math.min(len, Math.min(sa.length - sp, da.length - dp)); - return encodeAsciiArray0(sa, sp, da, dp, minLen); - } - @IntrinsicCandidate - static int encodeAsciiArray0(char[] sa, int sp, - byte[] da, int dp, int len) { + public static int implEncodeAsciiArray(char[] sa, int sp, + byte[] da, int dp, int len) + { int i = 0; for (; i < len; i++) { char c = sa[sp++]; diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 5c2b47afe3d..f3a57c34165 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -55,6 +55,7 @@ import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; import java.util.function.Supplier; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; @@ -2176,8 +2177,8 @@ public final class System { return String.decodeASCII(src, srcOff, dst, dstOff, len); } - public int encodeASCII(char[] sa, int sp, byte[] da, int dp, int len) { - return StringCoding.encodeAsciiArray(sa, sp, da, dp, len); + public int uncheckedEncodeASCII(char[] src, int srcOff, byte[] dst, int dstOff, int len) { + return StringCoding.implEncodeAsciiArray(src, srcOff, dst, dstOff, len); } public InputStream initialSystemIn() { 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 86e5f317dc7..c5c45ca3553 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -448,19 +448,15 @@ public interface JavaLangAccess { PrintStream initialSystemErr(); /** - * Encodes as many ASCII codepoints as possible from the source - * character array into the destination byte array, assuming that - * the encoding is ASCII compatible. + * Encodes as many ASCII codepoints as possible from the source array into + * the destination byte array, assuming that the encoding is ASCII + * compatible. + *

+ * WARNING: This method does not perform any bound checks. * - * @param sa the source character array - * @param sp the index of the source array to start reading from - * @param da the target byte array - * @param dp the index of the target array to start writing to - * @param len the total number of characters to be encoded - * @return the total number of characters successfully encoded - * @throws NullPointerException if any of the provided arrays is null + * @return the number of bytes successfully encoded, or 0 if none */ - int encodeASCII(char[] sa, int sp, byte[] da, int dp, int len); + int uncheckedEncodeASCII(char[] src, int srcOff, byte[] dst, int dstOff, int len); /** * Set the cause of Throwable diff --git a/src/java.base/share/classes/sun/nio/cs/CESU_8.java b/src/java.base/share/classes/sun/nio/cs/CESU_8.java index 409b375ec88..11f21f56139 100644 --- a/src/java.base/share/classes/sun/nio/cs/CESU_8.java +++ b/src/java.base/share/classes/sun/nio/cs/CESU_8.java @@ -445,7 +445,7 @@ class CESU_8 extends Unicode int dl = dst.arrayOffset() + dst.limit(); // Handle ASCII-only prefix - int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp)); + int n = JLA.uncheckedEncodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp)); sp += n; dp += n; diff --git a/src/java.base/share/classes/sun/nio/cs/DoubleByte.java b/src/java.base/share/classes/sun/nio/cs/DoubleByte.java index 0969669a35b..2a4dbdc95ed 100644 --- a/src/java.base/share/classes/sun/nio/cs/DoubleByte.java +++ b/src/java.base/share/classes/sun/nio/cs/DoubleByte.java @@ -600,7 +600,7 @@ public class DoubleByte { try { if (isASCIICompatible) { - int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(dl - dp, sl - sp)); + int n = JLA.uncheckedEncodeASCII(sa, sp, da, dp, Math.min(dl - dp, sl - sp)); sp += n; dp += n; } diff --git a/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java b/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java index ff5970e92a8..39215bfa93d 100644 --- a/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java +++ b/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java @@ -35,6 +35,7 @@ import java.util.Objects; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.IntrinsicCandidate; public class ISO_8859_1 @@ -141,34 +142,20 @@ public class ISO_8859_1 private final Surrogate.Parser sgp = new Surrogate.Parser(); - /** - * Encodes as many ISO-8859-1 codepoints as possible from the source - * character array into the destination byte array, assuming that - * the encoding is ISO-8859-1 compatible. - * - * @param sa the source character array - * @param sp the index of the source array to start reading from - * @param da the target byte array - * @param dp the index of the target array to start writing to - * @param len the maximum number of characters to be encoded - * @return the total number of characters successfully encoded - * @throws NullPointerException if any of the provided arrays is null - */ + // Method possible replaced with a compiler intrinsic. private static int encodeISOArray(char[] sa, int sp, byte[] da, int dp, int len) { - // This method should tolerate invalid arguments, matching the lenient behavior of the VM intrinsic. - // Hence, using operator expressions instead of `Preconditions`, which throw on failure. - if ((sp | dp | len) < 0 || - sp >= sa.length || // Implicit null check on `sa` - dp >= da.length) { // Implicit null check on `da` + if (len <= 0) { return 0; } - int minLen = Math.min(len, Math.min(sa.length - sp, da.length - dp)); - return encodeISOArray0(sa, sp, da, dp, minLen); + encodeISOArrayCheck(sa, sp, da, dp, len); + return implEncodeISOArray(sa, sp, da, dp, len); } @IntrinsicCandidate - private static int encodeISOArray0(char[] sa, int sp, byte[] da, int dp, int len) { + private static int implEncodeISOArray(char[] sa, int sp, + byte[] da, int dp, int len) + { int i = 0; for (; i < len; i++) { char c = sa[sp++]; @@ -179,6 +166,17 @@ public class ISO_8859_1 return i; } + private static void encodeISOArrayCheck(char[] sa, int sp, + byte[] da, int dp, int len) { + Objects.requireNonNull(sa); + Objects.requireNonNull(da); + Preconditions.checkIndex(sp, sa.length, Preconditions.AIOOBE_FORMATTER); + Preconditions.checkIndex(dp, da.length, Preconditions.AIOOBE_FORMATTER); + + Preconditions.checkIndex(sp + len - 1, sa.length, Preconditions.AIOOBE_FORMATTER); + Preconditions.checkIndex(dp + len - 1, da.length, Preconditions.AIOOBE_FORMATTER); + } + private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { diff --git a/src/java.base/share/classes/sun/nio/cs/SingleByte.java b/src/java.base/share/classes/sun/nio/cs/SingleByte.java index a5bf06cb251..59887b944d3 100644 --- a/src/java.base/share/classes/sun/nio/cs/SingleByte.java +++ b/src/java.base/share/classes/sun/nio/cs/SingleByte.java @@ -217,7 +217,7 @@ public class SingleByte int len = Math.min(dl - dp, sl - sp); if (isASCIICompatible) { - int n = JLA.encodeASCII(sa, sp, da, dp, len); + int n = JLA.uncheckedEncodeASCII(sa, sp, da, dp, len); sp += n; dp += n; len -= n; diff --git a/src/java.base/share/classes/sun/nio/cs/US_ASCII.java b/src/java.base/share/classes/sun/nio/cs/US_ASCII.java index 3886978d209..bb84ab1bd4b 100644 --- a/src/java.base/share/classes/sun/nio/cs/US_ASCII.java +++ b/src/java.base/share/classes/sun/nio/cs/US_ASCII.java @@ -159,7 +159,7 @@ public class US_ASCII assert (dp <= dl); dp = (dp <= dl ? dp : dl); - int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp)); + int n = JLA.uncheckedEncodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp)); sp += n; dp += n; diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_8.java b/src/java.base/share/classes/sun/nio/cs/UTF_8.java index d2d6d7e485d..54e479f838a 100644 --- a/src/java.base/share/classes/sun/nio/cs/UTF_8.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_8.java @@ -452,7 +452,7 @@ public final class UTF_8 extends Unicode { int dl = dst.arrayOffset() + dst.limit(); // Handle ASCII-only prefix - int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp)); + int n = JLA.uncheckedEncodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp)); sp += n; dp += n; diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template index f3d03a9e9c7..4fc0b2796ee 100644 --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template @@ -309,7 +309,7 @@ public class EUC_JP try { if (enc0201.isASCIICompatible()) { - int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(dl - dp, sl - sp)); + int n = JLA.uncheckedEncodeASCII(sa, sp, da, dp, Math.min(dl - dp, sl - sp)); sp += n; dp += n; } diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestVerifyIntrinsicChecks.java b/test/hotspot/jtreg/compiler/intrinsics/TestVerifyIntrinsicChecks.java deleted file mode 100644 index c482a73affd..00000000000 --- a/test/hotspot/jtreg/compiler/intrinsics/TestVerifyIntrinsicChecks.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 8361842 - * @summary Verify the effectiveness of the `VerifyIntrinsicChecks` VM flag - * through (bypassing `StringCoding::encodeAsciiArray`, and) feeding - * invalid input to an intrinsified `StringCoding::encodeAsciiArray0` - * (note the `0` suffix!). - * @library /compiler/patches - * @library /test/lib - * @build java.base/java.lang.Helper - * @comment `vm.debug == true` is required since `VerifyIntrinsicChecks` is a - * development flag - * @requires vm.debug == true & vm.flavor == "server" & !vm.graal.enabled - * @requires (os.arch != "riscv64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*")) - * @run main/othervm compiler.intrinsics.TestVerifyIntrinsicChecks verify - */ - -package compiler.intrinsics; - -import java.lang.Helper; -import java.time.Instant; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; - -public final class TestVerifyIntrinsicChecks { - - public static void main(String[] args) throws Exception { - switch (args[0]) { - case "verify" -> { - log("Starting JVM in a separate process to verify the crash"); - OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava( - "-Xcomp", - "-XX:-TieredCompilation", - "-XX:CompileCommand=inline,java.lang.StringCoding::encodeAsciiArray0", - "-XX:+VerifyIntrinsicChecks", - "--patch-module", "java.base=%s/java.base".formatted(System.getProperty("test.patch.path")), - "compiler.intrinsics.TestVerifyIntrinsicChecks", - "crash"); - outputAnalyzer.shouldContain("unexpected null in intrinsic"); - outputAnalyzer.shouldNotHaveExitValue(0); - } - case "crash" -> { - log("Triggering the crash"); - warmUpIntrinsicMethod(); - violateIntrinsicMethodContract(); - } - default -> throw new IllegalArgumentException(); - } - } - - private static void warmUpIntrinsicMethod() { - log("Warming up the intrinsic method"); - char[] sa = createAsciiChars(8192); - byte[] sp = new byte[4096]; - for (int i = 0; i < 1_000; i++) { - Helper.StringCodingEncodeAsciiArray0(sa, i, sp, 0, sp.length - i); - } - } - - private static char[] createAsciiChars(int length) { - char[] buffer = new char[length]; - for (int i = 0; i < length; i++) { - buffer[i] = (char) (i % '\u0080'); - } - return buffer; - } - - private static void violateIntrinsicMethodContract() { - log("Violating the intrinsic method contract (sa=null)"); - Helper.StringCodingEncodeAsciiArray0(null, 1, null, 1, 1); - } - - private synchronized static void log(String format, Object... args) { - Object[] extendedArgs = new Object[2 + args.length]; - extendedArgs[0] = Instant.now(); - extendedArgs[1] = Thread.currentThread().getName(); - System.arraycopy(args, 0, extendedArgs, extendedArgs.length - args.length, args.length); - String extendedFormat = "%%s [%%s] %s%%n".formatted(format); - System.out.printf(extendedFormat, extendedArgs); - } - -} diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java index 1c20a49d281..76ef4766159 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -32,7 +32,6 @@ * @build java.base/java.lang.Helper * @run main compiler.intrinsics.string.TestCountPositives */ - /* * @test * @bug 8281146 8318509 @@ -47,38 +46,17 @@ * @run main/othervm/timeout=1200 -XX:UseAVX=3 compiler.intrinsics.string.TestCountPositives * @run main/othervm/timeout=1200 -XX:UseAVX=3 -XX:+UnlockDiagnosticVMOptions -XX:AVX3Threshold=0 compiler.intrinsics.string.TestCountPositives */ - -/* - * @test - * @bug 8281146 - * @summary Verify `StringCoding::countPositives` intrinsic Java wrapper checks - * by enabling the ones in the VM intrinsic using - * `-XX:+VerifyIntrinsicChecks` - * @comment This does not check out-of-range conditions. The - * `-XX:+VerifyIntrinsicChecks` version of this test simply ensures - * that the VM intrinsic will produce no spurious errors. - * @key randomness - * @library /compiler/patches - * @library /test/lib - * @comment `vm.debug == true` is required since `VerifyIntrinsicChecks` is a - * development flag - * @requires vm.debug == true - * @build java.base/java.lang.Helper - * @run main/othervm - * -XX:+VerifyIntrinsicChecks - * compiler.intrinsics.string.TestCountPositives +/** + * This test was derived from compiler.intrinsics.string.TestHasNegatives */ - package compiler.intrinsics.string; import java.lang.Helper; import java.util.Random; +import java.util.stream.IntStream; import jdk.test.lib.Utils; -/** - * This test was derived from {@link TestHasNegatives}. - */ public class TestCountPositives { private static byte[] bytes = new byte[4096 + 32]; diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestEncodeIntrinsics.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestEncodeIntrinsics.java index bb343b246ff..38a516e7521 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/string/TestEncodeIntrinsics.java +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestEncodeIntrinsics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,26 +31,6 @@ * @run main/othervm/timeout=1200 --add-opens=java.base/sun.nio.cs=ALL-UNNAMED -Xbatch -Xmx256m compiler.intrinsics.string.TestEncodeIntrinsics */ -/* - * @test - * @bug 6896617 8274242 - * @summary Verify `sun.nio.cs.ISO_8859_1.Encoder::encodeISOArray` intrinsic - * Java wrapper checks by enabling the ones in the VM intrinsic using - * `-XX:+VerifyIntrinsicChecks` - * @comment This does not check out-of-range conditions. The - * `-XX:+VerifyIntrinsicChecks` version of this test simply ensures - * that the VM intrinsic will produce no spurious errors. - * @key randomness - * @library /test/lib - * @comment `vm.debug == true` is required since `VerifyIntrinsicChecks` is a - * development flag - * @requires vm.debug == true - * @run main/othervm/timeout=1200 - * -XX:+VerifyIntrinsicChecks - * --add-opens=java.base/sun.nio.cs=ALL-UNNAMED -Xbatch -Xmx256m - * compiler.intrinsics.string.TestEncodeIntrinsics - */ - package compiler.intrinsics.string; import jdk.test.lib.Utils; diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestHasNegatives.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestHasNegatives.java index a15f6aade2e..6edf2dc2e56 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/string/TestHasNegatives.java +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestHasNegatives.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ * @build java.base/java.lang.Helper * @run main compiler.intrinsics.string.TestHasNegatives */ - /* * @test * @bug 8054307 8318509 @@ -47,31 +46,11 @@ * @run main/othervm/timeout=1200 -XX:UseAVX=3 -XX:+UnlockDiagnosticVMOptions -XX:AVX3Threshold=0 compiler.intrinsics.string.TestHasNegatives */ -/* - * @test - * @bug 8054307 - * @summary Verify `StringCoding::hasNegatives` intrinsic Java wrapper checks - * by enabling the ones in the VM intrinsic using - * `-XX:+VerifyIntrinsicChecks` - * @comment This does not check out-of-range conditions. The - * `-XX:+VerifyIntrinsicChecks` version of this test simply ensures - * that the VM intrinsic will produce no spurious errors. - * @key randomness - * @library /compiler/patches - * @library /test/lib - * @comment `vm.debug == true` is required since `VerifyIntrinsicChecks` is a - * development flag - * @requires vm.debug == true - * @build java.base/java.lang.Helper - * @run main/othervm - * -XX:+VerifyIntrinsicChecks - * compiler.intrinsics.string.TestHasNegatives - */ - package compiler.intrinsics.string; import java.lang.Helper; import java.util.Random; +import java.util.stream.IntStream; import jdk.test.lib.Utils; diff --git a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java index 3985ad8ea90..e6c8b68fc6f 100644 --- a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java +++ b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java @@ -39,11 +39,6 @@ public class Helper { return StringCoding.countPositives(ba, off, len); } - @jdk.internal.vm.annotation.ForceInline - public static int StringCodingEncodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len) { - return StringCoding.encodeAsciiArray0(sa, sp, da, dp, len); - } - @jdk.internal.vm.annotation.ForceInline public static byte[] compressByte(byte[] src, int srcOff, int dstSize, int dstOff, int len) { byte[] dst = new byte[dstSize];