--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java 2019-03-09 03:57:24.033215476 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java 2019-03-09 03:57:23.673212930 +0100 @@ -24,25 +24,27 @@ package org.graalvm.compiler.replacements.amd64; +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.nodes.DeoptimizeNode; +import org.graalvm.compiler.replacements.ReplacementsUtil; +import org.graalvm.compiler.replacements.StringUTF16Substitutions; import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; +import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.Pointer; -import jdk.vm.ci.meta.DeoptimizationAction; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; - // JaCoCo Exclude /** * Substitutions for {@code java.lang.StringUTF16} methods. - * + *

* Since JDK 9. */ @ClassSubstitution(className = "java.lang.StringUTF16", optional = true) @@ -68,9 +70,15 @@ return metaAccess.getArrayIndexScale(JavaKind.Char); } - /** Marker value for the {@link InjectedParameter} injected parameter. */ + /** + * Marker value for the {@link InjectedParameter} injected parameter. + */ static final MetaAccessProvider INJECTED = null; + public static int length(byte[] value) { + return value.length >> 1; + } + /** * @param value is char[] * @param other is char[] @@ -93,9 +101,9 @@ return ArrayCompareToNode.compareTo(other, value, other.length, value.length, JavaKind.Char, JavaKind.Byte); } - @MethodSubstitution(optional = true) + @MethodSubstitution public static int indexOfCharUnsafe(byte[] value, int ch, int fromIndex, int max) { - Pointer sourcePointer = Word.objectToTrackedPointer(value).add(byteArrayBaseOffset(INJECTED)).add(fromIndex * charArrayIndexScale(INJECTED)); + Pointer sourcePointer = charOffsetPointer(value, fromIndex); int result = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, max - fromIndex, (char) ch); if (result != -1) { return result + fromIndex; @@ -103,6 +111,100 @@ return result; } + private static Word pointer(byte[] target) { + return Word.objectToTrackedPointer(target).add(byteArrayBaseOffset(INJECTED)); + } + + private static Word charOffsetPointer(byte[] value, int offset) { + return pointer(value).add(offset * charArrayIndexScale(INJECTED)); + } + + @MethodSubstitution + public static int indexOfUnsafe(byte[] source, int sourceCount, byte[] target, int targetCount, int fromIndex) { + ReplacementsUtil.runtimeAssert(fromIndex >= 0, "StringUTF16.indexOfUnsafe invalid args: fromIndex negative"); + ReplacementsUtil.runtimeAssert(targetCount > 0, "StringUTF16.indexOfUnsafe invalid args: targetCount <= 0"); + ReplacementsUtil.runtimeAssert(targetCount <= length(target), "StringUTF16.indexOfUnsafe invalid args: targetCount > length(target)"); + ReplacementsUtil.runtimeAssert(sourceCount >= targetCount, "StringUTF16.indexOfUnsafe invalid args: sourceCount < targetCount"); + int totalOffset = fromIndex; + if (targetCount == 1) { + Pointer sourcePointer = charOffsetPointer(source, totalOffset); + int indexOfResult = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, StringUTF16Substitutions.getChar(target, 0)); + if (indexOfResult >= 0) { + return indexOfResult + totalOffset; + } + return indexOfResult; + } else if (targetCount == 2) { + Pointer sourcePointer = charOffsetPointer(source, totalOffset); + int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, sourceCount - fromIndex, StringUTF16Substitutions.getChar(target, 0), + StringUTF16Substitutions.getChar(target, 1)); + if (indexOfResult >= 0) { + return indexOfResult + totalOffset; + } + return indexOfResult; + } else { + int haystackLength = sourceCount - (fromIndex + (targetCount - 2)); + while (haystackLength > 0) { + Pointer sourcePointer = charOffsetPointer(source, totalOffset); + int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, haystackLength, StringUTF16Substitutions.getChar(target, 0), + StringUTF16Substitutions.getChar(target, 1)); + if (indexOfResult < 0) { + return -1; + } + totalOffset += indexOfResult; + haystackLength -= (indexOfResult + 1); + Pointer cmpSourcePointer = charOffsetPointer(source, totalOffset); + Pointer targetPointer = pointer(target); + if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Char)) { + return totalOffset; + } + totalOffset++; + } + return -1; + } + } + + @MethodSubstitution + public static int indexOfLatin1Unsafe(byte[] source, int sourceCount, byte[] target, int targetCount, int fromIndex) { + ReplacementsUtil.runtimeAssert(fromIndex >= 0, "StringUTF16.indexOfLatin1Unsafe invalid args: fromIndex negative"); + ReplacementsUtil.runtimeAssert(targetCount > 0, "StringUTF16.indexOfLatin1Unsafe invalid args: targetCount <= 0"); + ReplacementsUtil.runtimeAssert(targetCount <= target.length, "StringUTF16.indexOfLatin1Unsafe invalid args: targetCount > length(target)"); + ReplacementsUtil.runtimeAssert(sourceCount >= targetCount, "StringUTF16.indexOfLatin1Unsafe invalid args: sourceCount < targetCount"); + int totalOffset = fromIndex; + if (targetCount == 1) { + Pointer sourcePointer = charOffsetPointer(source, totalOffset); + int indexOfResult = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, (char) Byte.toUnsignedInt(target[0])); + if (indexOfResult >= 0) { + return indexOfResult + totalOffset; + } + return indexOfResult; + } else if (targetCount == 2) { + Pointer sourcePointer = charOffsetPointer(source, totalOffset); + int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, sourceCount - fromIndex, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1])); + if (indexOfResult >= 0) { + return indexOfResult + totalOffset; + } + return indexOfResult; + } else { + int haystackLength = sourceCount - (fromIndex + (targetCount - 2)); + while (haystackLength > 0) { + Pointer sourcePointer = charOffsetPointer(source, totalOffset); + int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, haystackLength, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1])); + if (indexOfResult < 0) { + return -1; + } + totalOffset += indexOfResult; + haystackLength -= (indexOfResult + 1); + Pointer cmpSourcePointer = charOffsetPointer(source, totalOffset); + Pointer targetPointer = pointer(target); + if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Char, JavaKind.Byte)) { + return totalOffset; + } + totalOffset++; + } + return -1; + } + } + /** * Intrinsic for {@code java.lang.StringUTF16.compress([CI[BII)I}. * @@ -129,7 +231,7 @@ * @HotSpotIntrinsicCandidate * public static int compress(byte[] src, int src_indx, byte[] dst, int dst_indx, int len) * - * + *

* In this variant {@code dest} refers to a byte array containing 2 byte per char so * {@code srcIndex} and {@code len} are in terms of char elements and have to be scaled by 2 * when referring to {@code src}.