Skip to content

Commit

Permalink
String.indexOf will be evaluated only if the receiver is small enough.
Browse files Browse the repository at this point in the history
  • Loading branch information
mur47x111 committed Apr 27, 2020
1 parent 15e2b86 commit d371979
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,7 @@ public final class GraalOptions {

@Option(help = "Alignment in bytes for loop header blocks.", type = OptionType.Expert)
public static final OptionKey<Integer> LoopHeaderAlignment = new OptionKey<>(16);

@Option(help = "String.indexOf invocations will be evaluated at compile time if the receiver is a constant and its length is lower than this value.", type = OptionType.Expert)
public static final OptionKey<Integer> StringIndexOfLimit = new OptionKey<>(4096);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import java.nio.ByteOrder;

import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
Expand Down Expand Up @@ -177,41 +178,44 @@ public Node canonical(CanonicalizerTool tool) {

if (searchValues.size() == 1 && searchValues.get(0).isConstant()) {
int ch = searchValues.get(0).asJavaConstant().asInt();
if (arrayKind == JavaKind.Byte) {
// Java 9+
if (valueKind == JavaKind.Byte) {
for (int i = fromIndexConstant; i < length; i++) {
if ((provider.readArrayElement(arrayConstant, i).asInt() & 0xFF) == ch) {
return ConstantNode.forInt(i);
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
if (arrayKind == JavaKind.Byte) {
// Java 9+
if (valueKind == JavaKind.Byte && length < GraalOptions.StringIndexOfLimit.getValue(tool.getOptions())) {
for (int i = fromIndexConstant; i < length; i++) {
if ((provider.readArrayElement(arrayConstant, i).asInt() & 0xFF) == ch) {
return ConstantNode.forInt(i);
}
}
return ConstantNode.forInt(-1);
} else if (length < GraalOptions.StringIndexOfLimit.getValue(tool.getOptions()) * 2) {
assert valueKind == JavaKind.Char;
length >>= 1;
for (int i = fromIndexConstant; i < length; i++) {
byte b0 = (byte) (provider.readArrayElement(arrayConstant, i * 2).asInt() & 0xFF);
byte b1 = (byte) (provider.readArrayElement(arrayConstant, i * 2 + 1).asInt() & 0xFF);
char c;
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
c = (char) (b0 << 8 | b1);
} else {
c = (char) (b0 | b1 << 8);
}
if (c == ch) {
return ConstantNode.forInt(i);
}
}
return ConstantNode.forInt(-1);
}
return ConstantNode.forInt(-1);
} else {
} else if (arrayKind == JavaKind.Char && length < GraalOptions.StringIndexOfLimit.getValue(tool.getOptions())) {
// Java 8
assert valueKind == JavaKind.Char;
length >>= 1;
for (int i = fromIndexConstant; i < length; i++) {
byte b0 = (byte) (provider.readArrayElement(arrayConstant, i * 2).asInt() & 0xFF);
byte b1 = (byte) (provider.readArrayElement(arrayConstant, i * 2 + 1).asInt() & 0xFF);
char c;
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
c = (char) (b0 << 8 | b1);
} else {
c = (char) (b0 | b1 << 8);
}
if (c == ch) {
if ((provider.readArrayElement(arrayConstant, i).asInt() & 0xFFFF) == ch) {
return ConstantNode.forInt(i);
}
}
return ConstantNode.forInt(-1);
}
} else if (arrayKind == JavaKind.Char) {
// Java 8
assert valueKind == JavaKind.Char;
for (int i = fromIndexConstant; i < length; i++) {
if ((provider.readArrayElement(arrayConstant, i).asInt() & 0xFFFF) == ch) {
return ConstantNode.forInt(i);
}
}
return ConstantNode.forInt(-1);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
*/
package org.graalvm.compiler.replacements.test;

import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StartNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.options.OptionValues;
Expand Down Expand Up @@ -57,6 +61,17 @@ protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, Str
/* forceCompile */ true, /* installAsDefault */ false, options);
}

@Override
protected void checkHighTierGraph(StructuredGraph graph) {
if (this.sourceString.length() < GraalOptions.StringIndexOfLimit.getValue(graph.getOptions()) && this.constantChar < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
StartNode start = graph.start();
FixedNode next = start.next();
assertTrue(next instanceof ReturnNode);
ReturnNode returnNode = (ReturnNode) next;
assertTrue(returnNode.result().isConstant());
}
}

@Test
@Override
public void testStringIndexOfConstant() {
Expand Down

0 comments on commit d371979

Please sign in to comment.