This commit is contained in:
Igor Veresov 2017-08-12 01:21:21 +00:00
commit f79aa532aa
74 changed files with 940 additions and 296 deletions

View File

@ -71,6 +71,7 @@ public final class AllocSpy implements AutoCloseable {
field.setAccessible(true);
enabled = field.get(null) != null;
} catch (Exception e) {
} catch (LinkageError e) {
}
ENABLED = enabled;
if (ENABLED) {

View File

@ -101,6 +101,14 @@ import jdk.vm.ci.meta.Value;
*/
public class CheckGraalInvariants extends GraalCompilerTest {
public CheckGraalInvariants() {
try {
Class.forName("java.lang.management.ManagementFactory");
} catch (ClassNotFoundException ex) {
Assume.assumeNoException("cannot run without java.management JDK9 module", ex);
}
}
private static boolean shouldVerifyEquals(ResolvedJavaMethod m) {
if (m.getName().equals("identityEquals")) {
ResolvedJavaType c = m.getDeclaringClass();

View File

@ -946,6 +946,7 @@ public abstract class GraalCompilerTest extends GraalTest {
InstalledCode installedCode = null;
StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph;
DebugContext debug = graphToCompile.getDebug();
try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) {
CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options);

View File

@ -26,6 +26,7 @@ import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitV
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL;
import static org.graalvm.compiler.debug.DebugOptions.Dump;
import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
@ -36,6 +37,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Map;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
@ -59,6 +61,8 @@ public abstract class CompilationWrapper<T> {
* {@link CompilationWrapper}. The actions are with respect to what the user sees on the
* console. The compilation requester determines what ultimate action is taken in
* {@link CompilationWrapper#handleException(Throwable)}.
*
* The actions are in ascending order of verbosity.
*/
public enum ExceptionAction {
/**
@ -97,16 +101,32 @@ public abstract class CompilationWrapper<T> {
return null;
}
}
/**
* Gets the action that is one level less verbose than this action, bottoming out at the
* least verbose action.
*/
ExceptionAction quieter() {
assert ExceptionAction.Silent.ordinal() == 0;
int index = Math.max(ordinal() - 1, 0);
return values()[index];
}
}
private final DiagnosticsOutputDirectory outputDirectory;
private final Map<ExceptionAction, Integer> problemsHandledPerAction;
/**
* @param outputDirectory object used to access a directory for dumping if the compilation is
* re-executed
* @param problemsHandledPerAction map used to count the number of compilation failures or
* bailouts handled by each action. This is provided by the caller as it is expected
* to be shared between instances of {@link CompilationWrapper}.
*/
public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory) {
public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory, Map<ExceptionAction, Integer> problemsHandledPerAction) {
this.outputDirectory = outputDirectory;
this.problemsHandledPerAction = problemsHandledPerAction;
}
/**
@ -177,9 +197,12 @@ public abstract class CompilationWrapper<T> {
}
ExceptionAction action = lookupAction(initialOptions, actionKey);
action = adjustAction(initialOptions, actionKey, action);
if (action == ExceptionAction.Silent) {
return handleException(cause);
}
if (action == ExceptionAction.Print) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (PrintStream ps = new PrintStream(baos)) {
@ -214,7 +237,7 @@ public abstract class CompilationWrapper<T> {
String dir = this.outputDirectory.getPath();
if (dir == null) {
return null;
return handleException(cause);
}
String dumpName = PathUtilities.sanitizeFileName(toString());
File dumpPath = new File(dir, dumpName);
@ -274,4 +297,31 @@ 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) {
ExceptionAction action = initialAction;
int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
synchronized (problemsHandledPerAction) {
while (action != ExceptionAction.Silent) {
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(),
MaxCompilationProblemsPerAction, maxProblems);
// Ensure that the message above is only printed once
problemsHandledPerAction.put(action, problems + 1);
}
action = action.quieter();
} else {
break;
}
}
problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1);
}
return action;
}
}

View File

@ -39,11 +39,14 @@ public class GraalCompilerOptions {
@Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " +
"This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug)
public static final OptionKey<String> CrashAt = new OptionKey<>(null);
@Option(help = "Specifies the action to take when compilation fails with a non-bailout exception.", type = OptionType.User)
@Option(help = "The action to take when compilation fails with a non-bailout exception.", type = OptionType.User)
public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose, ExceptionAction.HELP);
@Option(help = "Specifies the action to take when compilation fails with a bailout exception.", type = OptionType.User)
@Option(help = "The action to take when compilation fails with a bailout exception.", type = OptionType.User)
public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent, ExceptionAction.HELP);
@Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.Debug)
@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.", type = OptionType.User)
public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(5);
@Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)
public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
// @formatter:on
}

View File

@ -45,11 +45,14 @@ import org.junit.Test;
@SuppressWarnings("try")
public class TimerKeyTest {
private static final ThreadMXBean threadMXBean = Management.getThreadMXBean();
@Before
public void checkCapabilities() {
Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
try {
ThreadMXBean threadMXBean = Management.getThreadMXBean();
Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
} catch (LinkageError err) {
Assume.assumeNoException("Cannot run without java.management JDK9 module", err);
}
}
/**
@ -60,6 +63,7 @@ public class TimerKeyTest {
* {@code ms}
*/
private static long spin(long ms) {
ThreadMXBean threadMXBean = Management.getThreadMXBean();
long start = threadMXBean.getCurrentThreadCpuTime();
do {
long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000;

View File

@ -22,11 +22,9 @@
*/
package org.graalvm.compiler.debug;
import com.sun.management.ThreadMXBean;
/**
* Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed
* using the try-with-resources pattern:
* Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility
* should be employed using the try-with-resources pattern:
*
* <pre>
* try (DebugMemUseTracker.Closeable a = memUseTracker.start()) {

View File

@ -25,7 +25,6 @@ package org.graalvm.compiler.debug;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
@ -74,16 +73,20 @@ public class DiagnosticsOutputDirectory {
* Gets a unique identifier for this execution such as a process ID.
*/
protected String getExecutionID() {
String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
try {
int index = runtimeName.indexOf('@');
if (index != -1) {
long pid = Long.parseLong(runtimeName.substring(0, index));
return Long.toString(pid);
String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
try {
int index = runtimeName.indexOf('@');
if (index != -1) {
long pid = Long.parseLong(runtimeName.substring(0, index));
return Long.toString(pid);
}
} catch (NumberFormatException e) {
}
} catch (NumberFormatException e) {
return runtimeName;
} catch (LinkageError err) {
return String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
}
return runtimeName;
}
private synchronized String getPath(boolean createIfNull) {

View File

@ -24,12 +24,6 @@ package org.graalvm.compiler.debug;
import static java.lang.Thread.currentThread;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import javax.management.ObjectName;
public class Management {
private static final com.sun.management.ThreadMXBean threadMXBean = Management.initThreadMXBean();
@ -46,20 +40,20 @@ public class Management {
private static com.sun.management.ThreadMXBean initThreadMXBean() {
try {
return (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
return (com.sun.management.ThreadMXBean) java.lang.management.ManagementFactory.getThreadMXBean();
} catch (Error err) {
return new UnimplementedBean();
}
}
public static ThreadMXBean getThreadMXBean() {
public static java.lang.management.ThreadMXBean getThreadMXBean() {
return threadMXBean;
}
private static class UnimplementedBean implements ThreadMXBean, com.sun.management.ThreadMXBean {
private static class UnimplementedBean implements java.lang.management.ThreadMXBean, com.sun.management.ThreadMXBean {
@Override
public ObjectName getObjectName() {
public javax.management.ObjectName getObjectName() {
return null;
}
@ -123,22 +117,22 @@ public class Management {
}
@Override
public ThreadInfo getThreadInfo(long id) {
public java.lang.management.ThreadInfo getThreadInfo(long id) {
return null;
}
@Override
public ThreadInfo[] getThreadInfo(long[] ids) {
public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids) {
return null;
}
@Override
public ThreadInfo getThreadInfo(long id, int maxDepth) {
public java.lang.management.ThreadInfo getThreadInfo(long id, int maxDepth) {
return null;
}
@Override
public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
return null;
}
@ -220,12 +214,12 @@ public class Management {
}
@Override
public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
return null;
}
@Override
public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
public java.lang.management.ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
return null;
}
}

View File

@ -22,11 +22,9 @@
*/
package org.graalvm.compiler.debug;
import com.sun.management.ThreadMXBean;
/**
* Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed
* using the try-with-resources pattern:
* Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility
* should be employed using the try-with-resources pattern:
*
* <pre>
* try (DebugCloseable a = memUseTracker.start()) {

View File

@ -22,14 +22,12 @@
*/
package org.graalvm.compiler.debug;
import java.lang.management.ThreadMXBean;
/**
* A consistent source of timing data that should be used by all facilities in the debug package.
*/
public class TimeSource {
private static final boolean USING_BEAN;
private static final ThreadMXBean threadMXBean;
private static final java.lang.management.ThreadMXBean threadMXBean;
static {
threadMXBean = Management.getThreadMXBean();

View File

@ -88,7 +88,19 @@ public class CheckGraalIntrinsics extends GraalTest {
}
public static ResolvedJavaMethod resolveIntrinsic(MetaAccessProvider metaAccess, VMIntrinsicMethod intrinsic) throws ClassNotFoundException {
Class<?> c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader());
Class<?> c;
try {
c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader());
} catch (ClassNotFoundException ex) {
try {
Class.forName("javax.naming.Reference");
} catch (ClassNotFoundException coreNamingMissing) {
// if core JDK classes aren't found, we are probably running in a
// JDK9 java.base environment and then missing class is OK
return null;
}
throw ex;
}
for (Method javaMethod : c.getDeclaredMethods()) {
if (javaMethod.getName().equals(intrinsic.name)) {
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(javaMethod);

View File

@ -29,28 +29,38 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.graalvm.compiler.core.GraalCompilerOptions;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.test.SubprocessUtil;
import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
/**
* Tests support for dumping graphs and other info useful for debugging a compiler crash.
*/
public class CompilationWrapperTest extends GraalCompilerTest {
public CompilationWrapperTest() {
try {
Class.forName("java.lang.management.ManagementFactory");
} catch (ClassNotFoundException ex) {
Assume.assumeNoException("skip this test if there is no java.management JDK9 module around", ex);
}
}
/**
* Tests compilation requested by the VM.
*/
@Test
public void testVMCompilation1() throws IOException, InterruptedException {
testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
"-XX:+UseJVMCICompiler",
"-Dgraal.CompilationFailureAction=ExitVM",
"-Dgraal.CrashAt=Object.*,String.*",
@ -63,31 +73,79 @@ public class CompilationWrapperTest extends GraalCompilerTest {
*/
@Test
public void testVMCompilation2() throws IOException, InterruptedException {
testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
"-XX:+UseJVMCICompiler",
"-Dgraal.ExitVMOnException=true",
"-Dgraal.CrashAt=Object.*,String.*",
"-version"));
}
static class Probe {
final String substring;
final int expectedOccurrences;
int actualOccurrences;
String lastMatchingLine;
Probe(String substring, int expectedOccurrences) {
this.substring = substring;
this.expectedOccurrences = expectedOccurrences;
}
boolean matches(String line) {
if (line.contains(substring)) {
actualOccurrences++;
lastMatchingLine = line;
return true;
}
return false;
}
String test() {
return expectedOccurrences == actualOccurrences ? null : String.format("expected %d, got %d occurrences", expectedOccurrences, actualOccurrences);
}
}
/**
* Tests {@link GraalCompilerOptions#MaxCompilationProblemsPerAction} in context of a
* compilation requested by the VM.
*/
@Test
public void testVMCompilation3() throws IOException, InterruptedException {
final int maxProblems = 4;
Probe[] probes = {
new Probe("To capture more information for diagnosing or reporting a compilation", maxProblems),
new Probe("Retrying compilation of", maxProblems),
new Probe("adjusting CompilationFailureAction from Diagnose to Print", 1),
new Probe("adjusting CompilationFailureAction from Print to Silent", 1),
};
testHelper(Arrays.asList(probes), Arrays.asList("-XX:+BootstrapJVMCI",
"-XX:+UseJVMCICompiler",
"-Dgraal.CompilationFailureAction=Diagnose",
"-Dgraal.MaxCompilationProblemsPerAction=" + maxProblems,
"-Dgraal.CrashAt=Object.*,String.*",
"-version"));
}
/**
* Tests compilation requested by Truffle.
*/
@Test
public void testTruffleCompilation() throws IOException, InterruptedException {
testHelper(Arrays.asList(
"-Dgraal.CompilationFailureAction=ExitVM",
"-Dgraal.CrashAt=root test1"),
"org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite",
"test");
testHelper(Collections.emptyList(),
Arrays.asList(
"-Dgraal.CompilationFailureAction=ExitVM",
"-Dgraal.CrashAt=root test1"),
"org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
}
private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose");
private static void testHelper(List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
private static void testHelper(List<Probe> initialProbes, List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
final File dumpPath = new File(CompilationWrapperTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
vmArgs.removeIf(a -> a.startsWith("-Dgraal."));
vmArgs.remove("-esa");
vmArgs.remove("-ea");
vmArgs.add("-Dgraal.DumpPath=" + dumpPath);
// Force output to a file even if there's a running IGV instance available.
vmArgs.add("-Dgraal.PrintGraphFile=true");
@ -98,35 +156,37 @@ public class CompilationWrapperTest extends GraalCompilerTest {
System.out.println(proc);
}
String forcedCrashString = "Forced crash after compiling";
String diagnosticOutputFilePrefix = "Graal diagnostic output saved in ";
boolean seenForcedCrashString = false;
String diagnosticOutputZip = null;
List<Probe> probes = new ArrayList<>(initialProbes);
Probe diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
probes.add(diagnosticProbe);
probes.add(new Probe("Forced crash after compiling", Integer.MAX_VALUE) {
@Override
String test() {
return actualOccurrences > 0 ? null : "expected at least 1 occurrence";
}
});
for (String line : proc.output) {
if (line.contains(forcedCrashString)) {
seenForcedCrashString = true;
} else if (diagnosticOutputZip == null) {
int index = line.indexOf(diagnosticOutputFilePrefix);
if (index != -1) {
diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim();
for (Probe probe : probes) {
if (probe.matches(line)) {
break;
}
}
}
if (!seenForcedCrashString) {
Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, proc));
}
if (diagnosticOutputZip == null) {
Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, proc));
for (Probe probe : probes) {
String error = probe.test();
if (error != null) {
Assert.fail(String.format("Did not find expected occurences of '%s' in output of command: %s%n%s", probe.substring, error, proc));
}
}
String[] dumpPathEntries = dumpPath.list();
String diagnosticOutputZip = diagnosticProbe.lastMatchingLine.substring(diagnosticProbe.substring.length()).trim();
List<String> dumpPathEntries = Arrays.asList(dumpPath.list());
File zip = new File(diagnosticOutputZip).getAbsoluteFile();
Assert.assertTrue(zip.toString(), zip.exists());
Assert.assertArrayEquals(dumpPathEntries, new String[]{zip.getName()});
Assert.assertTrue(zip + " not in " + dumpPathEntries, dumpPathEntries.contains(zip.getName()));
try {
int bgv = 0;
int cfg = 0;

View File

@ -43,6 +43,7 @@ import org.junit.Assert;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.junit.Assume;
/**
* Test on-stack-replacement with locks.
@ -51,6 +52,14 @@ public class GraalOSRLockTest extends GraalOSRTestBase {
private static boolean TestInSeparateThread = false;
public GraalOSRLockTest() {
try {
Class.forName("java.lang.management.ManagementFactory");
} catch (ClassNotFoundException ex) {
Assume.assumeNoException("cannot check for monitors without java.management JDK9 module", ex);
}
}
// testing only
public static boolean isMonitorLockHeld(Object o) {
return isMonitorLockHeldByThread(o, null);

View File

@ -110,7 +110,7 @@ public class HotSpotGraalMBeanTest {
MBeanInfo info = server.getMBeanInfo(name);
assertNotNull("Info is found", info);
MBeanAttributeInfo printCompilation = findAttributeInfo("PrintCompilation", info);
MBeanAttributeInfo printCompilation = (MBeanAttributeInfo) findAttributeInfo("PrintCompilation", info);
assertNotNull("PrintCompilation found", printCompilation);
assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
@ -124,9 +124,9 @@ public class HotSpotGraalMBeanTest {
assertEquals("Changed to on", Boolean.TRUE, after);
}
private static MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) {
private static Object findAttributeInfo(String attrName, Object info) {
MBeanAttributeInfo printCompilation = null;
for (MBeanAttributeInfo attr : info.getAttributes()) {
for (MBeanAttributeInfo attr : ((MBeanInfo) info).getAttributes()) {
if (attr.getName().equals(attrName)) {
assertTrue("Readable", attr.isReadable());
assertTrue("Writable", attr.isWritable());
@ -157,7 +157,7 @@ public class HotSpotGraalMBeanTest {
MBeanInfo info = server.getMBeanInfo(name);
assertNotNull("Info is found", info);
MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
Attribute dumpTo1 = new Attribute(dump.getName(), 1);
@ -215,7 +215,7 @@ public class HotSpotGraalMBeanTest {
"java.util.Arrays", "asList", ":3"
}, null);
MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
Attribute dumpTo1 = new Attribute(dump.getName(), "");
server.setAttribute(name, dumpTo1);
Object after = server.getAttribute(name, dump.getName());

View File

@ -46,7 +46,6 @@ import org.graalvm.compiler.debug.Management;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import com.sun.management.ThreadMXBean;
import jdk.vm.ci.hotspot.HotSpotInstalledCode;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@ -88,7 +87,7 @@ public final class CompilationStatistics {
private static long zeroTime = System.nanoTime();
private static long getThreadAllocatedBytes() {
ThreadMXBean thread = (ThreadMXBean) Management.getThreadMXBean();
com.sun.management.ThreadMXBean thread = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
return thread.getThreadAllocatedBytes(currentThread().getId());
}

View File

@ -96,7 +96,7 @@ public class CompilationTask {
CompilationResult result;
HotSpotCompilationWrapper(EventProvider.CompilationEvent compilationEvent) {
super(compiler.getGraalRuntime().getOutputDirectory());
super(compiler.getGraalRuntime().getOutputDirectory(), compiler.getGraalRuntime().getCompilationProblemsPerAction());
this.compilationEvent = compilationEvent;
}

View File

@ -146,7 +146,7 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
}
}
public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
public StructuredGraph createGraph(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
HotSpotBackend backend = graalRuntime.getHostBackend();
HotSpotProviders providers = backend.getProviders();
final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
@ -160,6 +160,15 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog(
speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build();
}
return graph;
}
public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo,
OptionValues options) {
HotSpotBackend backend = graalRuntime.getHostBackend();
HotSpotProviders providers = backend.getProviders();
final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
Suites suites = getSuites(providers, options);
LIRSuites lirSuites = getLIRSuites(providers, options);
@ -173,11 +182,11 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
if (isOSR && !OnStackReplacementPhase.Options.DeoptAfterOSR.getValue(options)) {
optimisticOpts.remove(Optimization.RemoveNeverExecutedCode);
}
CompilationResult result = new CompilationResult();
result.setEntryBCI(entryBCI);
boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints();
PhaseSuite<HighTierContext> graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR);
GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, CompilationResultBuilderFactory.Default);
GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf);
if (!isOSR && useProfilingInfo) {
ProfilingInfo profile = profilingInfo;
@ -187,6 +196,12 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
return result;
}
public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug);
CompilationResult result = new CompilationResult();
return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options);
}
/**
* Gets a graph produced from the intrinsic for a given method that can be compiled and
* installed for the method.

View File

@ -22,7 +22,6 @@
*/
package org.graalvm.compiler.hotspot;
import java.lang.management.ManagementFactory;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
@ -30,22 +29,6 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
@ -66,14 +49,14 @@ import org.graalvm.util.EconomicSet;
import org.graalvm.util.Equivalence;
import org.graalvm.util.UnmodifiableEconomicMap;
public final class HotSpotGraalMBean implements DynamicMBean {
public final class HotSpotGraalMBean implements javax.management.DynamicMBean {
private static Object mBeanServerField;
private final HotSpotGraalCompiler compiler;
private final OptionValues options;
private final EconomicMap<OptionKey<?>, Object> changes;
private final EconomicSet<Dump> methodDumps;
private volatile EconomicSet<Reference<ClassLoader>> loaders;
private ObjectName registered;
private javax.management.ObjectName registered;
private OptionValues cachedOptions;
private HotSpotGraalMBean(HotSpotGraalCompiler compiler, OptionValues options) {
@ -89,11 +72,11 @@ public final class HotSpotGraalMBean implements DynamicMBean {
private static boolean isMXServerOn() {
if (mBeanServerField == null) {
try {
final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
final Field field = java.lang.management.ManagementFactory.class.getDeclaredField("platformMBeanServer");
field.setAccessible(true);
mBeanServerField = field;
} catch (Exception ex) {
mBeanServerField = ManagementFactory.class;
mBeanServerField = java.lang.management.ManagementFactory.class;
}
}
if (mBeanServerField instanceof Field) {
@ -113,7 +96,7 @@ public final class HotSpotGraalMBean implements DynamicMBean {
return mbean;
}
public ObjectName ensureRegistered(boolean check) {
public javax.management.ObjectName ensureRegistered(boolean check) {
for (int cnt = 0;; cnt++) {
if (registered != null) {
return registered;
@ -122,14 +105,14 @@ public final class HotSpotGraalMBean implements DynamicMBean {
return null;
}
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer();
javax.management.ObjectName name = new javax.management.ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
mbs.registerMBean(this, name);
registered = name;
break;
} catch (MalformedObjectNameException | MBeanRegistrationException | NotCompliantMBeanException ex) {
} catch (javax.management.MalformedObjectNameException | javax.management.MBeanRegistrationException | javax.management.NotCompliantMBeanException ex) {
throw new IllegalStateException(ex);
} catch (InstanceAlreadyExistsException ex) {
} catch (javax.management.InstanceAlreadyExistsException ex) {
continue;
}
}
@ -188,14 +171,14 @@ public final class HotSpotGraalMBean implements DynamicMBean {
}
@Override
public void setAttribute(Attribute attribute) throws AttributeNotFoundException {
Attribute newAttr = setImpl(attribute);
public void setAttribute(javax.management.Attribute attribute) throws javax.management.AttributeNotFoundException {
javax.management.Attribute newAttr = setImpl(attribute);
if (newAttr == null) {
throw new AttributeNotFoundException();
throw new javax.management.AttributeNotFoundException();
}
}
private Attribute setImpl(Attribute attribute) {
private javax.management.Attribute setImpl(javax.management.Attribute attribute) {
cachedOptions = null;
for (OptionDescriptor option : allOptionDescriptors()) {
if (option.getName().equals(attribute.getName())) {
@ -207,22 +190,22 @@ public final class HotSpotGraalMBean implements DynamicMBean {
}
@Override
public AttributeList getAttributes(String[] names) {
AttributeList list = new AttributeList();
public javax.management.AttributeList getAttributes(String[] names) {
javax.management.AttributeList list = new javax.management.AttributeList();
for (String name : names) {
Object value = getAttribute(name);
if (value != null) {
list.add(new Attribute(name, value));
list.add(new javax.management.Attribute(name, value));
}
}
return list;
}
@Override
public AttributeList setAttributes(AttributeList attributes) {
AttributeList setOk = new AttributeList();
for (Attribute attr : attributes.asList()) {
Attribute newAttr = setImpl(attr);
public javax.management.AttributeList setAttributes(javax.management.AttributeList attributes) {
javax.management.AttributeList setOk = new javax.management.AttributeList();
for (javax.management.Attribute attr : attributes.asList()) {
javax.management.Attribute newAttr = setImpl(attr);
if (newAttr != null) {
setOk.add(newAttr);
}
@ -231,7 +214,7 @@ public final class HotSpotGraalMBean implements DynamicMBean {
}
@Override
public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
public Object invoke(String actionName, Object[] params, String[] signature) throws javax.management.MBeanException, javax.management.ReflectionException {
if ("dumpMethod".equals(actionName)) {
try {
String className = param(params, 0, "className", String.class, null);
@ -241,7 +224,7 @@ public final class HotSpotGraalMBean implements DynamicMBean {
Number port = param(params, 4, "port", Number.class, 4445);
dumpMethod(className, methodName, filter, host, port.intValue());
} catch (Exception ex) {
throw new ReflectionException(ex);
throw new javax.management.ReflectionException(ex);
}
}
return null;
@ -261,7 +244,7 @@ public final class HotSpotGraalMBean implements DynamicMBean {
throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
}
public void dumpMethod(String className, String methodName, String filter, String host, int port) throws MBeanException {
public void dumpMethod(String className, String methodName, String filter, String host, int port) throws javax.management.MBeanException {
String jvmName = MetaUtil.toInternalName(className);
methodDumps.add(new Dump(host, port, jvmName, methodName, filter));
@ -293,41 +276,41 @@ public final class HotSpotGraalMBean implements DynamicMBean {
}
}
if (found.isEmpty()) {
throw new MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
throw new javax.management.MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
}
}
@Override
public MBeanInfo getMBeanInfo() {
List<MBeanAttributeInfo> attrs = new ArrayList<>();
public javax.management.MBeanInfo getMBeanInfo() {
List<javax.management.MBeanAttributeInfo> attrs = new ArrayList<>();
if (registered != null) {
for (OptionDescriptor descr : allOptionDescriptors()) {
attrs.add(new MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
}
}
MBeanOperationInfo[] ops = {
new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
}, "void", MBeanOperationInfo.ACTION),
new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
}, "void", MBeanOperationInfo.ACTION),
new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
}, "void", MBeanOperationInfo.ACTION)
javax.management.MBeanOperationInfo[] ops = {
new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
}, "void", javax.management.MBeanOperationInfo.ACTION),
new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
}, "void", javax.management.MBeanOperationInfo.ACTION),
new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
new javax.management.MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
new javax.management.MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
}, "void", javax.management.MBeanOperationInfo.ACTION)
};
return new MBeanInfo(
return new javax.management.MBeanInfo(
HotSpotGraalMBean.class.getName(),
"Graal",
attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
attrs.toArray(new javax.management.MBeanAttributeInfo[attrs.size()]),
null, ops, null);
}

View File

@ -30,10 +30,13 @@ import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining
import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.api.runtime.GraalRuntime;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.target.Backend;
@ -95,6 +98,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
private final OptionValues options;
private final DiagnosticsOutputDirectory outputDirectory;
private final Map<ExceptionAction, Integer> compilationProblemsPerAction;
private final HotSpotGraalMBean mBean;
/**
@ -114,11 +118,12 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
}
outputDirectory = new DiagnosticsOutputDirectory(options);
compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class);
snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions);
this.mBean = HotSpotGraalMBean.create(compiler);
this.mBean = createHotSpotGraalMBean(compiler);
BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
@ -167,6 +172,14 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
}
private static HotSpotGraalMBean createHotSpotGraalMBean(HotSpotGraalCompiler compiler) {
try {
return HotSpotGraalMBean.create(compiler);
} catch (LinkageError ex) {
return null;
}
}
private HotSpotBackend registerBackend(HotSpotBackend backend) {
Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
HotSpotBackend oldValue = backends.put(arch, backend);
@ -192,12 +205,12 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
@Override
public OptionValues getOptions() {
return mBean.optionsFor(options, null);
return mBean == null ? options : mBean.optionsFor(options, null);
}
@Override
public OptionValues getOptions(ResolvedJavaMethod forMethod) {
return mBean.optionsFor(options, forMethod);
return mBean == null ? options : mBean.optionsFor(options, forMethod);
}
@Override
@ -298,4 +311,9 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
public DiagnosticsOutputDirectory getOutputDirectory() {
return outputDirectory;
}
@Override
public Map<ExceptionAction, Integer> getCompilationProblemsPerAction() {
return compilationProblemsPerAction;
}
}

View File

@ -22,7 +22,10 @@
*/
package org.graalvm.compiler.hotspot;
import java.util.Map;
import org.graalvm.compiler.api.runtime.GraalRuntime;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
@ -95,4 +98,9 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid
* Gets a directory into which diagnostics such crash reports and dumps should be written.
*/
DiagnosticsOutputDirectory getOutputDirectory();
/**
* Gets the map used to count compilation problems at each {@link ExceptionAction} level.
*/
Map<ExceptionAction, Integer> getCompilationProblemsPerAction();
}

View File

@ -27,7 +27,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
@ -53,8 +52,8 @@ public class PrintStreamOptionKey extends OptionKey<String> {
private String getFilename(OptionValues options) {
String name = getValue(options);
if (name.contains("%p")) {
String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
try {
String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
int index = runtimeName.indexOf('@');
if (index != -1) {
long pid = Long.parseLong(runtimeName.substring(0, index));
@ -63,6 +62,8 @@ public class PrintStreamOptionKey extends OptionKey<String> {
name = name.replaceAll("%p", runtimeName);
} catch (NumberFormatException e) {
} catch (LinkageError err) {
name = String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
}
}
if (name.contains("%t")) {
@ -124,7 +125,7 @@ public class PrintStreamOptionKey extends OptionKey<String> {
/*
* Add the JVM and Java arguments to the log file to help identity it.
*/
String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments());
String inputArguments = String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
ps.println("VM Arguments: " + inputArguments);
String cmd = System.getProperty("sun.java.command");
if (cmd != null) {

View File

@ -510,6 +510,8 @@ public class BytecodeParser implements GraphBuilderContext {
*/
private void processPlaceholderFrameStates(IntrinsicContext intrinsic) {
StructuredGraph graph = parser.getGraph();
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method);
boolean sawInvalidFrameState = false;
for (Node node : graph.getNewNodes(mark)) {
if (node instanceof FrameState) {
FrameState frameState = (FrameState) node;
@ -547,6 +549,7 @@ public class BytecodeParser implements GraphBuilderContext {
FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
frameState.replaceAndDelete(newFrameState);
sawInvalidFrameState = true;
} else {
// An intrinsic for a void method.
FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null);
@ -585,6 +588,17 @@ public class BytecodeParser implements GraphBuilderContext {
}
}
}
if (sawInvalidFrameState) {
JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
FrameStateBuilder frameStateBuilder = parser.frameState;
ValueNode returnValue = frameStateBuilder.pop(returnKind);
StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue));
parser.lastInstr.setNext(proxy);
frameStateBuilder.push(returnKind, proxy);
proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy));
parser.lastInstr = proxy;
}
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method);
}
}
@ -1345,7 +1359,7 @@ public class BytecodeParser implements GraphBuilderContext {
/*
* Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...)
* or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
* https://wiki.openjdk.java.net/display/HotSpot/Method+handles+and+invokedynamic
* https://wikis.oracle.com/display/HotSpotInternals/Method+handles +and+invokedynamic
*/
boolean hasReceiver = !((ResolvedJavaMethod) target).isStatic();
JavaConstant appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
@ -1987,7 +2001,7 @@ public class BytecodeParser implements GraphBuilderContext {
*/
private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) {
byte[] bytecode = targetMethod.getCode();
if (bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
if (bytecode != null && bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
Bytes.beU1(bytecode, 0) == ALOAD_0 &&
Bytes.beU1(bytecode, 1) == GETFIELD) {
int b4 = Bytes.beU1(bytecode, 4);
@ -2188,6 +2202,14 @@ public class BytecodeParser implements GraphBuilderContext {
lastInstr = finishInstruction(returnMergeNode, frameState);
}
}
/*
* Propagate any side effects into the caller when parsing intrinsics.
*/
if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
for (StateSplit sideEffect : parser.frameState.sideEffects()) {
frameState.addSideEffect(sideEffect);
}
}
FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
if (calleeBeforeUnwindNode != null) {
@ -3037,7 +3059,7 @@ public class BytecodeParser implements GraphBuilderContext {
ConstantNode falseValue = graph.unique(ConstantNode.forInt(falseBlockInt));
ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue);
if (conditionalNode.graph() == null) {
conditionalNode = graph.addOrUnique(conditionalNode);
conditionalNode = graph.addOrUniqueWithInputs(conditionalNode);
}
if (genReturn) {
JavaKind returnKind = method.getSignature().getReturnKind().getStackKind();

View File

@ -102,6 +102,7 @@ public final class FrameStateBuilder implements SideEffectsState {
private final StructuredGraph graph;
private final boolean clearNonLiveLocals;
private FrameState outerFrameState;
private NodeSourcePosition outerSourcePosition;
/**
* The closest {@link StateSplit#hasSideEffect() side-effect} predecessors. There will be more
@ -364,13 +365,12 @@ public final class FrameStateBuilder implements SideEffectsState {
// Skip intrinsic frames
parent = parser.getNonIntrinsicAncestor();
}
return create(null, constantReceiver, bci, parent, hideSubstitutionStates);
return create(constantReceiver, bci, parent, hideSubstitutionStates);
}
private NodeSourcePosition create(NodeSourcePosition o, JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) {
NodeSourcePosition outer = o;
if (outer == null && parent != null) {
outer = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates);
private NodeSourcePosition create(JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) {
if (outerSourcePosition == null && parent != null) {
outerSourcePosition = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates);
}
if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) {
return FrameState.toSourcePosition(outerFrameState);
@ -378,7 +378,7 @@ public final class FrameStateBuilder implements SideEffectsState {
if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
throw shouldNotReachHere();
}
return new NodeSourcePosition(receiver, outer, code.getMethod(), bci);
return new NodeSourcePosition(receiver, outerSourcePosition, code.getMethod(), bci);
}
public FrameStateBuilder copy() {

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2011, 2012, 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.jtt.hotspot;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public final class NotOnDebug {
public static TestRule create(Timeout seconds) {
try {
return new DisableOnDebug(seconds);
} catch (LinkageError ex) {
return null;
}
}
}

View File

@ -25,13 +25,12 @@ package org.graalvm.compiler.jtt.hotspot;
import org.graalvm.compiler.jtt.JTTTest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Test6959129 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
public static long test() {
int min = Integer.MAX_VALUE - 30000;

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public final class Monitor_contended01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static class TestClass implements Runnable {
boolean started = false;

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Monitor_notowner01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
static Object monitor = new Object();
static Object finished = new Object();

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public final class Monitorenter01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
static final Object object = new Object();

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public final class Monitorenter02 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
static final Object object = new Object();

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Object_wait01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static class TestClass implements Runnable {
@Override

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Object_wait02 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static class TestClass implements Runnable {
@Override

View File

@ -30,11 +30,11 @@ import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.nodes.Cancellable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
public class Object_wait03 extends JTTTest {
@ -48,7 +48,7 @@ public class Object_wait03 extends JTTTest {
*/
static final long TIMEOUT_MS = COMPILATION_TIMEOUT_MS * 2;
@Rule public TestRule timeout = new DisableOnDebug(Timeout.millis(TIMEOUT_MS));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.millis(TIMEOUT_MS));
private static class TestClass implements Runnable {
@Override

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Object_wait04 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static class TestClass implements Runnable {
@Override

View File

@ -25,9 +25,9 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
@ -39,7 +39,7 @@ import org.junit.rules.Timeout;
*/
public final class SynchronizedLoopExit01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
protected Object object = new Object();
protected volatile boolean drained = false;

View File

@ -27,17 +27,17 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
//Test all, mainly monitors
public class Thread_isInterrupted02 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static final Object start = new Object();
private static final Object end = new Object();

View File

@ -23,9 +23,9 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
@ -35,7 +35,7 @@ import org.junit.rules.Timeout;
// Interrupted while sleeping, throws an interrupted exception
public class Thread_isInterrupted03 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
public static boolean test() throws InterruptedException {
final Thread1 thread = new Thread1();

View File

@ -23,9 +23,9 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
@ -35,7 +35,7 @@ import org.junit.rules.Timeout;
// Interrupted during wait, with interrupter joining
public class Thread_isInterrupted05 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
public static boolean test() throws InterruptedException {
final WaitInterruptee waitInterruptee = new WaitInterruptee();

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Thread_join01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static class TestClass implements Runnable {
@Override

View File

@ -28,15 +28,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Thread_join02 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static class TestClass implements Runnable {
@Override

View File

@ -28,15 +28,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public class Thread_join03 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
private static class TestClass implements Runnable {
@Override

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public final class Thread_sleep01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
public static boolean test(int i) throws InterruptedException {
final long before = System.currentTimeMillis();

View File

@ -25,15 +25,15 @@
package org.graalvm.compiler.jtt.threads;
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
public final class Thread_yield01 extends JTTTest {
@Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
@Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
public static boolean test() {
Thread.yield();

View File

@ -110,6 +110,8 @@ public class AMD64ControlFlow {
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
boolean isNegated = false;
int jccPos = masm.position();
/*
* The strategy for emitting jumps is: If either trueDestination or falseDestination is
* the successor block, assume the block scheduler did the correct thing and jcc to the
@ -120,15 +122,18 @@ public class AMD64ControlFlow {
*/
if (crb.isSuccessorEdge(trueDestination)) {
jcc(masm, true, falseDestination);
isNegated = true;
} else if (crb.isSuccessorEdge(falseDestination)) {
jcc(masm, false, trueDestination);
} else if (trueDestinationProbability < 0.5) {
jcc(masm, true, falseDestination);
masm.jmp(trueDestination.label());
isNegated = true;
} else {
jcc(masm, false, trueDestination);
masm.jmp(falseDestination.label());
}
crb.recordBranch(jccPos, isNegated);
}
protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) {

View File

@ -34,11 +34,11 @@ import java.util.function.Consumer;
import org.graalvm.compiler.asm.AbstractAddress;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
import org.graalvm.compiler.code.DataSection.Data;
import org.graalvm.compiler.code.DataSection.RawData;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.DataPointerConstant;
@ -130,12 +130,12 @@ public class CompilationResultBuilder {
/**
* The LIR for which code is being generated.
*/
private LIR lir;
protected LIR lir;
/**
* The index of the block currently being emitted.
*/
private int currentBlockIndex;
protected int currentBlockIndex;
/**
* The object that emits code for managing a method's frame.
@ -312,6 +312,15 @@ public class CompilationResultBuilder {
return recordDataSectionReference(new RawData(data, alignment));
}
/**
* Notifies this object of a branch instruction at offset {@code pos} in the code.
*
* @param isNegated negation status of the branch's condition.
*/
@SuppressWarnings("unused")
public void recordBranch(int pos, boolean isNegated) {
}
/**
* Returns the integer value of any constant that can be represented by a 32-bit integer value,
* including long constants that fit into the 32-bit range.
@ -520,4 +529,5 @@ public class CompilationResultBuilder {
public OptionValues getOptions() {
return options;
}
}

View File

@ -22,6 +22,14 @@
*/
package org.graalvm.compiler.loop.phases;
import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
import static org.graalvm.compiler.loop.MathUtil.add;
import static org.graalvm.compiler.loop.MathUtil.sub;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.graalvm.compiler.core.common.RetryableBailoutException;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
@ -56,18 +64,9 @@ import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.calc.ConditionalNode;
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
import org.graalvm.compiler.nodes.extended.SwitchNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
import static org.graalvm.compiler.loop.MathUtil.add;
import static org.graalvm.compiler.loop.MathUtil.sub;
public abstract class LoopTransformations {
private LoopTransformations() {
@ -282,10 +281,10 @@ public abstract class LoopTransformations {
// The pre and post loops don't require safepoints at all
for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) {
GraphUtil.removeFixedWithUnusedInputs(safepoint);
graph.removeFixed(safepoint);
}
for (SafepointNode safepoint : postLoop.nodes().filter(SafepointNode.class)) {
GraphUtil.removeFixedWithUnusedInputs(safepoint);
graph.removeFixed(safepoint);
}
}
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "InsertPrePostLoops %s", loop);
@ -442,7 +441,7 @@ public abstract class LoopTransformations {
}
public static boolean isUnrollableLoop(LoopEx loop) {
if (!loop.isCounted() || !loop.counted().getCounter().isConstantStride()) {
if (!loop.isCounted() || !loop.counted().getCounter().isConstantStride() || !loop.loop().getChildren().isEmpty()) {
return false;
}
LoopBeginNode loopBegin = loop.loopBegin();

View File

@ -22,6 +22,9 @@
*/
package org.graalvm.compiler.loop;
import java.util.LinkedList;
import java.util.List;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
@ -60,9 +63,6 @@ import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.util.EconomicMap;
import org.graalvm.util.Equivalence;
import java.util.LinkedList;
import java.util.List;
public class LoopFragmentInside extends LoopFragment {
/**
@ -153,7 +153,7 @@ public class LoopFragmentInside extends LoopFragment {
if (duplicatedNode != null) {
mainPhiNode.setValueAt(1, duplicatedNode);
} else {
assert mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1));
assert mainPhiNode.valueAt(1).isConstant() || mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1)) : mainPhiNode.valueAt(1);
}
}
@ -162,7 +162,7 @@ public class LoopFragmentInside extends LoopFragment {
// Remove any safepoints from the original copy leaving only the duplicated one
assert loop.whole().nodes().filter(SafepointNode.class).count() == nodes().filter(SafepointNode.class).count();
for (SafepointNode safepoint : loop.whole().nodes().filter(SafepointNode.class)) {
GraphUtil.removeFixedWithUnusedInputs(safepoint);
graph().removeFixed(safepoint);
}
int unrollFactor = mainLoopBegin.getUnrollFactor();

View File

@ -145,14 +145,45 @@ public final class ConditionalNode extends FloatingNode implements Canonicalizab
}
public static ValueNode canonicalizeConditional(LogicNode condition, ValueNode trueValue, ValueNode falseValue, Stamp stamp) {
// this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1
if (trueValue.isConstant() && falseValue.isConstant() && condition instanceof IntegerEqualsNode) {
IntegerEqualsNode equals = (IntegerEqualsNode) condition;
if (equals.getY().isConstant() && equals.getY().asConstant().equals(JavaConstant.INT_0) && equals.getX().stamp() instanceof IntegerStamp) {
IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
if (equalsXStamp.upMask() == 1) {
if (trueValue.asConstant().equals(JavaConstant.INT_0) && falseValue.asConstant().equals(JavaConstant.INT_1)) {
return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
// this optimizes the case where a value from the range 0 - 1 is mapped to the range 0 - 1
if (trueValue.isConstant() && falseValue.isConstant() && trueValue.stamp() instanceof IntegerStamp && falseValue.stamp() instanceof IntegerStamp) {
long constTrueValue = trueValue.asJavaConstant().asLong();
long constFalseValue = falseValue.asJavaConstant().asLong();
if (condition instanceof IntegerEqualsNode) {
IntegerEqualsNode equals = (IntegerEqualsNode) condition;
if (equals.getY().isConstant() && equals.getX().stamp() instanceof IntegerStamp) {
IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
if (equalsXStamp.upMask() == 1) {
long equalsY = equals.getY().asJavaConstant().asLong();
if (equalsY == 0) {
if (constTrueValue == 0 && constFalseValue == 1) {
// return x when: x == 0 ? 0 : 1;
return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
} else if (constTrueValue == 1 && constFalseValue == 0) {
// negate a boolean value via xor
return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
}
} else if (equalsY == 1) {
if (constTrueValue == 1 && constFalseValue == 0) {
// return x when: x == 1 ? 1 : 0;
return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
} else if (constTrueValue == 0 && constFalseValue == 1) {
// negate a boolean value via xor
return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
}
}
}
}
} else if (condition instanceof IntegerTestNode) {
// replace IntegerTestNode with AndNode for the following patterns:
// (value & 1) == 0 ? 0 : 1
// (value & 1) == 1 ? 1 : 0
IntegerTestNode integerTestNode = (IntegerTestNode) condition;
if (integerTestNode.getY().isConstant()) {
assert integerTestNode.getX().stamp() instanceof IntegerStamp;
long testY = integerTestNode.getY().asJavaConstant().asLong();
if (testY == 1 && constTrueValue == 0 && constFalseValue == 1) {
return IntegerConvertNode.convertUnsigned(AndNode.create(integerTestNode.getX(), integerTestNode.getY()), stamp);
}
}
}

View File

@ -153,6 +153,7 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut
} else if (forX.stamp().alwaysDistinct(forY.stamp())) {
return LogicConstantNode.contradiction();
}
if (forX instanceof AddNode && forY instanceof AddNode) {
AddNode addX = (AddNode) forX;
AddNode addY = (AddNode) forY;
@ -176,6 +177,7 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut
return create(v1, v2);
}
}
return super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY);
}
@ -255,6 +257,15 @@ public final class IntegerEqualsNode extends CompareNode implements BinaryCommut
return new LogicNegationNode(new IntegerTestNode(andNode.getX(), andNode.getY()));
}
}
if (nonConstant instanceof XorNode && nonConstant.stamp() instanceof IntegerStamp) {
XorNode xorNode = (XorNode) nonConstant;
if (xorNode.getY().isJavaConstant() && xorNode.getY().asJavaConstant().asLong() == 1 && ((IntegerStamp) xorNode.getX().stamp()).upMask() == 1) {
// x ^ 1 == 0 is the same as x == 1 if x in [0, 1]
// x ^ 1 == 1 is the same as x == 0 if x in [0, 1]
return new IntegerEqualsNode(xorNode.getX(), ConstantNode.forIntegerStamp(xorNode.getX().stamp(), primitiveConstant.asLong() ^ 1));
}
}
}
return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue);
}

View File

@ -37,6 +37,9 @@ import org.graalvm.compiler.nodes.ValueNode;
/**
* This node provides a state split along with the functionality of {@link FixedValueAnchorNode}.
* This is used to capture a state for deoptimization when a node has side effects which aren't
* easily represented. The anchored value is usually part of the FrameState since this forces uses
* of the value below this node so they will consume this frame state instead of an earlier one.
*/
@NodeInfo(cycles = CYCLES_0, size = SIZE_0)
public final class StateSplitProxyNode extends FixedValueAnchorNode implements Canonicalizable, StateSplit {
@ -44,6 +47,19 @@ public final class StateSplitProxyNode extends FixedValueAnchorNode implements C
public static final NodeClass<StateSplitProxyNode> TYPE = NodeClass.create(StateSplitProxyNode.class);
@OptionalInput(InputType.State) FrameState stateAfter;
/**
* Disallows elimination of this node until after the FrameState has been consumed.
*/
private final boolean delayElimination;
public StateSplitProxyNode(ValueNode object) {
this(object, false);
}
public StateSplitProxyNode(ValueNode object, boolean delayElimination) {
super(TYPE, object);
this.delayElimination = delayElimination;
}
@Override
public FrameState stateAfter() {
@ -62,13 +78,9 @@ public final class StateSplitProxyNode extends FixedValueAnchorNode implements C
return true;
}
public StateSplitProxyNode(ValueNode object) {
super(TYPE, object);
}
@Override
public Node canonical(CanonicalizerTool tool) {
if (object.isConstant()) {
if (object.isConstant() && !delayElimination || stateAfter == null) {
return object;
}
return this;

View File

@ -34,8 +34,8 @@ import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.PiNode;
@ -241,7 +241,12 @@ public interface GraphBuilderContext extends GraphBuilderTool {
*/
default int getDepth() {
GraphBuilderContext parent = getParent();
return parent == null ? 0 : 1 + parent.getDepth();
int result = 0;
while (parent != null) {
result++;
parent = parent.getParent();
}
return result;
}
/**

View File

@ -25,6 +25,7 @@ package org.graalvm.compiler.nodes.java;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
@ -84,10 +85,21 @@ public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable,
if (kind == JavaKind.Object && type != null && type.isArray()) {
return StampFactory.object(TypeReference.createTrusted(assumptions, type.getComponentType()));
} else {
return StampFactory.forKind(kind);
JavaKind preciseKind = determinePreciseArrayElementType(array, kind);
return StampFactory.forKind(preciseKind);
}
}
private static JavaKind determinePreciseArrayElementType(ValueNode array, JavaKind kind) {
if (kind == JavaKind.Byte) {
ResolvedJavaType javaType = ((ObjectStamp) array.stamp()).type();
if (javaType != null && javaType.isArray() && javaType.getComponentType() != null && javaType.getComponentType().getJavaKind() == JavaKind.Boolean) {
return JavaKind.Boolean;
}
}
return kind;
}
@Override
public boolean inferStamp() {
return updateStamp(stamp.improveWith(createStamp(graph().getAssumptions(), array(), elementKind())));

View File

@ -47,6 +47,7 @@ import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;
import org.graalvm.compiler.phases.Phase;
public class ExpandLogicPhase extends Phase {
private static final double EPSILON = 1E-6;
@Override
protected void run(StructuredGraph graph) {
@ -99,18 +100,39 @@ public class ExpandLogicPhase extends Phase {
}
private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
/*
* this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into two
* separate IfNodes: if(X) and if(Y)
*
* for computing the probabilities P(X) and P(Y), we use two different approaches. The first
* one assumes that the shortCircuitProbability and the probability on the IfNode were
* created with each other in mind. If this assumption does not hold, we fall back to
* another mechanism for computing the probabilities.
*/
AbstractBeginNode trueTarget = ifNode.trueSuccessor();
AbstractBeginNode falseTarget = ifNode.falseSuccessor();
// while the first if node is reached by all cases, the true values are split between the
// first and the second if
double firstIfProbability = ifNode.probability(trueTarget) * shortCircuitProbability;
// the second if node is reached by a reduced number of true cases but the same number of
// false cases
double secondIfProbability = 1 - ifNode.probability(falseTarget) / (1 - firstIfProbability);
secondIfProbability = Math.min(1.0, Math.max(0.0, secondIfProbability));
if (Double.isNaN(secondIfProbability)) {
secondIfProbability = 0.5;
// 1st approach
// assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
double firstIfTrueProbability = shortCircuitProbability;
double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability));
double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability;
if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) {
/*
* 2nd approach
*
* the assumption above did not hold, so we either used an artificial probability as
* shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode.
*
* so, we distribute the if's trueSuccessorProbability between the newly generated if
* nodes according to the shortCircuitProbability. the following invariant is always
* true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
*/
firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability;
secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability)));
}
ifNode.clearSuccessors();
Graph graph = ifNode.graph();
AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
@ -122,17 +144,30 @@ public class ExpandLogicPhase extends Phase {
AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
if (yNegated) {
secondIfProbability = 1.0 - secondIfProbability;
secondIfTrueProbability = 1.0 - secondIfTrueProbability;
}
if (xNegated) {
firstIfProbability = 1.0 - firstIfProbability;
firstIfTrueProbability = 1.0 - firstIfTrueProbability;
}
AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability)));
IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability));
ifNode.replaceAtPredecessor(firstIf);
ifNode.safeDelete();
}
private static boolean doubleEquals(double a, double b) {
assert !Double.isNaN(a) && !Double.isNaN(b) && !Double.isInfinite(a) && !Double.isInfinite(b);
return a - EPSILON < b && a + EPSILON > b;
}
private static double sanitizeProbability(double value) {
double newValue = Math.min(1.0, Math.max(0.0, value));
if (Double.isNaN(newValue)) {
newValue = 0.5;
}
return newValue;
}
private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional) {
ValueNode trueTarget = conditional.trueValue();
ValueNode falseTarget = conditional.falseValue();

View File

@ -42,6 +42,8 @@ import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.BytecodeFrame;
/**
* This phase transfers {@link FrameState} nodes from {@link StateSplit} nodes to
* {@link DeoptimizingNode DeoptimizingNodes}.
@ -71,7 +73,11 @@ public class FrameStateAssignmentPhase extends Phase {
StateSplit stateSplit = (StateSplit) node;
FrameState stateAfter = stateSplit.stateAfter();
if (stateAfter != null) {
currentState = stateAfter;
if (stateAfter.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
currentState = null;
} else {
currentState = stateAfter;
}
stateSplit.setStateAfter(null);
}
}
@ -141,7 +147,10 @@ public class FrameStateAssignmentPhase extends Phase {
return null;
}
}
return singleState;
if (singleState != null && singleState.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI) {
return singleState;
}
return null;
}
@Override

View File

@ -131,13 +131,13 @@ public class PhaseSuite<C> extends BasePhase<C> {
return findNextPhase(it, phaseClass, false);
}
@SuppressWarnings("unchecked")
public static <C> boolean findNextPhase(ListIterator<BasePhase<? super C>> it, Class<? extends BasePhase<? super C>> phaseClass, boolean recursive) {
while (it.hasNext()) {
BasePhase<? super C> phase = it.next();
if (phaseClass.isInstance(phase)) {
return true;
} else if (recursive && phase instanceof PhaseSuite) {
@SuppressWarnings("unchecked")
PhaseSuite<C> suite = (PhaseSuite<C>) phase;
if (suite.findPhase(phaseClass, true) != null) {
return true;
@ -151,6 +151,7 @@ public class PhaseSuite<C> extends BasePhase<C> {
* Removes the first instance of the given phase class, looking recursively into inner phase
* suites.
*/
@SuppressWarnings("unchecked")
public boolean removePhase(Class<? extends BasePhase<? super C>> phaseClass) {
ListIterator<BasePhase<? super C>> it = phases.listIterator();
while (it.hasNext()) {
@ -159,7 +160,6 @@ public class PhaseSuite<C> extends BasePhase<C> {
it.remove();
return true;
} else if (phase instanceof PhaseSuite) {
@SuppressWarnings("unchecked")
PhaseSuite<C> innerSuite = (PhaseSuite<C>) phase;
if (innerSuite.removePhase(phaseClass)) {
if (innerSuite.phases.isEmpty()) {
@ -176,6 +176,7 @@ public class PhaseSuite<C> extends BasePhase<C> {
* Removes the first instance of the given phase class, looking recursively into inner phase
* suites.
*/
@SuppressWarnings("unchecked")
public boolean replacePhase(Class<? extends BasePhase<? super C>> phaseClass, BasePhase<? super C> newPhase) {
ListIterator<BasePhase<? super C>> it = phases.listIterator();
while (it.hasNext()) {
@ -184,7 +185,6 @@ public class PhaseSuite<C> extends BasePhase<C> {
it.set(newPhase);
return true;
} else if (phase instanceof PhaseSuite) {
@SuppressWarnings("unchecked")
PhaseSuite<C> innerSuite = (PhaseSuite<C>) phase;
if (innerSuite.removePhase(phaseClass)) {
if (innerSuite.phases.isEmpty()) {

View File

@ -25,7 +25,6 @@ package org.graalvm.compiler.printer;
import static org.graalvm.compiler.debug.DebugConfig.asJavaMethod;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.nio.channels.ClosedByInterruptException;
import java.util.ArrayList;
import java.util.Arrays;
@ -82,10 +81,18 @@ public class GraphPrinterDumpHandler implements DebugDumpHandler {
public GraphPrinterDumpHandler(GraphPrinterSupplier printerSupplier) {
this.printerSupplier = printerSupplier;
/* Add the JVM and Java arguments to the graph properties to help identify it. */
this.jvmArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments());
this.jvmArguments = jvmArguments();
this.sunJavaCommand = System.getProperty("sun.java.command");
}
private static String jvmArguments() {
try {
return String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
} catch (LinkageError err) {
return "unknown";
}
}
private void ensureInitialized(Graph graph) {
if (printer == null) {
if (failuresCount >= FAILURE_LIMIT) {

View File

@ -24,6 +24,8 @@ package org.graalvm.compiler.replacements.test;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@ -80,7 +82,10 @@ public class PointerTrackingTest extends ReplacementsTest implements Snippets {
@Test(expected = GraalError.class)
@SuppressWarnings("try")
public void testVerification() {
compile(getResolvedJavaMethod("verificationSnippet"), null);
DebugContext debug = getDebugContext();
try (DebugCloseable d = debug.disableIntercept(); DebugContext.Scope s = debug.scope("PointerTrackingTest")) {
compile(getResolvedJavaMethod("verificationSnippet"), null);
}
}
public static long verificationSnippet(Object obj) {

View File

@ -29,24 +29,46 @@ import java.util.function.Function;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.GraalGraphError;
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.debug.OpaqueNode;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.FloatingReadPhase;
import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase;
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.word.LocationIdentity;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
@ -158,6 +180,14 @@ public class ReplacementsParseTest extends ReplacementsTest {
static int copyFirstL2R(byte[] left, byte[] right) {
return copyFirstL2RBody(left, right);
}
static int nonVoidIntrinsicWithCall(@SuppressWarnings("unused") int x, int y) {
return y;
}
static int nonVoidIntrinsicWithOptimizedSplit(int x) {
return x;
}
}
@ClassSubstitution(TestObject.class)
@ -240,18 +270,45 @@ public class ReplacementsParseTest extends ReplacementsTest {
private static String apply(Function<String, String> f, String value) {
return f.apply(value);
}
@MethodSubstitution(isStatic = true)
static int nonVoidIntrinsicWithCall(int x, int y) {
nonVoidIntrinsicWithCallStub(x);
return y;
}
@MethodSubstitution(isStatic = true)
static int nonVoidIntrinsicWithOptimizedSplit(int x) {
if (x == GraalDirectives.opaque(x)) {
nonVoidIntrinsicWithCallStub(x);
}
return x;
}
public static void nonVoidIntrinsicWithCallStub(int zLen) {
nonVoidIntrinsicWithCallStub(STUB_CALL, zLen);
}
static final ForeignCallDescriptor STUB_CALL = new ForeignCallDescriptor("stubCall", void.class, int.class);
@NodeIntrinsic(ForeignCallNode.class)
private static native void nonVoidIntrinsicWithCallStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, int zLen);
}
@Override
protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider();
Registration r = new Registration(invocationPlugins, TestObject.class, replacementBytecodeProvider);
new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, null);
NodeIntrinsicPluginFactory.InjectionProvider injections = new DummyInjectionProvider();
new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, injections);
r.registerMethodSubstitution(TestObjectSubstitutions.class, "nextAfter", double.class, double.class);
r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringize", Object.class);
r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringizeId", Receiver.class);
r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirst", byte[].class, byte[].class, boolean.class);
r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirstL2R", byte[].class, byte[].class);
r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithCall", int.class, int.class);
r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithOptimizedSplit", int.class);
if (replacementBytecodeProvider.supportsInvokedynamic()) {
r.registerMethodSubstitution(TestObjectSubstitutions.class, "identity", String.class);
@ -496,4 +553,108 @@ public class ReplacementsParseTest extends ReplacementsTest {
inlineInvokeDecision = null;
}
}
public static int nonVoidIntrinsicWithCall(int x, int y) {
if (TestObject.nonVoidIntrinsicWithCall(x, y) == x) {
GraalDirectives.deoptimize();
}
return y;
}
/**
* This tests the case where an intrinsic ends with a runtime call but returns some kind of
* value. This requires that a FrameState is available after the {@link ForeignCallNode} since
* the return value must be computed on return from the call.
*/
@Test
public void testNonVoidIntrinsicWithCall() {
testGraph("nonVoidIntrinsicWithCall");
}
public static int nonVoidIntrinsicWithOptimizedSplit(int x) {
if (TestObject.nonVoidIntrinsicWithOptimizedSplit(x) == x) {
GraalDirectives.deoptimize();
}
return x;
}
/**
* This is similar to {@link #testNonVoidIntrinsicWithCall()} but has a merge after the call
* which would normally capture the {@link FrameState} but in this case we force the merge to be
* optimized away.
*/
@Test
public void testNonVoidIntrinsicWithOptimizedSplit() {
testGraph("nonVoidIntrinsicWithOptimizedSplit");
}
@SuppressWarnings("try")
private void testGraph(String name) {
StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES);
try (DebugContext.Scope s0 = graph.getDebug().scope(name, graph)) {
for (OpaqueNode node : graph.getNodes().filter(OpaqueNode.class)) {
node.replaceAndDelete(node.getValue());
}
HighTierContext context = getDefaultHighTierContext();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new FloatingReadPhase().apply(graph);
canonicalizer.apply(graph, context);
new DeadCodeEliminationPhase().apply(graph);
new GuardLoweringPhase().apply(graph, getDefaultMidTierContext());
new FrameStateAssignmentPhase().apply(graph);
} catch (Throwable e) {
throw graph.getDebug().handle(e);
}
}
private class DummyInjectionProvider implements NodeIntrinsicPluginFactory.InjectionProvider {
@SuppressWarnings("unchecked")
@Override
public <T> T getInjectedArgument(Class<T> type) {
if (type == ForeignCallsProvider.class) {
return (T) new ForeignCallsProvider() {
@Override
public LIRKind getValueKind(JavaKind javaKind) {
return null;
}
@Override
public boolean isReexecutable(ForeignCallDescriptor descriptor) {
return false;
}
@Override
public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
return new LocationIdentity[0];
}
@Override
public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
return false;
}
@Override
public boolean isGuaranteedSafepoint(ForeignCallDescriptor descriptor) {
return false;
}
@Override
public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
return null;
}
};
}
if (type == SnippetReflectionProvider.class) {
return (T) getSnippetReflection();
}
return null;
}
@Override
public Stamp getInjectedStamp(Class<?> type, boolean nonNull) {
JavaKind kind = JavaKind.fromJavaClass(type);
return StampFactory.forKind(kind);
}
}
}

View File

@ -100,6 +100,12 @@ public class RedefineIntrinsicTest extends ReplacementsTest {
@Test
public void test() throws Throwable {
try {
Class.forName("java.lang.instrument.Instrumentation");
} catch (ClassNotFoundException ex) {
// skip this test if java.instrument JDK9 module is missing
return;
}
String recursionPropName = getClass().getName() + ".recursion";
if (Java8OrEarlier || Boolean.getBoolean(recursionPropName)) {
testHelper();
@ -134,7 +140,10 @@ public class RedefineIntrinsicTest extends ReplacementsTest {
testAgainstExpected(callIntrinsicGetValue, new Result("intrinsic", null), receiver, args);
// Apply redefinition of intrinsic bytecode
redefineIntrinsic();
if (!redefineIntrinsic()) {
// running on JDK9 without agent
return;
}
// Expect redefinition to have no effect
Assert.assertEquals("original", Original.getValue());
@ -166,7 +175,7 @@ public class RedefineIntrinsicTest extends ReplacementsTest {
jar.closeEntry();
}
static void redefineIntrinsic() throws Exception {
static boolean redefineIntrinsic() throws Exception {
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
Attributes mainAttrs = manifest.getMainAttributes();
@ -181,13 +190,13 @@ public class RedefineIntrinsicTest extends ReplacementsTest {
add(jarStream, Redefiner.class);
jarStream.close();
loadAgent(jar);
return loadAgent(jar);
} finally {
Files.deleteIfExists(jar);
}
}
public static void loadAgent(Path agent) throws Exception {
public static boolean loadAgent(Path agent) throws Exception {
String vmName = ManagementFactory.getRuntimeMXBean().getName();
int p = vmName.indexOf('@');
assumeTrue("VM name not in <pid>@<host> format: " + vmName, p != -1);
@ -197,8 +206,19 @@ public class RedefineIntrinsicTest extends ReplacementsTest {
ClassLoader cl = ToolProvider.getSystemToolClassLoader();
c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl);
} else {
// I don't know what changed to make this necessary...
c = Class.forName("com.sun.tools.attach.VirtualMachine", true, RedefineIntrinsicTest.class.getClassLoader());
try {
// I don't know what changed to make this necessary...
c = Class.forName("com.sun.tools.attach.VirtualMachine", true, RedefineIntrinsicTest.class.getClassLoader());
} catch (ClassNotFoundException ex) {
try {
Class.forName("javax.naming.Reference");
} catch (ClassNotFoundException coreNamingMissing) {
// if core JDK classes aren't found, we are probably running in a
// JDK9 java.base environment and then missing class is OK
return false;
}
throw ex;
}
}
Method attach = c.getDeclaredMethod("attach", String.class);
Method loadAgent = c.getDeclaredMethod("loadAgent", String.class, String.class);
@ -206,6 +226,7 @@ public class RedefineIntrinsicTest extends ReplacementsTest {
Object vm = attach.invoke(null, pid);
loadAgent.invoke(vm, agent.toString(), "");
detach.invoke(vm);
return true;
}
public static class RedefinerAgent {

View File

@ -435,11 +435,11 @@ public class StandardGraphBuilderPlugins {
}
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4,
ValueNode arg5, ValueNode arg6, ValueNode arg7) {
if (arg3.isConstant()) {
b.addPush(JavaKind.Int,
new StringIndexOfNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), arg1, arg2, arg3, arg4, arg5, arg6, arg7));
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode source, ValueNode sourceOffset, ValueNode sourceCount,
ValueNode target, ValueNode targetOffset, ValueNode targetCount, ValueNode origFromIndex) {
if (target.isConstant()) {
b.addPush(JavaKind.Int, new StringIndexOfNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), source, sourceOffset, sourceCount,
target, targetOffset, targetCount, origFromIndex));
return true;
}
return false;

View File

@ -25,7 +25,6 @@ package org.graalvm.compiler.replacements.classfile;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeProvider;
@ -45,7 +44,8 @@ import jdk.vm.ci.meta.TriState;
/**
* The bytecode properties of a method as parsed directly from a class file without any
* {@linkplain Instrumentation instrumentation} or other rewriting performed on the bytecode.
* {@linkplain java.lang.instrument.Instrumentation instrumentation} or other rewriting performed on
* the bytecode.
*/
public class ClassfileBytecode implements Bytecode {

View File

@ -28,7 +28,6 @@ import static org.graalvm.compiler.serviceprovider.JDK9Method.getResourceAsStrea
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.Instrumentation;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.Bytecode;
@ -45,8 +44,8 @@ import jdk.vm.ci.meta.ResolvedJavaType;
/**
* A {@link BytecodeProvider} that provides bytecode properties of a {@link ResolvedJavaMethod} as
* parsed from a class file. This avoids all {@linkplain Instrumentation instrumentation} and any
* bytecode rewriting performed by the VM.
* parsed from a class file. This avoids all {@linkplain java.lang.instrument.Instrumentation
* instrumentation} and any bytecode rewriting performed by the VM.
*
* This mechanism retrieves class files based on the name and {@link ClassLoader} of existing
* {@link Class} instances. It bypasses all VM parsing and verification of the class file and

View File

@ -263,10 +263,10 @@ public abstract class PartialEscapeClosure<BlockT extends PartialEscapeBlockStat
/**
* This tries to canonicalize the node based on improved (replaced) inputs.
*/
@SuppressWarnings("unchecked")
private boolean processNodeWithScalarReplacedInputs(ValueNode node, FixedNode insertBefore, BlockT state, GraphEffectList effects) {
ValueNode canonicalizedValue = node;
if (node instanceof Canonicalizable.Unary<?>) {
@SuppressWarnings("unchecked")
Canonicalizable.Unary<ValueNode> canonicalizable = (Canonicalizable.Unary<ValueNode>) node;
ObjectState valueObj = getObjectState(state, canonicalizable.getValue());
ValueNode valueAlias = valueObj != null ? valueObj.getMaterializedValue() : getScalarAlias(canonicalizable.getValue());
@ -274,7 +274,6 @@ public abstract class PartialEscapeClosure<BlockT extends PartialEscapeBlockStat
canonicalizedValue = (ValueNode) canonicalizable.canonical(tool, valueAlias);
}
} else if (node instanceof Canonicalizable.Binary<?>) {
@SuppressWarnings("unchecked")
Canonicalizable.Binary<ValueNode> canonicalizable = (Canonicalizable.Binary<ValueNode>) node;
ObjectState xObj = getObjectState(state, canonicalizable.getX());
ValueNode xAlias = xObj != null ? xObj.getMaterializedValue() : getScalarAlias(canonicalizable.getX());

View File

@ -32,10 +32,8 @@ import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
@State(Scope.Thread)
public class ArrayDuplicationBenchmark extends GraalBenchmark {
public class ArrayDuplicationBenchmark extends BenchmarkBase {
/** How large should the test-arrays be. */
private static final int TESTSIZE = 300;

View File

@ -24,7 +24,6 @@ package micro.benchmarks;
import java.util.ArrayList;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Scope;
@ -35,7 +34,7 @@ import org.openjdk.jmh.annotations.Warmup;
/**
* Benchmarks cost of ArrayList.
*/
public class ArrayListBenchmark extends GraalBenchmark {
public class ArrayListBenchmark extends BenchmarkBase {
private static final int N = 100;

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2015, 2017, 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 micro.benchmarks;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Warmup;
/**
* Base class for JMH benchmarks.
*/
@Warmup(iterations = BenchmarkBase.Defaults.WARMUP_ITERATIONS)
@Measurement(iterations = BenchmarkBase.Defaults.MEASUREMENT_ITERATIONS)
@Fork(BenchmarkBase.Defaults.FORKS)
public class BenchmarkBase {
public static class Defaults {
public static final int MEASUREMENT_ITERATIONS = 5;
public static final int WARMUP_ITERATIONS = 5;
public static final int FORKS = 1;
}
}

View File

@ -27,12 +27,10 @@ import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
/**
* Benchmarks cost of ArrayList.
*/
public class BoxingBenchmark extends GraalBenchmark {
public class BoxingBenchmark extends BenchmarkBase {
@State(Scope.Benchmark)
public static class ThreadState {

View File

@ -29,12 +29,10 @@ import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
/**
* Benchmarks cost of ArrayList.
*/
public class ConcurrentSkipListBenchmark extends GraalBenchmark {
public class ConcurrentSkipListBenchmark extends BenchmarkBase {
private static final int N = 100;

View File

@ -29,12 +29,10 @@ import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
/**
* Benchmarks cost of guarded intrinsics at indirect call sites.
*/
public class GuardedIntrinsicBenchmark extends GraalBenchmark {
public class GuardedIntrinsicBenchmark extends BenchmarkBase {
public static class HashcodeState {
public Object val1;

View File

@ -27,12 +27,10 @@ import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
/**
* Benchmarks cost of hasing a character array.
* Benchmarks cost of hashing a character array.
*/
public class HashBenchmark extends GraalBenchmark {
public class HashBenchmark extends BenchmarkBase {
@State(Scope.Benchmark)
public static class ThreadState {

View File

@ -29,12 +29,10 @@ import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
/**
* Benchmarks cost of Math intrinsics.
*/
public class MathFunctionBenchmark extends GraalBenchmark {
public class MathFunctionBenchmark extends BenchmarkBase {
@State(Scope.Benchmark)
public static class ThreadState {

View File

@ -27,12 +27,10 @@ import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
/**
* Benchmarks cost of non-contended synchronization.
*/
public class SimpleSyncBenchmark extends GraalBenchmark {
public class SimpleSyncBenchmark extends BenchmarkBase {
public static class Person {
public int age;

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2017, 2017, 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 micro.benchmarks;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
/**
* Benchmarks cost of {@link String#indexOf(int)} and {@link String#indexOf(String)}.
*/
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class StringBenchmark extends BenchmarkBase {
@State(Scope.Benchmark)
public static class BenchState {
char ch1 = 'Q';
char ch2 = 'X';
String s1 = "Qu";
String s2 = "ne";
// Checkstyle: stop
String lorem = "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
// Checkstyle: resume
}
@Benchmark
@Warmup(iterations = 5)
public int indexOfChar(BenchState state) {
return state.lorem.indexOf(state.ch1);
}
@Benchmark
@Warmup(iterations = 5)
public int indexOfCharNotFound(BenchState state) {
return state.lorem.indexOf(state.ch2);
}
@Benchmark
@Warmup(iterations = 5)
public int indexOfString(BenchState state) {
return state.lorem.indexOf(state.s1);
}
@Benchmark
@Warmup(iterations = 5)
public int indexOfStringNotFound(BenchState state) {
return state.lorem.indexOf(state.s2);
}
}