8220389: Update Graal

Reviewed-by: kvn, dlong
This commit is contained in:
Jesper Wilhelmsson 2019-03-20 22:53:44 +01:00
parent a8d038277d
commit ea61da4d5f
20 changed files with 392 additions and 137 deletions

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.core.test;
import org.junit.Test;
public class IntegerStampShiftTest extends GraalCompilerTest {
public static int unsignedShiftPositiveInt(boolean f) {
int h = f ? 0x7FFFFFF0 : 0x7FFFFF00;
return h >>> 8;
}
@Test
public void testUnsignedShiftPositiveInt() {
test("unsignedShiftPositiveInt", false);
}
public static int unsignedShiftNegativeInt(boolean f) {
int h = f ? 0xFFFFFFF0 : 0xFFFFFF00;
return h >>> 8;
}
@Test
public void testUnsignedShiftNegativeInt() {
test("unsignedShiftNegativeInt", false);
}
public static long unsignedShiftPositiveLong(boolean f) {
long h = f ? 0x7FFFFFFFFFFFFFF0L : 0x7FFFFFFFFFFFFF00L;
return h >>> 8;
}
@Test
public void testUnsignedShiftPositiveLong() {
test("unsignedShiftPositiveLong", false);
}
public static long unsignedShiftNegativeLong(boolean f) {
long h = f ? 0xFFFFFFFFFFFFFFF0L : 0xFFFFFFFFFFFFFF00L;
return h >>> 8;
}
@Test
public void testUnsignedShiftNegativeLong() {
test("unsignedShiftNegativeLong", false);
}
}

View File

