undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings
|
||||
* @bug 8148869
|
||||
*
|
||||
* @compile -XDstringConcat=indy CompactStringsInitialCoder.java
|
||||
* @run main/othervm -Xverify:all -XX:+CompactStrings CompactStringsInitialCoder
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants CompactStringsInitialCoder.java
|
||||
* @run main/othervm -Xverify:all -XX:+CompactStrings CompactStringsInitialCoder
|
||||
*
|
||||
* @compile -XDstringConcat=indy CompactStringsInitialCoder.java
|
||||
* @run main/othervm -Xverify:all -XX:-CompactStrings CompactStringsInitialCoder
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants CompactStringsInitialCoder.java
|
||||
* @run main/othervm -Xverify:all -XX:-CompactStrings CompactStringsInitialCoder
|
||||
*/
|
||||
import java.lang.StringBuilder;
|
||||
|
||||
public class CompactStringsInitialCoder {
|
||||
|
||||
static String strEmpty = "";
|
||||
static String strLatin1 = "\u0042";
|
||||
static String strUTF16 = "\u4242";
|
||||
static char charLatin1 = '\u0042';
|
||||
static char charUTF16 = '\u4242';
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test("\u0042", "" + '\u0042');
|
||||
test("\u4242", "" + '\u4242');
|
||||
|
||||
test("\u0042", "" + charLatin1);
|
||||
test("\u4242", "" + charUTF16);
|
||||
|
||||
test("\u0042", strEmpty + '\u0042');
|
||||
test("\u4242", strEmpty + '\u4242');
|
||||
|
||||
test("\u0042\u0042", strLatin1 + '\u0042');
|
||||
test("\u0042\u4242", strLatin1 + '\u4242');
|
||||
test("\u4242\u0042", strUTF16 + '\u0042');
|
||||
test("\u4242\u4242", strUTF16 + '\u4242');
|
||||
|
||||
test("\u0042\u0042", "\u0042" + charLatin1);
|
||||
test("\u0042\u4242", "\u0042" + charUTF16);
|
||||
test("\u4242\u0042", "\u4242" + charLatin1);
|
||||
test("\u4242\u4242", "\u4242" + charUTF16);
|
||||
|
||||
test("\u0042\u0042", "" + charLatin1 + charLatin1);
|
||||
test("\u0042\u4242", "" + charLatin1 + charUTF16);
|
||||
test("\u4242\u0042", "" + charUTF16 + charLatin1);
|
||||
test("\u4242\u4242", "" + charUTF16 + charUTF16);
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
if (!expected.equals(actual)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append(", actual = ");
|
||||
sb.append(actual);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
79
test/jdk/java/lang/String/concat/HiddenClassUnloading.java
Normal file
79
test/jdk/java/lang/String/concat/HiddenClassUnloading.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Alibaba Group Holding 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.
|
||||
*/
|
||||
|
||||
import java.lang.StringBuilder;
|
||||
|
||||
import java.lang.invoke.*;
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import jdk.test.whitebox.WhiteBox;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test whether the hidden class unloading of StringConcatFactory works
|
||||
*
|
||||
* @library /test/lib
|
||||
* @build jdk.test.whitebox.WhiteBox
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
||||
* @requires vm.flagless
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xverify:all HiddenClassUnloading
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xverify:all -XX:-CompactStrings HiddenClassUnloading
|
||||
*/
|
||||
public class HiddenClassUnloading {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
var lookup = MethodHandles.lookup();
|
||||
var types = new Class<?>[] {
|
||||
int.class, long.class, double.class, float.class, char.class, boolean.class, String.class,
|
||||
};
|
||||
|
||||
long initUnloadedClassCount = ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount();
|
||||
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
int radix = types.length;
|
||||
String str = Integer.toString(i, radix);
|
||||
int length = str.length();
|
||||
var ptypes = new Class[length];
|
||||
for (int j = 0; j < length; j++) {
|
||||
int index = Integer.parseInt(str.substring(j, j + 1), radix);
|
||||
ptypes[j] = types[index];
|
||||
}
|
||||
StringConcatFactory.makeConcatWithConstants(
|
||||
lookup,
|
||||
"concat",
|
||||
MethodType.methodType(String.class, ptypes),
|
||||
"\1".repeat(length), // recipe
|
||||
new Object[0]
|
||||
);
|
||||
}
|
||||
|
||||
// Request GC which performs class unloading
|
||||
WhiteBox.getWhiteBox().fullGC();
|
||||
|
||||
long unloadedClassCount = ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount();
|
||||
if (initUnloadedClassCount == unloadedClassCount) {
|
||||
throw new RuntimeException("unloadedClassCount is zero");
|
||||
}
|
||||
}
|
||||
}
|
||||
78
test/jdk/java/lang/String/concat/HugeConcatTest.java
Normal file
78
test/jdk/java/lang/String/concat/HugeConcatTest.java
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 8356152
|
||||
* @summary Check that huge concatenations throw OutOfMemoryError
|
||||
* @requires os.maxMemory > 8G
|
||||
* @run junit/othervm -Xmx8G -XX:+CompactStrings -Dcompact=true HugeConcatTest
|
||||
* @run junit/othervm -Xmx8G -XX:-CompactStrings -Dcompact=false HugeConcatTest
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
public class HugeConcatTest {
|
||||
|
||||
private static final int HUGE_LENGTH_UTF16 = Integer.MAX_VALUE / 2 - 2;
|
||||
|
||||
private static String hugeLatin1;
|
||||
private static final String hugeUTF16 = "\u20AC".repeat(HUGE_LENGTH_UTF16);
|
||||
|
||||
@BeforeAll
|
||||
public static void initHugeLatin1() {
|
||||
String compact = System.getProperty("compact", "true");
|
||||
int hugeLatin1Length = Boolean.parseBoolean(compact)
|
||||
? Integer.MAX_VALUE - 2
|
||||
: HUGE_LENGTH_UTF16;
|
||||
hugeLatin1 = "a".repeat(hugeLatin1Length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcat_Latin1_Latin1() {
|
||||
assertThrows(OutOfMemoryError.class, () -> { var s = hugeLatin1 + hugeLatin1; });
|
||||
assertThrows(OutOfMemoryError.class, () -> hugeLatin1.concat(hugeLatin1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcat_Latin1_UTF16() {
|
||||
assertThrows(OutOfMemoryError.class, () -> { var s = hugeLatin1 + hugeUTF16; });
|
||||
assertThrows(OutOfMemoryError.class, () -> hugeLatin1.concat(hugeUTF16));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcat_UTF16_Latin1() {
|
||||
assertThrows(OutOfMemoryError.class, () -> { var s = hugeUTF16 + hugeLatin1; });
|
||||
assertThrows(OutOfMemoryError.class, () -> hugeUTF16.concat(hugeLatin1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcat_UTF16_UTF16() {
|
||||
assertThrows(OutOfMemoryError.class, () -> { var s = hugeUTF16 + hugeUTF16; });
|
||||
assertThrows(OutOfMemoryError.class, () -> hugeUTF16.concat(hugeUTF16));
|
||||
}
|
||||
|
||||
}
|
||||
162
test/jdk/java/lang/String/concat/ImplicitStringConcat.java
Normal file
162
test/jdk/java/lang/String/concat/ImplicitStringConcat.java
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 implicit String concatenations
|
||||
*
|
||||
* @compile ImplicitStringConcat.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcat
|
||||
*
|
||||
* @compile -XDstringConcat=inline ImplicitStringConcat.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcat
|
||||
*
|
||||
* @compile -XDstringConcat=indy ImplicitStringConcat.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcat
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcat.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcat
|
||||
*/
|
||||
import java.lang.StringBuilder;
|
||||
|
||||
public class ImplicitStringConcat {
|
||||
|
||||
static boolean b = true;
|
||||
static byte by = 42;
|
||||
static short sh = 42;
|
||||
static char ch = 'a';
|
||||
static int i = 42;
|
||||
static float fl = 42.0f;
|
||||
static long l = 42;
|
||||
static double d = 42.0d;
|
||||
static String s = "foo";
|
||||
static String sNull = null;
|
||||
static Object o = "bar";
|
||||
static Object oNull = null;
|
||||
static CharSequence cs = "bar";
|
||||
static char[] chars = new char[] {'a'};
|
||||
|
||||
static MyClass myCl = new MyClass();
|
||||
static MyClassNull myClNull = new MyClassNull();
|
||||
static Object myCl2 = new MyClass();
|
||||
static Object[] myArr = new Object[] { myCl };
|
||||
static final Object[] s_myArr = new Object[] { myCl };
|
||||
|
||||
static StringBuffer sb = new StringBuffer("a");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
test("footrue", s + b);
|
||||
test("foo42", s + by);
|
||||
test("foo42", s + sh);
|
||||
test("fooa", s + ch);
|
||||
test("foo42", s + i);
|
||||
test("foo42", s + l);
|
||||
test("foo42.0", s + fl);
|
||||
test("foo42.0", s + d);
|
||||
test("foofoo", s + s);
|
||||
test("foonull", s + sNull);
|
||||
test("foobar", s + o);
|
||||
test("foonull", s + oNull);
|
||||
test("foobar", s + cs);
|
||||
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("foo");
|
||||
sb.append(myArr.toString());
|
||||
test(sb.toString(), s + myArr);
|
||||
}
|
||||
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("foo");
|
||||
sb.append(s_myArr.toString());
|
||||
test(sb.toString(), s + s_myArr);
|
||||
}
|
||||
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("foo[C@");
|
||||
sb.append(Integer.toHexString(System.identityHashCode(chars)));
|
||||
test(sb.toString(), s + chars);
|
||||
}
|
||||
|
||||
test("fooa", s + ImplicitStringConcat.sb);
|
||||
test("foonull", s + null);
|
||||
test("fooMyClass", s + myCl);
|
||||
test("foonull", s + myClNull);
|
||||
test("fooMyClass", s + myCl2);
|
||||
|
||||
s = "foo"; s += b; test("footrue", s);
|
||||
s = "foo"; s += by; test("foo42", s);
|
||||
s = "foo"; s += sh; test("foo42", s);
|
||||
s = "foo"; s += ch; test("fooa", s);
|
||||
s = "foo"; s += i; test("foo42", s);
|
||||
s = "foo"; s += l; test("foo42", s);
|
||||
s = "foo"; s += fl; test("foo42.0", s);
|
||||
s = "foo"; s += d; test("foo42.0", s);
|
||||
s = "foo"; s += s; test("foofoo", s);
|
||||
s = "foo"; s += sNull; test("foonull", s);
|
||||
s = "foo"; s += o; test("foobar", s);
|
||||
s = "foo"; s += oNull; test("foonull", s);
|
||||
s = "foo"; s += cs; test("foobar", s);
|
||||
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("foo[C@");
|
||||
sb.append(Integer.toHexString(System.identityHashCode(chars)));
|
||||
s = "foo";
|
||||
s += chars;
|
||||
test(sb.toString(), s);
|
||||
}
|
||||
|
||||
s = "foo"; s += ImplicitStringConcat.sb; test("fooa", s);
|
||||
s = "foo"; s += null; test("foonull", s);
|
||||
s = "foo"; s += myCl; test("fooMyClass", s);
|
||||
s = "foo"; s += myCl2; test("fooMyClass", s);
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
// Fingers crossed: String concat should work.
|
||||
if (!expected.equals(actual)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append(", actual = ");
|
||||
sb.append(actual);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static class MyClass {
|
||||
public String toString() {
|
||||
return "MyClass";
|
||||
}
|
||||
}
|
||||
|
||||
static class MyClassNull {
|
||||
public String toString() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 multiple number of arguments to concatenate.
|
||||
*
|
||||
* @compile ImplicitStringConcatArgCount.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
|
||||
*
|
||||
* @compile -XDallowStringFolding=false -XDstringConcat=inline ImplicitStringConcatArgCount.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
|
||||
*
|
||||
* @compile -XDallowStringFolding=false -XDstringConcat=indy ImplicitStringConcatArgCount.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
|
||||
*
|
||||
* @compile -XDallowStringFolding=false -XDstringConcat=indyWithConstants ImplicitStringConcatArgCount.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
|
||||
*/
|
||||
public class ImplicitStringConcatArgCount {
|
||||
static final String s = "f";
|
||||
static final String s1 = "o";
|
||||
static String s2 = "o";
|
||||
static int i = 7;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test("fo", s + s1);
|
||||
test("foo", s + s1 + s2);
|
||||
test("foo7", s + s1 + s2 + i);
|
||||
test("foo77", s + s1 + s2 + i + i);
|
||||
test("foo777", s + s1 + s2 + i + i + i);
|
||||
test("foo7777", s + s1 + s2 + i + i + i + i);
|
||||
test("foo77777", s + s1 + s2 + i + i + i + i + i);
|
||||
test("foo777777", s + s1 + s2 + i + i + i + i + i + i);
|
||||
test("foo7777777", s + s1 + s2 + i + i + i + i + i + i + i);
|
||||
test("foo77777777", s + s1 + s2 + i + i + i + i + i + i + i + i);
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
if (!expected.equals(actual)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append(", actual = ");
|
||||
sb.append(actual);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 "+=" applied to String operands can provoke side effects
|
||||
* @bug 8204322
|
||||
*
|
||||
* @compile ImplicitStringConcatAssignLHS.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
|
||||
*
|
||||
* @compile -XDstringConcat=inline ImplicitStringConcatAssignLHS.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
|
||||
*
|
||||
* @compile -XDstringConcat=indy ImplicitStringConcatAssignLHS.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatAssignLHS.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
|
||||
*/
|
||||
import java.lang.StringBuilder;
|
||||
|
||||
public class ImplicitStringConcatAssignLHS {
|
||||
|
||||
static final int ARR_SIZE = 10; // enough padding to capture ill offsets
|
||||
|
||||
static int x;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
{
|
||||
x = 0;
|
||||
Object[] arr = new Object[ARR_SIZE];
|
||||
arr[x++] += "foo";
|
||||
check(1, "plain-plain Object[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getObjArray()[x++] += "foo";
|
||||
check(2, "method-plain Object[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getObjArray()[getIndex()] += "foo";
|
||||
check(2, "method-method Object[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
String[] arr = new String[ARR_SIZE];
|
||||
arr[x++] += "foo";
|
||||
check(1, "plain-plain String[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getStringArray()[x++] += "foo";
|
||||
check(2, "method-plain String[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getStringArray()[getIndex()] += "foo";
|
||||
check(2, "method-method String[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
CharSequence[] arr = new CharSequence[ARR_SIZE];
|
||||
arr[x++] += "foo";
|
||||
check(1, "plain-plain CharSequence[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getCharSequenceArray()[x++] += "foo";
|
||||
check(2, "method-plain CharSequence[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getCharSequenceArray()[getIndex()] += "foo";
|
||||
check(2, "method-method CharSequence[]");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
new MyClass().s += "foo";
|
||||
check(1, "MyClass::new (String)");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getMyClass().s += "foo";
|
||||
check(1, "method MyClass::new (String)");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
new MyClass().o += "foo";
|
||||
check(1, "MyClass::new (object)");
|
||||
}
|
||||
|
||||
{
|
||||
x = 0;
|
||||
getMyClass().o += "foo";
|
||||
check(1, "method MyClass::new (object)");
|
||||
}
|
||||
}
|
||||
|
||||
public static void check(int expected, String label) {
|
||||
if (x != expected) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(label);
|
||||
sb.append(": ");
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append("actual = ");
|
||||
sb.append(x);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static int getIndex() {
|
||||
return x++;
|
||||
}
|
||||
|
||||
public static class MyClass {
|
||||
Object o;
|
||||
String s;
|
||||
|
||||
public MyClass() {
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
public static MyClass getMyClass() {
|
||||
return new MyClass();
|
||||
}
|
||||
|
||||
public static Object[] getObjArray() {
|
||||
x++;
|
||||
return new Object[ARR_SIZE];
|
||||
}
|
||||
|
||||
public static String[] getStringArray() {
|
||||
x++;
|
||||
return new String[ARR_SIZE];
|
||||
}
|
||||
|
||||
public static CharSequence[] getCharSequenceArray() {
|
||||
x++;
|
||||
return new String[ARR_SIZE];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test the boundary values for concatenation arguments.
|
||||
*
|
||||
* @compile ImplicitStringConcatBoundaries.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
|
||||
*
|
||||
* @compile -XDstringConcat=inline ImplicitStringConcatBoundaries.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
|
||||
*
|
||||
* @compile -XDstringConcat=indy ImplicitStringConcatBoundaries.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatBoundaries.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
|
||||
*/
|
||||
|
||||
public class ImplicitStringConcatBoundaries {
|
||||
|
||||
public static final boolean BOOL_TRUE_1 = true;
|
||||
public static boolean BOOL_TRUE_2 = true;
|
||||
public static final boolean BOOL_FALSE_1 = false;
|
||||
public static boolean BOOL_FALSE_2 = false;
|
||||
|
||||
public static final byte BYTE_MIN_1 = Byte.MIN_VALUE;
|
||||
public static byte BYTE_MIN_2 = Byte.MIN_VALUE;
|
||||
public static final byte BYTE_MAX_1 = Byte.MAX_VALUE;
|
||||
public static byte BYTE_MAX_2 = Byte.MAX_VALUE;
|
||||
|
||||
public static final short SHORT_MIN_1 = Short.MIN_VALUE;
|
||||
public static short SHORT_MIN_2 = Short.MIN_VALUE;
|
||||
public static final short SHORT_MAX_1 = Short.MAX_VALUE;
|
||||
public static short SHORT_MAX_2 = Short.MAX_VALUE;
|
||||
|
||||
public static final char CHAR_MIN_1 = Character.MIN_VALUE;
|
||||
public static char CHAR_MIN_2 = Character.MIN_VALUE;
|
||||
public static final char CHAR_MAX_1 = Character.MAX_VALUE;
|
||||
public static char CHAR_MAX_2 = Character.MAX_VALUE;
|
||||
|
||||
public static final int INT_MIN_1 = Integer.MIN_VALUE;
|
||||
public static int INT_MIN_2 = Integer.MIN_VALUE;
|
||||
public static final int INT_MAX_1 = Integer.MAX_VALUE;
|
||||
public static int INT_MAX_2 = Integer.MAX_VALUE;
|
||||
|
||||
public static final float FLOAT_MIN_EXP_1 = Float.MIN_EXPONENT;
|
||||
public static float FLOAT_MIN_EXP_2 = Float.MIN_EXPONENT;
|
||||
public static final float FLOAT_MIN_NORM_1 = Float.MIN_NORMAL;
|
||||
public static float FLOAT_MIN_NORM_2 = Float.MIN_NORMAL;
|
||||
public static final float FLOAT_MIN_1 = Float.MIN_VALUE;
|
||||
public static float FLOAT_MIN_2 = Float.MIN_VALUE;
|
||||
public static final float FLOAT_MAX_1 = Float.MAX_VALUE;
|
||||
public static float FLOAT_MAX_2 = Float.MAX_VALUE;
|
||||
|
||||
public static final long LONG_MIN_1 = Long.MIN_VALUE;
|
||||
public static long LONG_MIN_2 = Long.MIN_VALUE;
|
||||
public static final long LONG_MAX_1 = Long.MAX_VALUE;
|
||||
public static long LONG_MAX_2 = Long.MAX_VALUE;
|
||||
|
||||
public static final double DOUBLE_MIN_EXP_1 = Double.MIN_EXPONENT;
|
||||
public static double DOUBLE_MIN_EXP_2 = Double.MIN_EXPONENT;
|
||||
public static final double DOUBLE_MIN_NORM_1 = Double.MIN_NORMAL;
|
||||
public static double DOUBLE_MIN_NORM_2 = Double.MIN_NORMAL;
|
||||
public static final double DOUBLE_MIN_1 = Double.MIN_VALUE;
|
||||
public static double DOUBLE_MIN_2 = Double.MIN_VALUE;
|
||||
public static final double DOUBLE_MAX_1 = Double.MAX_VALUE;
|
||||
public static double DOUBLE_MAX_2 = Double.MAX_VALUE;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test("foofalse", "foo" + BOOL_FALSE_1);
|
||||
test("foofalse", "foo" + BOOL_FALSE_2);
|
||||
test("footrue", "foo" + BOOL_TRUE_1);
|
||||
test("footrue", "foo" + BOOL_TRUE_2);
|
||||
|
||||
test("foo127", "foo" + BYTE_MAX_1);
|
||||
test("foo127", "foo" + BYTE_MAX_2);
|
||||
test("foo-128", "foo" + BYTE_MIN_1);
|
||||
test("foo-128", "foo" + BYTE_MIN_2);
|
||||
|
||||
test("foo32767", "foo" + SHORT_MAX_1);
|
||||
test("foo32767", "foo" + SHORT_MAX_2);
|
||||
test("foo-32768", "foo" + SHORT_MIN_1);
|
||||
test("foo-32768", "foo" + SHORT_MIN_2);
|
||||
|
||||
test("foo\u0000", "foo" + CHAR_MIN_1);
|
||||
test("foo\u0000", "foo" + CHAR_MIN_2);
|
||||
test("foo\uFFFF", "foo" + CHAR_MAX_1);
|
||||
test("foo\uFFFF", "foo" + CHAR_MAX_2);
|
||||
|
||||
test("foo2147483647", "foo" + INT_MAX_1);
|
||||
test("foo2147483647", "foo" + INT_MAX_2);
|
||||
test("foo-2147483648", "foo" + INT_MIN_1);
|
||||
test("foo-2147483648", "foo" + INT_MIN_2);
|
||||
|
||||
test("foo1.1754944E-38", "foo" + FLOAT_MIN_NORM_1);
|
||||
test("foo1.1754944E-38", "foo" + FLOAT_MIN_NORM_2);
|
||||
test("foo-126.0", "foo" + FLOAT_MIN_EXP_1);
|
||||
test("foo-126.0", "foo" + FLOAT_MIN_EXP_2);
|
||||
test("foo1.4E-45", "foo" + FLOAT_MIN_1);
|
||||
test("foo1.4E-45", "foo" + FLOAT_MIN_2);
|
||||
test("foo3.4028235E38", "foo" + FLOAT_MAX_1);
|
||||
test("foo3.4028235E38", "foo" + FLOAT_MAX_2);
|
||||
|
||||
test("foo-9223372036854775808", "foo" + LONG_MIN_1);
|
||||
test("foo-9223372036854775808", "foo" + LONG_MIN_2);
|
||||
test("foo9223372036854775807", "foo" + LONG_MAX_1);
|
||||
test("foo9223372036854775807", "foo" + LONG_MAX_2);
|
||||
|
||||
test("foo2.2250738585072014E-308", "foo" + DOUBLE_MIN_NORM_1);
|
||||
test("foo2.2250738585072014E-308", "foo" + DOUBLE_MIN_NORM_2);
|
||||
test("foo-1022.0", "foo" + DOUBLE_MIN_EXP_1);
|
||||
test("foo-1022.0", "foo" + DOUBLE_MIN_EXP_2);
|
||||
test("foo4.9E-324", "foo" + DOUBLE_MIN_1);
|
||||
test("foo4.9E-324", "foo" + DOUBLE_MIN_2);
|
||||
test("foo1.7976931348623157E308", "foo" + DOUBLE_MAX_1);
|
||||
test("foo1.7976931348623157E308", "foo" + DOUBLE_MAX_2);
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
if (!expected.equals(actual)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append(", actual = ");
|
||||
sb.append(actual);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
141
test/jdk/java/lang/String/concat/ImplicitStringConcatMany.java
Normal file
141
test/jdk/java/lang/String/concat/ImplicitStringConcatMany.java
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 implicit String concatenations with lots of arguments.
|
||||
*
|
||||
* @compile ImplicitStringConcatMany.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatMany
|
||||
*
|
||||
* @compile -XDstringConcat=inline ImplicitStringConcatMany.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatMany
|
||||
*
|
||||
* @compile -XDstringConcat=indy ImplicitStringConcatMany.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatMany
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatMany.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatMany
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ImplicitStringConcatMany {
|
||||
|
||||
static String s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
|
||||
static String s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
|
||||
static String s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
|
||||
static String s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
|
||||
static String s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
|
||||
static String s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
|
||||
static String s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
|
||||
static String s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
|
||||
static String s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
|
||||
static String s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
|
||||
|
||||
static String s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
|
||||
static String s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
|
||||
static String s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
|
||||
static String s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
|
||||
static String s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
|
||||
static String s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
|
||||
static String s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
|
||||
static String s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
|
||||
static String s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
|
||||
static String s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
|
||||
|
||||
static String s200, s201, s202, s203, s204, s205, s206, s207, s208, s209;
|
||||
static String s210, s211, s212, s213, s214, s215, s216, s217, s218, s219;
|
||||
static String s220, s221, s222, s223, s224, s225, s226, s227, s228, s229;
|
||||
static String s230, s231, s232, s233, s234, s235, s236, s237, s238, s239;
|
||||
static String s240, s241, s242, s243, s244, s245, s246, s247, s248, s249;
|
||||
static String s250, s251, s252, s253, s254, s255, s256, s257, s258, s259;
|
||||
static String s260, s261, s262, s263, s264, s265, s266, s267, s268, s269;
|
||||
static String s270, s271, s272, s273, s274, s275, s276, s277, s278, s279;
|
||||
static String s280, s281, s282, s283, s284, s285, s286, s287, s288, s289;
|
||||
static String s290, s291, s292, s293, s294, s295, s296, s297, s298, s299;
|
||||
|
||||
static {
|
||||
for (Field f : ImplicitStringConcatMany.class.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(f.getModifiers())) {
|
||||
String name = f.getName();
|
||||
try {
|
||||
f.set(null, name);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String res =
|
||||
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
|
||||
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
|
||||
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
|
||||
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
|
||||
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
|
||||
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
|
||||
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
|
||||
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
|
||||
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
|
||||
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
|
||||
|
||||
s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
|
||||
s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
|
||||
s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
|
||||
s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
|
||||
s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
|
||||
s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
|
||||
s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
|
||||
s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
|
||||
s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
|
||||
s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199 +
|
||||
|
||||
s200 + s201 + s202 + s203 + s204 + s205 + s206 + s207 + s208 + s209 +
|
||||
s210 + s211 + s212 + s213 + s214 + s215 + s216 + s217 + s218 + s219 +
|
||||
s220 + s221 + s222 + s223 + s224 + s225 + s226 + s227 + s228 + s229 +
|
||||
s230 + s231 + s232 + s233 + s234 + s235 + s236 + s237 + s238 + s239 +
|
||||
s240 + s241 + s242 + s243 + s244 + s245 + s246 + s247 + s248 + s249 +
|
||||
s250 + s251 + s252 + s253 + s254 + s255 + s256 + s257 + s258 + s259 +
|
||||
s260 + s261 + s262 + s263 + s264 + s265 + s266 + s267 + s268 + s269 +
|
||||
s270 + s271 + s272 + s273 + s274 + s275 + s276 + s277 + s278 + s279 +
|
||||
s280 + s281 + s282 + s283 + s284 + s285 + s286 + s287 + s288 + s289 +
|
||||
s290 + s291 + s292 + s293 + s294 + s295 + s296 + s297 + s298 + s299;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int c = 0; c < 300; c++) {
|
||||
sb.append(String.format("s%03d", c));
|
||||
}
|
||||
test(sb.toString(), res);
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
// Fingers crossed: String concat should work.
|
||||
if (!expected.equals(actual)) {
|
||||
throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 implicit String concatenations with lots of arguments (two-slot version)
|
||||
*
|
||||
* @compile ImplicitStringConcatManyLongs.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
|
||||
*
|
||||
* @compile -XDstringConcat=inline ImplicitStringConcatManyLongs.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
|
||||
*
|
||||
* @compile -XDstringConcat=indy ImplicitStringConcatManyLongs.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatManyLongs.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ImplicitStringConcatManyLongs {
|
||||
|
||||
static long s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
|
||||
static long s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
|
||||
static long s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
|
||||
static long s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
|
||||
static long s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
|
||||
static long s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
|
||||
static long s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
|
||||
static long s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
|
||||
static long s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
|
||||
static long s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
|
||||
|
||||
static long s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
|
||||
static long s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
|
||||
static long s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
|
||||
static long s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
|
||||
static long s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
|
||||
static long s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
|
||||
static long s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
|
||||
static long s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
|
||||
static long s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
|
||||
static long s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
|
||||
|
||||
static long s200, s201, s202, s203, s204, s205, s206, s207, s208, s209;
|
||||
static long s210, s211, s212, s213, s214, s215, s216, s217, s218, s219;
|
||||
static long s220, s221, s222, s223, s224, s225, s226, s227, s228, s229;
|
||||
static long s230, s231, s232, s233, s234, s235, s236, s237, s238, s239;
|
||||
static long s240, s241, s242, s243, s244, s245, s246, s247, s248, s249;
|
||||
static long s250, s251, s252, s253, s254, s255, s256, s257, s258, s259;
|
||||
static long s260, s261, s262, s263, s264, s265, s266, s267, s268, s269;
|
||||
static long s270, s271, s272, s273, s274, s275, s276, s277, s278, s279;
|
||||
static long s280, s281, s282, s283, s284, s285, s286, s287, s288, s289;
|
||||
static long s290, s291, s292, s293, s294, s295, s296, s297, s298, s299;
|
||||
|
||||
static {
|
||||
for (Field f : ImplicitStringConcatManyLongs.class.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(f.getModifiers())) {
|
||||
String name = f.getName();
|
||||
try {
|
||||
f.set(null, Long.valueOf(name.substring(1)));
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String res = "" +
|
||||
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
|
||||
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
|
||||
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
|
||||
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
|
||||
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
|
||||
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
|
||||
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
|
||||
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
|
||||
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
|
||||
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
|
||||
|
||||
s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
|
||||
s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
|
||||
s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
|
||||
s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
|
||||
s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
|
||||
s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
|
||||
s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
|
||||
s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
|
||||
s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
|
||||
s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199 +
|
||||
|
||||
s200 + s201 + s202 + s203 + s204 + s205 + s206 + s207 + s208 + s209 +
|
||||
s210 + s211 + s212 + s213 + s214 + s215 + s216 + s217 + s218 + s219 +
|
||||
s220 + s221 + s222 + s223 + s224 + s225 + s226 + s227 + s228 + s229 +
|
||||
s230 + s231 + s232 + s233 + s234 + s235 + s236 + s237 + s238 + s239 +
|
||||
s240 + s241 + s242 + s243 + s244 + s245 + s246 + s247 + s248 + s249 +
|
||||
s250 + s251 + s252 + s253 + s254 + s255 + s256 + s257 + s258 + s259 +
|
||||
s260 + s261 + s262 + s263 + s264 + s265 + s266 + s267 + s268 + s269 +
|
||||
s270 + s271 + s272 + s273 + s274 + s275 + s276 + s277 + s278 + s279 +
|
||||
s280 + s281 + s282 + s283 + s284 + s285 + s286 + s287 + s288 + s289 +
|
||||
s290 + s291 + s292 + s293 + s294 + s295 + s296 + s297 + s298 + s299;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int c = 0; c < 300; c++) {
|
||||
sb.append(c);
|
||||
}
|
||||
test(sb.toString(), res);
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
// Fingers crossed: String concat should work.
|
||||
if (!expected.equals(actual)) {
|
||||
throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
136
test/jdk/java/lang/String/concat/ImplicitStringConcatOOME.java
Normal file
136
test/jdk/java/lang/String/concat/ImplicitStringConcatOOME.java
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 8297530
|
||||
* @summary This sanity tests that OOME is correctly thrown when
|
||||
* the length of the array to be allocated for a concatenation.
|
||||
* Before the fix for 8297530 an IllegalArgumentException could
|
||||
* erroneously be thrown when the length of the string is between
|
||||
* Integer.MAX_VALUE / 2 and Integer.MAX_VALUE and the String coder
|
||||
* is UTF16.
|
||||
*
|
||||
* @requires sun.arch.data.model == "64"
|
||||
* @run main/othervm -Xverify:all -Xmx4g ImplicitStringConcatOOME
|
||||
* @run main/othervm -Xverify:all -Xmx4g -XX:-CompactStrings ImplicitStringConcatOOME
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ImplicitStringConcatOOME {
|
||||
|
||||
static String s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
|
||||
static String s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
|
||||
static String s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
|
||||
static String s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
|
||||
static String s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
|
||||
static String s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
|
||||
static String s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
|
||||
static String s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
|
||||
static String s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
|
||||
static String s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
|
||||
|
||||
static String s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
|
||||
static String s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
|
||||
static String s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
|
||||
static String s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
|
||||
static String s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
|
||||
static String s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
|
||||
static String s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
|
||||
static String s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
|
||||
static String s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
|
||||
static String s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
|
||||
|
||||
static String s_utf16;
|
||||
static {
|
||||
String s = "10 letters".repeat(1_073_742);
|
||||
for (Field f : ImplicitStringConcatOOME.class.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(f.getModifiers())) {
|
||||
try {
|
||||
f.set(null, s);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
s_utf16 = "\u0257";
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
String res =
|
||||
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
|
||||
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
|
||||
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
|
||||
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
|
||||
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
|
||||
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
|
||||
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
|
||||
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
|
||||
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
|
||||
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
|
||||
|
||||
s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
|
||||
s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
|
||||
s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
|
||||
s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
|
||||
s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
|
||||
s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
|
||||
s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
|
||||
s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
|
||||
s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
|
||||
s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199;
|
||||
throw new IllegalStateException("Expected OOME");
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Expected
|
||||
}
|
||||
try {
|
||||
// Compact Strings meant capacity for UTF16 strings were cut in
|
||||
// half, regardless of -XX:+CompactStrings setting
|
||||
String res =
|
||||
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
|
||||
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
|
||||
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
|
||||
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
|
||||
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
|
||||
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
|
||||
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
|
||||
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
|
||||
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
|
||||
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
|
||||
s_utf16;
|
||||
throw new IllegalStateException("Expected OOME");
|
||||
} catch (OutOfMemoryError e) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
// Fingers crossed: String concat should work.
|
||||
if (!expected.equals(actual)) {
|
||||
throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 implicit string concat calls argument conversions in the right order
|
||||
* @bug 8200118
|
||||
*
|
||||
* @compile ImplicitStringConcatOrder.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
|
||||
*
|
||||
* @compile -XDstringConcat=inline ImplicitStringConcatOrder.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
|
||||
*
|
||||
* @compile -XDstringConcat=indy ImplicitStringConcatOrder.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatOrder.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
|
||||
*/
|
||||
import java.lang.StringBuilder;
|
||||
|
||||
public class ImplicitStringConcatOrder {
|
||||
|
||||
static MyClass c = new MyClass();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
test("foo123bar", "foo" + c + c + c + "bar");
|
||||
test("bazxyz456abc", "baz" + ("xyz" + c + c) + c + "abc");
|
||||
test("caf7eba89be", "caf" + c + ("eba" + c + c) + "be");
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
if (!expected.equals(actual)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append(", actual = ");
|
||||
sb.append(actual);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static class MyClass {
|
||||
int x;
|
||||
public String toString() {
|
||||
return String.valueOf(++x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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 implicit String concatenations, multiple shapes.
|
||||
* @bug 8148483 8245959 8247681
|
||||
*
|
||||
* @compile ImplicitStringConcatShapes.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
|
||||
*
|
||||
* @compile -XDstringConcat=inline ImplicitStringConcatShapes.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
|
||||
*
|
||||
* @compile -XDstringConcat=indy ImplicitStringConcatShapes.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatShapes.java
|
||||
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
|
||||
*/
|
||||
public class ImplicitStringConcatShapes {
|
||||
public static void test(String expected, String actual) {
|
||||
// Fingers crossed: String concat should work.
|
||||
if (!expected.equals(actual)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append(", actual = ");
|
||||
sb.append(actual);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static class MyClass {
|
||||
private final int i;
|
||||
|
||||
public MyClass(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new StringBuilder("C(").append(i).append(")").toString();
|
||||
}
|
||||
}
|
||||
|
||||
static class MyClassNullToString {
|
||||
public String toString() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new ImplicitStringConcatShapes().run();
|
||||
}
|
||||
17401
test/jdk/java/lang/String/concat/ImplicitStringConcatShapes.java
Normal file
17401
test/jdk/java/lang/String/concat/ImplicitStringConcatShapes.java
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
public class ImplicitStringConcatShapesTestGen {
|
||||
public static String escapeToUnicode(String str) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (char c : str.toCharArray()) {
|
||||
if (c < 128) {
|
||||
b.append(c);
|
||||
} else {
|
||||
b.append("\\u").append(String.format("%04X", (int) c));
|
||||
}
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public static void main(String... args) throws IOException {
|
||||
PrintWriter pw = new PrintWriter(System.out);
|
||||
|
||||
String[] types = {
|
||||
"boolean",
|
||||
"byte",
|
||||
"byteMinus",
|
||||
"char",
|
||||
"short",
|
||||
"shortMinus",
|
||||
"int",
|
||||
"intMinus",
|
||||
"integer",
|
||||
"integerNull",
|
||||
"float",
|
||||
"floatMinus",
|
||||
"long",
|
||||
"longMinus",
|
||||
"double",
|
||||
"doubleMinus",
|
||||
"object",
|
||||
"objectNull",
|
||||
"objectNullToString",
|
||||
"String",
|
||||
"StringUTF16",
|
||||
"StringU1",
|
||||
"StringU2",
|
||||
"intArrayNull",
|
||||
"objectArrayNull",
|
||||
};
|
||||
|
||||
for (String t : Files.readAllLines(Paths.get("ImplicitStringConcatShapes-head.template"))) {
|
||||
pw.println(t);
|
||||
}
|
||||
|
||||
Map<String, String> values = new HashMap<>();
|
||||
|
||||
Random current = new Random(12345);
|
||||
for (int mode = 0; mode <= 2; mode++) {
|
||||
for (String type : types) {
|
||||
int i = current.nextInt(100);
|
||||
boolean isStatic = (mode | 1) == 1;
|
||||
boolean isFinal = (mode | 2) == 2;
|
||||
String fieldName = (isStatic ? "s" : "") + (isFinal ? "f" : "") + "_" + typeSig(type);
|
||||
String value = initValue(type, i);
|
||||
String stringValue = stringValue(type, i);
|
||||
values.put(fieldName, stringValue);
|
||||
pw.printf(" %s %s %s %s = %s;%n", isStatic ? "static" : "", isFinal ? "final" : "", typeValue(type, i), fieldName, value);
|
||||
}
|
||||
}
|
||||
|
||||
pw.println();
|
||||
|
||||
List<String> lines = new ArrayList<>();
|
||||
List<String> l = new ArrayList<>(values.keySet());
|
||||
|
||||
for (String l1 : l) {
|
||||
lines.add(String.format("test(\"%s\", \"\" + %s);",
|
||||
escapeToUnicode(values.get(l1)),
|
||||
l1
|
||||
));
|
||||
lines.add(String.format("test(\"%s\", \"prefix\" + %s);",
|
||||
escapeToUnicode("prefix" + values.get(l1)),
|
||||
l1
|
||||
));
|
||||
lines.add(String.format("test(\"%s\", %s + \"suffix\");",
|
||||
escapeToUnicode(values.get(l1) + "suffix"),
|
||||
l1
|
||||
));
|
||||
lines.add(String.format("test(\"%s\", \"prefix\" + %s + \"suffix\");",
|
||||
escapeToUnicode("prefix" + values.get(l1) + "suffix"),
|
||||
l1
|
||||
));
|
||||
}
|
||||
|
||||
for (String l1 : l) {
|
||||
for (String l2 : l) {
|
||||
lines.add(String.format("test(\"%s\", \"\" + %s + %s);",
|
||||
escapeToUnicode(values.get(l1) + values.get(l2)),
|
||||
l1, l2
|
||||
));
|
||||
lines.add(String.format("test(\"%s\", \"\" + %s + %s + \"suffix\");",
|
||||
escapeToUnicode(values.get(l1) + values.get(l2) + "suffix"),
|
||||
l1, l2
|
||||
));
|
||||
lines.add(String.format("test(\"%s\", \"prefix\" + %s + \"suffix1\" + %s + \"suffix2\");",
|
||||
escapeToUnicode("prefix" + values.get(l1) + "suffix1" + values.get(l2) + "suffix2"),
|
||||
l1, l2
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
final int STRIDE = 1000;
|
||||
int strides = lines.size() / STRIDE + 1;
|
||||
|
||||
pw.println(" public void run() {");
|
||||
for (int c = 0; c < strides; c++) {
|
||||
pw.println(" run" + c + "();");
|
||||
}
|
||||
pw.println(" }");
|
||||
pw.println();
|
||||
|
||||
for (int c = 0; c < strides; c++) {
|
||||
pw.println(" public void run" + c + "() {");
|
||||
for (String line : lines.subList(c * STRIDE, Math.min(lines.size(), (c+1) * STRIDE))) {
|
||||
pw.println(" " + line);
|
||||
}
|
||||
pw.println(" }");
|
||||
pw.println();
|
||||
}
|
||||
|
||||
pw.println("}");
|
||||
|
||||
pw.flush();
|
||||
pw.close();
|
||||
}
|
||||
|
||||
private static String typeSig(String type) {
|
||||
switch (type) {
|
||||
case "boolean": return "bl";
|
||||
case "byte": return "b";
|
||||
case "byteMinus": return "bM";
|
||||
case "short": return "s";
|
||||
case "shortMinus": return "sM";
|
||||
case "char": return "c";
|
||||
case "int": return "i";
|
||||
case "intMinus": return "iM";
|
||||
case "integer": return "I";
|
||||
case "integerNull": return "IN";
|
||||
case "float": return "f";
|
||||
case "floatMinus": return "fM";
|
||||
case "long": return "l";
|
||||
case "longMinus": return "lM";
|
||||
case "double": return "d";
|
||||
case "doubleMinus": return "dM";
|
||||
case "String": return "str";
|
||||
case "StringUTF16": return "strU";
|
||||
case "StringU1": return "strU1";
|
||||
case "StringU2": return "strU2";
|
||||
case "object": return "o";
|
||||
case "objectNull": return "oN";
|
||||
case "objectNullToString": return "oNtS";
|
||||
case "intArrayNull": return "iAN";
|
||||
case "objectArrayNull": return "oAN";
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private static String typeValue(String type, int i) {
|
||||
switch (type) {
|
||||
case "boolean":
|
||||
case "byte":
|
||||
case "byteMinus":
|
||||
case "char":
|
||||
case "short":
|
||||
case "shortMinus":
|
||||
case "int":
|
||||
case "intMinus":
|
||||
case "float":
|
||||
case "floatMinus":
|
||||
case "long":
|
||||
case "longMinus":
|
||||
case "double":
|
||||
case "doubleMinus":
|
||||
return type.replace("Minus", "");
|
||||
case "String":
|
||||
case "StringUTF16":
|
||||
case "StringU1":
|
||||
case "StringU2":
|
||||
return "String";
|
||||
case "object":
|
||||
case "objectNull":
|
||||
case "objectNullToString":
|
||||
return "Object";
|
||||
case "integer":
|
||||
case "integerNull":
|
||||
return "Integer";
|
||||
case "intArrayNull":
|
||||
return "int[]";
|
||||
case "objectArrayNull":
|
||||
return "Object[]";
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private static String initValue(String type, int i) {
|
||||
switch (type) {
|
||||
case "boolean":
|
||||
return String.valueOf((i & 1) == 1);
|
||||
case "byte":
|
||||
return String.valueOf(i);
|
||||
case "byteMinus":
|
||||
return String.valueOf(-i);
|
||||
case "short":
|
||||
return String.valueOf(i*100);
|
||||
case "shortMinus":
|
||||
return String.valueOf(-i*100);
|
||||
case "intMinus":
|
||||
return String.valueOf(-i*1_000_000);
|
||||
case "int":
|
||||
case "integer":
|
||||
return String.valueOf(i*1_000_000);
|
||||
case "long":
|
||||
return String.valueOf(i*1_000_000_000) + "L";
|
||||
case "longMinus":
|
||||
return String.valueOf(-i*1_000_000_000) + "L";
|
||||
case "char":
|
||||
return "'" + (char)(i % 26 + 65) + "'";
|
||||
case "double":
|
||||
return String.valueOf(i) + ".0d";
|
||||
case "doubleMinus":
|
||||
return "-" + String.valueOf(i) + ".0d";
|
||||
case "float":
|
||||
return String.valueOf(i) + ".0f";
|
||||
case "floatMinus":
|
||||
return "-" + String.valueOf(i) + ".0f";
|
||||
case "object":
|
||||
return "new MyClass(" + i + ")";
|
||||
case "objectNullToString":
|
||||
return "new MyClassNullToString()";
|
||||
case "integerNull":
|
||||
case "objectNull":
|
||||
case "intArrayNull":
|
||||
case "objectArrayNull":
|
||||
return "null";
|
||||
case "String":
|
||||
return "\"" + i + "\"";
|
||||
case "StringUTF16":
|
||||
return "\"\\u0451" + i + "\"";
|
||||
case "StringU1":
|
||||
return "\"\\u0001" + i + "\"";
|
||||
case "StringU2":
|
||||
return "\"\\u0002" + i + "\"";
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private static String stringValue(String type, int i) {
|
||||
switch (type) {
|
||||
case "boolean":
|
||||
return String.valueOf((i & 1) == 1);
|
||||
case "byte":
|
||||
return String.valueOf(i);
|
||||
case "byteMinus":
|
||||
return String.valueOf(-i);
|
||||
case "short":
|
||||
return String.valueOf(i*100);
|
||||
case "shortMinus":
|
||||
return String.valueOf(-i*100);
|
||||
case "intMinus":
|
||||
return String.valueOf(-i*1_000_000);
|
||||
case "int":
|
||||
case "integer":
|
||||
return String.valueOf(i*1_000_000);
|
||||
case "long":
|
||||
return String.valueOf(i*1_000_000_000);
|
||||
case "longMinus":
|
||||
return String.valueOf(-i*1_000_000_000);
|
||||
case "char":
|
||||
return String.valueOf((char) (i % 26 + 65));
|
||||
case "double":
|
||||
case "float":
|
||||
return String.valueOf(i) + ".0";
|
||||
case "doubleMinus":
|
||||
case "floatMinus":
|
||||
return "-" + String.valueOf(i) + ".0";
|
||||
case "object":
|
||||
return "C(" + i + ")";
|
||||
case "integerNull":
|
||||
case "objectNull":
|
||||
case "objectNullToString":
|
||||
case "intArrayNull":
|
||||
case "objectArrayNull":
|
||||
return "null";
|
||||
case "String":
|
||||
return "" + i;
|
||||
case "StringUTF16":
|
||||
return "\u0451" + i;
|
||||
case "StringU1":
|
||||
return "\u0001" + i;
|
||||
case "StringU2":
|
||||
return "\u0002" + i;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
60
test/jdk/java/lang/String/concat/IntegerMinValue.java
Normal file
60
test/jdk/java/lang/String/concat/IntegerMinValue.java
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8267773
|
||||
* @summary Test
|
||||
*
|
||||
* @compile IntegerMinValue.java
|
||||
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
|
||||
*
|
||||
* @compile -XDstringConcat=inline IntegerMinValue.java
|
||||
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
|
||||
*
|
||||
* @compile -XDstringConcat=indy IntegerMinValue.java
|
||||
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
|
||||
*
|
||||
* @compile -XDstringConcat=indyWithConstants IntegerMinValue.java
|
||||
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
|
||||
*/
|
||||
|
||||
public class IntegerMinValue {
|
||||
|
||||
public void test() {
|
||||
int i = Integer.MIN_VALUE;
|
||||
String s = "" + i;
|
||||
if (!"-2147483648".equals(s)) {
|
||||
throw new IllegalStateException("Failed: " + s);
|
||||
}
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
public static void main(String[] strArr) {
|
||||
IntegerMinValue t = new IntegerMinValue();
|
||||
for (int i = 0; i < 100_000; i++ ) {
|
||||
t.test();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please 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.Serializable;
|
||||
import java.lang.invoke.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test input invariants for StringConcatFactory
|
||||
* @bug 8246152 8247681
|
||||
*
|
||||
* @compile StringConcatFactoryInvariants.java
|
||||
*
|
||||
* @run main/othervm -Xverify:all StringConcatFactoryInvariants
|
||||
*
|
||||
*/
|
||||
public class StringConcatFactoryInvariants {
|
||||
|
||||
private static final char TAG_ARG = '\u0001';
|
||||
private static final char TAG_CONST = '\u0002';
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
String methodName = "foo";
|
||||
MethodType mt = MethodType.methodType(String.class, String.class, int.class);
|
||||
String recipe = "" + TAG_ARG + TAG_ARG + TAG_CONST;
|
||||
Object[][] constants = new Object[][] {
|
||||
new String[] { "" },
|
||||
new String[] { "bar" },
|
||||
new Integer[] { 1 },
|
||||
new Short[] { 2 },
|
||||
new Long[] { 3L },
|
||||
new Boolean[] { true },
|
||||
new Character[] { 'a' },
|
||||
new Byte[] { -128 },
|
||||
new Class[] { String.class },
|
||||
new MethodHandle[] { MethodHandles.constant(String.class, "constant") },
|
||||
new MethodType[] { MethodType.methodType(String.class) }
|
||||
};
|
||||
// The string representation that should end up if the corresponding
|
||||
// Object[] in constants is used as an argument to makeConcatWithConstants
|
||||
String[] constantString = new String[] {
|
||||
"",
|
||||
"bar",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"true",
|
||||
"a",
|
||||
"-128",
|
||||
"class java.lang.String",
|
||||
"MethodHandle()String",
|
||||
"()String"
|
||||
};
|
||||
|
||||
|
||||
final int LIMIT = 200;
|
||||
|
||||
// Simple factory: check for dynamic arguments overflow
|
||||
Class<?>[] underThreshold = new Class<?>[LIMIT - 1];
|
||||
Class<?>[] threshold = new Class<?>[LIMIT];
|
||||
Class<?>[] overThreshold = new Class<?>[LIMIT + 1];
|
||||
|
||||
StringBuilder sbUnderThreshold = new StringBuilder();
|
||||
sbUnderThreshold.append(TAG_CONST);
|
||||
for (int c = 0; c < LIMIT - 1; c++) {
|
||||
underThreshold[c] = int.class;
|
||||
threshold[c] = int.class;
|
||||
overThreshold[c] = int.class;
|
||||
sbUnderThreshold.append(TAG_ARG);
|
||||
}
|
||||
threshold[LIMIT - 1] = int.class;
|
||||
overThreshold[LIMIT - 1] = int.class;
|
||||
overThreshold[LIMIT] = int.class;
|
||||
|
||||
String recipeEmpty = "";
|
||||
String recipeUnderThreshold = sbUnderThreshold.toString();
|
||||
String recipeThreshold = sbUnderThreshold.append(TAG_ARG).toString();
|
||||
String recipeOverThreshold = sbUnderThreshold.append(TAG_ARG).toString();
|
||||
|
||||
MethodType mtEmpty = MethodType.methodType(String.class);
|
||||
MethodType mtUnderThreshold = MethodType.methodType(String.class, underThreshold);
|
||||
MethodType mtThreshold = MethodType.methodType(String.class, threshold);
|
||||
MethodType mtOverThreshold = MethodType.methodType(String.class, overThreshold);
|
||||
|
||||
|
||||
// Check the basic functionality is working
|
||||
{
|
||||
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, mt);
|
||||
test("foo42", (String) cs.getTarget().invokeExact("foo", 42));
|
||||
}
|
||||
|
||||
{
|
||||
for (int i = 0; i < constants.length; i++) {
|
||||
CallSite cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, constants[i]);
|
||||
test("foo42".concat(constantString[i]), (String) cs.getTarget().invokeExact("foo", 42));
|
||||
}
|
||||
}
|
||||
|
||||
// Check unary expressions with pre- and postfix constants
|
||||
{
|
||||
String constArgRecipe = "" + TAG_CONST + TAG_ARG;
|
||||
String argConstRecipe = "" + TAG_ARG + TAG_CONST;
|
||||
MethodType unaryMt = MethodType.methodType(String.class, String.class);
|
||||
|
||||
for (int i = 0; i < constants.length; i++) {
|
||||
CallSite prefixCS = StringConcatFactory.makeConcatWithConstants(lookup, methodName, unaryMt, constArgRecipe, constants[i]);
|
||||
test(constantString[i].concat("foo"), (String) prefixCS.getTarget().invokeExact("foo"));
|
||||
|
||||
CallSite postfixCS = StringConcatFactory.makeConcatWithConstants(lookup, methodName, unaryMt, argConstRecipe, constants[i]);
|
||||
test("foo".concat(constantString[i]), (String) postfixCS.getTarget().invokeExact("foo"));
|
||||
}
|
||||
}
|
||||
|
||||
// Simple factory, check for nulls:
|
||||
failNPE("Lookup is null",
|
||||
() -> StringConcatFactory.makeConcat(null, methodName, mt));
|
||||
|
||||
failNPE("Method name is null",
|
||||
() -> StringConcatFactory.makeConcat(lookup, null, mt));
|
||||
|
||||
failNPE("MethodType is null",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, null));
|
||||
|
||||
// Advanced factory, check for nulls:
|
||||
for (int i = 0; i < constants.length; i++) {
|
||||
final Object[] consts = constants[i];
|
||||
|
||||
failNPE("Lookup is null",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, consts));
|
||||
|
||||
failNPE("Method name is null",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, consts));
|
||||
|
||||
failNPE("MethodType is null",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, consts));
|
||||
|
||||
failNPE("Recipe is null",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, consts));
|
||||
}
|
||||
|
||||
failNPE("Constants vararg is null",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, (Object[]) null));
|
||||
|
||||
failNPE("Constant argument is null",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, new Object[] { null }));
|
||||
|
||||
// Simple factory, check for return type
|
||||
fail("Return type: void",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(void.class, String.class, int.class)));
|
||||
|
||||
fail("Return type: int",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(int.class, String.class, int.class)));
|
||||
|
||||
fail("Return type: StringBuilder",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class)));
|
||||
|
||||
ok("Return type: Object",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class)));
|
||||
|
||||
ok("Return type: CharSequence",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class)));
|
||||
|
||||
ok("Return type: Serializable",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class)));
|
||||
|
||||
// Advanced factory, check for return types
|
||||
for (int i = 0; i < constants.length; i++) {
|
||||
final Object[] consts = constants[i];
|
||||
fail("Return type: void",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, consts));
|
||||
|
||||
fail("Return type: int",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(int.class, String.class, int.class), recipe, consts));
|
||||
|
||||
fail("Return type: StringBuilder",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class), recipe, consts));
|
||||
|
||||
ok("Return type: Object",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, consts));
|
||||
|
||||
ok("Return type: CharSequence",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, consts));
|
||||
|
||||
ok("Return type: Serializable",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, consts));
|
||||
}
|
||||
|
||||
// Simple factory: check for dynamic arguments overflow
|
||||
ok("Dynamic arguments is under limit",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, mtUnderThreshold));
|
||||
|
||||
ok("Dynamic arguments is at the limit",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, mtThreshold));
|
||||
|
||||
fail("Dynamic arguments is over the limit",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, mtOverThreshold));
|
||||
|
||||
// Advanced factory: check for dynamic arguments overflow
|
||||
ok("Dynamic arguments is under limit",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtUnderThreshold, recipeUnderThreshold, constants[0]));
|
||||
|
||||
ok("Dynamic arguments is at the limit",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants[0]));
|
||||
|
||||
fail("Dynamic arguments is over the limit",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtOverThreshold, recipeOverThreshold, constants[0]));
|
||||
|
||||
// Advanced factory: check for mismatched recipe and Constants
|
||||
ok("Static arguments and recipe match",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar"));
|
||||
|
||||
fail("Static arguments and recipe mismatch: too few",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold));
|
||||
|
||||
fail("Static arguments and recipe mismatch: too many",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar", "baz"));
|
||||
|
||||
failNPE("Static arguments and recipe mismatch, too many, overflowing constant is null",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar", null));
|
||||
|
||||
// Advanced factory: check for mismatched recipe and dynamic arguments
|
||||
fail("Dynamic arguments and recipe mismatch",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeUnderThreshold, constants[0]));
|
||||
|
||||
ok("Dynamic arguments and recipe match",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants[0]));
|
||||
|
||||
fail("Dynamic arguments and recipe mismatch",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeOverThreshold, constants[0]));
|
||||
|
||||
// Test passing array as constant
|
||||
{
|
||||
Object[] arg = {"boo", "bar"};
|
||||
|
||||
CallSite cs1 = StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST + TAG_CONST, arg);
|
||||
test("42boobar", (String) cs1.getTarget().invokeExact(42));
|
||||
}
|
||||
|
||||
// Test passing null constant
|
||||
ok("Can pass regular constants",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, "foo"));
|
||||
|
||||
failNPE("Cannot pass null constants",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, new Object[]{null}));
|
||||
|
||||
// Simple factory: test empty arguments
|
||||
ok("Ok to pass empty arguments",
|
||||
() -> StringConcatFactory.makeConcat(lookup, methodName, mtEmpty));
|
||||
|
||||
// Advanced factory: test empty arguments
|
||||
ok("Ok to pass empty arguments",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtEmpty, recipeEmpty));
|
||||
|
||||
// Simple factory: public Lookup is rejected
|
||||
fail("Passing public Lookup",
|
||||
() -> StringConcatFactory.makeConcat(MethodHandles.publicLookup(), methodName, mtEmpty));
|
||||
|
||||
// Advanced factory: public Lookup is rejected
|
||||
fail("Passing public Lookup",
|
||||
() -> StringConcatFactory.makeConcatWithConstants(MethodHandles.publicLookup(), methodName, mtEmpty, recipeEmpty));
|
||||
|
||||
// Zero inputs
|
||||
{
|
||||
MethodType zero = MethodType.methodType(String.class);
|
||||
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, zero);
|
||||
test("", (String) cs.getTarget().invokeExact());
|
||||
|
||||
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "");
|
||||
test("", (String) cs.getTarget().invokeExact());
|
||||
}
|
||||
|
||||
// One input
|
||||
{
|
||||
MethodType zero = MethodType.methodType(String.class);
|
||||
MethodType one = MethodType.methodType(String.class, String.class);
|
||||
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, one);
|
||||
test("A", (String) cs.getTarget().invokeExact("A"));
|
||||
|
||||
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, one, "\1");
|
||||
test("A", (String) cs.getTarget().invokeExact("A"));
|
||||
|
||||
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "\2", "A");
|
||||
test("A", (String) cs.getTarget().invokeExact());
|
||||
}
|
||||
}
|
||||
|
||||
public static void ok(String msg, Callable runnable) {
|
||||
try {
|
||||
runnable.call();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalStateException(msg + ", should have passed", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void fail(String msg, Callable runnable) {
|
||||
boolean expected = false;
|
||||
try {
|
||||
runnable.call();
|
||||
} catch (StringConcatException e) {
|
||||
expected = true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!expected) {
|
||||
throw new IllegalStateException(msg + ", should have failed with StringConcatException");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void failNPE(String msg, Callable runnable) {
|
||||
boolean expected = false;
|
||||
try {
|
||||
runnable.call();
|
||||
} catch (NullPointerException e) {
|
||||
expected = true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!expected) {
|
||||
throw new IllegalStateException(msg + ", should have failed with NullPointerException");
|
||||
}
|
||||
}
|
||||
|
||||
public static void test(String expected, String actual) {
|
||||
// Fingers crossed: String concat should work.
|
||||
if (!expected.equals(actual)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Expected = ");
|
||||
sb.append(expected);
|
||||
sb.append(", actual = ");
|
||||
sb.append(actual);
|
||||
throw new IllegalStateException(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.StringConcatFactory;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary StringConcatFactory allow recipes with repeated constants, but this
|
||||
* is not expressible with java code and needs an explicit sanity test
|
||||
* @bug 8222852
|
||||
*
|
||||
* @compile StringConcatFactoryRepeatedConstants.java
|
||||
*
|
||||
* @run main/othervm -Xverify:all StringConcatFactoryRepeatedConstants
|
||||
*/
|
||||
public class StringConcatFactoryRepeatedConstants {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
CallSite site = StringConcatFactory.makeConcatWithConstants(
|
||||
MethodHandles.lookup(),
|
||||
"foo",
|
||||
MethodType.methodType(String.class),
|
||||
"\u0002\u0002",
|
||||
"foo", "bar"
|
||||
);
|
||||
String string = (String)site.dynamicInvoker().invoke();
|
||||
if (!"foobar".equals(string)) {
|
||||
throw new IllegalStateException("Expected: foobar, got: " + string);
|
||||
}
|
||||
|
||||
site = StringConcatFactory.makeConcatWithConstants(
|
||||
MethodHandles.lookup(),
|
||||
"foo",
|
||||
MethodType.methodType(String.class),
|
||||
"\u0002\u0002test\u0002\u0002",
|
||||
"foo", 17.0f, 4711L, "bar"
|
||||
);
|
||||
string = (String)site.dynamicInvoker().invoke();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("foo").append(17.0f).append("test").append(4711L).append("bar");
|
||||
if (!sb.toString().equals(string)) {
|
||||
throw new IllegalStateException("Expected: " + sb.toString() + ", got: " + string);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
26
test/jdk/java/lang/String/concat/update-tests.sh
Normal file
26
test/jdk/java/lang/String/concat/update-tests.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# 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.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
javac ImplicitStringConcatShapesTestGen.java
|
||||
java ImplicitStringConcatShapesTestGen > ImplicitStringConcatShapes.java
|
||||
rm ImplicitStringConcatShapesTestGen.class
|
||||
Loading…
Add table
Add a link
Reference in a new issue