src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java
changeset 54328 37648a9c4a6a
parent 52910 583fd71c47d6
child 58299 6df94ce3ab2f
equal deleted inserted replaced
54327:a4d19817609c 54328:37648a9c4a6a
    23 
    23 
    24 
    24 
    25 package org.graalvm.compiler.replacements;
    25 package org.graalvm.compiler.replacements;
    26 
    26 
    27 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
    27 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
       
    28 import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe;
    28 
    29 
    29 import org.graalvm.compiler.api.replacements.Fold;
    30 import org.graalvm.compiler.api.replacements.Fold;
    30 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
    31 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
    31 import org.graalvm.compiler.api.replacements.Snippet;
    32 import org.graalvm.compiler.api.replacements.Snippet;
    32 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
    33 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
    42 import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
    43 import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
    43 
    44 
    44 import jdk.vm.ci.code.TargetDescription;
    45 import jdk.vm.ci.code.TargetDescription;
    45 import jdk.vm.ci.meta.JavaKind;
    46 import jdk.vm.ci.meta.JavaKind;
    46 import jdk.vm.ci.meta.MetaAccessProvider;
    47 import jdk.vm.ci.meta.MetaAccessProvider;
       
    48 import sun.misc.Unsafe;
    47 
    49 
    48 public class ConstantStringIndexOfSnippets implements Snippets {
    50 public class ConstantStringIndexOfSnippets implements Snippets {
       
    51     private static final Unsafe UNSAFE = getUnsafe();
       
    52 
    49     public static class Templates extends AbstractTemplates {
    53     public static class Templates extends AbstractTemplates {
    50 
    54 
    51         private final SnippetInfo indexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "indexOfConstant");
    55         private final SnippetInfo indexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "indexOfConstant");
    52         private final SnippetInfo latin1IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "latin1IndexOfConstant");
    56         private final SnippetInfo latin1IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "latin1IndexOfConstant");
    53         private final SnippetInfo utf16IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "utf16IndexOfConstant");
    57         private final SnippetInfo utf16IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "utf16IndexOfConstant");
   155         int c = target.length / 2;
   159         int c = target.length / 2;
   156         if (c == 0) {
   160         if (c == 0) {
   157             return 0;
   161             return 0;
   158         }
   162         }
   159         long base = metaAccess.getArrayBaseOffset(JavaKind.Byte);
   163         long base = metaAccess.getArrayBaseOffset(JavaKind.Byte);
   160         char lastChar = UnsafeAccess.UNSAFE.getChar(target, base + (c - 1) * 2);
   164         char lastChar = UNSAFE.getChar(target, base + (c - 1) * 2);
   161         int md2 = c;
   165         int md2 = c;
   162         for (int i = 0; i < c - 1; i++) {
   166         for (int i = 0; i < c - 1; i++) {
   163             char currChar = UnsafeAccess.UNSAFE.getChar(target, base + i * 2);
   167             char currChar = UNSAFE.getChar(target, base + i * 2);
   164             if (currChar == lastChar) {
   168             if (currChar == lastChar) {
   165                 md2 = (c - 1) - i;
   169                 md2 = (c - 1) - i;
   166             }
   170             }
   167         }
   171         }
   168         return md2;
   172         return md2;
   172         int c = s.length / 2;
   176         int c = s.length / 2;
   173         int cache = 0;
   177         int cache = 0;
   174         int i;
   178         int i;
   175         long base = metaAccess.getArrayBaseOffset(JavaKind.Byte);
   179         long base = metaAccess.getArrayBaseOffset(JavaKind.Byte);
   176         for (i = 0; i < c - 1; i++) {
   180         for (i = 0; i < c - 1; i++) {
   177             char currChar = UnsafeAccess.UNSAFE.getChar(s, base + i * 2);
   181             char currChar = UNSAFE.getChar(s, base + i * 2);
   178             cache |= (1 << (currChar & 63));
   182             cache |= (1 << (currChar & 63));
   179         }
   183         }
   180         return cache;
   184         return cache;
   181     }
   185     }
   182 
   186 
   210 
   214 
   211         int targetCountLess1 = targetCount - 1;
   215         int targetCountLess1 = targetCount - 1;
   212         int sourceEnd = sourceCount - targetCountLess1;
   216         int sourceEnd = sourceCount - targetCountLess1;
   213 
   217 
   214         long base = charArrayBaseOffset(INJECTED);
   218         long base = charArrayBaseOffset(INJECTED);
   215         int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2);
   219         int lastChar = UNSAFE.getChar(target, base + targetCountLess1 * 2);
   216 
   220 
   217         outer_loop: for (long i = sourceOffset + fromIndex; i < sourceEnd;) {
   221         outer_loop: for (long i = sourceOffset + fromIndex; i < sourceEnd;) {
   218             int src = UnsafeAccess.UNSAFE.getChar(source, base + (i + targetCountLess1) * 2);
   222             int src = UNSAFE.getChar(source, base + (i + targetCountLess1) * 2);
   219             if (src == lastChar) {
   223             if (src == lastChar) {
   220                 // With random strings and a 4-character alphabet,
   224                 // With random strings and a 4-character alphabet,
   221                 // reverse matching at this point sets up 0.8% fewer
   225                 // reverse matching at this point sets up 0.8% fewer
   222                 // frames, but (paradoxically) makes 0.3% more probes.
   226                 // frames, but (paradoxically) makes 0.3% more probes.
   223                 // Since those probes are nearer the lastChar probe,
   227                 // Since those probes are nearer the lastChar probe,
   227                 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
   231                 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
   228                 if (targetCount <= 8) {
   232                 if (targetCount <= 8) {
   229                     ExplodeLoopNode.explodeLoop();
   233                     ExplodeLoopNode.explodeLoop();
   230                 }
   234                 }
   231                 for (long j = 0; j < targetCountLess1; j++) {
   235                 for (long j = 0; j < targetCountLess1; j++) {
   232                     char sourceChar = UnsafeAccess.UNSAFE.getChar(source, base + (i + j) * 2);
   236                     char sourceChar = UNSAFE.getChar(source, base + (i + j) * 2);
   233                     if (UnsafeAccess.UNSAFE.getChar(target, base + (targetOffset + j) * 2) != sourceChar) {
   237                     if (UNSAFE.getChar(target, base + (targetOffset + j) * 2) != sourceChar) {
   234                         if ((cache & (1 << sourceChar)) == 0) {
   238                         if ((cache & (1 << sourceChar)) == 0) {
   235                             if (md2 < j + 1) {
   239                             if (md2 < j + 1) {
   236                                 i += j + 1;
   240                                 i += j + 1;
   237                                 continue outer_loop;
   241                                 continue outer_loop;
   238                             }
   242                             }
   268 
   272 
   269         int targetCountLess1 = targetCount - 1;
   273         int targetCountLess1 = targetCount - 1;
   270         int sourceEnd = sourceCount - targetCountLess1;
   274         int sourceEnd = sourceCount - targetCountLess1;
   271 
   275 
   272         long base = byteArrayBaseOffset(INJECTED);
   276         long base = byteArrayBaseOffset(INJECTED);
   273         int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2);
   277         int lastChar = UNSAFE.getChar(target, base + targetCountLess1 * 2);
   274 
   278 
   275         outer_loop: for (long i = fromIndex; i < sourceEnd;) {
   279         outer_loop: for (long i = fromIndex; i < sourceEnd;) {
   276             int src = UnsafeAccess.UNSAFE.getChar(source, base + (i + targetCountLess1) * 2);
   280             int src = UNSAFE.getChar(source, base + (i + targetCountLess1) * 2);
   277             if (src == lastChar) {
   281             if (src == lastChar) {
   278                 // With random strings and a 4-character alphabet,
   282                 // With random strings and a 4-character alphabet,
   279                 // reverse matching at this point sets up 0.8% fewer
   283                 // reverse matching at this point sets up 0.8% fewer
   280                 // frames, but (paradoxically) makes 0.3% more probes.
   284                 // frames, but (paradoxically) makes 0.3% more probes.
   281                 // Since those probes are nearer the lastChar probe,
   285                 // Since those probes are nearer the lastChar probe,
   285                 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
   289                 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
   286                 if (targetCount <= 8) {
   290                 if (targetCount <= 8) {
   287                     ExplodeLoopNode.explodeLoop();
   291                     ExplodeLoopNode.explodeLoop();
   288                 }
   292                 }
   289                 for (long j = 0; j < targetCountLess1; j++) {
   293                 for (long j = 0; j < targetCountLess1; j++) {
   290                     char sourceChar = UnsafeAccess.UNSAFE.getChar(source, base + (i + j) * 2);
   294                     char sourceChar = UNSAFE.getChar(source, base + (i + j) * 2);
   291                     if (UnsafeAccess.UNSAFE.getChar(target, base + j * 2) != sourceChar) {
   295                     if (UNSAFE.getChar(target, base + j * 2) != sourceChar) {
   292                         if ((cache & (1 << sourceChar)) == 0) {
   296                         if ((cache & (1 << sourceChar)) == 0) {
   293                             if (md2 < j + 1) {
   297                             if (md2 < j + 1) {
   294                                 i += j + 1;
   298                                 i += j + 1;
   295                                 continue outer_loop;
   299                                 continue outer_loop;
   296                             }
   300                             }
   326 
   330 
   327         int targetCountLess1 = targetCount - 1;
   331         int targetCountLess1 = targetCount - 1;
   328         int sourceEnd = sourceCount - targetCountLess1;
   332         int sourceEnd = sourceCount - targetCountLess1;
   329 
   333 
   330         long base = byteArrayBaseOffset(INJECTED);
   334         long base = byteArrayBaseOffset(INJECTED);
   331         int lastByte = UnsafeAccess.UNSAFE.getByte(target, base + targetCountLess1);
   335         int lastByte = UNSAFE.getByte(target, base + targetCountLess1);
   332 
   336 
   333         outer_loop: for (long i = fromIndex; i < sourceEnd;) {
   337         outer_loop: for (long i = fromIndex; i < sourceEnd;) {
   334             int src = UnsafeAccess.UNSAFE.getByte(source, base + i + targetCountLess1);
   338             int src = UNSAFE.getByte(source, base + i + targetCountLess1);
   335             if (src == lastByte) {
   339             if (src == lastByte) {
   336                 // With random strings and a 4-character alphabet,
   340                 // With random strings and a 4-character alphabet,
   337                 // reverse matching at this point sets up 0.8% fewer
   341                 // reverse matching at this point sets up 0.8% fewer
   338                 // frames, but (paradoxically) makes 0.3% more probes.
   342                 // frames, but (paradoxically) makes 0.3% more probes.
   339                 // Since those probes are nearer the lastByte probe,
   343                 // Since those probes are nearer the lastByte probe,
   343                 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
   347                 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
   344                 if (targetCount <= 8) {
   348                 if (targetCount <= 8) {
   345                     ExplodeLoopNode.explodeLoop();
   349                     ExplodeLoopNode.explodeLoop();
   346                 }
   350                 }
   347                 for (long j = 0; j < targetCountLess1; j++) {
   351                 for (long j = 0; j < targetCountLess1; j++) {
   348                     byte sourceByte = UnsafeAccess.UNSAFE.getByte(source, base + i + j);
   352                     byte sourceByte = UNSAFE.getByte(source, base + i + j);
   349                     if (UnsafeAccess.UNSAFE.getByte(target, base + j) != sourceByte) {
   353                     if (UNSAFE.getByte(target, base + j) != sourceByte) {
   350                         if ((cache & (1 << sourceByte)) == 0) {
   354                         if ((cache & (1 << sourceByte)) == 0) {
   351                             if (md2 < j + 1) {
   355                             if (md2 < j + 1) {
   352                                 i += j + 1;
   356                                 i += j + 1;
   353                                 continue outer_loop;
   357                                 continue outer_loop;
   354                             }
   358                             }