@ -25,7 +25,7 @@
package org.graalvm.compiler.core;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
@ -45,14 +45,13 @@ import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
import org.graalvm.compiler.debug.PathUtilities;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.code.BailoutException;
/**
* Wrapper for a compilation that centralizes what action to take based on
* {@link GraalCompilerOptions#CompilationBailoutAction} and
* {@link GraalCompilerOptions#CompilationBailoutAsFailure} and
* {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during
* compilation.
*/
@ -71,14 +70,17 @@ public abstract class CompilationWrapper<T> {
* Print nothing to the console.
*/
Silent,
/**
* Print a stack trace to the console.
*/
Print,
/**
* An exception causes the compilation to be retried with extra diagnostics enabled.
*/
Diagnose,
/**
* Same as {@link #Diagnose} except that the VM process is exited after retrying.
*/
@ -122,27 +124,30 @@ public abstract class CompilationWrapper<T> {
protected abstract T handleException(Throwable t);
/**
* Gets the action to take based on the value of {@code actionKey} in {@code options}.
* Gets the action to take based on the value of
* {@link GraalCompilerOptions#CompilationBailoutAsFailure},
* {@link GraalCompilerOptions#CompilationFailureAction} and
* {@link GraalCompilerOptions#ExitVMOnException} in {@code options}.
*
* Subclasses can override this to choose a different action based on factors such as whether
* {@code actionKey} has been explicitly set in {@code options} for example.
* Subclasses can override this to choose a different action.
*
* @param cause the cause of the bailout or failure
*/
protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
if (actionKey == CompilationFailureAction) {
if (ExitVMOnException.getValue(options)) {
assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
assert ExitVMOnException.getDefaultValue() != true;
if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
ExitVMOnException.getName());
}
return ExceptionAction.ExitVM;
}
protected ExceptionAction lookupAction(OptionValues options, Throwable cause) {
if (cause instanceof BailoutException && !CompilationBailoutAsFailure.getValue(options)) {
return ExceptionAction.Silent;
}
return actionKey.getValue(options);
if (ExitVMOnException.getValue(options)) {
assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
assert ExitVMOnException.getDefaultValue() != true;
if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
ExitVMOnException.getName());
}
return ExceptionAction.ExitVM;
}
return CompilationFailureAction.getValue(options);
}
/**
@ -173,15 +178,6 @@ public abstract class CompilationWrapper<T> {
} catch (Throwable cause) {
OptionValues initialOptions = initialDebug.getOptions();
String causeType = "failure";
EnumOptionKey<ExceptionAction> actionKey;
if (cause instanceof BailoutException) {
actionKey = CompilationBailoutAction;
causeType = "bailout";
} else {
actionKey = CompilationFailureAction;
causeType = "failure";
}
synchronized (CompilationFailureAction) {
// Serialize all compilation failure handling.
// This prevents retry compilation storms and interleaving
@ -191,9 +187,9 @@ public abstract class CompilationWrapper<T> {
// forced crash (i.e., use of GraalCompilerOptions.CrashAt)
// is truncated.
ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
ExceptionAction action = lookupAction(initialOptions, cause);
action = adjustAction(initialOptions, actionKey, action);
action = adjustAction(initialOptions, action);
if (action == ExceptionAction.Silent) {
return handleException(cause);
@ -204,16 +200,14 @@ public abstract class CompilationWrapper<T> {
try (PrintStream ps = new PrintStream(baos)) {
ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
cause.printStackTrace(ps);
ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
causeType,
actionKey.getName(), ExceptionAction.Silent,
actionKey.getName(), ExceptionAction.Silent);
ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
CompilationFailureAction.getName(), ExceptionAction.Silent,
CompilationFailureAction.getName(), ExceptionAction.Silent);
ps.printf("To capture more information for diagnosing or reporting a compilation failure, " +
"set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
causeType,
actionKey.getName(), ExceptionAction.Diagnose,
CompilationFailureAction.getName(), ExceptionAction.Diagnose,
ExceptionAction.ExitVM,
actionKey.getName(), ExceptionAction.Diagnose);
CompilationFailureAction.getName(), ExceptionAction.Diagnose);
}
TTY.print(baos.toString());
return handleException(cause);
@ -249,15 +243,13 @@ public abstract class CompilationWrapper<T> {
try (PrintStream ps = new PrintStream(baos)) {
ps.printf("%s: Compilation of %s failed:%n", Thread.currentThread(), this);
cause.printStackTrace(ps);
ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
causeType,
actionKey.getName(), ExceptionAction.Silent,
actionKey.getName(), ExceptionAction.Silent);
ps.printf("To print a message for a compilation %s without retrying the compilation, " +
ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
CompilationFailureAction.getName(), ExceptionAction.Silent,
CompilationFailureAction.getName(), ExceptionAction.Silent);
ps.printf("To print a message for a compilation failure without retrying the compilation, " +
"set %s to %s (e.g., -Dgraal.%s=%s).%n",
causeType,
actionKey.getName(), ExceptionAction.Print,
actionKey.getName(), ExceptionAction.Print);
CompilationFailureAction.getName(), ExceptionAction.Print,
CompilationFailureAction.getName(), ExceptionAction.Print);
if (dumpPath != null) {
ps.println("Retrying compilation of " + this);
} else {
@ -320,7 +312,7 @@ public abstract class CompilationWrapper<T> {
* Adjusts {@code initialAction} if necessary based on
* {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
*/
private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
private ExceptionAction adjustAction(OptionValues initialOptions, ExceptionAction initialAction) {
ExceptionAction action = initialAction;
int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
if (action != ExceptionAction.ExitVM) {
@ -329,7 +321,7 @@ public abstract class CompilationWrapper<T> {
int problems = problemsHandledPerAction.getOrDefault(action, 0);
if (problems >= maxProblems) {
if (problems == maxProblems) {
TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", CompilationFailureAction, action, action.quieter(),
MaxCompilationProblemsPerAction, maxProblems);
// Ensure that the message above is only printed once
problemsHandledPerAction.put(action, problems + 1);

View File

@ -44,13 +44,12 @@ public class GraalCompilerOptions {
"suffix will raise a bailout exception and a ':PermanentBailout' " +
"suffix will raise a permanent bailout exception.", type = OptionType.Debug)
public static final OptionKey<String> CrashAt = new OptionKey<>(null);
@Option(help = "file:doc-files/CompilationBailoutActionHelp.txt", type = OptionType.User)
public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent);
@Option(help = "Specifies the action to take when compilation fails with a bailout exception. " +
"The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
@Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
"by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action. " +
@Option(help = "Treat compilation bailouts like compilation failures.", type = OptionType.User)
public static final OptionKey<Boolean> CompilationBailoutAsFailure = new OptionKey<>(false);
@Option(help = "file:doc-files/CompilationFailureActionHelp.txt", type = OptionType.User)
public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Silent);
@Option(help = "The maximum number of compilation failures to handle with the action specified " +
"by CompilationFailureAction before changing to a less verbose action. " +
"This does not apply to the ExitVM action.", type = OptionType.User)
public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(2);
@Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)

View File

@ -1,4 +1,4 @@
Specifies the action to take when compilation fails with a bailout exception.
Specifies the action to take when compilation fails.
The accepted values are:
Silent - Print nothing to the console.
Print - Print a stack trace to the console.

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.hotspot.amd64;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.stubs.SnippetStub;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
import jdk.internal.vm.compiler.word.Pointer;
import jdk.vm.ci.meta.JavaKind;
public final class AMD64ArrayEqualsStub extends SnippetStub {
public static final ForeignCallDescriptor STUB_BOOLEAN_ARRAY_EQUALS = new ForeignCallDescriptor(
"booleanArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public static final ForeignCallDescriptor STUB_BYTE_ARRAY_EQUALS = new ForeignCallDescriptor(
"byteArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public static final ForeignCallDescriptor STUB_CHAR_ARRAY_EQUALS = new ForeignCallDescriptor(
"charArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public static final ForeignCallDescriptor STUB_SHORT_ARRAY_EQUALS = new ForeignCallDescriptor(
"shortArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public static final ForeignCallDescriptor STUB_INT_ARRAY_EQUALS = new ForeignCallDescriptor(
"intArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public static final ForeignCallDescriptor STUB_LONG_ARRAY_EQUALS = new ForeignCallDescriptor(
"longArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public static final ForeignCallDescriptor STUB_FLOAT_ARRAY_EQUALS = new ForeignCallDescriptor(
"floatArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public static final ForeignCallDescriptor STUB_DOUBLE_ARRAY_EQUALS = new ForeignCallDescriptor(
"doubleArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
public AMD64ArrayEqualsStub(ForeignCallDescriptor foreignCallDescriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
super(foreignCallDescriptor.getName(), options, providers, linkage);
}
@Snippet
private static boolean booleanArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Boolean);
}
@Snippet
private static boolean byteArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Byte);
}
@Snippet
private static boolean charArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Char);
}
@Snippet
private static boolean shortArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Short);
}
@Snippet
private static boolean intArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Int);
}
@Snippet
private static boolean longArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Long);
}
@Snippet
private static boolean floatArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Float);
}
@Snippet
private static boolean doubleArraysEquals(Pointer array1, Pointer array2, int length) {
return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Double);
}
}

