d2827ec8f7
Reviewed-by: thartmann, kvn
187 lines
7.8 KiB
Java
187 lines
7.8 KiB
Java
/*
|
|
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8173585
|
|
* @summary Test intrinsification of StringLatin1.indexOf(char). Note that
|
|
* differing code paths are taken contingent upon the length of the input String.
|
|
* Hence we must test against differing string lengths in order to validate
|
|
* correct functionality. We also ensure the strings are long enough to trigger
|
|
* the looping conditions of the individual code paths.
|
|
*
|
|
* Run with varing levels of AVX and SSE support, also without the intrinsic at all
|
|
*
|
|
* @requires vm.compiler2.enabled
|
|
* @library /compiler/patches /test/lib /
|
|
* @build jdk.test.whitebox.WhiteBox
|
|
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
* -Xbatch compiler.intrinsics.string.TestStringLatin1IndexOfChar
|
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
* -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_indexOfL_char compiler.intrinsics.string.TestStringLatin1IndexOfChar
|
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
* -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=0 compiler.intrinsics.string.TestStringLatin1IndexOfChar
|
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
* -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=1 compiler.intrinsics.string.TestStringLatin1IndexOfChar
|
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
* -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=2 compiler.intrinsics.string.TestStringLatin1IndexOfChar
|
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
|
* -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=3 compiler.intrinsics.string.TestStringLatin1IndexOfChar
|
|
*/
|
|
|
|
package compiler.intrinsics.string;
|
|
|
|
import jdk.test.lib.Asserts;
|
|
import jdk.test.whitebox.WhiteBox;
|
|
import java.lang.reflect.Method;
|
|
import compiler.whitebox.CompilerWhiteBoxTest;
|
|
|
|
public class TestStringLatin1IndexOfChar{
|
|
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
|
private final static int MAX_LENGTH = 2048;//future proof for AVX-512 instructions
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
Method methodFindOneItem = TestStringLatin1IndexOfChar.class.getDeclaredMethod("findOneItem");
|
|
Method methodWithOffsetTest = TestStringLatin1IndexOfChar.class.getDeclaredMethod("withOffsetTest");
|
|
Method methodTestEmpty = TestStringLatin1IndexOfChar.class.getDeclaredMethod("testEmpty");
|
|
Asserts.assertNotNull(methodFindOneItem);
|
|
Asserts.assertNotNull(methodWithOffsetTest);
|
|
Asserts.assertNotNull(methodTestEmpty);
|
|
|
|
// Warmup - profiling must inline the methods
|
|
for (int i = 0; i < 10; ++i) {
|
|
findOneItem();
|
|
withOffsetTest();
|
|
testEmpty();
|
|
}
|
|
|
|
// Compile
|
|
WHITE_BOX.enqueueMethodForCompilation(methodFindOneItem, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
|
|
WHITE_BOX.enqueueMethodForCompilation(methodWithOffsetTest, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
|
|
WHITE_BOX.enqueueMethodForCompilation(methodTestEmpty, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
|
|
|
|
// Run compiled method
|
|
for (int i = 0; i < 10; ++i) {
|
|
findOneItem();
|
|
withOffsetTest();
|
|
testEmpty();
|
|
}
|
|
}
|
|
|
|
private static void testEmpty(){
|
|
Asserts.assertEQ("".indexOf('a'), -1);
|
|
}
|
|
|
|
private final static char SEARCH_CHAR = 'z';
|
|
private final static char INVERLEAVING_CHAR = 'a';
|
|
private final static char MISSING_CHAR = 'd';
|
|
|
|
private static void findOneItem(){
|
|
//test strings of varying length ensuring that for all lengths one instance of the
|
|
//search char can be found. We check what happens when the search character is in
|
|
//each position of the search string (including first and last positions)
|
|
for(int strLength : new int[]{1, 15, 31, 32, 79}){
|
|
for(int searchPos = 0; searchPos < strLength; searchPos++){
|
|
String totest = makeOneItemStringLatin1(strLength, searchPos);
|
|
|
|
int intri = totest.indexOf(SEARCH_CHAR);
|
|
int nonintri = indexOfCharNonIntrinsic(totest, SEARCH_CHAR, 0);
|
|
Asserts.assertEQ(intri, nonintri);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static String makeOneItemStringLatin1(int length, int searchPos){
|
|
StringBuilder sb = new StringBuilder(length);
|
|
|
|
for(int n =0; n < length; n++){
|
|
sb.append(searchPos==n?SEARCH_CHAR:INVERLEAVING_CHAR);
|
|
}
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
private static void withOffsetTest(){
|
|
//progressivly move through string checking indexes and starting offset correctly processed
|
|
//string is of form azaza, aazaazaa, aaazaaazaaa, etc
|
|
//we find n s.t. maxlength = (n*3) + 2
|
|
int maxaInstances = (MAX_LENGTH-2)/3;
|
|
|
|
for(int aInstances = 5; aInstances < MAX_LENGTH; aInstances++){
|
|
String totest = makeWithOffsetStringLatin1(aInstances);
|
|
|
|
int startoffset;
|
|
{
|
|
int intri = totest.indexOf(SEARCH_CHAR);
|
|
int nonintri = indexOfCharNonIntrinsic(totest, SEARCH_CHAR, 0);
|
|
|
|
Asserts.assertEQ(intri, nonintri);
|
|
startoffset = intri+1;
|
|
}
|
|
|
|
{
|
|
int intri = totest.indexOf(SEARCH_CHAR, startoffset);
|
|
int nonintri = indexOfCharNonIntrinsic(totest, SEARCH_CHAR, startoffset);
|
|
|
|
Asserts.assertEQ(intri, nonintri);
|
|
startoffset = intri+1;
|
|
}
|
|
|
|
Asserts.assertEQ(totest.indexOf(SEARCH_CHAR, startoffset), -1);//only two SEARCH_CHAR per string
|
|
Asserts.assertEQ(totest.indexOf(MISSING_CHAR), -1);
|
|
}
|
|
}
|
|
|
|
private static String makeWithOffsetStringLatin1(int aInstances){
|
|
StringBuilder sb = new StringBuilder((aInstances*3) + 2);
|
|
for(int n =0; n < aInstances; n++){
|
|
sb.append(INVERLEAVING_CHAR);
|
|
}
|
|
|
|
sb.append(SEARCH_CHAR);
|
|
|
|
for(int n =0; n < aInstances; n++){
|
|
sb.append(INVERLEAVING_CHAR);
|
|
}
|
|
|
|
sb.append(SEARCH_CHAR);
|
|
|
|
for(int n =0; n < aInstances; n++){
|
|
sb.append(INVERLEAVING_CHAR);
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
private static int indexOfCharNonIntrinsic(String value, int ch, int fromIndex) {
|
|
//non intrinsic version of indexOfChar
|
|
byte c = (byte)ch;
|
|
for (int i = fromIndex; i < value.length(); i++) {
|
|
if (value.charAt(i) == c) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|