7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.replacements.amd64; 26 27 import org.graalvm.compiler.api.replacements.ClassSubstitution; 28 import org.graalvm.compiler.api.replacements.Fold; 29 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; 30 import org.graalvm.compiler.api.replacements.MethodSubstitution; 31 import org.graalvm.compiler.nodes.DeoptimizeNode; 32 import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; 33 import org.graalvm.compiler.word.Word; 34 import jdk.internal.vm.compiler.word.Pointer; 35 36 import jdk.vm.ci.meta.DeoptimizationAction; 37 import jdk.vm.ci.meta.DeoptimizationReason; 38 import jdk.vm.ci.meta.JavaKind; 39 import jdk.vm.ci.meta.MetaAccessProvider; 40 41 // JaCoCo Exclude 42 43 /** 44 * Substitutions for {@code java.lang.StringUTF16} methods. 45 * 46 * Since JDK 9. 47 */ 48 @ClassSubstitution(className = "java.lang.StringUTF16", optional = true) 49 public class AMD64StringUTF16Substitutions { 50 51 @Fold 52 static int byteArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { 53 return metaAccess.getArrayBaseOffset(JavaKind.Byte); 54 } 55 56 @Fold 57 static int byteArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { 58 return metaAccess.getArrayIndexScale(JavaKind.Byte); 59 } 60 61 @Fold 62 static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { 63 return metaAccess.getArrayBaseOffset(JavaKind.Char); 64 } 65 66 @Fold 67 static int charArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { 68 return metaAccess.getArrayIndexScale(JavaKind.Char); 69 } 70 71 /** Marker value for the {@link InjectedParameter} injected parameter. */ 72 static final MetaAccessProvider INJECTED = null; 73 74 /** 75 * @param value is char[] 76 * @param other is char[] 77 */ 78 @MethodSubstitution 79 public static int compareTo(byte[] value, byte[] other) { 80 return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Char, JavaKind.Char); 81 } 82 83 /** 84 * @param value is char[] 85 * @param other is byte[] 86 */ 87 @MethodSubstitution 88 public static int compareToLatin1(byte[] value, byte[] other) { 89 /* 90 * Swapping array arguments because intrinsic expects order to be byte[]/char[] but kind 91 * arguments stay in original order. 92 */ 93 return ArrayCompareToNode.compareTo(other, value, other.length, value.length, JavaKind.Char, JavaKind.Byte); 94 } 95 96 @MethodSubstitution(optional = true) 97 public static int indexOfCharUnsafe(byte[] value, int ch, int fromIndex, int max) { 98 Pointer sourcePointer = Word.objectToTrackedPointer(value).add(byteArrayBaseOffset(INJECTED)).add(fromIndex * charArrayIndexScale(INJECTED)); 99 int result = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, max - fromIndex, (char) ch); 100 if (result != -1) { 101 return result + fromIndex; 102 } 103 return result; 104 } 105 106 /** 107 * Intrinsic for {@code java.lang.StringUTF16.compress([CI[BII)I}. 108 * 109 * <pre> 110 * @HotSpotIntrinsicCandidate 111 * public static int compress(char[] src, int src_indx, byte[] dst, int dst_indx, int len) 112 * </pre> 113 */ 114 @MethodSubstitution 115 public static int compress(char[] src, int srcIndex, byte[] dest, int destIndex, int len) { 116 if (len < 0 || srcIndex < 0 || (srcIndex + len > src.length) || destIndex < 0 || (destIndex + len > dest.length)) { 117 DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.BoundsCheckException); 118 } 119 120 Pointer srcPointer = Word.objectToTrackedPointer(src).add(charArrayBaseOffset(INJECTED)).add(srcIndex * charArrayIndexScale(INJECTED)); 121 Pointer destPointer = Word.objectToTrackedPointer(dest).add(byteArrayBaseOffset(INJECTED)).add(destIndex * byteArrayIndexScale(INJECTED)); 122 return AMD64StringUTF16CompressNode.compress(srcPointer, destPointer, len, JavaKind.Char); 123 } 124 125 /** 126 * Intrinsic for {@code }java.lang.StringUTF16.compress([BI[BII)I}. 127 * 128 * <pre> 129 * @HotSpotIntrinsicCandidate 130 * public static int compress(byte[] src, int src_indx, byte[] dst, int dst_indx, int len) 131 * </pre> 132 * 133 * In this variant {@code dest} refers to a byte array containing 2 byte per char so 134 * {@code srcIndex} and {@code len} are in terms of char elements and have to be scaled by 2 135 * when referring to {@code src}. 136 */ 137 @MethodSubstitution 138 public static int compress(byte[] src, int srcIndex, byte[] dest, int destIndex, int len) { 139 if (len < 0 || srcIndex < 0 || (srcIndex * 2 + len * 2 > src.length) || destIndex < 0 || (destIndex + len > dest.length)) { 140 DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.BoundsCheckException); 141 } 142 143 Pointer srcPointer = Word.objectToTrackedPointer(src).add(byteArrayBaseOffset(INJECTED)).add(srcIndex * 2 * byteArrayIndexScale(INJECTED)); 144 Pointer destPointer = Word.objectToTrackedPointer(dest).add(byteArrayBaseOffset(INJECTED)).add(destIndex * byteArrayIndexScale(INJECTED)); 145 return AMD64StringUTF16CompressNode.compress(srcPointer, destPointer, len, JavaKind.Byte); 146 } 147 148 } | 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.replacements.amd64; 26 27 import jdk.vm.ci.meta.DeoptimizationAction; 28 import jdk.vm.ci.meta.DeoptimizationReason; 29 import jdk.vm.ci.meta.JavaKind; 30 import jdk.vm.ci.meta.MetaAccessProvider; 31 import org.graalvm.compiler.api.replacements.ClassSubstitution; 32 import org.graalvm.compiler.api.replacements.Fold; 33 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; 34 import org.graalvm.compiler.api.replacements.MethodSubstitution; 35 import org.graalvm.compiler.nodes.DeoptimizeNode; 36 import org.graalvm.compiler.replacements.ReplacementsUtil; 37 import org.graalvm.compiler.replacements.StringUTF16Substitutions; 38 import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; 39 import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; 40 import org.graalvm.compiler.word.Word; 41 import jdk.internal.vm.compiler.word.Pointer; 42 43 // JaCoCo Exclude 44 45 /** 46 * Substitutions for {@code java.lang.StringUTF16} methods. 47 * <p> 48 * Since JDK 9. 49 */ 50 @ClassSubstitution(className = "java.lang.StringUTF16", optional = true) 51 public class AMD64StringUTF16Substitutions { 52 53 @Fold 54 static int byteArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { 55 return metaAccess.getArrayBaseOffset(JavaKind.Byte); 56 } 57 58 @Fold 59 static int byteArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { 60 return metaAccess.getArrayIndexScale(JavaKind.Byte); 61 } 62 63 @Fold 64 static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { 65 return metaAccess.getArrayBaseOffset(JavaKind.Char); 66 } 67 68 @Fold 69 static int charArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { 70 return metaAccess.getArrayIndexScale(JavaKind.Char); 71 } 72 73 /** 74 * Marker value for the {@link InjectedParameter} injected parameter. 75 */ 76 static final MetaAccessProvider INJECTED = null; 77 78 public static int length(byte[] value) { 79 return value.length >> 1; 80 } 81 82 /** 83 * @param value is char[] 84 * @param other is char[] 85 */ 86 @MethodSubstitution 87 public static int compareTo(byte[] value, byte[] other) { 88 return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Char, JavaKind.Char); 89 } 90 91 /** 92 * @param value is char[] 93 * @param other is byte[] 94 */ 95 @MethodSubstitution 96 public static int compareToLatin1(byte[] value, byte[] other) { 97 /* 98 * Swapping array arguments because intrinsic expects order to be byte[]/char[] but kind 99 * arguments stay in original order. 100 */ 101 return ArrayCompareToNode.compareTo(other, value, other.length, value.length, JavaKind.Char, JavaKind.Byte); 102 } 103 104 @MethodSubstitution 105 public static int indexOfCharUnsafe(byte[] value, int ch, int fromIndex, int max) { 106 Pointer sourcePointer = charOffsetPointer(value, fromIndex); 107 int result = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, max - fromIndex, (char) ch); 108 if (result != -1) { 109 return result + fromIndex; 110 } 111 return result; 112 } 113 114 private static Word pointer(byte[] target) { 115 return Word.objectToTrackedPointer(target).add(byteArrayBaseOffset(INJECTED)); 116 } 117 118 private static Word charOffsetPointer(byte[] value, int offset) { 119 return pointer(value).add(offset * charArrayIndexScale(INJECTED)); 120 } 121 122 @MethodSubstitution 123 public static int indexOfUnsafe(byte[] source, int sourceCount, byte[] target, int targetCount, int fromIndex) { 124 ReplacementsUtil.runtimeAssert(fromIndex >= 0, "StringUTF16.indexOfUnsafe invalid args: fromIndex negative"); 125 ReplacementsUtil.runtimeAssert(targetCount > 0, "StringUTF16.indexOfUnsafe invalid args: targetCount <= 0"); 126 ReplacementsUtil.runtimeAssert(targetCount <= length(target), "StringUTF16.indexOfUnsafe invalid args: targetCount > length(target)"); 127 ReplacementsUtil.runtimeAssert(sourceCount >= targetCount, "StringUTF16.indexOfUnsafe invalid args: sourceCount < targetCount"); 128 int totalOffset = fromIndex; 129 if (targetCount == 1) { 130 Pointer sourcePointer = charOffsetPointer(source, totalOffset); 131 int indexOfResult = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, StringUTF16Substitutions.getChar(target, 0)); 132 if (indexOfResult >= 0) { 133 return indexOfResult + totalOffset; 134 } 135 return indexOfResult; 136 } else if (targetCount == 2) { 137 Pointer sourcePointer = charOffsetPointer(source, totalOffset); 138 int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, sourceCount - fromIndex, StringUTF16Substitutions.getChar(target, 0), 139 StringUTF16Substitutions.getChar(target, 1)); 140 if (indexOfResult >= 0) { 141 return indexOfResult + totalOffset; 142 } 143 return indexOfResult; 144 } else { 145 int haystackLength = sourceCount - (fromIndex + (targetCount - 2)); 146 while (haystackLength > 0) { 147 Pointer sourcePointer = charOffsetPointer(source, totalOffset); 148 int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, haystackLength, StringUTF16Substitutions.getChar(target, 0), 149 StringUTF16Substitutions.getChar(target, 1)); 150 if (indexOfResult < 0) { 151 return -1; 152 } 153 totalOffset += indexOfResult; 154 haystackLength -= (indexOfResult + 1); 155 Pointer cmpSourcePointer = charOffsetPointer(source, totalOffset); 156 Pointer targetPointer = pointer(target); 157 if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Char)) { 158 return totalOffset; 159 } 160 totalOffset++; 161 } 162 return -1; 163 } 164 } 165 166 @MethodSubstitution 167 public static int indexOfLatin1Unsafe(byte[] source, int sourceCount, byte[] target, int targetCount, int fromIndex) { 168 ReplacementsUtil.runtimeAssert(fromIndex >= 0, "StringUTF16.indexOfLatin1Unsafe invalid args: fromIndex negative"); 169 ReplacementsUtil.runtimeAssert(targetCount > 0, "StringUTF16.indexOfLatin1Unsafe invalid args: targetCount <= 0"); 170 ReplacementsUtil.runtimeAssert(targetCount <= target.length, "StringUTF16.indexOfLatin1Unsafe invalid args: targetCount > length(target)"); 171 ReplacementsUtil.runtimeAssert(sourceCount >= targetCount, "StringUTF16.indexOfLatin1Unsafe invalid args: sourceCount < targetCount"); 172 int totalOffset = fromIndex; 173 if (targetCount == 1) { 174 Pointer sourcePointer = charOffsetPointer(source, totalOffset); 175 int indexOfResult = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, (char) Byte.toUnsignedInt(target[0])); 176 if (indexOfResult >= 0) { 177 return indexOfResult + totalOffset; 178 } 179 return indexOfResult; 180 } else if (targetCount == 2) { 181 Pointer sourcePointer = charOffsetPointer(source, totalOffset); 182 int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, sourceCount - fromIndex, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1])); 183 if (indexOfResult >= 0) { 184 return indexOfResult + totalOffset; 185 } 186 return indexOfResult; 187 } else { 188 int haystackLength = sourceCount - (fromIndex + (targetCount - 2)); 189 while (haystackLength > 0) { 190 Pointer sourcePointer = charOffsetPointer(source, totalOffset); 191 int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, haystackLength, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1])); 192 if (indexOfResult < 0) { 193 return -1; 194 } 195 totalOffset += indexOfResult; 196 haystackLength -= (indexOfResult + 1); 197 Pointer cmpSourcePointer = charOffsetPointer(source, totalOffset); 198 Pointer targetPointer = pointer(target); 199 if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Char, JavaKind.Byte)) { 200 return totalOffset; 201 } 202 totalOffset++; 203 } 204 return -1; 205 } 206 } 207 208 /** 209 * Intrinsic for {@code java.lang.StringUTF16.compress([CI[BII)I}. 210 * 211 * <pre> 212 * @HotSpotIntrinsicCandidate 213 * public static int compress(char[] src, int src_indx, byte[] dst, int dst_indx, int len) 214 * </pre> 215 */ 216 @MethodSubstitution 217 public static int compress(char[] src, int srcIndex, byte[] dest, int destIndex, int len) { 218 if (len < 0 || srcIndex < 0 || (srcIndex + len > src.length) || destIndex < 0 || (destIndex + len > dest.length)) { 219 DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.BoundsCheckException); 220 } 221 222 Pointer srcPointer = Word.objectToTrackedPointer(src).add(charArrayBaseOffset(INJECTED)).add(srcIndex * charArrayIndexScale(INJECTED)); 223 Pointer destPointer = Word.objectToTrackedPointer(dest).add(byteArrayBaseOffset(INJECTED)).add(destIndex * byteArrayIndexScale(INJECTED)); 224 return AMD64StringUTF16CompressNode.compress(srcPointer, destPointer, len, JavaKind.Char); 225 } 226 227 /** 228 * Intrinsic for {@code }java.lang.StringUTF16.compress([BI[BII)I}. 229 * 230 * <pre> 231 * @HotSpotIntrinsicCandidate 232 * public static int compress(byte[] src, int src_indx, byte[] dst, int dst_indx, int len) 233 * </pre> 234 * <p> 235 * In this variant {@code dest} refers to a byte array containing 2 byte per char so 236 * {@code srcIndex} and {@code len} are in terms of char elements and have to be scaled by 2 237 * when referring to {@code src}. 238 */ 239 @MethodSubstitution 240 public static int compress(byte[] src, int srcIndex, byte[] dest, int destIndex, int len) { 241 if (len < 0 || srcIndex < 0 || (srcIndex * 2 + len * 2 > src.length) || destIndex < 0 || (destIndex + len > dest.length)) { 242 DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.BoundsCheckException); 243 } 244 245 Pointer srcPointer = Word.objectToTrackedPointer(src).add(byteArrayBaseOffset(INJECTED)).add(srcIndex * 2 * byteArrayIndexScale(INJECTED)); 246 Pointer destPointer = Word.objectToTrackedPointer(dest).add(byteArrayBaseOffset(INJECTED)).add(destIndex * byteArrayIndexScale(INJECTED)); 247 return AMD64StringUTF16CompressNode.compress(srcPointer, destPointer, len, JavaKind.Byte); 248 } 249 250 } |