View File

@ -25,6 +25,7 @@
package org.graalvm.compiler.hotspot.amd64;
import static jdk.vm.ci.common.InitTimer.timer;
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
import java.util.ArrayList;
import java.util.List;
@ -160,7 +161,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false);
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9);
return plugins;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -121,6 +121,22 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro
link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, options, providers,
registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
super.initialize(providers, options);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -676,4 +676,32 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
}
@Override
public ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
if (constantLength >= 0 && constantLength * kind.getByteCount() < 2 * getMaxVectorSize()) {
// Yield constant-length arrays comparison assembly
return null;
}
switch (kind) {
case Boolean:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS);
case Byte:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS);
case Char:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS);
case Short:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS);
case Int:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS);
case Long:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS);
case Float:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS);
case Double:
return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS);
default:
return null;
}
}
}

View File

@ -26,8 +26,6 @@ package org.graalvm.compiler.hotspot.jdk9.test;
import static org.junit.Assume.assumeFalse;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions;
import org.graalvm.compiler.nodes.StructuredGraph;
@ -35,9 +33,11 @@ import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
* Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by
* {@link StringUTF16Substitutions}.
@ -48,8 +48,7 @@ public final class StringUTF16ToBytesGetCharsTest extends MethodSubstitutionTest
private static final int N = 1000;
private static final int N_OVERFLOW = 10;
@Before
public void checkAMD64() {
public StringUTF16ToBytesGetCharsTest() {
assumeFalse(Java8OrEarlier);
}

View File

@ -21,6 +21,8 @@
* questions.
*/
package org.graalvm.compiler.hotspot.test;
import java.lang.reflect.InvocationTargetException;
@ -193,8 +195,7 @@ public final class BigIntegerIntrinsicsTest extends GraalCompilerTest {
Object invokeCode(Object... args) {
try {
return testcode.executeVarargs(args);
}
catch (InvalidInstalledCodeException e) {
} catch (InvalidInstalledCodeException e) {
// Ensure the installed code is valid, possibly recompiled.
testcode = getCode(testmethod);
@ -208,8 +209,7 @@ public final class BigIntegerIntrinsicsTest extends GraalCompilerTest {
private Object invokeSafe(ResolvedJavaMethod method, Object receiver, Object... args) {
try {
return invoke(method, receiver, args);
} catch (IllegalAccessException | InvocationTargetException |
IllegalArgumentException | InstantiationException e) {
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException | InstantiationException e) {
throw new RuntimeException(e);
}
}
@ -220,8 +220,7 @@ public final class BigIntegerIntrinsicsTest extends GraalCompilerTest {
private InstalledCode testcode;
}
private static GraalHotSpotVMConfig config =
((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
private static GraalHotSpotVMConfig config = ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
private static BigInteger bigTwo = BigInteger.valueOf(2);
private static Random rnd = new Random(17);

View File

@ -26,7 +26,7 @@ package org.graalvm.compiler.hotspot.test;
import static java.util.Collections.singletonList;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
@ -215,7 +215,7 @@ public final class CompileTheWorld {
compilationOptionsCopy.putAll(compilationOptions);
// We want to see stack traces when a method fails to compile
CompilationBailoutAction.putIfAbsent(compilationOptionsCopy, Print);
CompilationBailoutAsFailure.putIfAbsent(compilationOptionsCopy, true);
CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print);
// By default only report statistics for the CTW threads themselves

View File

@ -24,7 +24,7 @@
package org.graalvm.compiler.hotspot.test;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import jdk.internal.vm.compiler.collections.EconomicMap;
@ -44,7 +44,7 @@ public class CompileTheWorldTest extends GraalCompilerTest {
@Test
public void testJDK() throws Throwable {
ExceptionAction originalBailoutAction = CompilationBailoutAction.getValue(getInitialOptions());
boolean originalBailoutAction = CompilationBailoutAsFailure.getValue(getInitialOptions());
ExceptionAction originalFailureAction = CompilationFailureAction.getValue(getInitialOptions());
// Compile a couple classes in rt.jar
HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
@ -52,7 +52,7 @@ public class CompileTheWorldTest extends GraalCompilerTest {
OptionValues initialOptions = getInitialOptions();
EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false");
new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile();
assert CompilationBailoutAction.getValue(initialOptions) == originalBailoutAction;
assert CompilationBailoutAsFailure.getValue(initialOptions) == originalBailoutAction;
assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction;
}
}

View File

@ -31,7 +31,6 @@ import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.bytecode.BytecodeStream;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
import org.graalvm.compiler.core.GraalCompilerOptions;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.core.test.GraalCompilerTest;
@ -134,8 +133,8 @@ public abstract class GraalOSRTestBase extends GraalCompilerTest {
OptionValues goptions = options;
// Silence diagnostics for permanent bailout errors as they
// are expected for some OSR tests.
if (!GraalCompilerOptions.CompilationBailoutAction.hasBeenSet(options)) {
goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAction, ExceptionAction.Silent);
if (!GraalCompilerOptions.CompilationBailoutAsFailure.hasBeenSet(options)) {
goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAsFailure, false);
}
// ensure eager resolving
StructuredGraph graph = parseEager(method, AllowAssumptions.YES, goptions);

View File

@ -26,7 +26,7 @@ package org.graalvm.compiler.hotspot;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
@ -47,7 +47,6 @@ import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugDumpScope;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
@ -145,25 +144,34 @@ public class CompilationTask {
}
@Override
protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
// Respect current action if it has been explicitly set.
if (!actionKey.hasBeenSet(values)) {
if (actionKey == CompilationFailureAction) {
// Automatically exit on non-bailout during bootstrap
// or when assertions are enabled.
if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
return ExitVM;
}
} else if (actionKey == CompilationBailoutAction && ((BailoutException) cause).isPermanent()) {
// Get more info for permanent bailouts during bootstrap
// or when assertions are enabled.
assert CompilationBailoutAction.getDefaultValue() == ExceptionAction.Silent;
if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
return Diagnose;
protected ExceptionAction lookupAction(OptionValues values, Throwable cause) {
if (cause instanceof BailoutException) {
BailoutException bailout = (BailoutException) cause;
if (bailout.isPermanent()) {
// Respect current action if it has been explicitly set.
if (!CompilationBailoutAsFailure.hasBeenSet(values)) {
// Get more info for permanent bailouts during bootstrap
// or when assertions are enabled.
if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
return Diagnose;
}
}
}
if (!CompilationBailoutAsFailure.getValue(values)) {
return super.lookupAction(values, cause);
}
}
return super.lookupAction(values, actionKey, cause);
// Respect current action if it has been explicitly set.
if (!CompilationFailureAction.hasBeenSet(values)) {
// Automatically exit on failure during bootstrap
// or when assertions are enabled.
if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
return ExitVM;
}
}
return super.lookupAction(values, cause);
}
@SuppressWarnings("try")

View File

@ -41,6 +41,7 @@ import org.graalvm.compiler.options.OptionsParser;
import jdk.vm.ci.common.InitTimer;
import jdk.vm.ci.common.NativeImageReinitialize;
import jdk.vm.ci.services.Services;
/**
* The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The
@ -89,15 +90,14 @@ public class HotSpotGraalOptionValues {
}
/**
* Global options. The values for these options are initialized by parsing the file denoted by
* the {@code VM.getSavedProperty(String) saved} system property named
* {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists followed by parsing the options
* encoded in saved system properties whose names start with
* {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned
* file with {@link Properties#load(java.io.Reader)}.
* Gets and parses options based on {@linkplain Services#getSavedProperties() saved system
* properties}. The values for these options are initialized by parsing the file denoted by the
* {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} property followed by parsing the options encoded
* in properties whose names start with {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs
* are parsed from the aforementioned file with {@link Properties#load(java.io.Reader)}.
*/
@SuppressWarnings("try")
private static OptionValues initializeOptions() {
public static EconomicMap<OptionKey<?>, Object> parseOptions() {
EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
try (InitTimer t = timer("InitializeOptions")) {
@ -142,7 +142,17 @@ public class HotSpotGraalOptionValues {
}
OptionsParser.parseOptions(optionSettings, values, loader);
return new OptionValues(values);
return values;
}
}
/**
* Substituted by
* {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalOptionValues}
* to update {@code com.oracle.svm.core.option.RuntimeOptionValues.singleton()} instead of
* creating a new {@link OptionValues} object.
*/
private static OptionValues initializeOptions() {
return new OptionValues(parseOptions());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -268,6 +268,11 @@ public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindF
Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers);
@SuppressWarnings("unused")
default ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
return null;
}
@SuppressWarnings("unused")
default Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
throw GraalError.unimplemented("Array.equals with different types substitution is not implemented on this architecture");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,7 @@
package org.graalvm.compiler.nodes.calc;
import jdk.vm.ci.code.CodeUtil;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.UShr;
import org.graalvm.compiler.core.common.type.IntegerStamp;
@ -84,10 +85,13 @@ public final class UnsignedRightShiftNode extends ShiftNode<UShr> {
Stamp xStampGeneric = forX.stamp(view);
if (xStampGeneric instanceof IntegerStamp) {
IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
long xMask = CodeUtil.mask(xStamp.getBits());
long xLowerBound = xStamp.lowerBound() & xMask;
long xUpperBound = xStamp.upperBound() & xMask;
if (xStamp.lowerBound() >>> amount == xStamp.upperBound() >>> amount) {
if (xLowerBound >>> amount == xUpperBound >>> amount) {
// The result of the shift is constant.
return ConstantNode.forIntegerKind(stamp.getStackKind(), xStamp.lowerBound() >>> amount);
return ConstantNode.forIntegerKind(stamp.getStackKind(), xLowerBound >>> amount);
}
if (amount == xStamp.getBits() - 1 && xStamp.lowerBound() == -1 && xStamp.upperBound() == 0) {

View File

@ -32,7 +32,6 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.Una
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
@ -71,7 +70,7 @@ import sun.misc.Unsafe;
public class AMD64GraphBuilderPlugins {
public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks) {
public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks, boolean emitJDK9StringSubstitutions) {
InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
invocationPlugins.defer(new Runnable() {
@Override
@ -83,8 +82,10 @@ public class AMD64GraphBuilderPlugins {
new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Float, JavaKind.Double});
registerUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks);
registerStringPlugins(invocationPlugins, replacementsBytecodeProvider);
registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
if (emitJDK9StringSubstitutions) {
registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
}
registerMathPlugins(invocationPlugins, arch, replacementsBytecodeProvider);
registerArraysEqualsPlugins(invocationPlugins, replacementsBytecodeProvider);
}
@ -215,30 +216,26 @@ public class AMD64GraphBuilderPlugins {
}
private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
if (JAVA_SPECIFICATION_VERSION >= 9) {
Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
}
Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
}
private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
if (JAVA_SPECIFICATION_VERSION >= 9) {
Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
}
Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
}
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider, boolean explicitUnsafeNullChecks) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,11 +26,14 @@ package org.graalvm.compiler.replacements.nodes;
import static org.graalvm.compiler.nodeinfo.InputType.Memory;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.NodeSize;
@ -48,11 +51,14 @@ import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Value;
// JaCoCo Exclude
@ -63,6 +69,13 @@ import jdk.vm.ci.meta.Value;
@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128)
public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
public static class Options {
// @formatter:off
@Option(help = "Use Array equals stubs instead of embedding all the emitted code.")
public static final OptionKey<Boolean> ArrayEqualsStubs = new OptionKey<>(true);
// @formatter:on
}
public static final NodeClass<ArrayEqualsNode> TYPE = NodeClass.create(ArrayEqualsNode.class);
/** {@link JavaKind} of the arrays to compare. */
protected final JavaKind kind;
@ -178,7 +191,7 @@ public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLower
}
@NodeIntrinsic
static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
public static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
public static boolean equals(boolean[] array1, boolean[] array2, int length) {
return equals(array1, array2, length, JavaKind.Boolean);
@ -214,11 +227,25 @@ public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLower
@Override
public void generate(NodeLIRBuilderTool gen) {
LIRGeneratorTool tool = gen.getLIRGeneratorTool();
int constantLength = -1;
if (length.isConstant()) {
constantLength = length.asJavaConstant().asInt();
}
Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
if (Options.ArrayEqualsStubs.getValue(graph().getOptions())) {
ResolvedJavaMethod method = graph().method();
if (method != null && method.getAnnotation(Snippet.class) == null) {
ForeignCallLinkage linkage = tool.lookupArrayEqualsStub(kind, constantLength);
if (linkage != null) {
Value result = tool.emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length));
gen.setResult(this, result);
return;
}
}
}
Value result = tool.emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
gen.setResult(this, result);
}