< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java

Print this page




   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 }
< prev index next >